From 63a349fd65f90016070ce34d7c63879db8f5daf9 Mon Sep 17 00:00:00 2001 From: Raghavendra Kakarla Date: Sun, 26 Apr 2020 16:50:31 +0530 Subject: [PATCH 001/698] soc: qcom: Add rpm master stats driver Add rpm master stats driver to display various master statistics. Change-Id: Ied112bf77a1e7e2203b491bad0a068dcf724ec88 Signed-off-by: Raghavendra Kakarla --- drivers/soc/qcom/Makefile | 3 + drivers/soc/qcom/rpm_master_stat.c | 479 +++++++++++++++++++++++++++++ 2 files changed, 482 insertions(+) create mode 100644 drivers/soc/qcom/rpm_master_stat.c diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile index 3eb350fa645c..111ed6e3cab7 100644 --- a/drivers/soc/qcom/Makefile +++ b/drivers/soc/qcom/Makefile @@ -69,6 +69,9 @@ obj-$(CONFIG_MSM_SPSS_UTILS) += spss_utils.o obj-$(CONFIG_MSM_IDLE_STATS) += lpm-stats.o obj-$(CONFIG_MSM_PERFORMANCE) += msm_performance.o obj-$(CONFIG_QTI_RPM_STATS_LOG) += rpmh_master_stat.o +ifdef CONFIG_MSM_RPM_SMD +obj-$(CONFIG_QTI_RPM_STATS_LOG) += rpm_master_stat.o +endif obj-$(CONFIG_QPNP_PBS) += qpnp-pbs.o obj-$(CONFIG_QCOM_WATCHDOG) += qcom_watchdog.o obj-$(CONFIG_MSM_SPCOM) += spcom.o diff --git a/drivers/soc/qcom/rpm_master_stat.c b/drivers/soc/qcom/rpm_master_stat.c new file mode 100644 index 000000000000..e438ba777154 --- /dev/null +++ b/drivers/soc/qcom/rpm_master_stat.c @@ -0,0 +1,479 @@ +// SPDX-License-Identifier: GPL-2.0-only + +/* + * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define RPM_MASTERS_BUF_LEN 400 + +#define SNPRINTF(buf, size, format, ...) \ + do { \ + if (size > 0) { \ + int ret; \ + ret = scnprintf(buf, size, format, ## __VA_ARGS__); \ + buf += ret; \ + size -= ret; \ + } \ + } while (0) + +#define GET_MASTER_NAME(a, prvdata) \ + ((a >= prvdata->num_masters) ? "Invalid Master Name" : \ + prvdata->master_names[a]) + +#define GET_FIELD(a) ((strnstr(#a, ".", 80) + 1)) + +struct msm_rpm_master_stats_platform_data { + phys_addr_t phys_addr_base; + u32 phys_size; + char **masters; + /* + * RPM maintains PC stats for each master in MSG RAM, + * it allocates 256 bytes for this use. + * No of masters differs for different targets. + * Based on the number of masters, linux rpm stat + * driver reads (32 * num_masters) bytes to display + * master stats. + */ + s32 num_masters; + u32 master_offset; + u32 version; +}; + +static DEFINE_MUTEX(msm_rpm_master_stats_mutex); + +struct msm_rpm_master_stats { + uint32_t active_cores; + uint32_t numshutdowns; + uint64_t shutdown_req; + uint64_t wakeup_ind; + uint64_t bringup_req; + uint64_t bringup_ack; + uint32_t wakeup_reason; /* 0 = rude wakeup, 1 = scheduled wakeup */ + uint32_t last_sleep_transition_duration; + uint32_t last_wake_transition_duration; + uint32_t xo_count; + uint64_t xo_last_entered_at; + uint64_t xo_last_exited_at; + uint64_t xo_accumulated_duration; +}; + +struct msm_rpm_master_stats_private_data { + void __iomem *reg_base; + u32 len; + char **master_names; + u32 num_masters; + char buf[RPM_MASTERS_BUF_LEN]; + struct msm_rpm_master_stats_platform_data *platform_data; +}; + +static int msm_rpm_master_stats_file_close(struct inode *inode, + struct file *file) +{ + struct msm_rpm_master_stats_private_data *private = file->private_data; + + mutex_lock(&msm_rpm_master_stats_mutex); + if (private->reg_base) + iounmap(private->reg_base); + kfree(file->private_data); + mutex_unlock(&msm_rpm_master_stats_mutex); + + return 0; +} + +static int msm_rpm_master_copy_stats( + struct msm_rpm_master_stats_private_data *prvdata) +{ + struct msm_rpm_master_stats record; + struct msm_rpm_master_stats_platform_data *pdata; + static int master_cnt; + int count, j = 0; + char *buf; + unsigned long active_cores; + + /* Iterate possible number of masters */ + if (master_cnt > prvdata->num_masters - 1) { + master_cnt = 0; + return 0; + } + + pdata = prvdata->platform_data; + count = RPM_MASTERS_BUF_LEN; + buf = prvdata->buf; + + if (prvdata->platform_data->version == 2) { + SNPRINTF(buf, count, "%s\n", + GET_MASTER_NAME(master_cnt, prvdata)); + + record.shutdown_req = readq_relaxed(prvdata->reg_base + + (master_cnt * pdata->master_offset + + offsetof(struct msm_rpm_master_stats, shutdown_req))); + + SNPRINTF(buf, count, "\t%s:0x%llX\n", + GET_FIELD(record.shutdown_req), + record.shutdown_req); + + record.wakeup_ind = readq_relaxed(prvdata->reg_base + + (master_cnt * pdata->master_offset + + offsetof(struct msm_rpm_master_stats, wakeup_ind))); + + SNPRINTF(buf, count, "\t%s:0x%llX\n", + GET_FIELD(record.wakeup_ind), + record.wakeup_ind); + + record.bringup_req = readq_relaxed(prvdata->reg_base + + (master_cnt * pdata->master_offset + + offsetof(struct msm_rpm_master_stats, bringup_req))); + + SNPRINTF(buf, count, "\t%s:0x%llX\n", + GET_FIELD(record.bringup_req), + record.bringup_req); + + record.bringup_ack = readq_relaxed(prvdata->reg_base + + (master_cnt * pdata->master_offset + + offsetof(struct msm_rpm_master_stats, bringup_ack))); + + SNPRINTF(buf, count, "\t%s:0x%llX\n", + GET_FIELD(record.bringup_ack), + record.bringup_ack); + + record.xo_last_entered_at = readq_relaxed(prvdata->reg_base + + (master_cnt * pdata->master_offset + + offsetof(struct msm_rpm_master_stats, + xo_last_entered_at))); + + SNPRINTF(buf, count, "\t%s:0x%llX\n", + GET_FIELD(record.xo_last_entered_at), + record.xo_last_entered_at); + + record.xo_last_exited_at = readq_relaxed(prvdata->reg_base + + (master_cnt * pdata->master_offset + + offsetof(struct msm_rpm_master_stats, + xo_last_exited_at))); + + SNPRINTF(buf, count, "\t%s:0x%llX\n", + GET_FIELD(record.xo_last_exited_at), + record.xo_last_exited_at); + + record.xo_accumulated_duration = + readq_relaxed(prvdata->reg_base + + (master_cnt * pdata->master_offset + + offsetof(struct msm_rpm_master_stats, + xo_accumulated_duration))); + + SNPRINTF(buf, count, "\t%s:0x%llX\n", + GET_FIELD(record.xo_accumulated_duration), + record.xo_accumulated_duration); + + record.last_sleep_transition_duration = + readl_relaxed(prvdata->reg_base + + (master_cnt * pdata->master_offset + + offsetof(struct msm_rpm_master_stats, + last_sleep_transition_duration))); + + SNPRINTF(buf, count, "\t%s:0x%x\n", + GET_FIELD(record.last_sleep_transition_duration), + record.last_sleep_transition_duration); + + record.last_wake_transition_duration = + readl_relaxed(prvdata->reg_base + + (master_cnt * pdata->master_offset + + offsetof(struct msm_rpm_master_stats, + last_wake_transition_duration))); + + SNPRINTF(buf, count, "\t%s:0x%x\n", + GET_FIELD(record.last_wake_transition_duration), + record.last_wake_transition_duration); + + record.xo_count = + readl_relaxed(prvdata->reg_base + + (master_cnt * pdata->master_offset + + offsetof(struct msm_rpm_master_stats, + xo_count))); + + SNPRINTF(buf, count, "\t%s:0x%x\n", + GET_FIELD(record.xo_count), + record.xo_count); + + record.wakeup_reason = readl_relaxed(prvdata->reg_base + + (master_cnt * pdata->master_offset + + offsetof(struct msm_rpm_master_stats, + wakeup_reason))); + + SNPRINTF(buf, count, "\t%s:0x%x\n", + GET_FIELD(record.wakeup_reason), + record.wakeup_reason); + + record.numshutdowns = readl_relaxed(prvdata->reg_base + + (master_cnt * pdata->master_offset + + offsetof(struct msm_rpm_master_stats, numshutdowns))); + + SNPRINTF(buf, count, "\t%s:0x%x\n", + GET_FIELD(record.numshutdowns), + record.numshutdowns); + + record.active_cores = readl_relaxed(prvdata->reg_base + + (master_cnt * pdata->master_offset) + + offsetof(struct msm_rpm_master_stats, active_cores)); + + SNPRINTF(buf, count, "\t%s:0x%x\n", + GET_FIELD(record.active_cores), + record.active_cores); + } else { + SNPRINTF(buf, count, "%s\n", + GET_MASTER_NAME(master_cnt, prvdata)); + + record.numshutdowns = readl_relaxed(prvdata->reg_base + + (master_cnt * pdata->master_offset) + 0x0); + + SNPRINTF(buf, count, "\t%s:0x%0x\n", + GET_FIELD(record.numshutdowns), + record.numshutdowns); + + record.active_cores = readl_relaxed(prvdata->reg_base + + (master_cnt * pdata->master_offset) + 0x4); + + SNPRINTF(buf, count, "\t%s:0x%0x\n", + GET_FIELD(record.active_cores), + record.active_cores); + } + + active_cores = record.active_cores; + j = find_first_bit(&active_cores, BITS_PER_LONG); + while (j < (BITS_PER_LONG - 1)) { + SNPRINTF(buf, count, "\t\tcore%d\n", j); + j = find_next_bit((const unsigned long *)&active_cores, + BITS_PER_LONG, j + 1); + } + + if (j == (BITS_PER_LONG - 1)) + SNPRINTF(buf, count, "\t\tcore%d\n", j); + + master_cnt++; + return RPM_MASTERS_BUF_LEN - count; +} + +static ssize_t msm_rpm_master_stats_file_read(struct file *file, + char __user *bufu, size_t count, loff_t *ppos) +{ + struct msm_rpm_master_stats_private_data *prvdata; + struct msm_rpm_master_stats_platform_data *pdata; + ssize_t ret = -EINVAL; + + mutex_lock(&msm_rpm_master_stats_mutex); + prvdata = file->private_data; + if (!prvdata) + goto exit; + + pdata = prvdata->platform_data; + if (!pdata) + goto exit; + + if (!bufu || count == 0) + goto exit; + + if (*ppos <= pdata->phys_size) { + prvdata->len = msm_rpm_master_copy_stats(prvdata); + *ppos = 0; + } + + ret = simple_read_from_buffer(bufu, count, ppos, + prvdata->buf, prvdata->len); +exit: + mutex_unlock(&msm_rpm_master_stats_mutex); + return ret; +} + +static int msm_rpm_master_stats_file_open(struct inode *inode, + struct file *file) +{ + struct msm_rpm_master_stats_private_data *prvdata; + struct msm_rpm_master_stats_platform_data *pdata; + int ret = 0; + + mutex_lock(&msm_rpm_master_stats_mutex); + pdata = inode->i_private; + + file->private_data = + kzalloc(sizeof(struct msm_rpm_master_stats_private_data), + GFP_KERNEL); + + if (!file->private_data) { + ret = -ENOMEM; + goto exit; + } + + prvdata = file->private_data; + + prvdata->reg_base = ioremap(pdata->phys_addr_base, + pdata->phys_size); + if (!prvdata->reg_base) { + kfree(file->private_data); + prvdata = NULL; + pr_err("%s: ERROR could not ioremap start=%pa, len=%u\n", + __func__, &pdata->phys_addr_base, + pdata->phys_size); + ret = -ENOMEM; + goto exit; + } + + prvdata->len = 0; + prvdata->num_masters = pdata->num_masters; + prvdata->master_names = pdata->masters; + prvdata->platform_data = pdata; +exit: + mutex_unlock(&msm_rpm_master_stats_mutex); + return ret; +} + +static const struct file_operations msm_rpm_master_stats_fops = { + .owner = THIS_MODULE, + .open = msm_rpm_master_stats_file_open, + .read = msm_rpm_master_stats_file_read, + .release = msm_rpm_master_stats_file_close, + .llseek = no_llseek, +}; + +static struct msm_rpm_master_stats_platform_data + *msm_rpm_master_populate_pdata(struct device *dev) +{ + struct msm_rpm_master_stats_platform_data *pdata; + struct device_node *node = dev->of_node; + int rc = 0, i; + + pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + goto err; + + rc = of_property_read_u32(node, "qcom,master-stats-version", + &pdata->version); + if (rc) { + dev_err(dev, "master-stats-version missing rc=%d\n", rc); + goto err; + } + + rc = of_property_read_u32(node, "qcom,master-offset", + &pdata->master_offset); + if (rc) { + dev_err(dev, "master-offset missing rc=%d\n", rc); + goto err; + } + + pdata->num_masters = of_property_count_strings(node, "qcom,masters"); + if (pdata->num_masters < 0) { + dev_err(dev, "Failed to get number of masters =%d\n", + pdata->num_masters); + goto err; + } + + pdata->masters = devm_kzalloc(dev, sizeof(char *) * pdata->num_masters, + GFP_KERNEL); + if (!pdata->masters) + goto err; + + /* + * Read master names from DT + */ + for (i = 0; i < pdata->num_masters; i++) { + const char *master_name; + + of_property_read_string_index(node, "qcom,masters", + i, &master_name); + pdata->masters[i] = devm_kstrdup(dev, master_name, GFP_KERNEL); + if (!pdata->masters[i]) + goto err; + } + return pdata; +err: + return NULL; +} + +static int msm_rpm_master_stats_probe(struct platform_device *pdev) +{ + struct dentry *dent; + struct msm_rpm_master_stats_platform_data *pdata; + struct resource *res = NULL; + + pdata = msm_rpm_master_populate_pdata(&pdev->dev); + if (!pdata) + return -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + + if (!res) { + dev_err(&pdev->dev, + "%s: Failed to get IO resource from platform device\n", + __func__); + return -ENXIO; + } + + pdata->phys_addr_base = res->start; + pdata->phys_size = resource_size(res); + + dent = debugfs_create_file("rpm_master_stats", 0444, NULL, + pdata, &msm_rpm_master_stats_fops); + + if (!dent) { + dev_err(&pdev->dev, "%s: ERROR debugfs_create_file failed\n", + __func__); + return -ENOMEM; + } + + platform_set_drvdata(pdev, dent); + return 0; +} + +static int msm_rpm_master_stats_remove(struct platform_device *pdev) +{ + struct dentry *dent; + + dent = platform_get_drvdata(pdev); + debugfs_remove(dent); + platform_set_drvdata(pdev, NULL); + return 0; +} + +static const struct of_device_id rpm_master_table[] = { + {.compatible = "qcom,rpm-master-stats"}, + {}, +}; + +static struct platform_driver msm_rpm_master_stats_driver = { + .probe = msm_rpm_master_stats_probe, + .remove = msm_rpm_master_stats_remove, + .driver = { + .name = "msm_rpm_master_stats", + .of_match_table = rpm_master_table, + }, +}; + +static int __init msm_rpm_master_stats_init(void) +{ + return platform_driver_register(&msm_rpm_master_stats_driver); +} + +static void __exit msm_rpm_master_stats_exit(void) +{ + platform_driver_unregister(&msm_rpm_master_stats_driver); +} + +module_init(msm_rpm_master_stats_init); +module_exit(msm_rpm_master_stats_exit); + +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("MSM RPM Master Statistics driver"); +MODULE_ALIAS("platform:msm_master_stat_log"); From 1ee4a13e84ef0142925b7cefab75e0b1f2a6ad62 Mon Sep 17 00:00:00 2001 From: Raghavendra Kakarla Date: Sat, 8 Aug 2020 22:05:32 +0530 Subject: [PATCH 002/698] irqchip: mpm: Forward the irq type for the mpm parent This patch adds the logic to forward the irq type from the mpm irq domain to its parent gic irq domain. Change-Id: Id7c42ba59e0d003ffaa0a7951be4a2d3ffdb64a4 Signed-off-by: Raghavendra Kakarla --- drivers/irqchip/qcom-mpm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/irqchip/qcom-mpm.c b/drivers/irqchip/qcom-mpm.c index 1f242cf729c0..a342948f55c9 100644 --- a/drivers/irqchip/qcom-mpm.c +++ b/drivers/irqchip/qcom-mpm.c @@ -400,6 +400,7 @@ static int msm_mpm_gic_chip_alloc(struct irq_domain *domain, parent_fwspec.param_count = 3; parent_fwspec.param[0] = 0; parent_fwspec.param[1] = parent_hwirq; + parent_fwspec.param[2] = type; return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &parent_fwspec); From afeca470183f7169606ed3e5b8fb6ce521091a04 Mon Sep 17 00:00:00 2001 From: Raghavendra Kakarla Date: Sun, 9 Aug 2020 13:55:15 +0530 Subject: [PATCH 003/698] irqchip: mpm: Update the mpm to gic irq mapping Update the mpm to gic irq mapping with valid mapping. Change-Id: Icd92eb40dadd15c4f601bd3a976f6831ab1898af Signed-off-by: Raghavendra Kakarla --- drivers/irqchip/qcom-mpm-holi.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/irqchip/qcom-mpm-holi.c b/drivers/irqchip/qcom-mpm-holi.c index 1b051404ed5a..c324e03c16a8 100644 --- a/drivers/irqchip/qcom-mpm-holi.c +++ b/drivers/irqchip/qcom-mpm-holi.c @@ -6,12 +6,12 @@ #include const struct mpm_pin mpm_holi_gic_chip_data[] = { - {5, 328}, /* lpass_irq_out_sdc */ - {12, 454}, /* qmp_usb3_lfps_rxterm_irq_cx */ - {86, 215}, /* mpm_wake,spmi_m */ - {89, 346}, /* tsens0_tsens_0C_int */ - {90, 347}, /* tsens1_tsens_0C_int */ - {93, 292}, /* eud_p0_dpse_int_mx */ - {94, 292}, /* eud_p0_dmse_int_mx */ + {5, 296}, /* lpass_irq_out_sdc */ + {12, 422}, /* qmp_usb3_lfps_rxterm_irq_cx */ + {86, 183}, /* mpm_wake,spmi_m */ + {89, 314}, /* tsens0_tsens_0C_int */ + {90, 315}, /* tsens1_tsens_0C_int */ + {93, 260}, /* eud_p0_dpse_int_mx */ + {94, 260}, /* eud_p0_dmse_int_mx */ {-1}, }; From b02f2a20620364bc0970ea7165c4090456236205 Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Sun, 9 Aug 2020 23:05:13 +0530 Subject: [PATCH 004/698] clk: qcom: gcc: update frequency table for csi3phytimer clock The Fmax table is updated as per the HW recommendation for csi3phytimer clock. Also at the same time remove the unwanted clk set rate flag for display rot clock. Change-Id: I761f2cb99da27d4d04dbbf95dd546faefdad225a Signed-off-by: Taniya Das --- drivers/clk/qcom/dispcc-holi.c | 1 - drivers/clk/qcom/gcc-holi.c | 14 +++----------- drivers/clk/qcom/gpucc-holi.c | 1 + 3 files changed, 4 insertions(+), 12 deletions(-) diff --git a/drivers/clk/qcom/dispcc-holi.c b/drivers/clk/qcom/dispcc-holi.c index 913c888965ee..2d3b236503ea 100644 --- a/drivers/clk/qcom/dispcc-holi.c +++ b/drivers/clk/qcom/dispcc-holi.c @@ -289,7 +289,6 @@ static struct clk_rcg2 disp_cc_mdss_rot_clk_src = { .name = "disp_cc_mdss_rot_clk_src", .parent_data = disp_cc_parent_data_1, .num_parents = 5, - .flags = CLK_SET_RATE_PARENT, .ops = &clk_rcg2_ops, }, .clkr.vdd_data = { diff --git a/drivers/clk/qcom/gcc-holi.c b/drivers/clk/qcom/gcc-holi.c index 8ed936e906d7..295957e1f0cb 100644 --- a/drivers/clk/qcom/gcc-holi.c +++ b/drivers/clk/qcom/gcc-holi.c @@ -992,20 +992,12 @@ static struct clk_rcg2 gcc_camss_csi2phytimer_clk_src = { }, }; -static const struct freq_tbl ftbl_gcc_camss_csi3phytimer_clk_src[] = { - F(19200000, P_BI_TCXO, 1, 0, 0), - F(133333333, P_GPLL0_OUT_ODD, 1.5, 0, 0), - F(200000000, P_GPLL0_OUT_ODD, 1, 0, 0), - F(268800000, P_GPLL4_OUT_EVEN, 3, 0, 0), - { } -}; - static struct clk_rcg2 gcc_camss_csi3phytimer_clk_src = { .cmd_rcgr = 0x59054, .mnd_width = 0, .hid_width = 5, .parent_map = gcc_parent_map_4, - .freq_tbl = ftbl_gcc_camss_csi3phytimer_clk_src, + .freq_tbl = ftbl_gcc_camss_csi0phytimer_clk_src, .enable_safe_config = true, .clkr.hw.init = &(struct clk_init_data){ .name = "gcc_camss_csi3phytimer_clk_src", @@ -1018,8 +1010,7 @@ static struct clk_rcg2 gcc_camss_csi3phytimer_clk_src = { .num_rate_max = VDD_NUM, .rate_max = (unsigned long[VDD_NUM]) { [VDD_LOWER] = 19200000, - [VDD_LOW] = 133333333, - [VDD_LOW_L1] = 200000000, + [VDD_LOW] = 200000000, [VDD_NOMINAL] = 268800000}, }, }; @@ -3181,6 +3172,7 @@ static struct clk_branch gcc_gpu_memnoc_gfx_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_gpu_memnoc_gfx_clk", + .flags = CLK_DONT_HOLD_STATE, .ops = &clk_branch2_ops, }, }, diff --git a/drivers/clk/qcom/gpucc-holi.c b/drivers/clk/qcom/gpucc-holi.c index 8a7cc21379bb..7621bbaca089 100644 --- a/drivers/clk/qcom/gpucc-holi.c +++ b/drivers/clk/qcom/gpucc-holi.c @@ -344,6 +344,7 @@ static struct clk_branch gpu_cc_cxo_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gpu_cc_cxo_clk", + .flags = CLK_DONT_HOLD_STATE, .ops = &clk_branch2_ops, }, }, From d08e185d63985ec4d51236d78ee1fc218e444422 Mon Sep 17 00:00:00 2001 From: Hareesh Gundu Date: Fri, 14 Aug 2020 12:25:33 +0530 Subject: [PATCH 005/698] msm: kgsl: Fix GMEM base for A615 family GPUs For all A615 GPU family GMEM base start with 1MB as per requirement. Change-Id: Ie4ca5b9d264492f10eff39daf758d5c72d32c653 Signed-off-by: Hareesh Gundu --- drivers/gpu/msm/adreno-gpulist.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/msm/adreno-gpulist.h b/drivers/gpu/msm/adreno-gpulist.h index 028dc5018177..f5a0cef7d3fc 100644 --- a/drivers/gpu/msm/adreno-gpulist.h +++ b/drivers/gpu/msm/adreno-gpulist.h @@ -936,6 +936,7 @@ static const struct adreno_a6xx_core adreno_gpu_core_a619 = { ADRENO_GPMU | ADRENO_CONTENT_PROTECTION | ADRENO_IFPC | ADRENO_IOCOHERENT, .gpudev = &adreno_a630_gpudev, + .gmem_base = 0x100000, .gmem_size = SZ_512K, .bus_width = 32, .snapshot_size = SZ_2M, @@ -961,6 +962,7 @@ static const struct adreno_a6xx_core adreno_gpu_core_a619_variant = { .compatible = "qcom,adreno-gpu-a619-holi", .features = ADRENO_PREEMPTION | ADRENO_CONTENT_PROTECTION, .gpudev = &adreno_a6xx_gpudev, + .gmem_base = 0x100000, .gmem_size = SZ_512K, .bus_width = 32, .snapshot_size = SZ_2M, From 76322f917ef500f67ae9583ea6a1ce753ed230b1 Mon Sep 17 00:00:00 2001 From: Manaf Meethalavalappu Pallikunhi Date: Sat, 15 Aug 2020 22:03:45 +0530 Subject: [PATCH 006/698] drivers: thermal: don't reset ops pointer in of-thermal sensor unregister The thermal zone ops pointer is allocated and initialized during building thermal zone at early boot. The framework expects this variable is valid as long as that thermal zone exist. Later if a sensor is registered to thermal zone and then unregistered the same due to some reason, it resets this thermal zone ops variable. It leads to unexpected behaviour whenever thermal framework tries to use it. Don't reset thermal zone ops variable during of-thermal sensor unregister context. Change-Id: I468cdfe08f4cde3fb1258ca335fe2ee8b457e014 Signed-off-by: Manaf Meethalavalappu Pallikunhi --- drivers/thermal/of-thermal.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/thermal/of-thermal.c b/drivers/thermal/of-thermal.c index 7995f433799f..0387a2f105ce 100644 --- a/drivers/thermal/of-thermal.c +++ b/drivers/thermal/of-thermal.c @@ -1021,7 +1021,6 @@ void thermal_zone_of_sensor_unregister(struct device *dev, pos_tzd->ops->get_temp = NULL; pos_tzd->ops->get_trend = NULL; pos_tzd->ops->set_emul_temp = NULL; - pos_tzd->ops = NULL; mutex_unlock(&pos_tzd->lock); } kfree(sens_param->tz_list); From ef39aeb5ee9e34b14576021babec15268dd1c789 Mon Sep 17 00:00:00 2001 From: Sarthak Garg Date: Thu, 6 Aug 2020 20:39:24 +0530 Subject: [PATCH 007/698] arm64: defconfig: Enable eMMC/SD card driver for holi QGKI defconfig Enable eMMC/SD card driver as a inbuilt module for holi QGKI defconfig. Also Enable a config flag to add Qualcomm specific code to upstream MMC drivers. Change-Id: Ic98253109fe656ee78c95ae21290210305f5ec4b Signed-off-by: Sarthak Garg --- arch/arm64/configs/vendor/holi_QGKI.config | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/configs/vendor/holi_QGKI.config b/arch/arm64/configs/vendor/holi_QGKI.config index 3556b8f47a82..75b76a9282c2 100644 --- a/arch/arm64/configs/vendor/holi_QGKI.config +++ b/arch/arm64/configs/vendor/holi_QGKI.config @@ -146,6 +146,8 @@ CONFIG_QTI_ADC_TM=y CONFIG_HAVE_USERSPACE_LOW_MEMORY_KILLER=y CONFIG_STACK_HASH_ORDER_SHIFT=12 CONFIG_PAGE_OWNER=y +CONFIG_MMC_SDHCI_MSM=y +CONFIG_SDC_QTI=y # CONFIG_DEBUG_DMA_BUF_REF is not set # CONFIG_PAGE_EXTENSION_PAGE_FREE is not set # CONFIG_PAGE_OWNER_ENABLE_DEFAULT is not set From b5d3e10b1b5657ca3ecddceb4de8a614b57c54ea Mon Sep 17 00:00:00 2001 From: Sarthak Garg Date: Thu, 6 Aug 2020 19:36:27 +0530 Subject: [PATCH 008/698] arm64: defconfig: Enable eMMC/SD card on holi Enable eMMC/SD card driver to be build as a loadable module in the holi GKI defconfig file. Change-Id: Ic13088afeaa70b9c0fddbbe03f5ca1545a1d4db5 Signed-off-by: Sarthak Garg --- arch/arm64/configs/vendor/holi_GKI.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/vendor/holi_GKI.config b/arch/arm64/configs/vendor/holi_GKI.config index 4488c5151736..8c556cc36e6a 100644 --- a/arch/arm64/configs/vendor/holi_GKI.config +++ b/arch/arm64/configs/vendor/holi_GKI.config @@ -180,6 +180,7 @@ CONFIG_MEDIA_USB_SUPPORT=y CONFIG_USB_VIDEO_CLASS=m CONFIG_LEDS_QPNP_FLASH_V2=m CONFIG_QTI_IOMMU_SUPPORT=m +CONFIG_MMC_SDHCI_MSM=m CONFIG_INTERCONNECT_QCOM_HOLI=m CONFIG_SERIAL_MSM_GENI=m CONFIG_SERIAL_MSM_GENI_HALF_SAMPLING=y From 49abb2645cb2a23254482e6ab4f1fc9233d1ca1c Mon Sep 17 00:00:00 2001 From: Sarthak Garg Date: Fri, 7 Aug 2020 17:02:52 +0530 Subject: [PATCH 009/698] mmc: sdhci-msm: skip eMMC slot probe if eMMC isn't a bootdevice If eMMC is not a primary bootdevice, there isn't any point of probing eMMC device hence disable the probing in such case. Change-Id: I67a025606b03bb3cc21e818c2b4b519aa2b53888 Signed-off-by: Sarthak Garg --- drivers/mmc/host/sdhci-msm.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c index 82a0788795b9..2057d31a8e40 100644 --- a/drivers/mmc/host/sdhci-msm.c +++ b/drivers/mmc/host/sdhci-msm.c @@ -396,6 +396,18 @@ struct sdhci_msm_host { struct sdhci_msm_regs_restore regs_restore; }; +#define ANDROID_BOOT_DEV_MAX 30 +static char android_boot_dev[ANDROID_BOOT_DEV_MAX]; + +#ifndef MODULE +static int __init get_android_boot_dev(char *str) +{ + strlcpy(android_boot_dev, str, ANDROID_BOOT_DEV_MAX); + return 1; +} +__setup("androidboot.bootdevice=", get_android_boot_dev); +#endif + static struct sdhci_msm_host *sdhci_slot[2]; static void sdhci_msm_bus_voting(struct sdhci_host *host, bool enable); @@ -3103,6 +3115,13 @@ static int sdhci_msm_probe(struct platform_device *pdev) dev_err(&pdev->dev, "get slot index failed %d\n", ret); else if (ret <= 2) sdhci_slot[ret-1] = msm_host; + + if (of_property_read_bool(dev->of_node, "non-removable") && + strlen(android_boot_dev) && + strcmp(android_boot_dev, dev_name(dev))) { + ret = -ENODEV; + goto pltfm_free; + } } /* From bcbde7f868388b7696c67b05d17175e5cad536d6 Mon Sep 17 00:00:00 2001 From: Ritesh Harjani Date: Fri, 7 Feb 2020 17:34:28 +0530 Subject: [PATCH 010/698] UPSTREAM: mmc: sdhci-msm: Don't enable PWRSAVE_DLL for certain sdhc hosts SDHC core with new 14lpp and later tech DLL should not enable PWRSAVE_DLL since such controller's internal gating cannot meet following MCLK requirement: When MCLK is gated OFF, it is not gated for less than 0.5us and MCLK must be switched on for at-least 1us before DATA starts coming. Adding support for this requirement. Change-Id: I571c8fb40835e094d8feb4df5c2d049c02a0a2f2 Signed-off-by: Ritesh Harjani Signed-off-by: Veerabhadrarao Badiganti Reviewed-by: Can Guo Acked-by: Adrian Hunter Link: https://lore.kernel.org/r/1581077075-26011-1-git-send-email-vbadigan@codeaurora.org Signed-off-by: Ulf Hansson Signed-off-by: Veerabhadrarao Badiganti Signed-off-by: Sarthak Garg --- drivers/mmc/host/sdhci-msm.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c index 2057d31a8e40..cea3fbb6246f 100644 --- a/drivers/mmc/host/sdhci-msm.c +++ b/drivers/mmc/host/sdhci-msm.c @@ -1181,9 +1181,21 @@ static int sdhci_msm_cm_dll_sdc4_calibration(struct sdhci_host *host) goto out; } - config = readl_relaxed(host->ioaddr + msm_offset->core_vendor_spec3); - config |= CORE_PWRSAVE_DLL; - writel_relaxed(config, host->ioaddr + msm_offset->core_vendor_spec3); + /* + * Set CORE_PWRSAVE_DLL bit in CORE_VENDOR_SPEC3. + * When MCLK is gated OFF, it is not gated for less than 0.5us + * and MCLK must be switched on for at-least 1us before DATA + * starts coming. Controllers with 14lpp and later tech DLL cannot + * guarantee above requirement. So PWRSAVE_DLL should not be + * turned on for host controllers using this DLL. + */ + if (!msm_host->use_14lpp_dll_reset) { + config = readl_relaxed(host->ioaddr + + msm_offset->core_vendor_spec3); + config |= CORE_PWRSAVE_DLL; + writel_relaxed(config, host->ioaddr + + msm_offset->core_vendor_spec3); + } /* * Drain writebuffer to ensure above DLL calibration From 591d7c5e7eccf5ed62e6271908a5d8abeaed3432 Mon Sep 17 00:00:00 2001 From: Yogesh Lal Date: Sun, 16 Aug 2020 20:14:42 +0530 Subject: [PATCH 011/698] soc: qcom: socinfo: Add support for IDP and ATP platforms Add support for IDP and ATP hw platforms in socinfo driver. Change-Id: Icc2a496d06e57c1869a5129b628c2d095db9186b Signed-off-by: Yogesh Lal --- drivers/soc/qcom/socinfo.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c index 5c2e8ed937ac..734805dcec70 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -54,6 +54,8 @@ enum { HW_PLATFORM_STP = 23, HW_PLATFORM_SBC = 24, HW_PLATFORM_HDK = 31, + HW_PLATFORM_ATP = 33, + HW_PLATFORM_IDP = 34, HW_PLATFORM_INVALID }; @@ -75,6 +77,8 @@ static const char * const hw_platform[] = { [HW_PLATFORM_STP] = "STP", [HW_PLATFORM_SBC] = "SBC", [HW_PLATFORM_HDK] = "HDK", + [HW_PLATFORM_ATP] = "ATP", + [HW_PLATFORM_IDP] = "IDP", }; enum { From 1b4e575a449c7a24c923b857c668994eb31dcb86 Mon Sep 17 00:00:00 2001 From: Pankaj Gupta Date: Fri, 14 Aug 2020 20:35:05 +0530 Subject: [PATCH 012/698] msm: kgsl: Fix GBIF Halt ack timeout for a619_holi For a619_holi GPU, use RBBM_GBIF_HALT registers to halt GX traffic and poll for the ack. Change-Id: Iaae9084a04a5acc05ae5561d0a3c44da0ab5cebb Signed-off-by: Pankaj Gupta --- drivers/gpu/msm/adreno.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c index 3a5f8a08cb64..6aa084f9b1da 100644 --- a/drivers/gpu/msm/adreno.c +++ b/drivers/gpu/msm/adreno.c @@ -1639,7 +1639,8 @@ int adreno_clear_pending_transactions(struct kgsl_device *device) if (adreno_has_gbif(adreno_dev)) { /* Halt GBIF GX traffic and poll for halt ack */ - if (adreno_is_a615_family(adreno_dev)) { + if (adreno_is_a615_family(adreno_dev) && + !adreno_is_a619_holi(adreno_dev)) { adreno_writereg(adreno_dev, ADRENO_REG_RBBM_GPR0_CNTL, GBIF_HALT_REQUEST); From e61d2dd83993bfdfa645d0c5f49a9b869a6ed066 Mon Sep 17 00:00:00 2001 From: Mayank Grover Date: Mon, 17 Aug 2020 14:27:30 +0530 Subject: [PATCH 013/698] arm: dts: enable CONFIG_DEBUG_PREEMPT for debug config Enable CONFIG_DEBUG_PREEMPT for debug builds, to help enable atomic context debugging. Change-Id: I301b15dc4f780e00f5c9146fca8e8122fd2ce3f6 Signed-off-by: Mayank Grover --- arch/arm64/configs/vendor/holi_debug.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/vendor/holi_debug.config b/arch/arm64/configs/vendor/holi_debug.config index 20a7bdb2f255..c2ce92503f03 100644 --- a/arch/arm64/configs/vendor/holi_debug.config +++ b/arch/arm64/configs/vendor/holi_debug.config @@ -125,3 +125,4 @@ CONFIG_STACK_HASH_ORDER_SHIFT=12 CONFIG_PAGE_POISONING=y CONFIG_PAGE_POISONING_ENABLE_DEFAULT=y CONFIG_PSI_FTRACE=y +CONFIG_DEBUG_PREEMPT=y From 931e9fd111a0c624a69f9148ee4acc8fb5e572b6 Mon Sep 17 00:00:00 2001 From: Lingutla Chandrasekhar Date: Wed, 19 Aug 2020 19:32:30 +0530 Subject: [PATCH 014/698] defconfig: Enable scheduler Uclamp for Holi Enable Uclamp for Holi, which is replacement of STUNE. Change-Id: Ie89b57b244bc818759e63b320d9f015dba5255ec Signed-off-by: Lingutla Chandrasekhar --- arch/arm64/configs/vendor/holi_QGKI.config | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm64/configs/vendor/holi_QGKI.config b/arch/arm64/configs/vendor/holi_QGKI.config index 75b76a9282c2..443fc31b44d5 100644 --- a/arch/arm64/configs/vendor/holi_QGKI.config +++ b/arch/arm64/configs/vendor/holi_QGKI.config @@ -112,7 +112,6 @@ CONFIG_CRYPTO_DEV_QCOM_MSM_QCE=y CONFIG_CRYPTO_DEV_QCRYPTO=y CONFIG_CRYPTO_DEV_QCEDEV=y CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y -# CONFIG_UCLAMP_TASK is not set CONFIG_SLIMBUS=y CONFIG_QCOM_KGSL=y CONFIG_QCOM_QFPROM=y From 4e581bcf28a3f12a3797cc8744ab2fb4513baa6f Mon Sep 17 00:00:00 2001 From: Prakash Gupta Date: Tue, 18 Aug 2020 15:56:24 +0530 Subject: [PATCH 015/698] iommu: skip iommu_tlb_sync in iommu_unmap() Downstream arm-smmu impl, perform SYNC as part of unmap(). This is done under arm_smmu_tlb_inv_context_s1. This double the sync operation. This impacts the unmap time, remove this duplicate sync operation. Change-Id: Ic98fc04a8102fe3a0b79e52b33daabf94732fcbf Signed-off-by: Prakash Gupta --- drivers/iommu/iommu.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index 2193417f39d9..470a364cd452 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -2030,7 +2030,6 @@ size_t iommu_unmap(struct iommu_domain *domain, iommu_iotlb_gather_init(&iotlb_gather); ret = __iommu_unmap(domain, iova, size, &iotlb_gather); - iommu_tlb_sync(domain, &iotlb_gather); return ret; } From 34679606394ad2269a0e7c67a91833dc18810ca2 Mon Sep 17 00:00:00 2001 From: Sandeep Singh Date: Thu, 20 Aug 2020 22:05:27 +0530 Subject: [PATCH 016/698] defconfig: Enable CONFIG_NL80211_TESTMODE config for holi This change enables CONFIG_NL80211_TESTMODE config for wlan host driver in holi. Change-Id: I0974f58a2f25c14991ff4a22b998827b0a579b95 Signed-off-by: Sandeep Singh --- arch/arm64/configs/vendor/holi_QGKI.config | 1 + arch/arm64/configs/vendor/holi_debug.config | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/configs/vendor/holi_QGKI.config b/arch/arm64/configs/vendor/holi_QGKI.config index 443fc31b44d5..cce22be7f686 100644 --- a/arch/arm64/configs/vendor/holi_QGKI.config +++ b/arch/arm64/configs/vendor/holi_QGKI.config @@ -155,3 +155,4 @@ CONFIG_CORESIGHT_CTI_SAVE_DISABLE=y # CONFIG_ARM64_LSE_ATOMICS is not set CONFIG_I2C_CHARDEV=y CONFIG_SPI_SPIDEV=y +CONFIG_NL80211_TESTMODE=y diff --git a/arch/arm64/configs/vendor/holi_debug.config b/arch/arm64/configs/vendor/holi_debug.config index c2ce92503f03..1e11e3649ce4 100644 --- a/arch/arm64/configs/vendor/holi_debug.config +++ b/arch/arm64/configs/vendor/holi_debug.config @@ -109,7 +109,6 @@ CONFIG_KPROBES=y CONFIG_QCOM_MPM=y CONFIG_ICNSS2_DEBUG=y # CONFIG_CLD_LL_CORE is not set -# CONFIG_NL80211_TESTMODE is not set CONFIG_INTERCONNECT_TEST=y CONFIG_INTERCONNECT_QCOM_HOLI=y # CONFIG_CORESIGHT_CTI_SAVE_DISABLE is not set From f30744703ec8874941c1f852a283253a2216fb68 Mon Sep 17 00:00:00 2001 From: Niranjan Reddy Dumbala Date: Fri, 4 Sep 2020 21:46:37 +0530 Subject: [PATCH 017/698] Revert "mmc: sdhci-msm: skip eMMC slot probe if eMMC isn't a bootdevice" This reverts commit 49abb2645cb2a23254482e6ab4f1fc9233d1ca1c. Change-Id: I423d356fe39f4e5d5bb2d31b79cea07b24c3be34 Signed-off-by: Niranjan Reddy Dumbala --- drivers/mmc/host/sdhci-msm.c | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c index af3bef9d8c6b..03ad1a6c2e17 100644 --- a/drivers/mmc/host/sdhci-msm.c +++ b/drivers/mmc/host/sdhci-msm.c @@ -442,18 +442,6 @@ struct sdhci_msm_host { u32 pm_qos_delay; }; -#define ANDROID_BOOT_DEV_MAX 30 -static char android_boot_dev[ANDROID_BOOT_DEV_MAX]; - -#ifndef MODULE -static int __init get_android_boot_dev(char *str) -{ - strlcpy(android_boot_dev, str, ANDROID_BOOT_DEV_MAX); - return 1; -} -__setup("androidboot.bootdevice=", get_android_boot_dev); -#endif - static struct sdhci_msm_host *sdhci_slot[2]; static int sdhci_msm_update_qos_constraints(struct qos_cpu_group *qcg, @@ -3634,13 +3622,6 @@ static int sdhci_msm_probe(struct platform_device *pdev) dev_err(&pdev->dev, "get slot index failed %d\n", ret); else if (ret <= 2) sdhci_slot[ret-1] = msm_host; - - if (of_property_read_bool(dev->of_node, "non-removable") && - strlen(android_boot_dev) && - strcmp(android_boot_dev, dev_name(dev))) { - ret = -ENODEV; - goto pltfm_free; - } } /* From d84b3ab9a3d1a6b087fd30d402123786715ce2e8 Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Wed, 2 Sep 2020 15:52:15 +0530 Subject: [PATCH 018/698] clk: qcom: clk-smd-rpm: Remove support for LN_BB_CLK3 for Holi As the LN_BB_CLK3 clock is no longer required to be controlled from the clock driver, thus remove support for the same. Change-Id: Iffa05a87e9f2e2d3a92377fbd60a1ebf32c935e2 Signed-off-by: Taniya Das --- drivers/clk/qcom/clk-smd-rpm.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/clk/qcom/clk-smd-rpm.c b/drivers/clk/qcom/clk-smd-rpm.c index da7b66001a53..35a004119844 100644 --- a/drivers/clk/qcom/clk-smd-rpm.c +++ b/drivers/clk/qcom/clk-smd-rpm.c @@ -831,8 +831,6 @@ DEFINE_CLK_SMD_RPM(holi, pka_clk, pka_a_clk, QCOM_SMD_RPM_PKA_CLK, 0); /* SMD_XO_BUFFER */ DEFINE_CLK_SMD_RPM_XO_BUFFER(holi, ln_bb_clk2, ln_bb_clk2_a, QCOM_SMD_RPM_CLK_BUF_G, 8); -DEFINE_CLK_SMD_RPM_XO_BUFFER(holi, ln_bb_clk3, ln_bb_clk3_a, - QCOM_SMD_RPM_CLK_BUF_G, 9); DEFINE_CLK_SMD_RPM_XO_BUFFER(holi, rf_clk5, rf_clk5_a, QCOM_SMD_RPM_CLK_BUF_G, 6); @@ -848,8 +846,6 @@ static struct clk_hw *holi_clks[] = { [RPM_SMD_QDSS_A_CLK] = &holi_qdss_a_clk.hw, [RPM_SMD_LN_BB_CLK2] = &holi_ln_bb_clk2.hw, [RPM_SMD_LN_BB_CLK2_A] = &holi_ln_bb_clk2_a.hw, - [RPM_SMD_LN_BB_CLK3] = &holi_ln_bb_clk3.hw, - [RPM_SMD_LN_BB_CLK3_A] = &holi_ln_bb_clk3_a.hw, [RPM_SMD_RF_CLK5] = &holi_rf_clk5.hw, [RPM_SMD_RF_CLK5_A] = &holi_rf_clk5_a.hw, [RPM_SMD_CNOC_CLK] = &holi_cnoc_clk.hw, From 7a2b1f821a4e8ffbdb4ae0b6a6fde4ef0c96a808 Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Tue, 1 Sep 2020 17:49:34 +0530 Subject: [PATCH 019/698] clk: qcom: smd-rpm: Add support for clock handoff During boot-up if the clock driver put across a initial high vote then there is no way to remove these votes which can cause the corresponding votes to be left always high till the CPU suspends causing power regression. Thus introduce a device property which can remove the initial votes from the clock driver and leave it up to the client to keep a vote. Change-Id: I068c87d06df908ee0ed0e58f69d46933b301ea6f Signed-off-by: Taniya Das --- drivers/clk/qcom/clk-smd-rpm.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/drivers/clk/qcom/clk-smd-rpm.c b/drivers/clk/qcom/clk-smd-rpm.c index 35a004119844..106d849e432e 100644 --- a/drivers/clk/qcom/clk-smd-rpm.c +++ b/drivers/clk/qcom/clk-smd-rpm.c @@ -912,7 +912,7 @@ static int rpm_smd_clk_probe(struct platform_device *pdev) { struct clk_hw **hw_clks; const struct rpm_smd_clk_desc *desc; - int ret, i, is_holi; + int ret, i, is_holi, hw_clk_handoff = false; desc = of_device_get_match_data(&pdev->dev); if (!desc) @@ -928,13 +928,17 @@ static int rpm_smd_clk_probe(struct platform_device *pdev) hw_clks = desc->clks; - for (i = 0; i < desc->num_clks; i++) { - if (!hw_clks[i]) - continue; + hw_clk_handoff = of_property_read_bool(pdev->dev.of_node, + "qcom,hw-clk-handoff"); + if (hw_clk_handoff) { + for (i = 0; i < desc->num_clks; i++) { + if (!hw_clks[i]) + continue; - ret = clk_smd_rpm_handoff(hw_clks[i]); - if (ret) - goto err; + ret = clk_smd_rpm_handoff(hw_clks[i]); + if (ret) + goto err; + } } ret = clk_smd_rpm_enable_scaling(); From d612e1bbaec173ad98764c311ed9a260465423a4 Mon Sep 17 00:00:00 2001 From: Pankaj Gupta Date: Tue, 1 Sep 2020 20:00:43 +0530 Subject: [PATCH 020/698] msm: kgsl: Define RBBM_SW_RESET_CMD for a6xx targets Define RBBM_SW_RESET_CMD in a6xx_register_offsets to enable soft reset for a6xx targets. Change-Id: Ibc0a3aa7f1a4db5f80617b751082d1c71e6eb262 Signed-off-by: Pankaj Gupta --- drivers/gpu/msm/adreno_a6xx.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/msm/adreno_a6xx.c b/drivers/gpu/msm/adreno_a6xx.c index c392d317747d..f0e159ed31c0 100644 --- a/drivers/gpu/msm/adreno_a6xx.c +++ b/drivers/gpu/msm/adreno_a6xx.c @@ -2587,6 +2587,7 @@ static unsigned int a6xx_register_offsets[ADRENO_REG_REGISTER_MAX] = { ADRENO_REG_DEFINE(ADRENO_REG_RBBM_INT_0_MASK, A6XX_RBBM_INT_0_MASK), ADRENO_REG_DEFINE(ADRENO_REG_RBBM_INT_0_STATUS, A6XX_RBBM_INT_0_STATUS), ADRENO_REG_DEFINE(ADRENO_REG_RBBM_CLOCK_CTL, A6XX_RBBM_CLOCK_CNTL), + ADRENO_REG_DEFINE(ADRENO_REG_RBBM_SW_RESET_CMD, A6XX_RBBM_SW_RESET_CMD), ADRENO_REG_DEFINE(ADRENO_REG_RBBM_PERFCTR_LOAD_VALUE_LO, A6XX_RBBM_PERFCTR_LOAD_VALUE_LO), ADRENO_REG_DEFINE(ADRENO_REG_RBBM_PERFCTR_LOAD_VALUE_HI, From b52abc820bfec2c9d7c07f014623f66d415e9674 Mon Sep 17 00:00:00 2001 From: Shadab Naseem Date: Fri, 10 Jan 2020 12:31:22 +0530 Subject: [PATCH 021/698] soc: qcom: eud: Do not fail the EUD probe for secure device TCSR register scm write is configured to fail for secure device. This results in eud probe failure. As dwc3 driver's probe is dependent on eud probe to be successful, ignore the register write failure. Change-Id: I3dc658bd89d2dacb636532d4b08b9aa3986a62e6 Signed-off-by: Shadab Naseem --- drivers/soc/qcom/eud.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/soc/qcom/eud.c b/drivers/soc/qcom/eud.c index f793266fe754..7243e4abaac7 100644 --- a/drivers/soc/qcom/eud.c +++ b/drivers/soc/qcom/eud.c @@ -693,7 +693,6 @@ static int msm_eud_probe(struct platform_device *pdev) dev_err(&pdev->dev, "TCSR qcom_scm_io_writel failed with rc:%d\n", ret); - goto error; } } else { dev_err(chip->dev, From f7ee13014eb0a7abcf63a574fbb0c29695e4c0ed Mon Sep 17 00:00:00 2001 From: Sandeep Singh Date: Thu, 3 Sep 2020 18:46:47 +0530 Subject: [PATCH 022/698] icnss: Allow register/unregister driver execution in serial manner In cases when wlan driver probe is in progress, icnss driver rejects wlan driver unregister as driver probe is not completed. This change enables wlan unregister driver to get scheduled in icnss driver wq if wlan driver has been regsitered. This ensures that wlan unregister and register driver get executed in serial manner. In cases when driver probe is in progress and wlan driver unregister gets called, unregister driver will be processed when wlan driver probe is finished. Change-Id: I0266723d081e9036ecbec122c56be8dfe3c3d1bb Signed-off-by: Sandeep Singh --- drivers/soc/qcom/icnss2/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/qcom/icnss2/main.c b/drivers/soc/qcom/icnss2/main.c index 6fa5ade98411..d46cb1b46c3a 100644 --- a/drivers/soc/qcom/icnss2/main.c +++ b/drivers/soc/qcom/icnss2/main.c @@ -2030,7 +2030,7 @@ int icnss_unregister_driver(struct icnss_driver_ops *ops) icnss_pr_dbg("Unregistering driver, state: 0x%lx\n", priv->state); - if (!priv->ops || (!test_bit(ICNSS_DRIVER_PROBED, &penv->state))) { + if (!priv->ops) { icnss_pr_err("Driver not registered\n"); ret = -ENOENT; goto out; From 3c01f5a086102fd3f9ca93267c8703f2c8c08d6a Mon Sep 17 00:00:00 2001 From: Akash Asthana Date: Thu, 3 Sep 2020 13:44:16 +0530 Subject: [PATCH 023/698] serial: msm_geni_serial: Move UART sys_suspend callback from suspend_noirq to suspend stage While executing suspend_noirq callbacks non-wakeup interrupts are disabled, wake-up interrupts are enabled but their handling is deferred till the completion of suspend_noirq stage. UART console vote/unvote the resources in suspend_noirq/resume_noirq stages. There is no issue wrt managing clk and pinctrl resources at noirq stage however ICC BW voting can't be done at noirq stage. ICC requests are converted to ack based requested for RPM driver, the ack here is nothing but interrupt from IPCC driver and it can't be processed at noirq stage, hence flow is indefinitely stuck in UART suspend_noirq callback. The above issue is triggered only for targets having RPM + IPCC combinations. Change-Id: Ie279580795d3c85db4dc42766b0b2d9a8adb3f00 Signed-off-by: Akash Asthana --- drivers/tty/serial/msm_geni_serial.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/tty/serial/msm_geni_serial.c b/drivers/tty/serial/msm_geni_serial.c index 52189f71899b..b321ebe38873 100644 --- a/drivers/tty/serial/msm_geni_serial.c +++ b/drivers/tty/serial/msm_geni_serial.c @@ -3190,7 +3190,7 @@ exit_runtime_resume: return ret; } -static int msm_geni_serial_sys_suspend_noirq(struct device *dev) +static int msm_geni_serial_sys_suspend(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct msm_geni_serial_port *port = platform_get_drvdata(pdev); @@ -3219,7 +3219,7 @@ static int msm_geni_serial_sys_suspend_noirq(struct device *dev) return 0; } -static int msm_geni_serial_sys_resume_noirq(struct device *dev) +static int msm_geni_serial_sys_resume(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct msm_geni_serial_port *port = platform_get_drvdata(pdev); @@ -3243,12 +3243,12 @@ static int msm_geni_serial_runtime_resume(struct device *dev) return 0; } -static int msm_geni_serial_sys_suspend_noirq(struct device *dev) +static int msm_geni_serial_sys_suspend(struct device *dev) { return 0; } -static int msm_geni_serial_sys_resume_noirq(struct device *dev) +static int msm_geni_serial_sys_resume(struct device *dev) { return 0; } @@ -3257,8 +3257,8 @@ static int msm_geni_serial_sys_resume_noirq(struct device *dev) static const struct dev_pm_ops msm_geni_serial_pm_ops = { .runtime_suspend = msm_geni_serial_runtime_suspend, .runtime_resume = msm_geni_serial_runtime_resume, - .suspend_noirq = msm_geni_serial_sys_suspend_noirq, - .resume_noirq = msm_geni_serial_sys_resume_noirq, + .suspend = msm_geni_serial_sys_suspend, + .resume = msm_geni_serial_sys_resume, }; static struct platform_driver msm_geni_serial_platform_driver = { From 45154684d7ddda2a530ef0531ccd6bbfbcf807c6 Mon Sep 17 00:00:00 2001 From: Pankaj Gupta Date: Tue, 18 Aug 2020 18:40:26 +0530 Subject: [PATCH 024/698] kgsl: msm: Correctly check hardware idle status for a619_holi target Use GMU_AO_GPU_CX_BUSY_STATUS instead of RBBM_STATUS to check the hardware idle status for A619_holi target. Change-Id: Ic66e80924331d9f1a0203fd96e352c3009a4eb75 Signed-off-by: Pankaj Gupta --- drivers/gpu/msm/adreno-gpulist.h | 2 +- drivers/gpu/msm/adreno.h | 1 + drivers/gpu/msm/adreno_a6xx.c | 48 ++++++++++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/msm/adreno-gpulist.h b/drivers/gpu/msm/adreno-gpulist.h index f43efef02fb3..f5d4f963a648 100644 --- a/drivers/gpu/msm/adreno-gpulist.h +++ b/drivers/gpu/msm/adreno-gpulist.h @@ -961,7 +961,7 @@ static const struct adreno_a6xx_core adreno_gpu_core_a619_variant = { DEFINE_ADRENO_REV(ADRENO_REV_A619, 6, 1, 9, ANY_ID), .compatible = "qcom,adreno-gpu-a619-holi", .features = ADRENO_PREEMPTION | ADRENO_CONTENT_PROTECTION, - .gpudev = &adreno_a6xx_gpudev, + .gpudev = &adreno_a619_holi_gpudev, .gmem_base = 0x100000, .gmem_size = SZ_512K, .bus_width = 32, diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h index 38871ae28635..a0907e53035d 100644 --- a/drivers/gpu/msm/adreno.h +++ b/drivers/gpu/msm/adreno.h @@ -900,6 +900,7 @@ extern struct adreno_gpudev adreno_a5xx_gpudev; extern struct adreno_gpudev adreno_a6xx_gpudev; extern struct adreno_gpudev adreno_a6xx_gmu_gpudev; extern struct adreno_gpudev adreno_a6xx_rgmu_gpudev; +extern struct adreno_gpudev adreno_a619_holi_gpudev; extern struct adreno_gpudev adreno_a630_gpudev; extern int adreno_wake_nice; diff --git a/drivers/gpu/msm/adreno_a6xx.c b/drivers/gpu/msm/adreno_a6xx.c index f0e159ed31c0..7c38f5c81e11 100644 --- a/drivers/gpu/msm/adreno_a6xx.c +++ b/drivers/gpu/msm/adreno_a6xx.c @@ -1074,6 +1074,17 @@ static void a6xx_gpu_keepalive(struct adreno_device *adreno_dev, gmu_core_regwrite(device, A6XX_GMU_GMU_PWR_COL_KEEPALIVE, state); } +static bool a619_holi_hw_isidle(struct adreno_device *adreno_dev) +{ + unsigned int reg; + + adreno_read_gmu_wrapper(adreno_dev, + A6XX_GPU_GMU_AO_GPU_CX_BUSY_STATUS, ®); + + /* Bit 23 is GPUBUSYIGNAHB */ + return (reg & BIT(23)) ? false : true; +} + static bool a6xx_hw_isidle(struct adreno_device *adreno_dev) { struct kgsl_device *device = KGSL_DEVICE(adreno_dev); @@ -2862,6 +2873,43 @@ struct adreno_gpudev adreno_a6xx_rgmu_gpudev = { .power_ops = &a6xx_rgmu_power_ops, }; +struct adreno_gpudev adreno_a619_holi_gpudev = { + .reg_offsets = a6xx_register_offsets, + .probe = a6xx_probe, + .start = a6xx_start, + .snapshot = a6xx_snapshot, + .init = a6xx_init, + .irq_handler = a6xx_irq_handler, + .rb_start = a6xx_rb_start, + .regulator_enable = a6xx_sptprac_enable, + .regulator_disable = a6xx_sptprac_disable, + .perfcounters = &a6xx_perfcounters, + .read_throttling_counters = a6xx_read_throttling_counters, + .microcode_read = a6xx_microcode_read, + .gpu_keepalive = a6xx_gpu_keepalive, + .hw_isidle = a619_holi_hw_isidle, + .iommu_fault_block = a6xx_iommu_fault_block, + .reset = a6xx_reset, + .preemption_pre_ibsubmit = a6xx_preemption_pre_ibsubmit, + .preemption_post_ibsubmit = a6xx_preemption_post_ibsubmit, + .preemption_init = a6xx_preemption_init, + .preemption_schedule = a6xx_preemption_schedule, + .set_marker = a6xx_set_marker, + .preemption_context_init = a6xx_preemption_context_init, + .preemption_context_destroy = a6xx_preemption_context_destroy, + .sptprac_is_on = a6xx_sptprac_is_on, + .ccu_invalidate = a6xx_ccu_invalidate, + .perfcounter_update = a6xx_perfcounter_update, +#ifdef CONFIG_QCOM_KGSL_CORESIGHT + .coresight = {&a6xx_coresight, &a6xx_coresight_cx}, +#endif +#if IS_ENABLED(CONFIG_COMMON_CLK_QCOM) + .clk_set_options = a6xx_clk_set_options, +#endif + .read_alwayson = a6xx_read_alwayson, + .power_ops = &adreno_power_operations, +}; + struct adreno_gpudev adreno_a630_gpudev = { .reg_offsets = a6xx_register_offsets, .probe = a6xx_gmu_device_probe, From 02c853b277707c8d2101a250fe6cc602dff24075 Mon Sep 17 00:00:00 2001 From: Pankaj Gupta Date: Wed, 2 Sep 2020 10:57:31 +0530 Subject: [PATCH 025/698] msm: kgsl: Skip state change in idle check, if requested state is NONE After scheduling the idle work for transitioning to either NAP or SLUMBER it's possible that requested state can change to NONE if any new workload comes before kgsl_idle_check is executed or it gets the device mutex. If this happens, current code calls pwrctrl_change_state which fails as this is not a valid transition. To prevent this, skip calling pwrctrl_change_state if requested state is NONE. Change-Id: Iae535c6e2a3230f9e7e210712990eeb405822f4f Signed-off-by: Deepak Kumar Signed-off-by: Pankaj Gupta --- drivers/gpu/msm/kgsl_pwrctrl.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c index 87245a77ee12..0347a4bdf732 100644 --- a/drivers/gpu/msm/kgsl_pwrctrl.c +++ b/drivers/gpu/msm/kgsl_pwrctrl.c @@ -1603,8 +1603,9 @@ void kgsl_idle_check(struct work_struct *work) requested_state = device->requested_state; - if (device->state == KGSL_STATE_ACTIVE - || kgsl_state_is_nap_or_minbw(device)) { + if (requested_state != KGSL_STATE_NONE && + (device->state == KGSL_STATE_ACTIVE || + kgsl_state_is_nap_or_minbw(device))) { if (!atomic_read(&device->active_cnt)) { spin_lock(&device->submit_lock); From 1d10a95e37aebd772d46da3165da3dcf9316eeca Mon Sep 17 00:00:00 2001 From: Kiran Gunda Date: Thu, 20 Aug 2020 13:23:39 +0530 Subject: [PATCH 026/698] backlight: qcom-spmi-wled: Add support for QCOM SPMI WLED driver qcom-spmi-wled driver adds support for controlling backlight for LCD panels that uses QTI PMICs like pmi8998, PM8150L and PM6150L. This snapshot is taken as of msm-4.19 commit b82b280d402 ("arm64: defconfig: Enable dm-snapshot"). Change-Id: I3eafddc1a2ce064552415516b168f452d0b3c638 Signed-off-by: Kiran Gunda --- drivers/video/backlight/Kconfig | 10 + drivers/video/backlight/Makefile | 1 + drivers/video/backlight/qcom-spmi-wled.c | 2388 ++++++++++++++++++++++ 3 files changed, 2399 insertions(+) create mode 100644 drivers/video/backlight/qcom-spmi-wled.c diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig index 40676be2e46a..9e4db1b7cdf8 100644 --- a/drivers/video/backlight/Kconfig +++ b/drivers/video/backlight/Kconfig @@ -289,6 +289,16 @@ config BACKLIGHT_PM8941_WLED If you have the Qualcomm PM8941, say Y to enable a driver for the WLED block. +config BACKLIGHT_QCOM_SPMI_WLED + tristate "Qualcomm Technologies, Inc. WLED Driver" + select REGMAP + help + If you have the Qualcomm Technologies, Inc. WLED used for backlight + control, say Y to enable a driver for the WLED block. This driver + provides the interface to the display driver to adjust the brightness + of the display backlight. This supports PMI8998, PM8150L, PM6150L + currently. + config BACKLIGHT_SAHARA tristate "Tabletkiosk Sahara Touch-iT Backlight Driver" depends on X86 diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile index 63c507c07437..7d42790da083 100644 --- a/drivers/video/backlight/Makefile +++ b/drivers/video/backlight/Makefile @@ -50,6 +50,7 @@ obj-$(CONFIG_BACKLIGHT_PANDORA) += pandora_bl.o obj-$(CONFIG_BACKLIGHT_PCF50633) += pcf50633-backlight.o obj-$(CONFIG_BACKLIGHT_PM8941_WLED) += pm8941-wled.o obj-$(CONFIG_BACKLIGHT_PWM) += pwm_bl.o +obj-$(CONFIG_BACKLIGHT_QCOM_SPMI_WLED) += qcom-spmi-wled.o obj-$(CONFIG_BACKLIGHT_SAHARA) += kb3886_bl.o obj-$(CONFIG_BACKLIGHT_SKY81452) += sky81452-backlight.o obj-$(CONFIG_BACKLIGHT_TOSA) += tosa_bl.o diff --git a/drivers/video/backlight/qcom-spmi-wled.c b/drivers/video/backlight/qcom-spmi-wled.c new file mode 100644 index 000000000000..89d19a7b09d9 --- /dev/null +++ b/drivers/video/backlight/qcom-spmi-wled.c @@ -0,0 +1,2388 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2015, Sony Mobile Communications, AB. + */ +/* + * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. + */ + +#define pr_fmt(fmt) "WLED: %s: " fmt, __func__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../../leds/leds.h" + +/* General definitions */ +#define WLED_DEFAULT_BRIGHTNESS 2048 +#define WLED_MAX_BRIGHTNESS_12B 4095 +#define WLED_MAX_BRIGHTNESS_15B 32767 + +#define WLED_SOFT_START_DLY_US 10000 + +/* WLED control registers */ +#define WLED_CTRL_FAULT_STATUS 0x08 +#define WLED_CTRL_ILIM_FAULT_BIT BIT(0) +#define WLED_CTRL_OVP_FAULT_BIT BIT(1) +#define WLED_CTRL_SC_FAULT_BIT BIT(2) +#define WLED5_CTRL_OVP_PRE_ALARM_BIT BIT(4) + +#define WLED_CTRL_INT_RT_STS 0x10 +#define WLED_CTRL_OVP_FLT_RT_STS_BIT BIT(1) + +#define WLED_CTRL_MOD_ENABLE 0x46 +#define WLED_CTRL_MOD_EN_MASK BIT(7) +#define WLED_CTRL_MODULE_EN_SHIFT 7 + +#define WLED_CTRL_FDBK_OP 0x48 + +#define WLED_CTRL_SWITCH_FREQ 0x4c +#define WLED_CTRL_SWITCH_FREQ_MASK GENMASK(3, 0) + +#define WLED_CTRL_OVP 0x4d +#define WLED_CTRL_OVP_MASK GENMASK(1, 0) +#define WLED5_CTRL_OVP_MASK GENMASK(3, 0) + +#define WLED_CTRL_ILIM 0x4e +#define WLED_CTRL_ILIM_MASK GENMASK(2, 0) + +#define WLED_CTRL_SHORT_PROTECT 0x5e +#define WLED_CTRL_SHORT_EN_MASK BIT(7) + +#define WLED_CTRL_SEC_ACCESS 0xd0 +#define WLED_CTRL_SEC_UNLOCK 0xa5 + +#define WLED_CTRL_TEST1 0xe2 +#define WLED_EXT_FET_DTEST2 0x09 + +/* WLED sink registers */ +#define WLED_SINK_CURR_SINK_EN 0x46 +#define WLED_SINK_CURR_SINK_MASK GENMASK(7, 4) +#define WLED_SINK_CURR_SINK_SHFT 0x04 + +#define WLED_SINK_SYNC 0x47 +#define WLED_SINK_SYNC_MASK GENMASK(3, 0) +#define WLED_SINK_SYNC_LED1 BIT(0) +#define WLED_SINK_SYNC_LED2 BIT(1) +#define WLED_SINK_SYNC_LED3 BIT(2) +#define WLED_SINK_SYNC_LED4 BIT(3) +#define WLED_SINK_SYNC_CLEAR 0x00 + +#define WLED_SINK_MOD_EN_REG(n) (0x50 + (n * 0x10)) +#define WLED_SINK_REG_STR_MOD_MASK BIT(7) +#define WLED_SINK_REG_STR_MOD_EN BIT(7) + +#define WLED_SINK_SYNC_DLY_REG(n) (0x51 + (n * 0x10)) +#define WLED_SINK_FS_CURR_REG(n) (0x52 + (n * 0x10)) +#define WLED_SINK_FS_MASK GENMASK(3, 0) + +#define WLED_SINK_CABC_REG(n) (0x56 + (n * 0x10)) +#define WLED_SINK_CABC_MASK BIT(7) +#define WLED_SINK_CABC_EN BIT(7) + +#define WLED_SINK_BRIGHT_LSB_REG(n) (0x57 + (n * 0x10)) +#define WLED_SINK_BRIGHT_MSB_REG(n) (0x58 + (n * 0x10)) + +/* WLED5 specific control registers */ +#define WLED5_CTRL_STATUS 0x07 + +#define WLED5_CTRL_SH_FOR_SOFTSTART_REG 0x58 +#define WLED5_SOFTSTART_EN_SH_SS BIT(0) + +#define WLED5_CTRL_OVP_INT_CTL_REG 0x5f +#define WLED5_OVP_INT_N_MASK GENMASK(6, 4) +#define WLED5_OVP_INT_N_SHIFT 4 +#define WLED5_OVP_INT_TIMER_MASK GENMASK(2, 0) + +#define WLED5_CTRL_PRE_FLASH_BRT_REG 0x61 +#define WLED5_CTRL_PRE_FLASH_SYNC_REG 0x62 +#define WLED5_CTRL_FLASH_BRT_REG 0x63 +#define WLED5_CTRL_FLASH_SYNC_REG 0x64 + +#define WLED5_CTRL_FLASH_STEP_CTL_REG 0x65 +#define WLED5_CTRL_FLASH_STEP_MASK GENMASK(2, 0) + +#define WLED5_CTRL_FLASH_HDRM_REG 0x69 + +#define WLED5_CTRL_TEST4_REG 0xe5 +#define WLED5_TEST4_EN_SH_SS BIT(5) + +/* WLED5 specific sink registers */ +#define WLED5_SINK_MOD_A_EN_REG 0x50 +#define WLED5_SINK_MOD_B_EN_REG 0x60 +#define WLED5_SINK_MOD_EN BIT(7) + +#define WLED5_SINK_MOD_A_SRC_SEL_REG 0x51 +#define WLED5_SINK_MOD_B_SRC_SEL_REG 0x61 +#define WLED5_SINK_MOD_SRC_SEL_HIGH 0 +#define WLED5_SINK_MOD_SRC_SEL_CABC1 BIT(0) +#define WLED5_SINK_MOD_SRC_SEL_CABC2 BIT(1) +#define WLED5_SINK_MOD_SRC_SEL_EXT 0x03 +#define WLED5_SINK_MOD_SRC_SEL_MASK GENMASK(1, 0) + +#define WLED5_SINK_MOD_A_BR_WID_SEL_REG 0x52 +#define WLED5_SINK_MOD_B_BR_WID_SEL_REG 0x62 +#define WLED5_SINK_BRT_WIDTH_12B 0 +#define WLED5_SINK_BRT_WIDTH_15B 1 + +#define WLED5_SINK_MOD_A_BRT_LSB_REG 0x53 +#define WLED5_SINK_MOD_A_BRT_MSB_REG 0x54 +#define WLED5_SINK_MOD_B_BRT_LSB_REG 0x63 +#define WLED5_SINK_MOD_B_BRT_MSB_REG 0x64 + +#define WLED5_SINK_MOD_SYNC_BIT_REG 0x65 +#define WLED5_SINK_SYNC_MODA_BIT BIT(0) +#define WLED5_SINK_SYNC_MODB_BIT BIT(1) +#define WLED5_SINK_SYNC_MASK GENMASK(1, 0) + +#define WLED5_SINK_FS_CURR_REG(n) (0x72 + (n * 0x10)) + +#define WLED5_SINK_SRC_SEL_REG(n) (0x73 + (n * 0x10)) +#define WLED5_SINK_SRC_SEL_MODA 0 +#define WLED5_SINK_SRC_SEL_MODB 1 +#define WLED5_SINK_SRC_SEL_MASK GENMASK(1, 0) + +#define WLED5_SINK_FLASH_CTL_REG 0xb0 +#define WLED5_SINK_FLASH_EN BIT(7) +#define WLED5_SINK_PRE_FLASH_EN BIT(6) + +#define WLED5_SINK_FLASH_SINK_EN_REG 0xb1 + +#define WLED5_SINK_FLASH_FSC_REG 0xb2 +#define WLED5_SINK_FLASH_FSC_MASK GENMASK(3, 0) + +#define WLED5_SINK_FLASH_SYNC_BIT_REG 0xb3 +#define WLED5_SINK_FLASH_FSC_SYNC_EN BIT(0) + +#define WLED5_SINK_FLASH_TIMER_CTL_REG 0xb5 +#define WLED5_DIS_PRE_FLASH_TIMER BIT(7) +#define WLED5_PRE_FLASH_SAFETY_TIME GENMASK(6, 4) +#define WLED5_PRE_FLASH_SAFETY_SHIFT 4 +#define WLED5_DIS_FLASH_TIMER BIT(3) +#define WLED5_FLASH_SAFETY_TIME GENMASK(2, 0) + +#define WLED5_SINK_FLASH_SHDN_CLR_REG 0xb6 + +enum wled_version { + WLED_PMI8998 = 4, + WLED_PM660L, + WLED_PM8150L, +}; + +enum wled_flash_mode { + WLED_FLASH_OFF, + WLED_PRE_FLASH, + WLED_FLASH, +}; + +static const int version_table[] = { + [0] = WLED_PMI8998, + [1] = WLED_PM660L, + [2] = WLED_PM8150L, +}; + +struct wled_config { + int boost_i_limit; + int ovp; + int switch_freq; + int fs_current; + int string_cfg; + int mod_sel; + int cabc_sel; + bool en_cabc; + bool ext_pfet_sc_pro_en; + bool auto_calib_enabled; +}; + +struct wled_flash_config { + int fs_current; + int step_delay; + int safety_timer; +}; + +struct wled { + const char *name; + struct platform_device *pdev; + struct regmap *regmap; + struct pmic_revid_data *pmic_rev_id; + struct power_supply *bms_psy; + struct mutex lock; + struct wled_config cfg; + ktime_t last_sc_event_time; + ktime_t start_ovp_fault_time; + u16 sink_addr; + u16 ctrl_addr; + u16 auto_calibration_ovp_count; + u32 brightness; + u32 max_brightness; + u32 sc_count; + const int *version; + int sc_irq; + int ovp_irq; + int flash_irq; + int pre_flash_irq; + bool prev_state; + bool ovp_irq_disabled; + bool auto_calib_done; + bool force_mod_disable; + bool cabc_disabled; + int (*cabc_config)(struct wled *wled, bool enable); + + struct led_classdev flash_cdev; + struct led_classdev torch_cdev; + struct led_classdev switch_cdev; + struct wled_flash_config fparams; + struct wled_flash_config tparams; + spinlock_t flash_lock; + enum wled_flash_mode flash_mode; + u8 num_strings; + u32 leds_per_string; +}; + +enum wled5_mod_sel { + MOD_A, + MOD_B, + MOD_MAX, +}; + +static const u8 wled5_brt_reg[MOD_MAX] = { + [MOD_A] = WLED5_SINK_MOD_A_BRT_LSB_REG, + [MOD_B] = WLED5_SINK_MOD_B_BRT_LSB_REG, +}; + +static const u8 wled5_src_sel_reg[MOD_MAX] = { + [MOD_A] = WLED5_SINK_MOD_A_SRC_SEL_REG, + [MOD_B] = WLED5_SINK_MOD_B_SRC_SEL_REG, +}; + +static const u8 wled5_brt_wid_sel_reg[MOD_MAX] = { + [MOD_A] = WLED5_SINK_MOD_A_BR_WID_SEL_REG, + [MOD_B] = WLED5_SINK_MOD_B_BR_WID_SEL_REG, +}; + +static int wled_flash_setup(struct wled *wled); + +static inline bool is_wled4(struct wled *wled) +{ + if (*wled->version == WLED_PMI8998 || *wled->version == WLED_PM660L) + return true; + + return false; +} + +static inline bool is_wled5(struct wled *wled) +{ + if (*wled->version == WLED_PM8150L) + return true; + + return false; +} + +static int wled_module_enable(struct wled *wled, int val) +{ + int rc; + + if (wled->force_mod_disable) + return 0; + + rc = regmap_update_bits(wled->regmap, wled->ctrl_addr + + WLED_CTRL_MOD_ENABLE, WLED_CTRL_MOD_EN_MASK, + val << WLED_CTRL_MODULE_EN_SHIFT); + if (rc < 0) + return rc; + /* + * Wait for at least 10ms before enabling OVP fault interrupt after + * enabling the module so that soft start is completed. Keep the OVP + * interrupt disabled when the module is disabled. + */ + if (val) { + usleep_range(WLED_SOFT_START_DLY_US, + WLED_SOFT_START_DLY_US + 1000); + + if (wled->ovp_irq > 0 && wled->ovp_irq_disabled) { + enable_irq(wled->ovp_irq); + wled->ovp_irq_disabled = false; + } + } else { + if (wled->ovp_irq > 0 && !wled->ovp_irq_disabled) { + disable_irq(wled->ovp_irq); + wled->ovp_irq_disabled = true; + } + } + + return rc; +} + +static int wled_get_brightness(struct backlight_device *bl) +{ + struct wled *wled = bl_get_data(bl); + + return wled->brightness; +} + +static int wled_sync_toggle(struct wled *wled) +{ + int rc; + + rc = regmap_update_bits(wled->regmap, + wled->sink_addr + WLED_SINK_SYNC, + WLED_SINK_SYNC_MASK, WLED_SINK_SYNC_MASK); + if (rc < 0) + return rc; + + rc = regmap_update_bits(wled->regmap, + wled->sink_addr + WLED_SINK_SYNC, + WLED_SINK_SYNC_MASK, WLED_SINK_SYNC_CLEAR); + + return rc; +} + +static int wled5_sample_hold_control(struct wled *wled, u16 brightness, + bool enable) +{ + int rc; + u16 offset, threshold; + u8 val, mask; + + /* + * Control S_H only when module was disabled and a lower brightness + * of < 1% is set. + */ + if (wled->prev_state) + return 0; + + /* If CABC is enabled, then don't do anything for now */ + if (!wled->cabc_disabled) + return 0; + + /* 1 % threshold to enable the workaround */ + threshold = DIV_ROUND_UP(wled->max_brightness, 100); + + /* If brightness is > 1%, don't do anything */ + if (brightness > threshold) + return 0; + + /* Wait for ~5ms before enabling S_H */ + if (enable) + usleep_range(5000, 5010); + + /* Disable S_H if brightness is < 1% */ + if (wled->pmic_rev_id->rev4 == PM8150L_V3P0_REV4) { + offset = WLED5_CTRL_SH_FOR_SOFTSTART_REG; + val = enable ? WLED5_SOFTSTART_EN_SH_SS : 0; + mask = WLED5_SOFTSTART_EN_SH_SS; + } else { + offset = WLED5_CTRL_TEST4_REG; + val = enable ? WLED5_TEST4_EN_SH_SS : 0; + mask = WLED5_TEST4_EN_SH_SS; + } + + rc = regmap_update_bits(wled->regmap, + wled->ctrl_addr + offset, mask, val); + if (rc < 0) + pr_err("Error in writing offset 0x%02X rc=%d\n", offset, rc); + + return rc; +} + +static int wled5_set_brightness(struct wled *wled, u16 brightness) +{ + int rc, offset; + u16 low_limit = wled->max_brightness * 1 / 1000; + u8 val, v[2], brightness_msb_mask; + + /* WLED5's lower limit is 0.1% */ + if (brightness > 0 && brightness < low_limit) + brightness = low_limit; + + brightness_msb_mask = 0xf; + if (wled->max_brightness == WLED_MAX_BRIGHTNESS_15B) + brightness_msb_mask = 0x7f; + + v[0] = brightness & 0xff; + v[1] = (brightness >> 8) & brightness_msb_mask; + + offset = wled5_brt_reg[wled->cfg.mod_sel]; + rc = regmap_bulk_write(wled->regmap, wled->sink_addr + offset, + v, 2); + if (rc < 0) + return rc; + + /* Update brightness values to modulator in WLED5 */ + val = (wled->cfg.mod_sel == MOD_A) ? WLED5_SINK_SYNC_MODA_BIT : + WLED5_SINK_SYNC_MODB_BIT; + rc = regmap_update_bits(wled->regmap, + wled->sink_addr + WLED5_SINK_MOD_SYNC_BIT_REG, + WLED5_SINK_SYNC_MASK, val); + if (rc < 0) + return rc; + + val = 0; + rc = regmap_update_bits(wled->regmap, + wled->sink_addr + WLED5_SINK_MOD_SYNC_BIT_REG, + WLED_SINK_SYNC_MASK, val); + return rc; +} + +static int wled4_set_brightness(struct wled *wled, u16 brightness) +{ + int rc, i; + u16 low_limit = wled->max_brightness * 4 / 1000; + u8 string_cfg = wled->cfg.string_cfg; + u8 v[2]; + + /* WLED4's lower limit of operation is 0.4% */ + if (brightness > 0 && brightness < low_limit) + brightness = low_limit; + + v[0] = brightness & 0xff; + v[1] = (brightness >> 8) & 0xf; + + for (i = 0; (string_cfg >> i) != 0; i++) { + rc = regmap_bulk_write(wled->regmap, wled->sink_addr + + WLED_SINK_BRIGHT_LSB_REG(i), v, 2); + if (rc < 0) + return rc; + } + + return 0; +} + +static int wled_set_brightness(struct wled *wled, u16 brightness) +{ + if (is_wled4(wled)) + return wled4_set_brightness(wled, brightness); + else if (is_wled5(wled)) + return wled5_set_brightness(wled, brightness); + + return 0; +} + +static int wled_update_status(struct backlight_device *bl) +{ + struct wled *wled = bl_get_data(bl); + u16 brightness = bl->props.brightness; + int rc; + + if (bl->props.power != FB_BLANK_UNBLANK || + bl->props.fb_blank != FB_BLANK_UNBLANK || + bl->props.state & BL_CORE_FBBLANK) + brightness = 0; + + mutex_lock(&wled->lock); + if (brightness) { + rc = wled_set_brightness(wled, brightness); + if (rc < 0) { + pr_err("wled failed to set brightness rc:%d\n", rc); + goto unlock_mutex; + } + + if (is_wled5(wled)) { + rc = wled5_sample_hold_control(wled, brightness, false); + if (rc < 0) { + pr_err("wled disabling sample and hold failed rc:%d\n", + rc); + goto unlock_mutex; + } + } + + if (!!brightness != wled->prev_state) { + rc = wled_module_enable(wled, !!brightness); + if (rc < 0) { + pr_err("wled enable failed rc:%d\n", rc); + goto unlock_mutex; + } + } + + if (is_wled5(wled)) { + rc = wled5_sample_hold_control(wled, brightness, true); + if (rc < 0) { + pr_err("wled enabling sample and hold failed rc:%d\n", + rc); + goto unlock_mutex; + } + } + } else { + rc = wled_module_enable(wled, brightness); + if (rc < 0) { + pr_err("wled disable failed rc:%d\n", rc); + goto unlock_mutex; + } + } + + wled->prev_state = !!brightness; + + if (is_wled4(wled)) { + rc = wled_sync_toggle(wled); + if (rc < 0) { + pr_err("wled sync failed rc:%d\n", rc); + goto unlock_mutex; + } + } + + wled->brightness = brightness; + +unlock_mutex: + mutex_unlock(&wled->lock); + return rc; +} + +#define WLED_SC_DLY_MS 20 +#define WLED_SC_CNT_MAX 5 +#define WLED_SC_RESET_CNT_DLY_US 1000000 +static irqreturn_t wled_sc_irq_handler(int irq, void *_wled) +{ + struct wled *wled = _wled; + int rc; + u32 val; + s64 elapsed_time; + + rc = regmap_read(wled->regmap, + wled->ctrl_addr + WLED_CTRL_FAULT_STATUS, &val); + if (rc < 0) { + pr_err("Error in reading WLED_FAULT_STATUS rc=%d\n", rc); + return IRQ_HANDLED; + } + + wled->sc_count++; + pr_err("WLED short circuit detected %d times fault_status=%x\n", + wled->sc_count, val); + mutex_lock(&wled->lock); + rc = wled_module_enable(wled, false); + if (rc < 0) { + pr_err("wled disable failed rc:%d\n", rc); + goto unlock_mutex; + } + + elapsed_time = ktime_us_delta(ktime_get(), + wled->last_sc_event_time); + if (elapsed_time > WLED_SC_RESET_CNT_DLY_US) { + wled->sc_count = 0; + } else if (wled->sc_count > WLED_SC_CNT_MAX) { + pr_err("SC trigged %d times, disabling WLED forever!\n", + wled->sc_count); + goto unlock_mutex; + } + + wled->last_sc_event_time = ktime_get(); + + msleep(WLED_SC_DLY_MS); + rc = wled_module_enable(wled, true); + if (rc < 0) + pr_err("wled enable failed rc:%d\n", rc); + +unlock_mutex: + mutex_unlock(&wled->lock); + + return IRQ_HANDLED; +} + +static int wled5_cabc_config(struct wled *wled, bool enable) +{ + int rc, offset; + u8 reg; + + if (wled->cabc_disabled) + return 0; + + reg = enable ? wled->cfg.cabc_sel : 0; + offset = wled5_src_sel_reg[wled->cfg.mod_sel]; + rc = regmap_update_bits(wled->regmap, wled->sink_addr + offset, + WLED5_SINK_MOD_SRC_SEL_MASK, reg); + if (rc < 0) { + pr_err("Error in configuring CABC rc=%d\n", rc); + return rc; + } + + if (!wled->cfg.cabc_sel) + wled->cabc_disabled = true; + + return 0; +} + +static int wled4_cabc_config(struct wled *wled, bool enable) +{ + int i, rc; + u8 reg; + + if (wled->cabc_disabled) + return 0; + + for (i = 0; (wled->cfg.string_cfg >> i) != 0; i++) { + reg = enable ? WLED_SINK_CABC_EN : 0; + rc = regmap_update_bits(wled->regmap, wled->sink_addr + + WLED_SINK_CABC_REG(i), + WLED_SINK_CABC_MASK, reg); + if (rc < 0) + return rc; + } + + if (!wled->cfg.en_cabc) + wled->cabc_disabled = true; + + return 0; +} + +static int wled_get_ovp_fault_status(struct wled *wled, bool *fault_set) +{ + int rc; + u32 int_rt_sts, fault_sts; + + *fault_set = false; + rc = regmap_read(wled->regmap, + wled->ctrl_addr + WLED_CTRL_INT_RT_STS, + &int_rt_sts); + if (rc < 0) { + pr_err("Failed to read INT_RT_STS rc=%d\n", rc); + return rc; + } + + rc = regmap_read(wled->regmap, + wled->ctrl_addr + WLED_CTRL_FAULT_STATUS, + &fault_sts); + if (rc < 0) { + pr_err("Failed to read FAULT_STATUS rc=%d\n", rc); + return rc; + } + + if (int_rt_sts & WLED_CTRL_OVP_FLT_RT_STS_BIT) + *fault_set = true; + + if (is_wled4(wled) && (fault_sts & WLED_CTRL_OVP_FAULT_BIT)) + *fault_set = true; + else if (is_wled5(wled) && (fault_sts & (WLED_CTRL_OVP_FAULT_BIT | + WLED5_CTRL_OVP_PRE_ALARM_BIT))) + *fault_set = true; + + if (*fault_set) + pr_debug("WLED OVP fault detected, int_rt_sts=0x%x fault_sts=0x%x\n", + int_rt_sts, fault_sts); + + return rc; +} + +static void wled_get_ovp_delay(struct wled *wled, int *delay_time_us) +{ + int rc; + u32 val; + u8 ovp_timer_ms[8] = {1, 2, 4, 8, 12, 16, 20, 24}; + + if (is_wled4(wled)) { + *delay_time_us = WLED_SOFT_START_DLY_US; + return; + } + + /* For WLED5, get the delay based on OVP timer */ + rc = regmap_read(wled->regmap, wled->ctrl_addr + + WLED5_CTRL_OVP_INT_CTL_REG, &val); + if (!rc) + *delay_time_us = + ovp_timer_ms[val & WLED5_OVP_INT_TIMER_MASK] * 1000; + else + *delay_time_us = 2 * WLED_SOFT_START_DLY_US; + + pr_debug("delay_time_us: %d\n", *delay_time_us); +} + +#define AUTO_CALIB_BRIGHTNESS 512 +static int wled_auto_calibrate(struct wled *wled) +{ + int rc = 0, i, delay_time_us; + u32 sink_config = 0; + u8 reg = 0, sink_test = 0, sink_valid = 0; + u8 string_cfg = wled->cfg.string_cfg; + bool fault_set; + + if (wled->auto_calib_done) + return 0; + + /* read configured sink configuration */ + rc = regmap_read(wled->regmap, wled->sink_addr + + WLED_SINK_CURR_SINK_EN, &sink_config); + if (rc < 0) { + pr_err("Failed to read SINK configuration rc=%d\n", rc); + goto failed_calib; + } + + /* disable the module before starting calibration */ + rc = regmap_update_bits(wled->regmap, + wled->ctrl_addr + WLED_CTRL_MOD_ENABLE, + WLED_CTRL_MOD_EN_MASK, 0); + if (rc < 0) { + pr_err("Failed to disable WLED module rc=%d\n", rc); + goto failed_calib; + } + + /* set low brightness across all sinks */ + rc = wled_set_brightness(wled, AUTO_CALIB_BRIGHTNESS); + if (rc < 0) { + pr_err("Failed to set brightness for calibration rc=%d\n", rc); + goto failed_calib; + } + + /* Disable CABC if it is enabled */ + rc = wled->cabc_config(wled, false); + if (rc < 0) + goto failed_calib; + + /* disable all sinks */ + rc = regmap_write(wled->regmap, + wled->sink_addr + WLED_SINK_CURR_SINK_EN, 0); + if (rc < 0) { + pr_err("Failed to disable all sinks rc=%d\n", rc); + goto failed_calib; + } + + /* iterate through the strings one by one */ + for (i = 0; (string_cfg >> i) != 0; i++) { + sink_test = 1 << (WLED_SINK_CURR_SINK_SHFT + i); + + /* Enable feedback control */ + rc = regmap_write(wled->regmap, wled->ctrl_addr + + WLED_CTRL_FDBK_OP, i + 1); + if (rc < 0) { + pr_err("Failed to enable feedback for SINK %d rc = %d\n", + i + 1, rc); + goto failed_calib; + } + + /* enable the sink */ + rc = regmap_write(wled->regmap, wled->sink_addr + + WLED_SINK_CURR_SINK_EN, sink_test); + if (rc < 0) { + pr_err("Failed to configure SINK %d rc=%d\n", + i + 1, rc); + goto failed_calib; + } + + /* Enable the module */ + rc = regmap_update_bits(wled->regmap, wled->ctrl_addr + + WLED_CTRL_MOD_ENABLE, + WLED_CTRL_MOD_EN_MASK, + WLED_CTRL_MOD_EN_MASK); + if (rc < 0) { + pr_err("Failed to enable WLED module rc=%d\n", rc); + goto failed_calib; + } + + wled_get_ovp_delay(wled, &delay_time_us); + if (delay_time_us < 20000) + usleep_range(delay_time_us, delay_time_us + 1000); + else + msleep(delay_time_us / 1000); + + rc = wled_get_ovp_fault_status(wled, &fault_set); + if (rc < 0) { + pr_err("Error in getting OVP fault_sts, rc=%d\n", rc); + goto failed_calib; + } + + if (fault_set) + pr_debug("WLED OVP fault detected with SINK %d\n", + i + 1); + else + sink_valid |= sink_test; + + /* Disable the module */ + rc = regmap_update_bits(wled->regmap, + wled->ctrl_addr + WLED_CTRL_MOD_ENABLE, + WLED_CTRL_MOD_EN_MASK, 0); + if (rc < 0) { + pr_err("Failed to disable WLED module rc=%d\n", rc); + goto failed_calib; + } + } + + if (sink_valid == sink_config) { + pr_debug("WLED auto-calibration complete, default sink-config=%x OK!\n", + sink_config); + } else { + pr_warn("Invalid WLED default sink config=%x changing it to=%x\n", + sink_config, sink_valid); + sink_config = sink_valid; + } + + if (!sink_config) { + pr_err("No valid WLED sinks found\n"); + wled->force_mod_disable = true; + goto failed_calib; + } + + /* write the new sink configuration */ + rc = regmap_write(wled->regmap, + wled->sink_addr + WLED_SINK_CURR_SINK_EN, + sink_config); + if (rc < 0) { + pr_err("Failed to reconfigure the default sink rc=%d\n", rc); + goto failed_calib; + } + + if (is_wled5(wled)) { + /* Update the flash sink configuration as well */ + rc = regmap_update_bits(wled->regmap, + wled->sink_addr + WLED5_SINK_FLASH_SINK_EN_REG, + WLED_SINK_CURR_SINK_MASK, sink_config); + if (rc < 0) + return rc; + } + + /* MODULATOR_EN setting for valid sinks */ + if (is_wled4(wled)) { + for (i = 0; (string_cfg >> i) != 0; i++) { + /* disable modulator_en for unused sink */ + if (sink_config & (1 << (WLED_SINK_CURR_SINK_SHFT + i))) + reg = WLED_SINK_REG_STR_MOD_EN; + else + reg = 0x0; + + rc = regmap_write(wled->regmap, wled->sink_addr + + WLED_SINK_MOD_EN_REG(i), reg); + if (rc < 0) { + pr_err("Failed to configure MODULATOR_EN rc=%d\n", + rc); + goto failed_calib; + } + } + } + + /* Enable CABC if it needs to be enabled */ + rc = wled->cabc_config(wled, true); + if (rc < 0) + goto failed_calib; + + /* restore the feedback setting */ + rc = regmap_write(wled->regmap, + wled->ctrl_addr + WLED_CTRL_FDBK_OP, 0); + if (rc < 0) { + pr_err("Failed to restore feedback setting rc=%d\n", rc); + goto failed_calib; + } + + /* restore brightness */ + rc = wled_set_brightness(wled, wled->brightness); + if (rc < 0) { + pr_err("Failed to set brightness after calibration rc=%d\n", + rc); + goto failed_calib; + } + + rc = regmap_update_bits(wled->regmap, + wled->ctrl_addr + WLED_CTRL_MOD_ENABLE, + WLED_CTRL_MOD_EN_MASK, + WLED_CTRL_MOD_EN_MASK); + if (rc < 0) { + pr_err("Failed to enable WLED module rc=%d\n", rc); + goto failed_calib; + } + + /* delay for WLED soft-start */ + usleep_range(WLED_SOFT_START_DLY_US, + WLED_SOFT_START_DLY_US + 1000); + + wled->auto_calib_done = true; + +failed_calib: + return rc; +} + +#define WLED_AUTO_CAL_OVP_COUNT 5 +#define WLED_AUTO_CAL_CNT_DLY_US 1000000 /* 1 second */ +static bool wled_auto_cal_required(struct wled *wled) +{ + s64 elapsed_time_us; + + /* + * Check if the OVP fault was an occasional one + * or if its firing continuously, the latter qualifies + * for an auto-calibration check. + */ + if (!wled->auto_calibration_ovp_count) { + wled->start_ovp_fault_time = ktime_get(); + wled->auto_calibration_ovp_count++; + return false; + } + + if (is_wled5(wled)) { + /* + * WLED5 has OVP fault density interrupt configuration i.e. to + * count the number of OVP alarms for a certain duration before + * triggering OVP fault interrupt. By default, number of OVP + * fault events counted before an interrupt is fired is 32 and + * the time interval is 12 ms. If we see more than one OVP fault + * interrupt, then that should qualify for a real OVP fault + * condition to run auto calibration algorithm. + */ + + if (wled->auto_calibration_ovp_count > 1) { + elapsed_time_us = ktime_us_delta(ktime_get(), + wled->start_ovp_fault_time); + wled->auto_calibration_ovp_count = 0; + pr_debug("Elapsed time: %lld us\n", elapsed_time_us); + return true; + } + wled->auto_calibration_ovp_count++; + } else if (is_wled4(wled)) { + elapsed_time_us = ktime_us_delta(ktime_get(), + wled->start_ovp_fault_time); + if (elapsed_time_us > WLED_AUTO_CAL_CNT_DLY_US) + wled->auto_calibration_ovp_count = 0; + else + wled->auto_calibration_ovp_count++; + + if (wled->auto_calibration_ovp_count >= + WLED_AUTO_CAL_OVP_COUNT) { + wled->auto_calibration_ovp_count = 0; + return true; + } + } + + return false; +} + +static int wled_auto_calibrate_at_init(struct wled *wled) +{ + int rc; + bool fault_set; + + if (!wled->cfg.auto_calib_enabled) + return 0; + + rc = wled_get_ovp_fault_status(wled, &fault_set); + if (rc < 0) { + pr_err("Error in getting OVP fault_sts, rc=%d\n", rc); + return rc; + } + + if (fault_set) { + mutex_lock(&wled->lock); + rc = wled_auto_calibrate(wled); + mutex_unlock(&wled->lock); + } + + return rc; +} + +static void handle_ovp_fault(struct wled *wled) +{ + int rc; + + if (!wled->cfg.auto_calib_enabled) + return; + + mutex_lock(&wled->lock); + if (wled->auto_calib_done) { + pr_warn("Disabling module since OVP persists\n"); + rc = regmap_update_bits(wled->regmap, + wled->ctrl_addr + WLED_CTRL_MOD_ENABLE, + WLED_CTRL_MOD_EN_MASK, 0); + if (!rc) + wled->force_mod_disable = true; + mutex_unlock(&wled->lock); + return; + } + + if (wled->ovp_irq > 0 && !wled->ovp_irq_disabled) { + disable_irq_nosync(wled->ovp_irq); + wled->ovp_irq_disabled = true; + } + + if (wled_auto_cal_required(wled)) + wled_auto_calibrate(wled); + + if (wled->ovp_irq > 0 && wled->ovp_irq_disabled) { + enable_irq(wled->ovp_irq); + wled->ovp_irq_disabled = false; + } + mutex_unlock(&wled->lock); +} + +static irqreturn_t wled_ovp_irq_handler(int irq, void *_wled) +{ + struct wled *wled = _wled; + int rc; + bool fault_set; + + rc = wled_get_ovp_fault_status(wled, &fault_set); + if (rc < 0) { + pr_err("Error in getting OVP fault_sts, rc=%d\n", rc); + return rc; + } + + if (fault_set) + handle_ovp_fault(wled); + + return IRQ_HANDLED; +} + +static irqreturn_t wled_flash_irq_handler(int irq, void *_wled) +{ + struct wled *wled = _wled; + int rc; + u32 val; + + if (irq == wled->flash_irq) + pr_debug("flash irq fired\n"); + else if (irq == wled->pre_flash_irq) + pr_debug("pre_flash irq fired\n"); + + rc = regmap_read(wled->regmap, + wled->ctrl_addr + WLED_CTRL_FAULT_STATUS, &val); + if (!rc) + pr_debug("WLED_FAULT_STATUS: 0x%x\n", val); + + rc = regmap_read(wled->regmap, + wled->ctrl_addr + WLED5_CTRL_STATUS, &val); + if (!rc) + pr_debug("WLED_STATUS: 0x%x\n", val); + + return IRQ_HANDLED; +} + +static inline u8 get_wled_safety_time(int time_ms) +{ + int i, table[8] = {50, 100, 200, 400, 600, 800, 1000, 1200}; + + for (i = 0; i < ARRAY_SIZE(table); i++) { + if (time_ms == table[i]) + return i; + } + + return 0; +} + +static int wled5_setup(struct wled *wled) +{ + int rc, temp, i; + u8 sink_en = 0; + u16 addr; + u32 val; + u8 string_cfg = wled->cfg.string_cfg; + + rc = wled_flash_setup(wled); + if (rc < 0) + dev_err(&wled->pdev->dev, "failed to setup WLED flash/torch rc:%d\n", + rc); + + rc = regmap_update_bits(wled->regmap, + wled->ctrl_addr + WLED_CTRL_OVP, + WLED5_CTRL_OVP_MASK, wled->cfg.ovp); + if (rc < 0) + return rc; + + rc = regmap_update_bits(wled->regmap, + wled->ctrl_addr + WLED_CTRL_ILIM, + WLED_CTRL_ILIM_MASK, wled->cfg.boost_i_limit); + if (rc < 0) + return rc; + + if (wled->cfg.switch_freq != -EINVAL) { + rc = regmap_update_bits(wled->regmap, + wled->ctrl_addr + WLED_CTRL_SWITCH_FREQ, + WLED_CTRL_SWITCH_FREQ_MASK, + wled->cfg.switch_freq); + if (rc < 0) + return rc; + } + + /* Per sink/string configuration */ + for (i = 0; (string_cfg >> i) != 0; i++) { + if (string_cfg & BIT(i)) { + addr = wled->sink_addr + + WLED5_SINK_FS_CURR_REG(i); + rc = regmap_update_bits(wled->regmap, addr, + WLED_SINK_FS_MASK, + wled->cfg.fs_current); + if (rc < 0) + return rc; + + addr = wled->sink_addr + + WLED5_SINK_SRC_SEL_REG(i); + rc = regmap_update_bits(wled->regmap, addr, + WLED5_SINK_SRC_SEL_MASK, + wled->cfg.mod_sel == MOD_A ? + WLED5_SINK_SRC_SEL_MODA : + WLED5_SINK_SRC_SEL_MODB); + + temp = i + WLED_SINK_CURR_SINK_SHFT; + sink_en |= 1 << temp; + } + } + + rc = wled5_cabc_config(wled, wled->cfg.cabc_sel ? true : false); + if (rc < 0) + return rc; + + /* Enable one of the modulators A or B based on mod_sel */ + addr = wled->sink_addr + WLED5_SINK_MOD_A_EN_REG; + val = (wled->cfg.mod_sel == MOD_A) ? WLED5_SINK_MOD_EN : 0; + rc = regmap_update_bits(wled->regmap, addr, + WLED5_SINK_MOD_EN, val); + if (rc < 0) + return rc; + + addr = wled->sink_addr + WLED5_SINK_MOD_B_EN_REG; + val = (wled->cfg.mod_sel == MOD_B) ? WLED5_SINK_MOD_EN : 0; + rc = regmap_update_bits(wled->regmap, addr, + WLED5_SINK_MOD_EN, val); + if (rc < 0) + return rc; + + addr = wled->sink_addr + wled5_brt_wid_sel_reg[wled->cfg.mod_sel]; + val = (wled->max_brightness == WLED_MAX_BRIGHTNESS_15B) + ? WLED5_SINK_BRT_WIDTH_15B : WLED5_SINK_BRT_WIDTH_12B; + rc = regmap_write(wled->regmap, addr, val); + if (rc < 0) + return rc; + + rc = regmap_write(wled->regmap, + wled->sink_addr + WLED_SINK_CURR_SINK_EN, sink_en); + if (rc < 0) + return rc; + + /* This updates only FSC configuration in WLED5 */ + rc = wled_sync_toggle(wled); + if (rc < 0) { + pr_err("Failed to toggle sync reg rc:%d\n", rc); + return rc; + } + + rc = wled_auto_calibrate_at_init(wled); + if (rc < 0) + return rc; + + if (wled->ovp_irq >= 0) { + rc = devm_request_threaded_irq(&wled->pdev->dev, wled->ovp_irq, + NULL, wled_ovp_irq_handler, IRQF_ONESHOT, + "wled_ovp_irq", wled); + if (rc < 0) { + pr_err("Unable to request ovp(%d) IRQ(err:%d)\n", + wled->ovp_irq, rc); + return rc; + } + + rc = regmap_read(wled->regmap, wled->ctrl_addr + + WLED_CTRL_MOD_ENABLE, &val); + /* disable the OVP irq only if the module is not enabled */ + if (!rc && !(val & WLED_CTRL_MOD_EN_MASK)) { + disable_irq(wled->ovp_irq); + wled->ovp_irq_disabled = true; + } + } + + if (wled->flash_irq >= 0) { + rc = devm_request_threaded_irq(&wled->pdev->dev, + wled->flash_irq, NULL, wled_flash_irq_handler, + IRQF_ONESHOT, "wled_flash_irq", wled); + if (rc < 0) + pr_err("Unable to request flash(%d) IRQ(err:%d)\n", + wled->flash_irq, rc); + } + + if (wled->pre_flash_irq >= 0) { + rc = devm_request_threaded_irq(&wled->pdev->dev, + wled->pre_flash_irq, NULL, + wled_flash_irq_handler, IRQF_ONESHOT, + "wled_pre_flash_irq", wled); + if (rc < 0) + pr_err("Unable to request pre_flash(%d) IRQ(err:%d)\n", + wled->pre_flash_irq, rc); + } + return 0; +} + +static int wled4_setup(struct wled *wled) +{ + int rc, temp, i; + u8 sink_en = 0; + u32 val; + u8 string_cfg = wled->cfg.string_cfg; + + rc = regmap_update_bits(wled->regmap, + wled->ctrl_addr + WLED_CTRL_OVP, + WLED_CTRL_OVP_MASK, wled->cfg.ovp); + if (rc < 0) + return rc; + + rc = regmap_update_bits(wled->regmap, + wled->ctrl_addr + WLED_CTRL_ILIM, + WLED_CTRL_ILIM_MASK, wled->cfg.boost_i_limit); + if (rc < 0) + return rc; + + rc = regmap_update_bits(wled->regmap, + wled->ctrl_addr + WLED_CTRL_SWITCH_FREQ, + WLED_CTRL_SWITCH_FREQ_MASK, wled->cfg.switch_freq); + if (rc < 0) + return rc; + + /* Per sink/string configuration */ + for (i = 0; (string_cfg >> i) != 0; i++) { + if (string_cfg & BIT(i)) { + u16 addr = wled->sink_addr + + WLED_SINK_MOD_EN_REG(i); + + rc = regmap_update_bits(wled->regmap, addr, + WLED_SINK_REG_STR_MOD_MASK, + WLED_SINK_REG_STR_MOD_EN); + if (rc < 0) + return rc; + + addr = wled->sink_addr + + WLED_SINK_FS_CURR_REG(i); + rc = regmap_update_bits(wled->regmap, addr, + WLED_SINK_FS_MASK, + wled->cfg.fs_current); + if (rc < 0) + return rc; + + temp = i + WLED_SINK_CURR_SINK_SHFT; + sink_en |= 1 << temp; + } + } + + rc = wled4_cabc_config(wled, wled->cfg.en_cabc); + if (rc < 0) + return rc; + + rc = regmap_write(wled->regmap, + wled->sink_addr + WLED_SINK_CURR_SINK_EN, sink_en); + if (rc < 0) + return rc; + + rc = wled_sync_toggle(wled); + if (rc < 0) { + pr_err("Failed to toggle sync reg rc:%d\n", rc); + return rc; + } + + rc = wled_auto_calibrate_at_init(wled); + if (rc < 0) + return rc; + + if (wled->sc_irq >= 0) { + rc = devm_request_threaded_irq(&wled->pdev->dev, wled->sc_irq, + NULL, wled_sc_irq_handler, IRQF_ONESHOT, + "wled_sc_irq", wled); + if (rc < 0) { + pr_err("Unable to request sc(%d) IRQ(err:%d)\n", + wled->sc_irq, rc); + return rc; + } + + rc = regmap_update_bits(wled->regmap, + wled->ctrl_addr + WLED_CTRL_SHORT_PROTECT, + WLED_CTRL_SHORT_EN_MASK, + WLED_CTRL_SHORT_EN_MASK); + if (rc < 0) + return rc; + } + + if (wled->cfg.ext_pfet_sc_pro_en) { + /* unlock the secure access register */ + rc = regmap_write(wled->regmap, wled->ctrl_addr + + WLED_CTRL_SEC_ACCESS, + WLED_CTRL_SEC_UNLOCK); + if (rc < 0) + return rc; + + rc = regmap_write(wled->regmap, + wled->ctrl_addr + WLED_CTRL_TEST1, + WLED_EXT_FET_DTEST2); + if (rc < 0) + return rc; + } + + if (wled->ovp_irq >= 0) { + rc = devm_request_threaded_irq(&wled->pdev->dev, wled->ovp_irq, + NULL, wled_ovp_irq_handler, IRQF_ONESHOT, + "wled_ovp_irq", wled); + if (rc < 0) { + pr_err("Unable to request ovp(%d) IRQ(err:%d)\n", + wled->ovp_irq, rc); + return rc; + } + + rc = regmap_read(wled->regmap, wled->ctrl_addr + + WLED_CTRL_MOD_ENABLE, &val); + /* disable the OVP irq only if the module is not enabled */ + if (!rc && !(val & WLED_CTRL_MOD_EN_MASK)) { + disable_irq(wled->ovp_irq); + wled->ovp_irq_disabled = true; + } + } + + return 0; +} + +static const struct wled_config wled4_config_defaults = { + .boost_i_limit = 4, + .fs_current = 10, + .ovp = 1, + .switch_freq = 11, + .string_cfg = 0xf, + .mod_sel = -EINVAL, + .cabc_sel = -EINVAL, + .en_cabc = 0, + .ext_pfet_sc_pro_en = 0, + .auto_calib_enabled = 0, +}; + +static const struct wled_config wled5_config_defaults = { + .boost_i_limit = 5, + .fs_current = 10, /* 25 mA */ + .ovp = 4, + .switch_freq = -EINVAL, + .string_cfg = 0xf, + .mod_sel = 0, + .cabc_sel = 0, + .en_cabc = 0, + .ext_pfet_sc_pro_en = 0, + .auto_calib_enabled = 0, +}; + +struct wled_var_cfg { + const u32 *values; + u32 (*fn)(u32 idx); + int size; +}; + +static const u32 wled4_boost_i_limit_values[] = { + 105, 280, 450, 620, 970, 1150, 1300, 1500, +}; + +static const struct wled_var_cfg wled4_boost_i_limit_cfg = { + .values = wled4_boost_i_limit_values, + .size = ARRAY_SIZE(wled4_boost_i_limit_values), +}; + +static inline u32 wled5_boost_i_limit_values_fn(u32 idx) +{ + return 525 + (idx * 175); +} + +static const struct wled_var_cfg wled5_boost_i_limit_cfg = { + .fn = wled5_boost_i_limit_values_fn, + .size = 8, +}; + +static const u32 wled_fs_current_values[] = { + 0, 2500, 5000, 7500, 10000, 12500, 15000, 17500, 20000, + 22500, 25000, 27500, 30000, +}; + +static const struct wled_var_cfg wled_fs_current_cfg = { + .values = wled_fs_current_values, + .size = ARRAY_SIZE(wled_fs_current_values), +}; + +static const u32 wled4_ovp_values[] = { + 31100, 29600, 19600, 18100, +}; + +static const struct wled_var_cfg wled4_ovp_cfg = { + .values = wled4_ovp_values, + .size = ARRAY_SIZE(wled4_ovp_values), +}; + +static inline u32 wled5_ovp_values_fn(u32 idx) +{ + /* + * 0000 - 38.5 V + * 0001 - 37 V .. + * 1111 - 16 V + */ + return 38500 - (idx * 1500); +} + +static const struct wled_var_cfg wled5_ovp_cfg = { + .fn = wled5_ovp_values_fn, + .size = 16, +}; + +static inline u32 wled_switch_freq_values_fn(u32 idx) +{ + return 9600 / (1 + idx); +} + +static const struct wled_var_cfg wled_switch_freq_cfg = { + .fn = wled_switch_freq_values_fn, + .size = 16, +}; + +static const struct wled_var_cfg wled_string_cfg = { + .size = 16, +}; + +static const struct wled_var_cfg wled5_mod_sel_cfg = { + .size = 2, +}; + +static const struct wled_var_cfg wled5_cabc_sel_cfg = { + .size = 4, +}; + +static u32 wled_values(const struct wled_var_cfg *cfg, u32 idx) +{ + if (!cfg) + return UINT_MAX; + if (idx >= cfg->size) + return UINT_MAX; + if (cfg->fn) + return cfg->fn(idx); + if (cfg->values) + return cfg->values[idx]; + return idx; +} + +static int wled_get_max_current(struct led_classdev *led_cdev, + int *max_current) +{ + struct wled *wled; + bool flash; + + if (!strcmp(led_cdev->name, "wled_flash")) { + wled = container_of(led_cdev, struct wled, flash_cdev); + flash = true; + } else if (!strcmp(led_cdev->name, "wled_torch")) { + wled = container_of(led_cdev, struct wled, torch_cdev); + flash = false; + } else { + return -ENODEV; + } + + if (flash) + *max_current = wled->flash_cdev.max_brightness; + else + *max_current = wled->torch_cdev.max_brightness; + + return 0; +} + +static int get_property_from_fg(struct wled *wled, + enum power_supply_property prop, int *val) +{ + int rc; + union power_supply_propval pval = {0, }; + + if (!wled->bms_psy) + wled->bms_psy = power_supply_get_by_name("bms"); + + if (!wled->bms_psy) + return -ENODEV; + + rc = power_supply_get_property(wled->bms_psy, prop, &pval); + if (rc < 0) { + pr_err("bms psy doesn't support reading prop %d rc = %d\n", + prop, rc); + return rc; + } + + *val = pval.intval; + return rc; +} + +#define V_HDRM_MV 400 +#define V_DROOP_MV 400 +#define V_LED_MV 3100 +#define I_FLASH_MAX_MA 60 +#define EFF_FACTOR 700 +static int wled_get_max_avail_current(struct led_classdev *led_cdev, + int *max_current) +{ + struct wled *wled; + int rc, ocv_mv, r_bat_mohms, i_bat_ma, i_sink_ma = 0, max_fsc_ma; + int64_t p_out_string, p_out, p_in, v_safe_mv, i_flash_ma, v_ph_mv; + + if (!strcmp(led_cdev->name, "wled_switch")) + wled = container_of(led_cdev, struct wled, switch_cdev); + else + return -ENODEV; + + max_fsc_ma = max(wled->flash_cdev.max_brightness, + wled->torch_cdev.max_brightness); + if (!wled->leds_per_string || (wled->num_strings == 2 && + wled->leds_per_string == 8)) { + /* Allow max for 8s2p */ + *max_current = max_fsc_ma; + return 0; + } + + rc = get_property_from_fg(wled, POWER_SUPPLY_PROP_VOLTAGE_OCV, &ocv_mv); + if (rc < 0) { + pr_err("Error in getting OCV rc=%d\n", rc); + return rc; + } + ocv_mv /= 1000; + + rc = get_property_from_fg(wled, POWER_SUPPLY_PROP_CURRENT_NOW, + &i_bat_ma); + if (rc < 0) { + pr_err("Error in getting I_BAT rc=%d\n", rc); + return rc; + } + i_bat_ma /= 1000; + + rc = get_property_from_fg(wled, POWER_SUPPLY_PROP_RESISTANCE, + &r_bat_mohms); + if (rc < 0) { + pr_err("Error in getting R_BAT rc=%d\n", rc); + return rc; + } + r_bat_mohms /= 1000; + + pr_debug("ocv: %d i_bat: %d r_bat: %d\n", ocv_mv, i_bat_ma, + r_bat_mohms); + + p_out_string = ((wled->leds_per_string * V_LED_MV) + V_HDRM_MV) * + I_FLASH_MAX_MA; + p_out = p_out_string * wled->num_strings; + p_in = (p_out * 1000) / EFF_FACTOR; + + pr_debug("p_out_string: %lld, p_out: %lld, p_in: %lld\n", p_out_string, + p_out, p_in); + + v_safe_mv = ocv_mv - V_DROOP_MV - ((i_bat_ma * r_bat_mohms) / 1000); + if (v_safe_mv <= 0) { + pr_err("V_safe_mv: %lld, cannot support flash\n", v_safe_mv); + *max_current = 0; + return 0; + } + + i_flash_ma = p_in / v_safe_mv; + v_ph_mv = ocv_mv - ((i_bat_ma + i_flash_ma) * r_bat_mohms) / 1000; + + pr_debug("v_safe: %lld, i_flash: %lld, v_ph: %lld\n", v_safe_mv, + i_flash_ma, v_ph_mv); + + i_sink_ma = max_fsc_ma; + if (wled->num_strings == 3 && wled->leds_per_string == 8) { + if (v_ph_mv < 3410) { + /* For 8s3p, I_sink(mA) = 25.396 * Vph(V) - 26.154 */ + i_sink_ma = (((25396 * v_ph_mv) / 1000) - 26154) / 1000; + i_sink_ma *= wled->num_strings; + } + } else if (wled->num_strings == 3 && wled->leds_per_string == 6) { + if (v_ph_mv < 2800) { + /* For 6s3p, I_sink(mA) = 41.311 * Vph(V) - 52.334 */ + i_sink_ma = (((41311 * v_ph_mv) / 1000) - 52334) / 1000; + i_sink_ma *= wled->num_strings; + } + } else if (wled->num_strings == 4 && wled->leds_per_string == 6) { + if (v_ph_mv < 3400) { + /* For 6s4p, I_sink(mA) = 26.24 * Vph(V) - 24.834 */ + i_sink_ma = (((26240 * v_ph_mv) / 1000) - 24834) / 1000; + i_sink_ma *= wled->num_strings; + } + } else if (v_ph_mv < 3200) { + i_sink_ma = max_fsc_ma / 2; + } + + /* Clamp the sink current to maximum FSC */ + *max_current = min(i_sink_ma, max_fsc_ma); + + pr_debug("i_sink_ma: %d\n", i_sink_ma); + return 0; +} + +static ssize_t wled_flash_max_avail_current_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct led_classdev *led_cdev = dev_get_drvdata(dev); + int rc, max_current = 0; + + rc = wled_get_max_avail_current(led_cdev, &max_current); + if (rc < 0) + pr_err("query max current failed, rc=%d\n", rc); + + return scnprintf(buf, PAGE_SIZE, "%d\n", max_current); +} + +static struct device_attribute wled_flash_attrs[] = { + __ATTR(max_avail_current, 0664, wled_flash_max_avail_current_show, + NULL), +}; + +int wled_flash_led_prepare(struct led_trigger *trig, int options, + int *max_current) +{ + struct led_classdev *led_cdev; + int rc; + + if (!(options & FLASH_LED_PREPARE_OPTIONS_MASK)) { + pr_err("Invalid options %d\n", options); + return -EINVAL; + } + + if (!trig) { + pr_err("Invalid led_trigger provided\n"); + return -EINVAL; + } + + led_cdev = trigger_to_lcdev(trig); + if (!led_cdev) { + pr_err("Invalid led_cdev in trigger %s\n", trig->name); + return -EINVAL; + } + + switch (options) { + case QUERY_MAX_CURRENT: + rc = wled_get_max_current(led_cdev, max_current); + if (rc < 0) { + pr_err("Error in getting max_current for %s\n", + led_cdev->name); + return rc; + } + break; + case QUERY_MAX_AVAIL_CURRENT: + rc = wled_get_max_avail_current(led_cdev, max_current); + if (rc < 0) { + pr_err("Error in getting max_avail_current for %s\n", + led_cdev->name); + return rc; + } + break; + case ENABLE_REGULATOR: + case DISABLE_REGULATOR: + /* Not supported */ + return 0; + default: + return -EINVAL; + } + + return 0; +} +EXPORT_SYMBOL(wled_flash_led_prepare); + +static int wled_flash_set_step_delay(struct wled *wled, int step_delay) +{ + int rc, table[8] = {50, 100, 150, 200, 250, 300, 350, 400}; + u8 val; + + if (step_delay < table[0]) + val = 0; + else if (step_delay > table[7]) + val = 7; + else + val = DIV_ROUND_CLOSEST(step_delay, 50) - 1; + + rc = regmap_update_bits(wled->regmap, wled->ctrl_addr + + WLED5_CTRL_FLASH_STEP_CTL_REG, + WLED5_CTRL_FLASH_STEP_MASK, val); + if (rc < 0) + pr_err("Error in configuring step delay, rc:%d\n", rc); + + return rc; +} + +static int wled_flash_set_fsc(struct wled *wled, enum led_brightness brightness, + int fs_current_max) +{ + int rc, fs_current; + u8 val; + + if (!wled->num_strings) { + pr_err("Incorrect number of strings\n"); + return -EINVAL; + } + + fs_current = (int)brightness / wled->num_strings; + if (fs_current > fs_current_max) + fs_current = fs_current_max; + + /* Each LSB is 5 mA */ + val = DIV_ROUND_CLOSEST(fs_current, 5); + rc = regmap_update_bits(wled->regmap, + wled->sink_addr + WLED5_SINK_FLASH_FSC_REG, + WLED5_SINK_FLASH_FSC_MASK, val); + if (rc < 0) { + pr_err("Error in configuring flash_fsc, rc:%d\n", rc); + return rc; + } + + /* Write 0 followed by 1 to sync FSC */ + rc = regmap_write(wled->regmap, + wled->sink_addr + WLED5_SINK_FLASH_SYNC_BIT_REG, 0); + if (rc < 0) { + pr_err("Error in configuring flash_sync, rc:%d\n", rc); + return rc; + } + + rc = regmap_write(wled->regmap, + wled->sink_addr + WLED5_SINK_FLASH_SYNC_BIT_REG, + WLED5_SINK_FLASH_FSC_SYNC_EN); + if (rc < 0) + pr_err("Error in configuring flash_sync, rc:%d\n", rc); + + return rc; +} + +static void wled_flash_brightness_set(struct led_classdev *cdev, + enum led_brightness brightness) +{ + struct wled *wled = container_of(cdev, struct wled, flash_cdev); + int rc; + + spin_lock(&wled->flash_lock); + if (brightness) { + rc = wled_flash_set_step_delay(wled, wled->fparams.step_delay); + if (rc < 0) + goto out; + } + + rc = wled_flash_set_fsc(wled, brightness, wled->fparams.fs_current); + if (rc < 0) + goto out; + + wled->flash_mode = brightness ? WLED_FLASH : WLED_FLASH_OFF; +out: + spin_unlock(&wled->flash_lock); +} + +static void wled_torch_brightness_set(struct led_classdev *cdev, + enum led_brightness brightness) +{ + struct wled *wled = container_of(cdev, struct wled, torch_cdev); + int rc; + + spin_lock(&wled->flash_lock); + if (brightness) { + rc = wled_flash_set_step_delay(wled, wled->tparams.step_delay); + if (rc < 0) + goto out; + } + + rc = wled_flash_set_fsc(wled, brightness, wled->tparams.fs_current); + if (rc < 0) + goto out; + + wled->flash_mode = brightness ? WLED_PRE_FLASH : WLED_FLASH_OFF; +out: + spin_unlock(&wled->flash_lock); +} + +static void wled_switch_brightness_set(struct led_classdev *cdev, + enum led_brightness brightness) +{ + struct wled *wled = container_of(cdev, struct wled, switch_cdev); + int rc; + u8 val; + + if (brightness && wled->flash_mode == WLED_FLASH_OFF) + return; + + spin_lock(&wled->flash_lock); + if (wled->flash_mode == WLED_PRE_FLASH) + val = brightness ? WLED5_SINK_PRE_FLASH_EN : 0; + else + val = brightness ? WLED5_SINK_FLASH_EN : 0; + + rc = regmap_write(wled->regmap, + wled->sink_addr + WLED5_SINK_FLASH_CTL_REG, val); + if (rc < 0) + pr_err("Error in configuring flash_ctl, rc:%d\n", rc); + + if (!brightness) { + rc = regmap_write(wled->regmap, + wled->sink_addr + WLED5_SINK_FLASH_SHDN_CLR_REG, + 1); + if (rc < 0) + pr_err("Error in configuring flash_shdn_clr, rc:%d\n", + rc); + } + + spin_unlock(&wled->flash_lock); +} + +static int wled_flash_device_register(struct wled *wled) +{ + int rc, i, max_brightness = 0; + + /* Not supported */ + if (is_wled4(wled)) + return 0; + + spin_lock_init(&wled->flash_lock); + + /* flash */ + for (i = 0; (wled->cfg.string_cfg >> i) != 0; i++) + max_brightness += wled->fparams.fs_current; + + wled->flash_cdev.name = "wled_flash"; + wled->flash_cdev.max_brightness = max_brightness; + wled->flash_cdev.brightness_set = wled_flash_brightness_set; + rc = devm_led_classdev_register(&wled->pdev->dev, &wled->flash_cdev); + if (rc < 0) + return rc; + + /* torch */ + for (max_brightness = 0, i = 0; (wled->cfg.string_cfg >> i) != 0; i++) + max_brightness += wled->tparams.fs_current; + + wled->torch_cdev.name = "wled_torch"; + wled->torch_cdev.max_brightness = max_brightness; + wled->torch_cdev.brightness_set = wled_torch_brightness_set; + rc = devm_led_classdev_register(&wled->pdev->dev, &wled->torch_cdev); + if (rc < 0) + return rc; + + /* switch */ + wled->switch_cdev.name = "wled_switch"; + wled->switch_cdev.brightness_set = wled_switch_brightness_set; + wled->switch_cdev.flags |= LED_KEEP_TRIGGER; + rc = devm_led_classdev_register(&wled->pdev->dev, &wled->switch_cdev); + if (rc < 0) + return rc; + + for (i = 0; i < ARRAY_SIZE(wled_flash_attrs); i++) { + rc = sysfs_create_file(&wled->switch_cdev.dev->kobj, + &wled_flash_attrs[i].attr); + if (rc < 0) { + pr_err("sysfs creation failed, rc=%d\n", rc); + goto sysfs_fail; + } + } + + return 0; + +sysfs_fail: + for (--i; i >= 0; i--) + sysfs_remove_file(&wled->switch_cdev.dev->kobj, + &wled_flash_attrs[i].attr); + + return rc; +} + +static int wled_flash_configure(struct wled *wled) +{ + int rc; + struct device_node *temp; + struct device *dev = &wled->pdev->dev; + const char *cdev_name; + + /* Not supported */ + if (is_wled4(wled)) + return 0; + + of_property_read_u32(wled->pdev->dev.of_node, "qcom,leds-per-string", + &wled->leds_per_string); + + for_each_available_child_of_node(wled->pdev->dev.of_node, temp) { + rc = of_property_read_string(temp, "label", &cdev_name); + if (rc < 0) + continue; + + if (!strcmp(cdev_name, "flash")) { + /* Value read in mA */ + wled->fparams.fs_current = 50; + rc = of_property_read_u32(temp, "qcom,wled-flash-fsc", + &wled->fparams.fs_current); + if (!rc) { + if (wled->fparams.fs_current <= 0 || + wled->fparams.fs_current > 60) { + dev_err(dev, "Incorrect WLED flash FSC rc:%d\n", + rc); + return rc; + } + } + + /* + * As per the hardware recommendation, FS current should + * be limited to 20 mA for PM8150L v1.0. + */ + if (wled->pmic_rev_id->rev4 == PM8150L_V1P0_REV4) + wled->fparams.fs_current = 20; + + /* Value read in us */ + wled->fparams.step_delay = 200; + rc = of_property_read_u32(temp, "qcom,wled-flash-step", + &wled->fparams.step_delay); + if (!rc) { + if (wled->fparams.step_delay < 50 || + wled->fparams.step_delay > 400) { + dev_err(dev, "Incorrect WLED flash step delay rc:%d\n", + rc); + return rc; + } + } + + /* Value read in ms */ + wled->fparams.safety_timer = 100; + rc = of_property_read_u32(temp, "qcom,wled-flash-timer", + &wled->fparams.safety_timer); + if (!rc) { + if (wled->fparams.safety_timer < 50 || + wled->fparams.safety_timer > 1200) { + dev_err(dev, "Incorrect WLED flash safety time rc:%d\n", + rc); + return rc; + } + } + + rc = of_property_read_string(temp, + "qcom,default-led-trigger", + &wled->flash_cdev.default_trigger); + if (rc < 0) + wled->flash_cdev.default_trigger = "wled_flash"; + } else if (!strcmp(cdev_name, "torch")) { + /* Value read in mA */ + wled->tparams.fs_current = 50; + rc = of_property_read_u32(temp, "qcom,wled-torch-fsc", + &wled->tparams.fs_current); + if (!rc) { + if (wled->tparams.fs_current <= 0 || + wled->tparams.fs_current > 60) { + dev_err(dev, "Incorrect WLED torch FSC rc:%d\n", + rc); + return rc; + } + } + + /* + * As per the hardware recommendation, FS current should + * be limited to 20 mA for PM8150L v1.0. + */ + if (wled->pmic_rev_id->rev4 == PM8150L_V1P0_REV4) + wled->tparams.fs_current = 20; + + /* Value read in us */ + wled->tparams.step_delay = 200; + rc = of_property_read_u32(temp, "qcom,wled-torch-step", + &wled->tparams.step_delay); + if (!rc) { + if (wled->tparams.step_delay < 50 || + wled->tparams.step_delay > 400) { + dev_err(dev, "Incorrect WLED torch step delay rc:%d\n", + rc); + return rc; + } + } + + /* Value read in ms */ + wled->tparams.safety_timer = 600; + rc = of_property_read_u32(temp, "qcom,wled-torch-timer", + &wled->tparams.safety_timer); + if (!rc) { + if (wled->tparams.safety_timer < 50 || + wled->tparams.safety_timer > 1200) { + dev_err(dev, "Incorrect WLED torch safety time rc:%d\n", + rc); + return rc; + } + } + + rc = of_property_read_string(temp, + "qcom,default-led-trigger", + &wled->torch_cdev.default_trigger); + if (rc < 0) + wled->torch_cdev.default_trigger = "wled_torch"; + } else if (!strcmp(cdev_name, "switch")) { + rc = of_property_read_string(temp, + "qcom,default-led-trigger", + &wled->switch_cdev.default_trigger); + if (rc < 0) + wled->switch_cdev.default_trigger = + "wled_switch"; + } else { + return -EINVAL; + } + } + + return 0; +} + +static int wled_flash_setup(struct wled *wled) +{ + int rc, i; + u8 val; + + /* Set FLASH_VREF_ADIM_HDIM to maximum */ + rc = regmap_write(wled->regmap, + wled->ctrl_addr + WLED5_CTRL_FLASH_HDRM_REG, 0xF); + if (rc < 0) + return rc; + + /* Write a full brightness value */ + rc = regmap_write(wled->regmap, + wled->ctrl_addr + WLED5_CTRL_PRE_FLASH_BRT_REG, 0xFF); + if (rc < 0) + return rc; + + /* Sync the brightness by writing a 0 followed by 1 */ + rc = regmap_write(wled->regmap, + wled->ctrl_addr + WLED5_CTRL_PRE_FLASH_SYNC_REG, 0); + if (rc < 0) + return rc; + + rc = regmap_write(wled->regmap, + wled->ctrl_addr + WLED5_CTRL_PRE_FLASH_SYNC_REG, 1); + if (rc < 0) + return rc; + + /* Write a full brightness value */ + rc = regmap_write(wled->regmap, + wled->ctrl_addr + WLED5_CTRL_FLASH_BRT_REG, 0xFF); + if (rc < 0) + return rc; + + /* Sync the brightness by writing a 0 followed by 1 */ + rc = regmap_write(wled->regmap, + wled->ctrl_addr + WLED5_CTRL_FLASH_SYNC_REG, 0); + if (rc < 0) + return rc; + + rc = regmap_write(wled->regmap, + wled->ctrl_addr + WLED5_CTRL_FLASH_SYNC_REG, 1); + if (rc < 0) + return rc; + + for (val = 0, i = 0; (wled->cfg.string_cfg >> i) != 0; i++) { + if (wled->cfg.string_cfg & BIT(i)) { + val |= 1 << (i + WLED_SINK_CURR_SINK_SHFT); + wled->num_strings++; + } + } + + /* Enable current sinks for flash */ + rc = regmap_update_bits(wled->regmap, + wled->sink_addr + WLED5_SINK_FLASH_SINK_EN_REG, + WLED_SINK_CURR_SINK_MASK, val); + if (rc < 0) + return rc; + + /* Enable flash and pre_flash safety timers */ + val = get_wled_safety_time(wled->tparams.safety_timer) << + WLED5_PRE_FLASH_SAFETY_SHIFT; + val |= get_wled_safety_time(wled->fparams.safety_timer); + rc = regmap_write(wled->regmap, + wled->sink_addr + WLED5_SINK_FLASH_TIMER_CTL_REG, val); + if (rc < 0) + return rc; + + return 0; +} + +static int wled_configure(struct wled *wled, struct device *dev) +{ + struct wled_config *cfg = &wled->cfg; + struct device_node *revid_node; + const __be32 *prop_addr; + u32 val, c; + int rc, i, j, size; + struct wled_u32_opts { + const char *name; + u32 *val_ptr; + const struct wled_var_cfg *cfg; + }; + + const struct wled_u32_opts *u32_opts; + const struct wled_u32_opts wled4_opts[] = { + { + .name = "qcom,boost-current-limit", + .val_ptr = &cfg->boost_i_limit, + .cfg = &wled4_boost_i_limit_cfg, + }, + { + .name = "qcom,fs-current-limit", + .val_ptr = &cfg->fs_current, + .cfg = &wled_fs_current_cfg, + }, + { + .name = "qcom,ovp", + .val_ptr = &cfg->ovp, + .cfg = &wled4_ovp_cfg, + }, + { + .name = "qcom,switching-freq", + .val_ptr = &cfg->switch_freq, + .cfg = &wled_switch_freq_cfg, + }, + { + .name = "qcom,string-cfg", + .val_ptr = &cfg->string_cfg, + .cfg = &wled_string_cfg, + }, + }; + + const struct wled_u32_opts wled5_opts[] = { + { + .name = "qcom,boost-current-limit", + .val_ptr = &cfg->boost_i_limit, + .cfg = &wled5_boost_i_limit_cfg, + }, + { + .name = "qcom,fs-current-limit", + .val_ptr = &cfg->fs_current, + .cfg = &wled_fs_current_cfg, + }, + { + .name = "qcom,ovp", + .val_ptr = &cfg->ovp, + .cfg = &wled5_ovp_cfg, + }, + { + .name = "qcom,switching-freq", + .val_ptr = &cfg->switch_freq, + .cfg = &wled_switch_freq_cfg, + }, + { + .name = "qcom,string-cfg", + .val_ptr = &cfg->string_cfg, + .cfg = &wled_string_cfg, + }, + { + .name = "qcom,modulator-sel", + .val_ptr = &cfg->mod_sel, + .cfg = &wled5_mod_sel_cfg, + }, + { + .name = "qcom,cabc-sel", + .val_ptr = &cfg->cabc_sel, + .cfg = &wled5_cabc_sel_cfg, + }, + }; + + const struct { + const char *name; + bool *val_ptr; + } bool_opts[] = { + { "qcom,en-cabc", &cfg->en_cabc, }, + { "qcom,ext-pfet-sc-pro", &cfg->ext_pfet_sc_pro_en, }, + { "qcom,auto-calibration", &cfg->auto_calib_enabled, }, + }; + + prop_addr = of_get_address(dev->of_node, 0, NULL, NULL); + if (!prop_addr) { + pr_err("invalid IO resources\n"); + return -EINVAL; + } + wled->ctrl_addr = be32_to_cpu(*prop_addr); + + prop_addr = of_get_address(dev->of_node, 1, NULL, NULL); + if (!prop_addr) { + pr_err("invalid IO resources\n"); + return -EINVAL; + } + wled->sink_addr = be32_to_cpu(*prop_addr); + rc = of_property_read_string(dev->of_node, "label", &wled->name); + if (rc < 0) + wled->name = dev->of_node->name; + + if (of_find_property(dev->of_node, "qcom,pmic-revid", NULL)) { + revid_node = of_parse_phandle(dev->of_node, "qcom,pmic-revid", + 0); + if (!revid_node) { + pr_err("Error in getting revid_node\n"); + return -EINVAL; + } + + wled->pmic_rev_id = get_revid_data(revid_node); + of_node_put(revid_node); + if (IS_ERR_OR_NULL(wled->pmic_rev_id)) { + pr_err("Unable to get pmic_revid rc=%ld\n", + PTR_ERR(wled->pmic_rev_id)); + wled->pmic_rev_id = NULL; + return -EPROBE_DEFER; + } + } + + if (is_wled5(wled)) { + u32_opts = wled5_opts; + size = ARRAY_SIZE(wled5_opts); + *cfg = wled5_config_defaults; + wled->cabc_config = wled5_cabc_config; + } else if (is_wled4(wled)) { + u32_opts = wled4_opts; + size = ARRAY_SIZE(wled4_opts); + *cfg = wled4_config_defaults; + wled->cabc_config = wled4_cabc_config; + } else { + pr_err("Unknown WLED version %d\n", *wled->version); + return -EINVAL; + } + + for (i = 0; i < size; ++i) { + rc = of_property_read_u32(dev->of_node, u32_opts[i].name, &val); + if (rc == -EINVAL) { + continue; + } else if (rc < 0) { + pr_err("error reading '%s'\n", u32_opts[i].name); + return rc; + } + + c = UINT_MAX; + for (j = 0; c != val; j++) { + c = wled_values(u32_opts[i].cfg, j); + if (c == UINT_MAX) { + pr_err("invalid value for '%s'\n", + u32_opts[i].name); + return -EINVAL; + } + + if (c == val) + break; + } + + pr_debug("'%s' = %u\n", u32_opts[i].name, c); + *u32_opts[i].val_ptr = j; + } + + for (i = 0; i < ARRAY_SIZE(bool_opts); ++i) { + if (of_property_read_bool(dev->of_node, bool_opts[i].name)) + *bool_opts[i].val_ptr = true; + } + + wled->sc_irq = platform_get_irq_byname(wled->pdev, "sc-irq"); + if (wled->sc_irq < 0) + dev_dbg(&wled->pdev->dev, "sc irq is not used\n"); + + wled->ovp_irq = platform_get_irq_byname(wled->pdev, "ovp-irq"); + if (wled->ovp_irq < 0) + dev_dbg(&wled->pdev->dev, "ovp irq is not used\n"); + + wled->flash_irq = platform_get_irq_byname(wled->pdev, "flash-irq"); + if (wled->flash_irq < 0) + dev_dbg(&wled->pdev->dev, "flash irq is not used\n"); + + wled->pre_flash_irq = platform_get_irq_byname(wled->pdev, + "pre-flash-irq"); + if (wled->pre_flash_irq < 0) + dev_dbg(&wled->pdev->dev, "pre_flash irq is not used\n"); + + return 0; +} + +static const struct backlight_ops wled_ops = { + .update_status = wled_update_status, + .get_brightness = wled_get_brightness, +}; + +static int wled_probe(struct platform_device *pdev) +{ + struct backlight_properties props; + struct backlight_device *bl; + struct wled *wled; + struct regmap *regmap; + u32 val; + int rc; + + regmap = dev_get_regmap(pdev->dev.parent, NULL); + if (!regmap) { + pr_err("Unable to get regmap\n"); + return -EINVAL; + } + + wled = devm_kzalloc(&pdev->dev, sizeof(*wled), GFP_KERNEL); + if (!wled) + return -ENOMEM; + + wled->regmap = regmap; + wled->pdev = pdev; + + wled->version = of_device_get_match_data(&pdev->dev); + if (!wled->version) { + dev_err(&pdev->dev, "Unknown device version\n"); + return -ENODEV; + } + + rc = wled_configure(wled, &pdev->dev); + if (rc < 0) { + dev_err(&pdev->dev, "wled configure failed rc:%d\n", rc); + return rc; + } + + rc = wled_flash_configure(wled); + if (rc < 0) { + dev_err(&pdev->dev, "wled configure failed rc:%d\n", rc); + return rc; + } + + mutex_init(&wled->lock); + + val = WLED_DEFAULT_BRIGHTNESS; + of_property_read_u32(pdev->dev.of_node, "default-brightness", &val); + wled->brightness = val; + + val = WLED_MAX_BRIGHTNESS_12B; + of_property_read_u32(pdev->dev.of_node, "max-brightness", &val); + wled->max_brightness = val; + + /* For WLED5, when CABC is enabled, max brightness is 4095. */ + if (is_wled5(wled) && wled->cfg.cabc_sel) + wled->max_brightness = WLED_MAX_BRIGHTNESS_12B; + + /* + * As per the hardware recommendation, FS current should + * be limited to 20 mA for PM8150L v1.0. + */ + if (wled->pmic_rev_id->rev4 == PM8150L_V1P0_REV4 && + wled->cfg.fs_current > 8) + wled->cfg.fs_current = 8; + + if (is_wled4(wled)) + rc = wled4_setup(wled); + else + rc = wled5_setup(wled); + if (rc < 0) { + dev_err(&pdev->dev, "wled setup failed rc:%d\n", rc); + return rc; + } + + platform_set_drvdata(pdev, wled); + + memset(&props, 0, sizeof(struct backlight_properties)); + props.type = BACKLIGHT_RAW; + props.brightness = val; + props.max_brightness = wled->max_brightness; + bl = devm_backlight_device_register(&pdev->dev, wled->name, + &pdev->dev, wled, + &wled_ops, &props); + if (IS_ERR_OR_NULL(bl)) { + rc = PTR_ERR_OR_ZERO(bl); + if (!rc) + rc = -ENODEV; + dev_err(&pdev->dev, "failed to register backlight rc:%d\n", rc); + return rc; + } + + rc = wled_flash_device_register(wled); + if (rc < 0) { + dev_err(&pdev->dev, "failed to register WLED flash/torch rc:%d\n", + rc); + return rc; + } + + return rc; +} + +static const struct of_device_id wled_match_table[] = { + { .compatible = "qcom,pmi8998-spmi-wled", .data = &version_table[0] }, + { .compatible = "qcom,pm8150l-spmi-wled", .data = &version_table[2] }, + { .compatible = "qcom,pm6150l-spmi-wled", .data = &version_table[2] }, + { .compatible = "qcom,pm660l-spmi-wled", .data = &version_table[1] }, + { }, +}; + +static struct platform_driver wled_driver = { + .probe = wled_probe, + .driver = { + .name = "qcom-spmi-wled", + .of_match_table = wled_match_table, + }, +}; + +module_platform_driver(wled_driver); + +MODULE_DESCRIPTION("Qualcomm Technologies, Inc. SPMI PMIC WLED driver"); +MODULE_LICENSE("GPL v2"); From 42a7e98e69f1b619ca7dabe93dc458e1088d6976 Mon Sep 17 00:00:00 2001 From: Jishnu Prakash Date: Mon, 31 Aug 2020 12:20:54 +0530 Subject: [PATCH 027/698] backlight: qcom-spmi-wled: Convert power_supply properties to iio Convert "bms" power_supply properties to iio channels. Also remove the revid support and workarounds for PM8150l V1.0 and identify the pmic type based on the driver match data. Change-Id: I4074d33e15f7df44e628291dca25c056877ba664 Signed-off-by: Jishnu Prakash --- drivers/video/backlight/qcom-spmi-wled.c | 155 +++++++++++++---------- include/linux/leds-qpnp-flash.h | 2 +- 2 files changed, 89 insertions(+), 68 deletions(-) diff --git a/drivers/video/backlight/qcom-spmi-wled.c b/drivers/video/backlight/qcom-spmi-wled.c index 89d19a7b09d9..bd6c7eb40767 100644 --- a/drivers/video/backlight/qcom-spmi-wled.c +++ b/drivers/video/backlight/qcom-spmi-wled.c @@ -18,11 +18,10 @@ #include #include #include -#include #include #include -#include #include +#include #include "../../leds/leds.h" /* General definitions */ @@ -33,6 +32,8 @@ #define WLED_SOFT_START_DLY_US 10000 /* WLED control registers */ +#define WLED_CTRL_REVISION2 0x01 + #define WLED_CTRL_FAULT_STATUS 0x08 #define WLED_CTRL_ILIM_FAULT_BIT BIT(0) #define WLED_CTRL_OVP_FAULT_BIT BIT(1) @@ -216,8 +217,7 @@ struct wled { const char *name; struct platform_device *pdev; struct regmap *regmap; - struct pmic_revid_data *pmic_rev_id; - struct power_supply *bms_psy; + struct iio_channel **iio_channels; struct mutex lock; struct wled_config cfg; ktime_t last_sc_event_time; @@ -228,6 +228,7 @@ struct wled { u32 brightness; u32 max_brightness; u32 sc_count; + u32 rev2; const int *version; int sc_irq; int ovp_irq; @@ -272,6 +273,18 @@ static const u8 wled5_brt_wid_sel_reg[MOD_MAX] = { [MOD_B] = WLED5_SINK_MOD_B_BR_WID_SEL_REG, }; +enum wled_iio_props { + RBATT, + OCV, + IBAT, +}; + +static const char *const wled_iio_prop_names[] = { + [RBATT] = "rbatt", + [OCV] = "voltage_ocv", + [IBAT] = "current_now", +}; + static int wled_flash_setup(struct wled *wled); static inline bool is_wled4(struct wled *wled) @@ -379,7 +392,7 @@ static int wled5_sample_hold_control(struct wled *wled, u16 brightness, usleep_range(5000, 5010); /* Disable S_H if brightness is < 1% */ - if (wled->pmic_rev_id->rev4 == PM8150L_V3P0_REV4) { + if (wled->rev2 >= 6) { offset = WLED5_CTRL_SH_FOR_SOFTSTART_REG; val = enable ? WLED5_SOFTSTART_EN_SH_SS : 0; mask = WLED5_SOFTSTART_EN_SH_SS; @@ -1470,26 +1483,49 @@ static int wled_get_max_current(struct led_classdev *led_cdev, return 0; } -static int get_property_from_fg(struct wled *wled, - enum power_supply_property prop, int *val) +static int wled_get_iio_chan(struct wled *wled, + enum wled_iio_props chan) { - int rc; - union power_supply_propval pval = {0, }; + int rc = 0; - if (!wled->bms_psy) - wled->bms_psy = power_supply_get_by_name("bms"); + /* + * if the channel pointer is not-NULL and has a ERR value it has + * already been queried upon earlier, hence return from here. + */ + if (IS_ERR(wled->iio_channels[chan])) + return -EINVAL; - if (!wled->bms_psy) - return -ENODEV; - - rc = power_supply_get_property(wled->bms_psy, prop, &pval); - if (rc < 0) { - pr_err("bms psy doesn't support reading prop %d rc = %d\n", - prop, rc); - return rc; + if (!wled->iio_channels[chan]) { + wled->iio_channels[chan] = iio_channel_get(&wled->pdev->dev, + wled_iio_prop_names[chan]); + if (IS_ERR(wled->iio_channels[chan])) { + rc = PTR_ERR(wled->iio_channels[chan]); + if (rc == -EPROBE_DEFER) { + wled->iio_channels[chan] = NULL; + return rc; + } + pr_err("%s channel unavailable %d\n", + wled_iio_prop_names[chan], rc); + return rc; + } } - *val = pval.intval; + return 0; +} + +static int wled_iio_get_prop(struct wled *wled, + enum wled_iio_props chan, int *data) +{ + int rc = 0; + + rc = wled_get_iio_chan(wled, chan); + if (rc < 0) + return rc; + + rc = iio_read_channel_processed(wled->iio_channels[chan], data); + if (rc < 0) + pr_err("Error in reading IIO channel data rc = %d\n", rc); + return rc; } @@ -1519,23 +1555,21 @@ static int wled_get_max_avail_current(struct led_classdev *led_cdev, return 0; } - rc = get_property_from_fg(wled, POWER_SUPPLY_PROP_VOLTAGE_OCV, &ocv_mv); + rc = wled_iio_get_prop(wled, OCV, &ocv_mv); if (rc < 0) { pr_err("Error in getting OCV rc=%d\n", rc); return rc; } ocv_mv /= 1000; - rc = get_property_from_fg(wled, POWER_SUPPLY_PROP_CURRENT_NOW, - &i_bat_ma); + rc = wled_iio_get_prop(wled, IBAT, &i_bat_ma); if (rc < 0) { pr_err("Error in getting I_BAT rc=%d\n", rc); return rc; } i_bat_ma /= 1000; - rc = get_property_from_fg(wled, POWER_SUPPLY_PROP_RESISTANCE, - &r_bat_mohms); + rc = wled_iio_get_prop(wled, RBATT, &r_bat_mohms); if (rc < 0) { pr_err("Error in getting R_BAT rc=%d\n", rc); return rc; @@ -1614,6 +1648,22 @@ static struct device_attribute wled_flash_attrs[] = { NULL), }; +static struct led_classdev *trigger_to_lcdev(struct led_trigger *trig) +{ + struct led_classdev *led_cdev; + + read_lock(&trig->leddev_list_lock); + list_for_each_entry(led_cdev, &trig->led_cdevs, trig_list) { + if (!strcmp(led_cdev->default_trigger, trig->name)) { + read_unlock(&trig->leddev_list_lock); + return led_cdev; + } + } + + read_unlock(&trig->leddev_list_lock); + return NULL; +} + int wled_flash_led_prepare(struct led_trigger *trig, int options, int *max_current) { @@ -1840,7 +1890,6 @@ static int wled_flash_device_register(struct wled *wled) /* switch */ wled->switch_cdev.name = "wled_switch"; wled->switch_cdev.brightness_set = wled_switch_brightness_set; - wled->switch_cdev.flags |= LED_KEEP_TRIGGER; rc = devm_led_classdev_register(&wled->pdev->dev, &wled->switch_cdev); if (rc < 0) return rc; @@ -1897,13 +1946,6 @@ static int wled_flash_configure(struct wled *wled) } } - /* - * As per the hardware recommendation, FS current should - * be limited to 20 mA for PM8150L v1.0. - */ - if (wled->pmic_rev_id->rev4 == PM8150L_V1P0_REV4) - wled->fparams.fs_current = 20; - /* Value read in us */ wled->fparams.step_delay = 200; rc = of_property_read_u32(temp, "qcom,wled-flash-step", @@ -1949,13 +1991,6 @@ static int wled_flash_configure(struct wled *wled) } } - /* - * As per the hardware recommendation, FS current should - * be limited to 20 mA for PM8150L v1.0. - */ - if (wled->pmic_rev_id->rev4 == PM8150L_V1P0_REV4) - wled->tparams.fs_current = 20; - /* Value read in us */ wled->tparams.step_delay = 200; rc = of_property_read_u32(temp, "qcom,wled-torch-step", @@ -2076,7 +2111,6 @@ static int wled_flash_setup(struct wled *wled) static int wled_configure(struct wled *wled, struct device *dev) { struct wled_config *cfg = &wled->cfg; - struct device_node *revid_node; const __be32 *prop_addr; u32 val, c; int rc, i, j, size; @@ -2169,6 +2203,13 @@ static int wled_configure(struct wled *wled, struct device *dev) } wled->ctrl_addr = be32_to_cpu(*prop_addr); + rc = regmap_read(wled->regmap, + wled->ctrl_addr + WLED_CTRL_REVISION2, &wled->rev2); + if (rc < 0) { + pr_err("Error in reading WLED_CTRL_REVISION2 rc=%d\n", rc); + return -EINVAL; + } + prop_addr = of_get_address(dev->of_node, 1, NULL, NULL); if (!prop_addr) { pr_err("invalid IO resources\n"); @@ -2179,24 +2220,6 @@ static int wled_configure(struct wled *wled, struct device *dev) if (rc < 0) wled->name = dev->of_node->name; - if (of_find_property(dev->of_node, "qcom,pmic-revid", NULL)) { - revid_node = of_parse_phandle(dev->of_node, "qcom,pmic-revid", - 0); - if (!revid_node) { - pr_err("Error in getting revid_node\n"); - return -EINVAL; - } - - wled->pmic_rev_id = get_revid_data(revid_node); - of_node_put(revid_node); - if (IS_ERR_OR_NULL(wled->pmic_rev_id)) { - pr_err("Unable to get pmic_revid rc=%ld\n", - PTR_ERR(wled->pmic_rev_id)); - wled->pmic_rev_id = NULL; - return -EPROBE_DEFER; - } - } - if (is_wled5(wled)) { u32_opts = wled5_opts; size = ARRAY_SIZE(wled5_opts); @@ -2322,14 +2345,6 @@ static int wled_probe(struct platform_device *pdev) if (is_wled5(wled) && wled->cfg.cabc_sel) wled->max_brightness = WLED_MAX_BRIGHTNESS_12B; - /* - * As per the hardware recommendation, FS current should - * be limited to 20 mA for PM8150L v1.0. - */ - if (wled->pmic_rev_id->rev4 == PM8150L_V1P0_REV4 && - wled->cfg.fs_current > 8) - wled->cfg.fs_current = 8; - if (is_wled4(wled)) rc = wled4_setup(wled); else @@ -2363,6 +2378,12 @@ static int wled_probe(struct platform_device *pdev) return rc; } + wled->iio_channels = devm_kcalloc(&pdev->dev, + ARRAY_SIZE(wled_iio_prop_names), + sizeof(struct iio_channel *), GFP_KERNEL); + if (!wled->iio_channels) + return -ENOMEM; + return rc; } diff --git a/include/linux/leds-qpnp-flash.h b/include/linux/leds-qpnp-flash.h index 0894efe63377..d351a56998ec 100644 --- a/include/linux/leds-qpnp-flash.h +++ b/include/linux/leds-qpnp-flash.h @@ -28,7 +28,7 @@ static inline int qpnp_flash_led_prepare(struct led_trigger *trig, int options, } #endif -#ifdef CONFIG_BACKLIGHT_QCOM_SPMI_WLED +#if IS_ENABLED(CONFIG_BACKLIGHT_QCOM_SPMI_WLED) int wled_flash_led_prepare(struct led_trigger *trig, int options, int *max_current); #else From c67502f32cca2ea6ba340dd83644414d308b88d0 Mon Sep 17 00:00:00 2001 From: Jishnu Prakash Date: Mon, 31 Aug 2020 12:28:58 +0530 Subject: [PATCH 028/698] arm64: defconfig: Enable QCOM_SPMI_WLED driver for holi Enable QCOM_SPMI_WLED driver for holi, needed for targets using LCD display. Change-Id: Icc5e3f12959c0689408bd33806e343917e8ef0e9 Signed-off-by: Jishnu Prakash --- arch/arm64/configs/vendor/holi_GKI.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/vendor/holi_GKI.config b/arch/arm64/configs/vendor/holi_GKI.config index cd791f87e827..35cc29c04666 100644 --- a/arch/arm64/configs/vendor/holi_GKI.config +++ b/arch/arm64/configs/vendor/holi_GKI.config @@ -200,3 +200,4 @@ CONFIG_QPNP_SMB5=m CONFIG_USB_PD_POLICY=m CONFIG_QPNP_USB_PDPHY=m CONFIG_INCREMENTAL_FS=y +CONFIG_BACKLIGHT_QCOM_SPMI_WLED=m From e2e0afcbb8965b1696894c355591ec9c9f0331a2 Mon Sep 17 00:00:00 2001 From: Ashish Bhimanpalliwar Date: Tue, 1 Sep 2020 22:26:01 +0530 Subject: [PATCH 029/698] arm64: defconfig: Enable CONFIG_QCOM_QFPROM_SYSFS on Holi Enable CONFIG_QCOM_QFPROM_SYSFS on Holi, so that feature config nodes etc. can be accessed from userspace and at the same time disabled CONFIG_NVMEM_SYSFS to avoid exposing full QFPROM region to user-space. Change-Id: I76910f10e61d0fdf20a6f94dc086aa801bd1d108 Signed-off-by: Ashish Bhimanpalliwar --- arch/arm64/configs/vendor/holi_QGKI.config | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/configs/vendor/holi_QGKI.config b/arch/arm64/configs/vendor/holi_QGKI.config index 26b0f0c8e1cf..c0378072e3e8 100644 --- a/arch/arm64/configs/vendor/holi_QGKI.config +++ b/arch/arm64/configs/vendor/holi_QGKI.config @@ -163,3 +163,5 @@ CONFIG_NETFILTER_XT_MATCH_DSCP=y CONFIG_NETFILTER_XT_MATCH_ESP=y CONFIG_NET_SCH_PRIO=y CONFIG_NET_CLS_FW=y +CONFIG_QCOM_QFPROM_SYSFS=y +# CONFIG_NVMEM_SYSFS is not set From dde7b3b4f36e0c18bb3c9171c7d5ef8c9f145a3e Mon Sep 17 00:00:00 2001 From: Mukesh Ojha Date: Fri, 28 Aug 2020 13:39:57 +0530 Subject: [PATCH 030/698] arm64: defconfig: Enable CONFIG_QCOM_QFPROM_SYSFS on Lahaina/Shima Enable CONFIG_QCOM_QFPROM_SYSFS on Lahaina/Shima, so that feature config nodes etc. can be accessed from userspace and at the same time disabled CONFIG_NVMEM_SYSFS to avoid exposing full QFPROM region to user-space. Change-Id: I43dd4f6f368d07d0a5047c3732065efe4200b3b3 Signed-off-by: Mukesh Ojha --- arch/arm64/configs/vendor/lahaina_QGKI.config | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/configs/vendor/lahaina_QGKI.config b/arch/arm64/configs/vendor/lahaina_QGKI.config index 3abf9748f2c9..36083864ec7e 100644 --- a/arch/arm64/configs/vendor/lahaina_QGKI.config +++ b/arch/arm64/configs/vendor/lahaina_QGKI.config @@ -231,3 +231,5 @@ CONFIG_MEDIA_RADIO_SUPPORT=y # CONFIG_RADIO_WL1273 is not set # CONFIG_INTERCONNECT_TEST is not set # CONFIG_BT_HCIUART is not set +CONFIG_QCOM_QFPROM_SYSFS=y +# CONFIG_NVMEM_SYSFS is not set From a4f7d02f035a0a7eda11123edad4bbd7f5f8e38b Mon Sep 17 00:00:00 2001 From: Jagadeesh Kona Date: Mon, 22 Jun 2020 20:06:28 +0530 Subject: [PATCH 031/698] arm64: defconfig: Enable cpufreq hw debug for HOLI and SHIMA Enable cpufreq hw debug support for HOLI and SHIMA. Change-Id: I62b3404b918a738addeada83a1069712c55ebc21 Signed-off-by: Jagadeesh Kona --- arch/arm64/configs/vendor/holi_QGKI.config | 1 + arch/arm64/configs/vendor/lahaina_QGKI.config | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/arm64/configs/vendor/holi_QGKI.config b/arch/arm64/configs/vendor/holi_QGKI.config index c0378072e3e8..9f70404b067e 100644 --- a/arch/arm64/configs/vendor/holi_QGKI.config +++ b/arch/arm64/configs/vendor/holi_QGKI.config @@ -165,3 +165,4 @@ CONFIG_NET_SCH_PRIO=y CONFIG_NET_CLS_FW=y CONFIG_QCOM_QFPROM_SYSFS=y # CONFIG_NVMEM_SYSFS is not set +CONFIG_ARM_QCOM_CPUFREQ_HW_DEBUG=y diff --git a/arch/arm64/configs/vendor/lahaina_QGKI.config b/arch/arm64/configs/vendor/lahaina_QGKI.config index 36083864ec7e..2eadadf43f7b 100644 --- a/arch/arm64/configs/vendor/lahaina_QGKI.config +++ b/arch/arm64/configs/vendor/lahaina_QGKI.config @@ -233,3 +233,4 @@ CONFIG_MEDIA_RADIO_SUPPORT=y # CONFIG_BT_HCIUART is not set CONFIG_QCOM_QFPROM_SYSFS=y # CONFIG_NVMEM_SYSFS is not set +CONFIG_ARM_QCOM_CPUFREQ_HW_DEBUG=y From ba97a7a9da64391d4edf18c5db245d0c6733b613 Mon Sep 17 00:00:00 2001 From: Odelu Kukatla Date: Mon, 17 Aug 2020 19:09:13 +0530 Subject: [PATCH 032/698] arm64: defconfig: Enable L3 interconnect driver for Holi Enable L3 interconnect driver so that consumers are able to obtain their path handles properly. Change-Id: I92b407621e6c65563e5e88b63cf6b776329657cb Signed-off-by: Odelu Kukatla --- arch/arm64/configs/vendor/holi_GKI.config | 2 +- arch/arm64/configs/vendor/holi_QGKI.config | 1 + arch/arm64/configs/vendor/holi_debug.config | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/arm64/configs/vendor/holi_GKI.config b/arch/arm64/configs/vendor/holi_GKI.config index 35cc29c04666..957c4b60dd34 100644 --- a/arch/arm64/configs/vendor/holi_GKI.config +++ b/arch/arm64/configs/vendor/holi_GKI.config @@ -94,7 +94,6 @@ CONFIG_QCOM_CLK_RPMH=m CONFIG_QCOM_LAZY_MAPPING=m CONFIG_MFD_SPMI_PMIC=m CONFIG_PWM_QTI_LPG=m -CONFIG_INTERCONNECT_QCOM_EPSS_L3=m CONFIG_LEDS_QTI_TRI_LED=m CONFIG_MSM_SPCOM=m CONFIG_MSM_ADSPRPC=m @@ -201,3 +200,4 @@ CONFIG_USB_PD_POLICY=m CONFIG_QPNP_USB_PDPHY=m CONFIG_INCREMENTAL_FS=y CONFIG_BACKLIGHT_QCOM_SPMI_WLED=m +CONFIG_INTERCONNECT_QCOM_CPUCP_L3=m diff --git a/arch/arm64/configs/vendor/holi_QGKI.config b/arch/arm64/configs/vendor/holi_QGKI.config index 9f70404b067e..822ffab2ecc4 100644 --- a/arch/arm64/configs/vendor/holi_QGKI.config +++ b/arch/arm64/configs/vendor/holi_QGKI.config @@ -166,3 +166,4 @@ CONFIG_NET_CLS_FW=y CONFIG_QCOM_QFPROM_SYSFS=y # CONFIG_NVMEM_SYSFS is not set CONFIG_ARM_QCOM_CPUFREQ_HW_DEBUG=y +CONFIG_INTERCONNECT_QCOM_CPUCP_L3=y diff --git a/arch/arm64/configs/vendor/holi_debug.config b/arch/arm64/configs/vendor/holi_debug.config index a8202dc255de..d11865de8349 100644 --- a/arch/arm64/configs/vendor/holi_debug.config +++ b/arch/arm64/configs/vendor/holi_debug.config @@ -122,3 +122,4 @@ CONFIG_PSI_FTRACE=y CONFIG_DEBUG_PREEMPT=y CONFIG_DYNAMIC_DEBUG=y CONFIG_PANIC_ON_DATA_CORRUPTION=y +CONFIG_INTERCONNECT_QCOM_CPUCP_L3=y From dd391843d4a651fefb498aaf43b83d38f8fb97ee Mon Sep 17 00:00:00 2001 From: Ashish Bhimanpalliwar Date: Thu, 3 Sep 2020 15:40:22 +0530 Subject: [PATCH 033/698] arm64: defconfig: Enable configs related to Watchdog in Holi Enable few watchdog related configs which are missing in Holi. Change-Id: I9e42cf4996a2958e5503fd70a0b5d8fc2d3d7cdd Signed-off-by: Ashish Bhimanpalliwar --- arch/arm64/configs/vendor/holi_GKI.config | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/configs/vendor/holi_GKI.config b/arch/arm64/configs/vendor/holi_GKI.config index 957c4b60dd34..2775767d7012 100644 --- a/arch/arm64/configs/vendor/holi_GKI.config +++ b/arch/arm64/configs/vendor/holi_GKI.config @@ -201,3 +201,5 @@ CONFIG_QPNP_USB_PDPHY=m CONFIG_INCREMENTAL_FS=y CONFIG_BACKLIGHT_QCOM_SPMI_WLED=m CONFIG_INTERCONNECT_QCOM_CPUCP_L3=m +CONFIG_QCOM_WDT_CORE=m +CONFIG_QCOM_SOC_WATCHDOG=m From e79f6fe6e92b8c1f3b8f07f87a3a55f7d47e3958 Mon Sep 17 00:00:00 2001 From: Ashish Bhimanpalliwar Date: Mon, 31 Aug 2020 12:22:38 +0530 Subject: [PATCH 034/698] arm64: defconfig: Enable misc config for debugging for Holi CONFIG_PM_DEBUG=y CONFIG_DEBUG_RWSEMS=y CONFIG_WQ_WATCHDOG=y CONFIG_LOCK_STAT=y Enable above for debug builds on Holi, to help debugging issues related to lock(mutex,rwsem), workqueue lockup etc. Change-Id: Id0a57ba8d9c64d01efa9c7192a2f7a73fdc8659b Signed-off-by: Ashish Bhimanpalliwar --- arch/arm64/configs/vendor/holi_debug.config | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm64/configs/vendor/holi_debug.config b/arch/arm64/configs/vendor/holi_debug.config index d11865de8349..7f9ec45e14e0 100644 --- a/arch/arm64/configs/vendor/holi_debug.config +++ b/arch/arm64/configs/vendor/holi_debug.config @@ -123,3 +123,7 @@ CONFIG_DEBUG_PREEMPT=y CONFIG_DYNAMIC_DEBUG=y CONFIG_PANIC_ON_DATA_CORRUPTION=y CONFIG_INTERCONNECT_QCOM_CPUCP_L3=y +CONFIG_PM_DEBUG=y +CONFIG_DEBUG_RWSEMS=y +CONFIG_WQ_WATCHDOG=y +CONFIG_LOCK_STAT=y From 1453a80ff0a03aa273a206fff57c24bf5bbd3a97 Mon Sep 17 00:00:00 2001 From: Pradeep P V K Date: Mon, 14 Sep 2020 12:57:53 +0530 Subject: [PATCH 035/698] block: Fix use-after-free issue while accessing ioscheduler lock Observes below crash while accessing (use-after-free) lock member of bfq data. context#1 context#2 process_one_work() kthread() blk_mq_run_work_fn() worker_thread() ->__blk_mq_run_hw_queue() process_one_work() ->blk_mq_sched_dispatch_requests() __blk_release_queue() ->blk_mq_do_dispatch_sched() ->__elevator_exit() ->blk_mq_exit_sched() ->exit_sched() ->kfree() ->bfq_dispatch_request() ->spin_unlock_irq(&bfqd->lock) This is because of the kblockd delayed work that might got scheduled around blk_release_queue() and accessed use-after-free member of bfq_data. 240.212359: <2> Unable to handle kernel paging request at virtual address ffffffee2e33ad70 ... 240.212637: <2> Workqueue: kblockd blk_mq_run_work_fn 240.212649: <2> pstate: 00c00085 (nzcv daIf +PAN +UAO) 240.212666: <2> pc : queued_spin_lock_slowpath+0x10c/0x2e0 240.212677: <2> lr : queued_spin_lock_slowpath+0x84/0x2e0 ... Call trace: 240.212865: <2> queued_spin_lock_slowpath+0x10c/0x2e0 240.212876: <2> do_raw_spin_lock+0xf0/0xf4 240.212890: <2> _raw_spin_lock_irq+0x74/0x94 240.212906: <2> bfq_dispatch_request+0x4c/0xd60 240.212918: <2> blk_mq_do_dispatch_sched+0xe0/0x1f0 240.212927: <2> blk_mq_sched_dispatch_requests+0x130/0x194 240.212940: <2> __blk_mq_run_hw_queue+0x100/0x158 240.212950: <2> blk_mq_run_work_fn+0x1c/0x28 240.212963: <2> process_one_work+0x280/0x460 240.212973: <2> worker_thread+0x27c/0x4dc 240.212986: <2> kthread+0x160/0x170 Fix this by cancelling the delayed work if any before elevator exits. Changes since V2: - Retained the code logic and Reviewed-by signoff from V1 Patch as per Ming comments. - Moved the new local variables into queue_is_mq() branch. - Removed 'cancel_delayed_work_sync' from blk_mq_hw_sysfs_release() Changes since V1: - Moved the logic into blk_cleanup_queue() as per Ming comments. Change-Id: If015576983e328aa726bac90a7a8de824d6532f0 Signed-off-by: Pradeep P V K Reviewed-by: Ming Lei Patch-mainline: linux-block@vger.kernel.org @ 16/09/2020, 13:53 Signed-off-by: Pradeep P V K --- block/blk-mq-sysfs.c | 1 - block/blk-sysfs.c | 8 ++++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/block/blk-mq-sysfs.c b/block/blk-mq-sysfs.c index a09ab0c3d074..28c9921c756f 100644 --- a/block/blk-mq-sysfs.c +++ b/block/blk-mq-sysfs.c @@ -36,7 +36,6 @@ static void blk_mq_hw_sysfs_release(struct kobject *kobj) struct blk_mq_hw_ctx *hctx = container_of(kobj, struct blk_mq_hw_ctx, kobj); - cancel_delayed_work_sync(&hctx->run_work); if (hctx->flags & BLK_MQ_F_BLOCKING) cleanup_srcu_struct(hctx->srcu); diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c index 46f5198be017..0bd8ff7b356c 100644 --- a/block/blk-sysfs.c +++ b/block/blk-sysfs.c @@ -891,9 +891,13 @@ static void __blk_release_queue(struct work_struct *work) blk_free_queue_stats(q->stats); - if (queue_is_mq(q)) + if (queue_is_mq(q)) { + struct blk_mq_hw_ctx *hctx; + int i; cancel_delayed_work_sync(&q->requeue_work); - + queue_for_each_hw_ctx(q, hctx, i) + cancel_delayed_work_sync(&hctx->run_work); + } blk_exit_queue(q); blk_queue_free_zone_bitmaps(q); From fb11d3302f9bc8dc55e4ce4bc634c269afeae615 Mon Sep 17 00:00:00 2001 From: Akash Asthana Date: Thu, 10 Sep 2020 12:45:14 +0530 Subject: [PATCH 036/698] i2c-msm-geni: Register suspend_late instead of suspend_noirq While executing suspend_noirq callbacks non-wakeup interrupts are disabled, wake-up interrupts are enabled but their handling is deferred till the completion of suspend_noirq stage. GENI I2C unvote the resources in the suspend_noirq stage. There is no issue wrt managing clk and pinctrl resources at noirq stage however ICC BW voting can't be done at noirq stage. ICC requests are converted to ack based requested for RPM driver, the ack here is nothing but interrupt from IPCC driver and it can't be processed at noirq stage, hence flow is indefinitely stuck in I2C suspend_noirq callback. This is for platforms using IPCC driver and also it is no harm in making this change applicable to all platforms. Change-Id: I9bf95e1dd990acb6ccc96e5a0ed9850de466a598 Signed-off-by: Akash Asthana --- drivers/i2c/busses/i2c-msm-geni.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/i2c/busses/i2c-msm-geni.c b/drivers/i2c/busses/i2c-msm-geni.c index 11345b627f99..ad91cbc45e3e 100644 --- a/drivers/i2c/busses/i2c-msm-geni.c +++ b/drivers/i2c/busses/i2c-msm-geni.c @@ -1359,7 +1359,7 @@ static int geni_i2c_remove(struct platform_device *pdev) return 0; } -static int geni_i2c_resume_noirq(struct device *device) +static int geni_i2c_resume_early(struct device *device) { struct geni_i2c_dev *gi2c = dev_get_drvdata(device); @@ -1448,11 +1448,12 @@ static int geni_i2c_runtime_resume(struct device *dev) return 0; } -static int geni_i2c_suspend_noirq(struct device *device) +static int geni_i2c_suspend_late(struct device *device) { struct geni_i2c_dev *gi2c = dev_get_drvdata(device); int ret; + GENI_SE_DBG(gi2c->ipcl, false, gi2c->dev, "%s\n", __func__); /* Make sure no transactions are pending */ ret = i2c_trylock_bus(&gi2c->adap, I2C_LOCK_SEGMENT); if (!ret) { @@ -1462,7 +1463,7 @@ static int geni_i2c_suspend_noirq(struct device *device) } if (!pm_runtime_status_suspended(device)) { GENI_SE_DBG(gi2c->ipcl, false, gi2c->dev, - "%s\n", __func__); + "%s: Force suspend\n", __func__); geni_i2c_runtime_suspend(device); pm_runtime_disable(device); pm_runtime_set_suspended(device); @@ -1482,15 +1483,15 @@ static int geni_i2c_runtime_resume(struct device *dev) return 0; } -static int geni_i2c_suspend_noirq(struct device *device) +static int geni_i2c_suspend_late(struct device *device) { return 0; } #endif static const struct dev_pm_ops geni_i2c_pm_ops = { - .suspend_noirq = geni_i2c_suspend_noirq, - .resume_noirq = geni_i2c_resume_noirq, + .suspend_late = geni_i2c_suspend_late, + .resume_early = geni_i2c_resume_early, .runtime_suspend = geni_i2c_runtime_suspend, .runtime_resume = geni_i2c_runtime_resume, }; From 6e77b3fbc7e437cec7622c7597666e8a4c3e93d3 Mon Sep 17 00:00:00 2001 From: Santosh Mardi Date: Mon, 28 Sep 2020 21:21:00 +0530 Subject: [PATCH 037/698] drivers: soc: qcom: update rimps memlat while saving pmu counters During hoplug cpu going down path pmu event handles will be freed. If the hotplug path and idle path run in parallel there are chances in idle path that the driver will try to read the PMU counters with freed pointer resulting in a crash. Add NULL pointer check before performing PMU reads. Change-Id: I9b8a4a8dfa63e70e879c3530a878a9c96062872f Signed-off-by: Santosh Mardi --- drivers/soc/qcom/rimps_memlat.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/soc/qcom/rimps_memlat.c b/drivers/soc/qcom/rimps_memlat.c index 78dba2de7939..51e0a3f2973b 100644 --- a/drivers/soc/qcom/rimps_memlat.c +++ b/drivers/soc/qcom/rimps_memlat.c @@ -620,7 +620,8 @@ static void save_cpugrp_pmu_events(struct memlat_cpu_grp *cpu_grp, u8 cpu) for (i = 0; i < NUM_COMMON_EVS; i++) { u8 hw_id = pmu[i].hw_cntr_idx; - if (hw_id == INVALID_PMU_HW_IDX) + if ((hw_id == INVALID_PMU_HW_IDX) || + !cpus_data->common_evs[i]) continue; perf_event_read_local(cpus_data->common_evs[i], &ev_count, NULL, NULL); @@ -639,7 +640,8 @@ static void save_mon_pmu_events(struct memlat_mon *mon, u8 cpu) for (i = 0; i < NUM_MON_EVS; i++) { u8 hw_id = pmu[i].hw_cntr_idx; - if (hw_id == INVALID_PMU_HW_IDX) + if (hw_id == INVALID_PMU_HW_IDX || + !ev_data->mon_evs[i]) continue; perf_event_read_local(ev_data->mon_evs[i], &ev_count, NULL, NULL); @@ -658,6 +660,7 @@ static void free_common_evs(struct memlat_cpu_grp *cpu_grp, cpumask_t *mask) if (!cpus_data->common_evs[i]) continue; perf_event_release_kernel(cpus_data->common_evs[i]); + cpus_data->common_evs[i] = NULL; } } } @@ -674,6 +677,7 @@ static void free_mon_evs(struct memlat_mon *mon, cpumask_t *mask) continue; perf_event_release_kernel(ev_data->mon_evs[i]); + ev_data->mon_evs[i] = NULL; } } } @@ -755,8 +759,12 @@ exit: static int memlat_event_hotplug_coming_up(unsigned int cpu) { - per_cpu(cpu_is_hp, cpu) = false; - return memlat_hp_restart_events(cpu, true); + int ret; + + ret = memlat_hp_restart_events(cpu, true); + if (!ret) + per_cpu(cpu_is_hp, cpu) = false; + return ret; } static int memlat_event_hotplug_going_down(unsigned int cpu) From aa6c052988386132e286b5f128797ce5d20afbf6 Mon Sep 17 00:00:00 2001 From: Kiran Gunda Date: Wed, 30 Sep 2020 12:41:24 +0530 Subject: [PATCH 038/698] power: smb1398: Update adapter_type in the work-queue's context There is mutex deadlock where the adapter_type is read in the context of a call-back from the main-charger driver. Fix it by moving it to the status_change work and using a local variable to hold the type. Change-Id: Id112097f70fbfb13acc368e9787cf6a0c3a1acff Signed-off-by: Kiran Gunda --- drivers/power/supply/qcom/smb1398-charger.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/drivers/power/supply/qcom/smb1398-charger.c b/drivers/power/supply/qcom/smb1398-charger.c index 4ffa5755f685..fd7ed58f152c 100644 --- a/drivers/power/supply/qcom/smb1398-charger.c +++ b/drivers/power/supply/qcom/smb1398-charger.c @@ -345,6 +345,7 @@ struct smb1398_chip { int cp_isns_master; int cp_isns_slave; int cp_ilim; + int adapter_type; bool status_change_running; bool taper_work_running; @@ -1023,17 +1024,13 @@ static void smb1398_toggle_switcher(struct smb1398_chip *chip) #define DEFAULT_HVDCP3_MIN_ICL_UA 1000000 static int smb1398_div2_cp_get_min_icl(struct smb1398_chip *chip) { - int rc, val = 0; + int min_ilim = chip->div2_cp_min_ilim_ua; /* Use max(dt_min_icl, 1A) for HVDCP3 */ - if (!IS_ERR_OR_NULL(chip->smb5_iio_chan_list)) { - rc = cp_read_iio_prop(chip, QPNP_SMB5, REAL_TYPE, &val); - if (rc >= 0 && (val == QTI_POWER_SUPPLY_TYPE_USB_HVDCP_3)) - return max(chip->div2_cp_min_ilim_ua, + if (chip->adapter_type == QTI_POWER_SUPPLY_TYPE_USB_HVDCP_3) + min_ilim = max(chip->div2_cp_min_ilim_ua, DEFAULT_HVDCP3_MIN_ICL_UA); - } - - return chip->div2_cp_min_ilim_ua; + return min_ilim; } static char *div2_cp_get_model_name(struct smb1398_chip *chip) @@ -1615,6 +1612,12 @@ static void smb1398_status_change_work(struct work_struct *work) goto out; } + rc = cp_read_iio_prop(chip, QPNP_SMB5, REAL_TYPE, &chip->adapter_type); + if (rc < 0) { + dev_err(chip->dev, "Couldn't get REAL_TYPE, rc=%d\n", rc); + goto out; + } + rc = cp_read_iio_prop(chip, QPNP_SMB5, SMB_EN_REASON, &val); if (rc < 0) { dev_err(chip->dev, "Couldn't get SMB_EN_REASON failed, rc=%d\n", From be9b73af3408f1b6c3fcff6344c64ceb45b323ec Mon Sep 17 00:00:00 2001 From: Hareesh Gundu Date: Mon, 28 Sep 2020 21:06:01 +0530 Subject: [PATCH 039/698] msm: kgsl: Use readl_poll_timeout() for crashdumper status Crashdumper required sometime to finish all register dumps. Hence add minimum 100msec sleep time before we start polling on crashdumper completion. Use readl_poll_timeout() for crashdumper completion check to reduce AHB traffic. Change-Id: I112466e67760f26e73e7c8a69bf466ce8b8ef09b Signed-off-by: Hareesh Gundu --- drivers/gpu/msm/adreno_a6xx_snapshot.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/msm/adreno_a6xx_snapshot.c b/drivers/gpu/msm/adreno_a6xx_snapshot.c index 4322cc87572d..67b8c43390fc 100644 --- a/drivers/gpu/msm/adreno_a6xx_snapshot.c +++ b/drivers/gpu/msm/adreno_a6xx_snapshot.c @@ -3,6 +3,8 @@ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ +#include + #include "adreno.h" #include "adreno_a6xx.h" #include "adreno_snapshot.h" @@ -1564,8 +1566,8 @@ static size_t a6xx_snapshot_sqe(struct kgsl_device *device, u8 *buf, static void _a6xx_do_crashdump(struct kgsl_device *device) { - unsigned long wait_time; - unsigned int reg = 0; + u32 val = 0; + int ret; crash_dump_valid = false; @@ -1590,19 +1592,21 @@ static void _a6xx_do_crashdump(struct kgsl_device *device) upper_32_bits(a6xx_capturescript->gpuaddr)); kgsl_regwrite(device, A6XX_CP_CRASH_DUMP_CNTL, 1); - wait_time = jiffies + msecs_to_jiffies(CP_CRASH_DUMPER_TIMEOUT); - while (!time_after(jiffies, wait_time)) { - kgsl_regread(device, A6XX_CP_CRASH_DUMP_STATUS, ®); - if (reg & 0x2) - break; - cpu_relax(); - } + /* wait 100 ms before starting the loop */ + schedule_timeout_interruptible(HZ/10); + + /* Read every 10ms for 900ms */ + ret = readl_poll_timeout(device->reg_virt + + (A6XX_CP_CRASH_DUMP_STATUS << 2), + val, val & 0x02, 10000, 900 * 1000); + if (ret) + kgsl_regread(device, A6XX_CP_CRASH_DUMP_STATUS, &val); if (!ADRENO_FEATURE(ADRENO_DEVICE(device), ADRENO_APRIV)) kgsl_regwrite(device, A6XX_CP_MISC_CNTL, 0); - if (!(reg & 0x2)) { - dev_err(device->dev, "Crash dump timed out: 0x%X\n", reg); + if (ret) { + dev_err(device->dev, "Crash dump timed out: 0x%X\n", val); return; } From 349126bed820fa2cd9d639469aae7f1d23a391ff Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Thu, 1 Oct 2020 21:42:28 +0530 Subject: [PATCH 040/698] clk: qcom: gpucc: Update the PLL 2x frequency The GPUCC PLL needs to lock at 2x the RCG frequency, thus update the RCG divider to '2' to lock the PLL at 2x. Change-Id: Iadeb8b03cf10c170efa8b11bf9aadc35f67ce736 Signed-off-by: Taniya Das --- drivers/clk/qcom/gpucc-holi.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/clk/qcom/gpucc-holi.c b/drivers/clk/qcom/gpucc-holi.c index 7621bbaca089..ef05bc2944cc 100644 --- a/drivers/clk/qcom/gpucc-holi.c +++ b/drivers/clk/qcom/gpucc-holi.c @@ -200,13 +200,13 @@ static struct clk_rcg2 gpu_cc_gmu_clk_src = { }; static const struct freq_tbl ftbl_gpu_cc_gx_gfx3d_clk_src[] = { - F(253000000, P_GPU_CC_PLL0_OUT_EVEN, 1, 0, 0), - F(355000000, P_GPU_CC_PLL0_OUT_EVEN, 1, 0, 0), - F(430000000, P_GPU_CC_PLL0_OUT_EVEN, 1, 0, 0), - F(565000000, P_GPU_CC_PLL0_OUT_EVEN, 1, 0, 0), - F(650000000, P_GPU_CC_PLL0_OUT_EVEN, 1, 0, 0), - F(800000000, P_GPU_CC_PLL0_OUT_EVEN, 1, 0, 0), - F(875000000, P_GPU_CC_PLL0_OUT_EVEN, 1, 0, 0), + F(253000000, P_GPU_CC_PLL0_OUT_EVEN, 2, 0, 0), + F(355000000, P_GPU_CC_PLL0_OUT_EVEN, 2, 0, 0), + F(430000000, P_GPU_CC_PLL0_OUT_EVEN, 2, 0, 0), + F(565000000, P_GPU_CC_PLL0_OUT_EVEN, 2, 0, 0), + F(650000000, P_GPU_CC_PLL0_OUT_EVEN, 2, 0, 0), + F(800000000, P_GPU_CC_PLL0_OUT_EVEN, 2, 0, 0), + F(875000000, P_GPU_CC_PLL0_OUT_EVEN, 2, 0, 0), { } }; From f404d3fd128f8f73f6cb20591c51467386ff0f3f Mon Sep 17 00:00:00 2001 From: Sandeep Singh Date: Tue, 6 Oct 2020 19:48:12 +0530 Subject: [PATCH 041/698] icnss: Assign priority for icnss modem notifier callback This change is to ensure that modem notifier callback for icnss2 driver gets called before it gets called for IPA. In one scenerio, wlan driver holds rtnl lock before trying to send WMI message to wlan fw, During same time watchdog bite happened on modem and IPA received modem notifier callback. Here IPA is also trying to hold rtnl lock which is held by wlan driver which never got released as driver is not aware of watchdog bite on modem. In this case icnss driver is not getting modem notifier callback.This change ensures modem notifier gets called for wlan first and rtnl lock held by wlan driver gets released. Change-Id: I9effd300f6b22138baec59a03a9c4bceb87a8130 Signed-off-by: Sandeep Singh --- drivers/soc/qcom/icnss2/main.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/soc/qcom/icnss2/main.c b/drivers/soc/qcom/icnss2/main.c index 5777a1941b61..54f7a9d62d0b 100644 --- a/drivers/soc/qcom/icnss2/main.c +++ b/drivers/soc/qcom/icnss2/main.c @@ -1549,6 +1549,11 @@ static int icnss_modem_ssr_register_notifier(struct icnss_priv *priv) int ret = 0; priv->modem_ssr_nb.notifier_call = icnss_modem_notifier_nb; + /* + * Assign priority of icnss modem notifier callback over IPA + * modem notifier callback which is 0 + */ + priv->modem_ssr_nb.priority = 1; priv->modem_notify_handler = subsys_notif_register_notifier("modem", &priv->modem_ssr_nb); From 84287e6792481907d85d42b11d78a6586de1e734 Mon Sep 17 00:00:00 2001 From: Sarthak Garg Date: Tue, 6 Oct 2020 14:36:51 +0530 Subject: [PATCH 042/698] mmc: core: Avoid mmc_power_off during shutdown/reboot During shutdown/sleep putting vdd-io in LPM mode after sending the Poweroff notify command is leading to OCP. Avoid putting vdd-io in LPM mode during shutdown/sleep. This change is inline with earlier kernels. Change-Id: I08698bc8b4f1c420910747b6374485f6265d553b Signed-off-by: Sarthak Garg --- drivers/mmc/core/mmc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index b975d6d0116f..bddb041a8a0e 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -2041,7 +2041,8 @@ static int _mmc_suspend(struct mmc_host *host, bool is_suspend) err = mmc_deselect_cards(host); if (!err) { - mmc_power_off(host); + if (is_suspend) + mmc_power_off(host); mmc_card_set_suspended(host->card); } out: From 120a15a0f770242c5bff437f6c3e6e163a2903f2 Mon Sep 17 00:00:00 2001 From: Hareesh Gundu Date: Tue, 29 Sep 2020 23:23:45 +0530 Subject: [PATCH 043/698] msm: kgsl: Relinquish CPU during the TLBSTATUS timeout wait Current cpu_relax() in hogging the CPU in TLBSTATUS check. So remove cpu_relax() and use readl_poll_timeout() to avoid CPU hogging long time during TLBSYNC timeout failure. Also reduce wait timeout from 2sec to 1sec. Change-Id: Ic29733528aa99de770d020b0b8b97eea83dd7f98 Signed-off-by: Hareesh Gundu --- drivers/gpu/msm/kgsl_iommu.c | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c index 9e6c0522ddbf..508bd1d39dfa 100644 --- a/drivers/gpu/msm/kgsl_iommu.c +++ b/drivers/gpu/msm/kgsl_iommu.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -130,6 +131,16 @@ static u32 KGSL_IOMMU_GET_CTX_REG(struct kgsl_iommu_context *ctx, u32 offset) return readl_relaxed(addr); } +static inline int KGSL_IOMMU_READ_POLL_TIMEOUT(struct kgsl_iommu_context *ctx, + u32 offset, u32 expected_ret, u32 timeout_ms, u32 mask) +{ + u32 val; + void __iomem *addr = kgsl_iommu_reg(ctx, offset); + + return readl_poll_timeout(addr, val, (val & mask) == expected_ret, + 100, timeout_ms * 1000); +} + static bool kgsl_iommu_is_global_pt(struct kgsl_pagetable *pt) { return (pt->name == KGSL_MMU_GLOBAL_PT || @@ -1783,6 +1794,7 @@ kgsl_iommu_get_current_ttbr0(struct kgsl_mmu *mmu) return val; } +#define KGSL_IOMMU_TLBSYNC_TIMEOUT 1000 /* msec */ /* * kgsl_iommu_set_pt - Change the IOMMU pagetable of the primary context bank * @mmu - Pointer to mmu structure @@ -1799,7 +1811,6 @@ static int kgsl_iommu_set_pt(struct kgsl_mmu *mmu, struct kgsl_pagetable *pt) struct kgsl_iommu_context *ctx = &iommu->user_context; uint64_t ttbr0, temp; unsigned int contextidr; - unsigned long wait_for_flush; /* Not needed if split tables are enabled */ if (kgsl_iommu_split_tables_enabled(mmu)) @@ -1825,22 +1836,17 @@ static int kgsl_iommu_set_pt(struct kgsl_mmu *mmu, struct kgsl_pagetable *pt) mb(); /* * Wait for flush to complete by polling the flush - * status bit of TLBSTATUS register for not more than - * 2 s. After 2s just exit, at that point the SMMU h/w + * status bit of TLBSTATUS register for not more + * than 1sec. After 1sec poll timeout SMMU hardware * may be stuck and will eventually cause GPU to hang * or bring the system down. */ - wait_for_flush = jiffies + msecs_to_jiffies(2000); KGSL_IOMMU_SET_CTX_REG(ctx, KGSL_IOMMU_CTX_TLBSYNC, 0); - while (KGSL_IOMMU_GET_CTX_REG(ctx, KGSL_IOMMU_CTX_TLBSTATUS) & - (KGSL_IOMMU_CTX_TLBSTATUS_SACTIVE)) { - if (time_after(jiffies, wait_for_flush)) { - dev_warn(KGSL_MMU_DEVICE(mmu)->dev, - "Wait limit reached for IOMMU tlb flush\n"); - break; - } - cpu_relax(); - } + if (KGSL_IOMMU_READ_POLL_TIMEOUT(ctx, KGSL_IOMMU_CTX_TLBSTATUS, + 0, KGSL_IOMMU_TLBSYNC_TIMEOUT, + KGSL_IOMMU_CTX_TLBSTATUS_SACTIVE)) + dev_warn(KGSL_MMU_DEVICE(mmu)->dev, + "Wait limit reached for IOMMU tlb flush\n"); kgsl_iommu_disable_clk(mmu); return 0; From f39638a1895546c3fd86e43bd912d8626a214411 Mon Sep 17 00:00:00 2001 From: Sandeep Singh Date: Thu, 15 Oct 2020 19:57:37 +0530 Subject: [PATCH 044/698] icnss2: Avoid sending fw down uevent to wlan driver twice Avoid sending fw down uevent to wlan driver twice for one ssr/pdr. Change-Id: I9c99b16c3760ef7b432df16b2f326db39371e3c3 Signed-off-by: Sandeep Singh --- drivers/soc/qcom/icnss2/main.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/soc/qcom/icnss2/main.c b/drivers/soc/qcom/icnss2/main.c index 363d4e8e790a..8f8de8d35170 100644 --- a/drivers/soc/qcom/icnss2/main.c +++ b/drivers/soc/qcom/icnss2/main.c @@ -417,6 +417,7 @@ static irqreturn_t fw_crash_indication_handler(int irq, void *ctx) icnss_ignore_fw_timeout(true); if (test_bit(ICNSS_FW_READY, &priv->state)) { + clear_bit(ICNSS_FW_READY, &priv->state); fw_down_data.crashed = true; icnss_call_driver_uevent(priv, ICNSS_UEVENT_FW_DOWN, &fw_down_data); @@ -1508,6 +1509,7 @@ static int icnss_modem_notifier_nb(struct notifier_block *nb, icnss_ignore_fw_timeout(true); if (test_bit(ICNSS_FW_READY, &priv->state)) { + clear_bit(ICNSS_FW_READY, &priv->state); fw_down_data.crashed = !!notif->crashed; icnss_call_driver_uevent(priv, ICNSS_UEVENT_FW_DOWN, @@ -1537,6 +1539,7 @@ static int icnss_modem_notifier_nb(struct notifier_block *nb, fw_down_data.crashed = !!notif->crashed; if (test_bit(ICNSS_FW_READY, &priv->state)) { + clear_bit(ICNSS_FW_READY, &priv->state); fw_down_data.crashed = !!notif->crashed; icnss_call_driver_uevent(priv, ICNSS_UEVENT_FW_DOWN, @@ -1665,6 +1668,7 @@ event_post: icnss_ignore_fw_timeout(true); if (test_bit(ICNSS_FW_READY, &priv->state)) { + clear_bit(ICNSS_FW_READY, &priv->state); fw_down_data.crashed = event_data->crashed; icnss_call_driver_uevent(priv, ICNSS_UEVENT_FW_DOWN, From 9fb3a209fff07496aac602154d8bbf7c5cf23110 Mon Sep 17 00:00:00 2001 From: Ravikanth Tuniki Date: Fri, 9 Oct 2020 17:48:39 +0530 Subject: [PATCH 045/698] input: touchscreen: Enable Synaptcis tcm Modules Change-Id: Id40deb882a80624b702731576effd43a6d43da4a Signed-off-by: Ravikanth Tuniki --- android/abi_gki_aarch64_qcom | 3 +++ arch/arm64/configs/vendor/holi_GKI.config | 11 +++++++++++ drivers/input/touchscreen/Kconfig | 12 ------------ drivers/input/touchscreen/synaptics_tcm/Kconfig | 16 +++------------- drivers/input/touchscreen/synaptics_tcm/Makefile | 3 ++- .../synaptics_tcm/synaptics_tcm_spi.c | 8 ++++---- 6 files changed, 23 insertions(+), 30 deletions(-) diff --git a/android/abi_gki_aarch64_qcom b/android/abi_gki_aarch64_qcom index 7aa6d06557aa..37f2500d256d 100644 --- a/android/abi_gki_aarch64_qcom +++ b/android/abi_gki_aarch64_qcom @@ -869,6 +869,7 @@ find_next_zero_bit find_snd_usb_substream find_vma + find_vpid finish_wait firmware_request_nowarn flow_keys_basic_dissector @@ -1658,6 +1659,7 @@ phy_start phy_stop physvirt_offset + pid_task pinconf_generic_dt_node_to_map pinctrl_dev_get_drvdata pinctrl_force_default @@ -1969,6 +1971,7 @@ sched_clock sched_setattr sched_setscheduler + sched_setscheduler_nocheck schedule schedule_timeout schedule_timeout_interruptible diff --git a/arch/arm64/configs/vendor/holi_GKI.config b/arch/arm64/configs/vendor/holi_GKI.config index 4f7a3c9a9b41..21402dacf883 100644 --- a/arch/arm64/configs/vendor/holi_GKI.config +++ b/arch/arm64/configs/vendor/holi_GKI.config @@ -126,6 +126,17 @@ CONFIG_HEADER_TEST=y CONFIG_HEADERS_INSTALL=y CONFIG_KERNEL_HEADER_TEST=y CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_SYNAPTICS_TCM=m +CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_SPI=m +CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_I2C=m +CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_CORE=m +CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_TOUCH=m +CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_DEVICE=m +CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_TESTING=m +CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_REFLASH=m +CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_RECOVERY=m +CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_ZEROFLASH=m +CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_DIAGNOSTICS=m CONFIG_TOUCHSCREEN_SYNAPTICS_DSX=y # CONFIG_TOUCHSCREEN_PROPERTIES is not set CONFIG_TOUCHSCREEN_USB_COMPOSITE=m diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index d37cd92620ec..38830610149c 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -1314,18 +1314,6 @@ source "drivers/input/touchscreen/st/Kconfig" source "drivers/input/touchscreen/focaltech_touch/Kconfig" -config TOUCHSCREEN_SYNAPTICS_TCM - bool "Synaptics TCM Touchscreen Driver" - depends on I2C - default y - help - Say Y here if you have a Synaptics Touchscreen. - - If unsure, say N. - - To compile this driver as a module, choose M here: the - module will be called synaptics_tcm. - source "drivers/input/touchscreen/synaptics_tcm/Kconfig" config TOUCHSCREEN_SYNAPTICS_DSX diff --git a/drivers/input/touchscreen/synaptics_tcm/Kconfig b/drivers/input/touchscreen/synaptics_tcm/Kconfig index 78c687df4fe6..6af7c9670065 100644 --- a/drivers/input/touchscreen/synaptics_tcm/Kconfig +++ b/drivers/input/touchscreen/synaptics_tcm/Kconfig @@ -2,21 +2,18 @@ # Synaptics TCM touchscreen driver configuration # menuconfig TOUCHSCREEN_SYNAPTICS_TCM - bool "Synaptics TCM touchscreen" - default y + tristate "Synaptics TCM touchscreen" help Say Y here if you have a Synaptics TCM touchscreen connected to your system. If unsure, say N. -if TOUCHSCREEN_SYNAPTICS_TCM - choice default TOUCHSCREEN_SYNAPTICS_TCM_I2C prompt "Synaptics TCM bus module" config TOUCHSCREEN_SYNAPTICS_TCM_I2C - bool "I2C" + tristate "I2C" depends on I2C help Say Y here to use I2C bus for communication. @@ -27,7 +24,7 @@ config TOUCHSCREEN_SYNAPTICS_TCM_I2C with touch controller. config TOUCHSCREEN_SYNAPTICS_TCM_SPI - bool "SPI" + tristate "SPI" depends on SPI_MASTER help Say Y here to use SPI bus for communication. @@ -42,7 +39,6 @@ endchoice config TOUCHSCREEN_SYNAPTICS_TCM_CORE tristate "Synaptics TCM core module" depends on I2C || SPI_MASTER - default y help Say Y here to enable core functionality. @@ -54,7 +50,6 @@ config TOUCHSCREEN_SYNAPTICS_TCM_CORE config TOUCHSCREEN_SYNAPTICS_TCM_TOUCH tristate "Synaptics TCM touch module" depends on TOUCHSCREEN_SYNAPTICS_TCM_CORE - default y help Say Y here to enable support for touch reporting. @@ -66,7 +61,6 @@ config TOUCHSCREEN_SYNAPTICS_TCM_TOUCH config TOUCHSCREEN_SYNAPTICS_TCM_DEVICE tristate "Synaptics TCM device module" depends on TOUCHSCREEN_SYNAPTICS_TCM_CORE - default y help Say Y here to enable support for TCM device functionality. @@ -89,7 +83,6 @@ config TOUCHSCREEN_SYNAPTICS_TCM_TESTING config TOUCHSCREEN_SYNAPTICS_TCM_REFLASH tristate "Synaptics TCM reflash module" depends on TOUCHSCREEN_SYNAPTICS_TCM_CORE - default y help Say Y here to enable support for reflash functionality. @@ -101,7 +94,6 @@ config TOUCHSCREEN_SYNAPTICS_TCM_REFLASH config TOUCHSCREEN_SYNAPTICS_TCM_RECOVERY tristate "Synaptics TCM recovery module" depends on TOUCHSCREEN_SYNAPTICS_TCM_CORE - default y help Say Y here to enable support for recovery functionality. @@ -124,7 +116,6 @@ config TOUCHSCREEN_SYNAPTICS_TCM_ZEROFLASH config TOUCHSCREEN_SYNAPTICS_TCM_DIAGNOSTICS tristate "Synaptics TCM diagnostics module" depends on TOUCHSCREEN_SYNAPTICS_TCM_CORE - default y help Say Y here to enable support for diagnostics functionality. @@ -132,4 +123,3 @@ config TOUCHSCREEN_SYNAPTICS_TCM_DIAGNOSTICS To compile this driver as a module, choose M here: the module will be called synaptics_tcm_diagnostics. -endif diff --git a/drivers/input/touchscreen/synaptics_tcm/Makefile b/drivers/input/touchscreen/synaptics_tcm/Makefile index 30db3b56516a..3292047e442d 100644 --- a/drivers/input/touchscreen/synaptics_tcm/Makefile +++ b/drivers/input/touchscreen/synaptics_tcm/Makefile @@ -6,7 +6,8 @@ obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_SPI) += synaptics_tcm_spi.o obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_I2C) += synaptics_tcm_i2c.o -obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_CORE) += synaptics_tcm_core.o +obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_CORE) += qcom_synaptics_tcm_core.o +qcom_synaptics_tcm_core-y += synaptics_tcm_core.o synaptics_tcm_i2c.o obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_TOUCH) += synaptics_tcm_touch.o obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_DEVICE) += synaptics_tcm_device.o obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_TESTING) += synaptics_tcm_testing.o diff --git a/drivers/input/touchscreen/synaptics_tcm/synaptics_tcm_spi.c b/drivers/input/touchscreen/synaptics_tcm/synaptics_tcm_spi.c index e54269c0f333..ee8751ac52f2 100644 --- a/drivers/input/touchscreen/synaptics_tcm/synaptics_tcm_spi.c +++ b/drivers/input/touchscreen/synaptics_tcm/synaptics_tcm_spi.c @@ -649,13 +649,13 @@ static struct spi_driver syna_tcm_spi_driver = { .id_table = syna_tcm_id_table, }; -int syna_tcm_bus_init(void) +int syna_tcm_bus_init_spi(void) { return spi_register_driver(&syna_tcm_spi_driver); } -EXPORT_SYMBOL(syna_tcm_bus_init); +EXPORT_SYMBOL(syna_tcm_bus_init_spi); -void syna_tcm_bus_exit(void) +void syna_tcm_bus_exit_spi(void) { kfree(buf); @@ -663,7 +663,7 @@ void syna_tcm_bus_exit(void) spi_unregister_driver(&syna_tcm_spi_driver); } -EXPORT_SYMBOL(syna_tcm_bus_exit); +EXPORT_SYMBOL(syna_tcm_bus_exit_spi); MODULE_AUTHOR("Synaptics, Inc."); MODULE_DESCRIPTION("Synaptics TCM SPI Bus Module"); From 2c12d0191266b03c2ef6e480aa6bb1218363143f Mon Sep 17 00:00:00 2001 From: Pankaj Gupta Date: Mon, 5 Oct 2020 22:12:54 +0530 Subject: [PATCH 046/698] msm: kgsl: Skip SP_INST_TAG and SP_INST_DATA dump in snapshot for A6xx For A6XX targets skip dumping of SP_INST_TAG and SP_INST_DATA to fix race in responding crashdumper status register through host path, when crashdumper is busy reading SP data. Change-Id: I8eb5647cefdba23571acc21f682782cfbf944eb1 Signed-off-by: Pankaj Gupta --- drivers/gpu/msm/adreno_a6xx_snapshot.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/msm/adreno_a6xx_snapshot.c b/drivers/gpu/msm/adreno_a6xx_snapshot.c index 67b8c43390fc..1ddfd14cf5d7 100644 --- a/drivers/gpu/msm/adreno_a6xx_snapshot.c +++ b/drivers/gpu/msm/adreno_a6xx_snapshot.c @@ -535,7 +535,6 @@ static struct a6xx_shader_block a6xx_shader_blocks[] = { {A6XX_TP1_TMO_DATA, 0x200}, {A6XX_TP1_SMO_DATA, 0x80,}, {A6XX_TP1_MIPMAP_BASE_DATA, 0x3C0}, - {A6XX_SP_INST_DATA, 0x800}, {A6XX_SP_LB_0_DATA, 0x800}, {A6XX_SP_LB_1_DATA, 0x800}, {A6XX_SP_LB_2_DATA, 0x800}, @@ -545,7 +544,6 @@ static struct a6xx_shader_block a6xx_shader_blocks[] = { {A6XX_SP_CB_BINDLESS_DATA, 0x800}, {A6XX_SP_CB_LEGACY_DATA, 0x280,}, {A6XX_SP_UAV_DATA, 0x80,}, - {A6XX_SP_INST_TAG, 0x80,}, {A6XX_SP_CB_BINDLESS_TAG, 0x80,}, {A6XX_SP_TMO_UMO_TAG, 0x80,}, {A6XX_SP_SMO_TAG, 0x80}, From da0f5586f30c4082b0d110e12a90d12f30a53eae Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Fri, 16 Oct 2020 10:18:53 +0530 Subject: [PATCH 047/698] clk: qcom: gcc-holi: Enable clocks for pm8008 by default The pm8008 regulator is connected over I2C and the I2C device configures its clocks in runtime_resume and runtime_suspend. These callbacks are triggered from the pm8008 driver's regmap calls. This means regulator framework requests for pm8008 call into the clock framework with the regulator framework locks held. The qcom clock providers also call into the regulator framework with the clock framework locks held. If thread A makes a pm8008 request at the same time thread B makes a clock request, then it can result in deadlocks. Thread A will be stuck waiting on the clock locks while thread B is stuck waiting on the regulator locks. To prevent these deadlocks, enable the I2C clocks required for pm8008 by default during probe and stop registering them with the framework. This NOPs any client requests, since of_clk_get() returns NULL when passed an unregistered clock and all other clock APIs return success before grabbing any locks when passed NULL. Change-Id: I90c72e2588745d95472ad4a5b28144a3d4439762 Signed-off-by: Taniya Das --- drivers/clk/qcom/gcc-holi.c | 65 ++++++++----------------------------- 1 file changed, 14 insertions(+), 51 deletions(-) diff --git a/drivers/clk/qcom/gcc-holi.c b/drivers/clk/qcom/gcc-holi.c index 295957e1f0cb..fe1970debcf7 100644 --- a/drivers/clk/qcom/gcc-holi.c +++ b/drivers/clk/qcom/gcc-holi.c @@ -3574,24 +3574,6 @@ static struct clk_branch gcc_qupv3_wrap1_s3_clk = { }, }; -static struct clk_branch gcc_qupv3_wrap1_s4_clk = { - .halt_reg = 0x534d8, - .halt_check = BRANCH_HALT_VOTED, - .clkr = { - .enable_reg = 0x7900c, - .enable_mask = BIT(25), - .hw.init = &(struct clk_init_data){ - .name = "gcc_qupv3_wrap1_s4_clk", - .parent_data = &(const struct clk_parent_data){ - .hw = &gcc_qupv3_wrap1_s4_clk_src.clkr.hw, - }, - .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, - .ops = &clk_branch2_ops, - }, - }, -}; - static struct clk_branch gcc_qupv3_wrap1_s5_clk = { .halt_reg = 0x53608, .halt_check = BRANCH_HALT_VOTED, @@ -3640,36 +3622,6 @@ static struct clk_branch gcc_qupv3_wrap_0_s_ahb_clk = { }, }; -static struct clk_branch gcc_qupv3_wrap_1_m_ahb_clk = { - .halt_reg = 0x53004, - .halt_check = BRANCH_HALT_VOTED, - .hwcg_reg = 0x53004, - .hwcg_bit = 1, - .clkr = { - .enable_reg = 0x7900c, - .enable_mask = BIT(17), - .hw.init = &(struct clk_init_data){ - .name = "gcc_qupv3_wrap_1_m_ahb_clk", - .ops = &clk_branch2_ops, - }, - }, -}; - -static struct clk_branch gcc_qupv3_wrap_1_s_ahb_clk = { - .halt_reg = 0x53008, - .halt_check = BRANCH_HALT_VOTED, - .hwcg_reg = 0x53008, - .hwcg_bit = 1, - .clkr = { - .enable_reg = 0x7900c, - .enable_mask = BIT(18), - .hw.init = &(struct clk_init_data){ - .name = "gcc_qupv3_wrap_1_s_ahb_clk", - .ops = &clk_branch2_ops, - }, - }, -}; - static struct clk_branch gcc_sdcc1_ahb_clk = { .halt_reg = 0x38008, .halt_check = BRANCH_HALT, @@ -4309,14 +4261,11 @@ static struct clk_regmap *gcc_holi_clocks[] = { [GCC_QUPV3_WRAP1_S2_CLK_SRC] = &gcc_qupv3_wrap1_s2_clk_src.clkr, [GCC_QUPV3_WRAP1_S3_CLK] = &gcc_qupv3_wrap1_s3_clk.clkr, [GCC_QUPV3_WRAP1_S3_CLK_SRC] = &gcc_qupv3_wrap1_s3_clk_src.clkr, - [GCC_QUPV3_WRAP1_S4_CLK] = &gcc_qupv3_wrap1_s4_clk.clkr, [GCC_QUPV3_WRAP1_S4_CLK_SRC] = &gcc_qupv3_wrap1_s4_clk_src.clkr, [GCC_QUPV3_WRAP1_S5_CLK] = &gcc_qupv3_wrap1_s5_clk.clkr, [GCC_QUPV3_WRAP1_S5_CLK_SRC] = &gcc_qupv3_wrap1_s5_clk_src.clkr, [GCC_QUPV3_WRAP_0_M_AHB_CLK] = &gcc_qupv3_wrap_0_m_ahb_clk.clkr, [GCC_QUPV3_WRAP_0_S_AHB_CLK] = &gcc_qupv3_wrap_0_s_ahb_clk.clkr, - [GCC_QUPV3_WRAP_1_M_AHB_CLK] = &gcc_qupv3_wrap_1_m_ahb_clk.clkr, - [GCC_QUPV3_WRAP_1_S_AHB_CLK] = &gcc_qupv3_wrap_1_s_ahb_clk.clkr, [GCC_SDCC1_AHB_CLK] = &gcc_sdcc1_ahb_clk.clkr, [GCC_SDCC1_APPS_CLK] = &gcc_sdcc1_apps_clk.clkr, [GCC_SDCC1_APPS_CLK_SRC] = &gcc_sdcc1_apps_clk_src.clkr, @@ -4476,6 +4425,20 @@ static int gcc_holi_probe(struct platform_device *pdev) /* GCC_DISP_GPLL0_CDIVR__CLK_DIV */ regmap_update_bits(regmap, 0x17058, 0x1, 0x1); + /* + * Enable clocks required by the i2c-connected pm8008 regulators. Don't + * register them with the clock framework so that client requests are + * short-circuited before grabbing the enable/prepare locks. This + * prevents deadlocks between the clk/regulator frameworks. + * + * gcc_qupv3_wrap_1_m_ahb_clk + * gcc_qupv3_wrap_1_s_ahb_clk + * gcc_qupv3_wrap1_s4_clk + */ + regmap_update_bits(regmap, 0x7900c, BIT(17), BIT(17)); + regmap_update_bits(regmap, 0x7900c, BIT(18), BIT(18)); + regmap_update_bits(regmap, 0x7900c, BIT(25), BIT(25)); + clk_fabia_pll_configure(&gpll10, regmap, &gpll10_config); clk_fabia_pll_configure(&gpll11, regmap, &gpll11_config); clk_fabia_pll_configure(&gpll8, regmap, &gpll8_config); From bec950f477cbbc7f4bd5f2c8c6fa73e145189a6b Mon Sep 17 00:00:00 2001 From: Gaurav Singh Date: Mon, 19 Oct 2020 14:59:52 +0530 Subject: [PATCH 048/698] Firmware: arm_scmi: Initial support for plh vendor protocol The perf lock hardening protocol is intended for the management of perf lock hardening on RIMPS The commands in this protocol provide functionality to configure plh details, plh tunables, configuring the log levels and debugging support. Change-Id: I9f5292ee3e32a038160e66d38ec15637a55458fd Signed-off-by: Gaurav Singh --- drivers/firmware/Kconfig | 11 +++ drivers/firmware/arm_scmi/Makefile | 1 + drivers/firmware/arm_scmi/plh_vendor.c | 126 +++++++++++++++++++++++++ include/linux/scmi_protocol.h | 26 +++++ 4 files changed, 164 insertions(+) create mode 100644 drivers/firmware/arm_scmi/plh_vendor.c diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig index e92975bc8d31..cfe983d86512 100644 --- a/drivers/firmware/Kconfig +++ b/drivers/firmware/Kconfig @@ -39,6 +39,17 @@ config QTI_SCMI_MEMLAT_PROTOCOL This driver defines the comands or message ID's used for this communication and also exposes the ops used by clients. +config QTI_SCMI_PLH_PROTOCOL + tristate "Qualcomm Technologies, Inc. SCMI PLH vendor Protocol" + depends on ARM_SCMI_PROTOCOL && QCOM_RIMPS && QGKI + help + System Control and Management Interface (SCMI) plh vendor protocol + this protocol provides interface to communicate with micro controller + which is executing the plh algorithm + + This driver defines the comands or message ID's used for this + communication and also exposes the ops used by clients. + config ARM_SCMI_POWER_DOMAIN tristate "SCMI power domain driver" depends on ARM_SCMI_PROTOCOL || (COMPILE_TEST && OF) diff --git a/drivers/firmware/arm_scmi/Makefile b/drivers/firmware/arm_scmi/Makefile index eeabc570042d..3a463ac60fca 100644 --- a/drivers/firmware/arm_scmi/Makefile +++ b/drivers/firmware/arm_scmi/Makefile @@ -5,3 +5,4 @@ scmi-driver-y = driver.o scmi-protocols-y = base.o clock.o perf.o power.o reset.o sensors.o obj-$(CONFIG_ARM_SCMI_POWER_DOMAIN) += scmi_pm_domain.o obj-$(CONFIG_QTI_SCMI_MEMLAT_PROTOCOL) += memlat_vendor.o +obj-$(CONFIG_QTI_SCMI_PLH_PROTOCOL) += plh_vendor.o diff --git a/drivers/firmware/arm_scmi/plh_vendor.c b/drivers/firmware/arm_scmi/plh_vendor.c new file mode 100644 index 000000000000..f81b62f6281f --- /dev/null +++ b/drivers/firmware/arm_scmi/plh_vendor.c @@ -0,0 +1,126 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#include "common.h" + +#define SCMI_MAX_TX_SIZE (100) //in bytes +#define SCMI_VENDOR_MSG_START (3) +#define SCMI_VENDOR_MSG_PLH_START (16) + +enum scmi_plh_protocol_cmd { + PERF_LOCK_SET_LOG_LEVEL = SCMI_VENDOR_MSG_START, + PERF_LOCK_SCROLL_INIT_IPC_FREQ_TBL_MSG_ID = SCMI_VENDOR_MSG_PLH_START, + PERF_LOCK_SCROLL_START_MSG_ID, + PERF_LOCK_SCROLL_STOP_MSG_ID, + PERF_LOCK_MAX_MSG_ID, +}; + + +static int scmi_plh_scroll_init_ipc_freq_tbl(const struct scmi_handle *handle, + u16 *p_init_args, u16 init_len) +{ + int ret, i = 0; + struct scmi_xfer *t; + uint16_t *msg, msg_size = init_len*sizeof(*msg); + + if (msg_size > SCMI_MAX_TX_SIZE) + return -EINVAL; + + ret = scmi_xfer_get_init(handle, PERF_LOCK_SCROLL_INIT_IPC_FREQ_TBL_MSG_ID, + SCMI_PROTOCOL_PLH, + (msg_size), sizeof(uint32_t), &t); + if (ret) + return ret; + + msg = t->tx.buf; + + for (i = 0; i < init_len; i++) { + *msg++ = cpu_to_le16(*p_init_args); + p_init_args++; + } + ret = scmi_do_xfer(handle, t); + scmi_xfer_put(handle, t); + return ret; +} + + +static int scmi_send_start_stop(const struct scmi_handle *handle, + u16 fps, u32 msg_id) +{ + int ret = 0; + struct scmi_xfer *t; + uint16_t *msg; + + ret = scmi_xfer_get_init(handle, msg_id, + SCMI_PROTOCOL_PLH, + sizeof(*msg), sizeof(uint32_t), &t); + if (ret) + return ret; + + msg = t->tx.buf; + *msg = cpu_to_le16(fps); + ret = scmi_do_xfer(handle, t); + scmi_xfer_put(handle, t); + return ret; +} + +static int scmi_plh_scroll_start_cmd(const struct scmi_handle *handle, + u16 fps) +{ + return scmi_send_start_stop(handle, fps, PERF_LOCK_SCROLL_START_MSG_ID); +} + +static int scmi_plh_scroll_stop_cmd(const struct scmi_handle *handle) +{ + return scmi_send_start_stop(handle, 0, PERF_LOCK_SCROLL_STOP_MSG_ID); +} + +static int scmi_plh_set_log_level(const struct scmi_handle *handle, + u16 val) +{ + int ret = 0; + struct scmi_xfer *t; + uint16_t *msg; + + ret = scmi_xfer_get_init(handle, PERF_LOCK_SET_LOG_LEVEL, + SCMI_PROTOCOL_PLH, sizeof(*msg), + sizeof(uint32_t), &t); + if (ret) + return ret; + + msg = t->tx.buf; + *msg = cpu_to_le16(val); + ret = scmi_do_xfer(handle, t); + scmi_xfer_put(handle, t); + return ret; +} + +static struct scmi_plh_vendor_ops plh_ops = { + .init_splh_ipc_freq_tbl = scmi_plh_scroll_init_ipc_freq_tbl, + .start_splh = scmi_plh_scroll_start_cmd, + .stop_splh = scmi_plh_scroll_stop_cmd, + .set_plh_log_level = scmi_plh_set_log_level, +}; + +static int scmi_plh_vendor_protocol_init(struct scmi_handle *handle) +{ + u32 version; + + scmi_version_get(handle, SCMI_PROTOCOL_PLH, &version); + + dev_dbg(handle->dev, "PLH version %d.%d\n", + PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version)); + + handle->plh_ops = &plh_ops; + + return 0; +} + +static int __init scmi_plh_init(void) +{ + return scmi_protocol_register(SCMI_PROTOCOL_PLH, + &scmi_plh_vendor_protocol_init); +} +subsys_initcall(scmi_plh_init); diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h index 63c5a8edcd20..65ebd4f01223 100644 --- a/include/linux/scmi_protocol.h +++ b/include/linux/scmi_protocol.h @@ -266,6 +266,26 @@ struct scmi_memlat_vendor_ops { }; #endif +#ifdef CONFIG_QTI_SCMI_PLH_PROTOCOL +/** + * struct scmi_plh_vendor_ops - represents the various operations provided + * by SCMI PLH Protocol + * + * @init_splh_ipc_freq_tbl: initialize scroll plh ipc freq voting table in rimps + * @start_splh: starts scroll plh in rimps + * @stop_splh: stops scroll plh in rimps + * @set_plh_log_level: configure the supported log_level in plh module of rimps + */ +struct scmi_plh_vendor_ops { + int (*init_splh_ipc_freq_tbl)(const struct scmi_handle *handle, + u16 *p_init_args, u16 init_len); + int (*start_splh)(const struct scmi_handle *handle, u16 fps); + int (*stop_splh)(const struct scmi_handle *handle); + int (*set_plh_log_level)(const struct scmi_handle *handle, + u16 log_level); +}; +#endif + /** * struct scmi_handle - Handle returned to ARM SCMI clients for usage. * @@ -297,6 +317,9 @@ struct scmi_handle { struct scmi_reset_ops *reset_ops; #ifdef CONFIG_QTI_SCMI_MEMLAT_PROTOCOL struct scmi_memlat_vendor_ops *memlat_ops; +#endif +#ifdef CONFIG_QTI_SCMI_PLH_PROTOCOL + struct scmi_plh_vendor_ops *plh_ops; #endif /* for protocol internal use */ void *perf_priv; @@ -317,6 +340,9 @@ enum scmi_std_protocol { #ifdef CONFIG_QTI_SCMI_MEMLAT_PROTOCOL SCMI_PROTOCOL_MEMLAT = 0x80, #endif +#ifdef CONFIG_QTI_SCMI_PLH_PROTOCOL + SCMI_PROTOCOL_PLH = 0x81, +#endif }; struct scmi_device { From fa38be187b73364242acd6f3e058bbc7a2f37652 Mon Sep 17 00:00:00 2001 From: Gaurav Singh Date: Mon, 19 Oct 2020 17:35:47 +0530 Subject: [PATCH 049/698] drivers: soc: qcom: Initial support for plh scmi client driver Add initial support for plh scmi client driver which registers into scmi framework for plh vendor protocol extension. Also registers with plh interface driver msm_performance. Change-Id: I448a714486ff4c7ea38cbeeec1ddb5e183b76e65 Signed-off-by: Gaurav Singh --- drivers/soc/qcom/Kconfig | 13 ++++++++++++ drivers/soc/qcom/Makefile | 1 + drivers/soc/qcom/plh_scmi.c | 40 +++++++++++++++++++++++++++++++++++++ 3 files changed, 54 insertions(+) create mode 100644 drivers/soc/qcom/plh_scmi.c diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index 6f0c03b0b8f6..ac125cd94bb6 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -747,6 +747,19 @@ config QTI_SYSTEM_PM config QTI_SYSTEM_PM_RPM bool +config QTI_PLH_SCMI_CLIENT + tristate "Qualcomm Technologies Inc. SCMI client driver for PLH" + depends on QTI_PLH + default n + help + SCMI client driver registers itself with SCMI framework for PLH + vendor protocol, and also registers with the plh interface driver + msm_performance. + + This driver deliver the PLH vendor protocol handle to interface + driver, and interface driver will use this handle to communicate + with RIMPS PLH. + config QTI_HW_MEMLAT tristate "Qualcomm Technologies Inc. RIMPS memlat interface driver" depends on PERF_EVENTS diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile index 98557a7f9b35..66207079ef97 100644 --- a/drivers/soc/qcom/Makefile +++ b/drivers/soc/qcom/Makefile @@ -94,6 +94,7 @@ obj-$(CONFIG_MSM_RPM_SMD) += rpm-smd-debug.o endif obj-$(CONFIG_QTI_SYS_PM_VX) += sys_pm_vx.o obj-$(CONFIG_ICNSS2) += icnss2/ +obj-$(CONFIG_QTI_PLH_SCMI_CLIENT) += plh_scmi.o obj-$(CONFIG_QTI_HW_MEMLAT_SCMI_CLIENT) += memlat_scmi.o obj-$(CONFIG_QTI_HW_MEMLAT) += rimps_memlat.o obj-$(CONFIG_QTI_HW_MEMLAT_LOG) += rimps_log.o diff --git a/drivers/soc/qcom/plh_scmi.c b/drivers/soc/qcom/plh_scmi.c new file mode 100644 index 000000000000..67ddad6413a5 --- /dev/null +++ b/drivers/soc/qcom/plh_scmi.c @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include + +extern void rimps_plh_init(struct scmi_handle *handle); + +static int scmi_plh_probe(struct scmi_device *sdev) +{ + struct scmi_handle *handle = sdev->handle; + + if (!handle || !handle->plh_ops) + return -ENODEV; + + rimps_plh_init(handle); + return 0; +} + +static const struct scmi_device_id scmi_id_table[] = { + { SCMI_PROTOCOL_PLH }, +}; +MODULE_DEVICE_TABLE(scmi, scmi_id_table); + +static struct scmi_driver scmi_plh_drv = { + .name = "scmi-plh-driver", + .probe = scmi_plh_probe, + .id_table = scmi_id_table, +}; +module_scmi_driver(scmi_plh_drv); + +MODULE_DESCRIPTION("ARM SCMI PLH driver"); +MODULE_LICENSE("GPL v2"); From 4d51cd653e40ab3baf8886f0bc5a4d8a50d43e7d Mon Sep 17 00:00:00 2001 From: Gaurav Singh Date: Tue, 20 Oct 2020 14:53:16 +0530 Subject: [PATCH 050/698] drivers: soc: qcom: msm_performance: PLH interface support Initial support of rimps PLH interface. This interface exposes sysfs nodes required to configure PLH running in rimps. Change-Id: I18a4cfc346b7923dc083a0433a1993df964dba86 Signed-off-by: Gaurav Singh --- drivers/soc/qcom/Kconfig | 9 ++ drivers/soc/qcom/msm_performance.c | 186 +++++++++++++++++++++++++++-- 2 files changed, 186 insertions(+), 9 deletions(-) diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index ac125cd94bb6..6f4367f19742 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -600,6 +600,15 @@ config MSM_PERFORMANCE fmin and fmax. The user space can request the cpu freq change by writing cpu#:freq values +config QTI_PLH + tristate "Qualcomm Technologies Inc. RIMPS PLH interface" + depends on MSM_PERFORMANCE + default n + help + Interface between RIMPS PLH and userspace, this interface is + responsible for handling the communication with RIMPS PLH + such as passing tunables and enable/disable PLH. + config QMP_DEBUGFS_CLIENT bool "Debugfs Client to communicate with AOP using QMP protocol" depends on DEBUG_FS diff --git a/drivers/soc/qcom/msm_performance.c b/drivers/soc/qcom/msm_performance.c index 3849f938126f..a2674d48d10c 100644 --- a/drivers/soc/qcom/msm_performance.c +++ b/drivers/soc/qcom/msm_performance.c @@ -25,6 +25,7 @@ #include #include #include +#include /* * Sched will provide the data for every 20ms window, @@ -925,20 +926,168 @@ static const struct kernel_param_ops param_ops_game_start_pid = { module_param_cb(evnt_gplaf_pid, ¶m_ops_game_start_pid, NULL, 0644); /*******************************GFX Call************************************/ - static int splh_notif; -static void init_splh_notif(const char *buf) +static struct scmi_handle *plh_handle; +void rimps_plh_init(struct scmi_handle *handle) { - /*buf contains the init info from user*/ - if (buf == NULL) - return; + if (handle) + plh_handle = handle; +} +EXPORT_SYMBOL(rimps_plh_init); - pr_debug("msm_perf:Init info for scroll :: %s\n", buf); +#ifdef CONFIG_QTI_PLH + +static int splh_init_done, plh_log_level; + +#define PLH_MIN_LOG_LEVEL 0 +#define PLH_MAX_LOG_LEVEL 0xF +#define SPLH_FPS_MAX_CNT 8 //fps supported count +#define SPLH_IPC_FREQ_VTBL_MAX_CNT 5 //ipc freq pair +#define SPLH_INIT_IPC_FREQ_TBL_PARAMS \ + (2+SPLH_FPS_MAX_CNT*(1+(2*SPLH_IPC_FREQ_VTBL_MAX_CNT))) + +static int set_plh_log_level(const char *buf, const struct kernel_param *kp) +{ + int ret, log_val_backup; + struct scmi_plh_vendor_ops *ops; + + if (!plh_handle || !plh_handle->plh_ops) + return -EINVAL; + + ops = plh_handle->plh_ops; + + log_val_backup = plh_log_level; + + ret = param_set_int(buf, kp); //Updates plh_log_level + if (ret < 0) + return ret; + + plh_log_level = max(plh_log_level, PLH_MIN_LOG_LEVEL); + plh_log_level = min(plh_log_level, PLH_MAX_LOG_LEVEL); + ret = ops->set_plh_log_level(plh_handle, plh_log_level); + if (ret < 0) { + plh_log_level = log_val_backup; + return ret; + } + return 0; +} + +static const struct kernel_param_ops param_ops_plh_log_level = { + .set = set_plh_log_level, + .get = param_get_int, +}; +module_param_cb(plh_log_level, ¶m_ops_plh_log_level, &plh_log_level, 0644); + +static int init_splh_notif(const char *buf) +{ + int i, j, ret, ntokens, nfps, n_ipc_freq_pair; + //format of cmd nfps, n_ipc_freq_pair, ,...>,... + u16 tmp[SPLH_INIT_IPC_FREQ_TBL_PARAMS]; + u16 *ptmp = tmp, tmp_valid_len = 0; + const char *cp, *cp1; + struct scmi_plh_vendor_ops *ops; + + /*buf contains the init info from user*/ + if (buf == NULL || !plh_handle || !plh_handle->plh_ops) + return -EINVAL; + + cp = buf; + ntokens = 0; + while ((cp = strpbrk(cp + 1, ":"))) + ntokens++; + + cp = buf; + if (sscanf(cp, INIT ":%d", &nfps)) { + if ((nfps != ntokens-1) || (nfps > SPLH_FPS_MAX_CNT)) + return -EINVAL; + + cp = strnchr(cp, strlen(cp), ':'); //skip INIT + cp++; + cp = strnchr(cp, strlen(cp), ':'); //skip nfps + + *ptmp++ = nfps; //nfps is first cmd param + tmp_valid_len++; + cp1 = cp; + ntokens = 0; + //get count of nfps * n_ipc_freq_pair * + while ((cp1 = strpbrk(cp1 + 1, ","))) + ntokens++; + + if (ntokens % (2*nfps)) //ipc freq pair values should be multiple of nfps + return -EINVAL; + + n_ipc_freq_pair = ntokens / (2*nfps); //ipc_freq pair values for each FPS + if (n_ipc_freq_pair > SPLH_IPC_FREQ_VTBL_MAX_CNT) + return -EINVAL; + + *ptmp++ = n_ipc_freq_pair; //n_ipc_freq_pair is second cmd param + tmp_valid_len++; + cp1 = cp; + for (i = 0; i < nfps; i++) { + if (sscanf(cp1, ":%u", ptmp) != 1) + return -EINVAL; + + ptmp++; //increment after storing FPS val + tmp_valid_len++; + cp1 = strnchr(cp1, strlen(cp1), ','); //move to ,ipc + for (j = 0; j < 2*n_ipc_freq_pair; j++) { + if (sscanf(cp1, ",%u", ptmp) != 1) + return -EINVAL; + + ptmp++; //increment after storing ipc or freq + tmp_valid_len++; + cp1 = strnchr(cp1, strlen(cp1), ','); + cp1++; + if (j != (2*n_ipc_freq_pair-1)) + cp1 = strnchr(cp1, strlen(cp1), ','); //move to next + } + + if (i != (nfps-1)) + cp1 = strnchr(cp1, strlen(cp1), ':'); //move to next FPS val + + } + } else { + return -EINVAL; + } + + ops = plh_handle->plh_ops; + ret = ops->init_splh_ipc_freq_tbl(plh_handle, tmp, tmp_valid_len); + if (ret < 0) + return -EINVAL; + + pr_info("msm_perf: nfps=%d n_ipc_freq_pair=%d last_freq_val=%d len=%d\n", + nfps, n_ipc_freq_pair, *--ptmp, tmp_valid_len); + splh_init_done = 1; + return 0; } static void activate_splh_notif(void) { + int ret; + struct scmi_plh_vendor_ops *ops; /*received event notification here*/ + if (splh_notif) { + if (plh_handle && plh_handle->plh_ops) { + ops = plh_handle->plh_ops; + ret = ops->start_splh(plh_handle, splh_notif); //splh_notif is fps + if (ret < 0) { + pr_err("msm_perf: splh start failed, ret=%d\n", ret); + return; + } + } else { + pr_err("msm_perf: splh not supported\n"); + return; + } + } else { + if (plh_handle && plh_handle->plh_ops) { + ops = plh_handle->plh_ops; + ret = ops->stop_splh(plh_handle); + if (ret < 0) { + pr_err("msm_perf: splh stop failed, ret=%d\n", ret); + return; + } + } + } } static int set_splh_notif(const char *buf, const struct kernel_param *kp) @@ -946,8 +1095,17 @@ static int set_splh_notif(const char *buf, const struct kernel_param *kp) int ret; if (strnstr(buf, INIT, sizeof(INIT)) != NULL) { - init_splh_notif(buf); - return 0; + splh_init_done = 0; + ret = init_splh_notif(buf); + if (ret < 0) + pr_err("msm_perf: splh ipc freq tbl init failed, ret=%d\n", ret); + + return ret; + } + + if (!splh_init_done) { + pr_err("msm_perf: splh ipc freq tbl not initialized\n"); + return -EINVAL; } ret = param_set_int(buf, kp); @@ -956,9 +1114,19 @@ static int set_splh_notif(const char *buf, const struct kernel_param *kp) activate_splh_notif(); - return ret; + return 0; } +#else //!CONFIG_QTI_PLH + +static int set_splh_notif(const char *buf, const struct kernel_param *kp) +{ + pr_err("msm_perf: splh not implemented\n"); + return -EINVAL; +} + +#endif //CONFIG_QTI_PLH + static const struct kernel_param_ops param_ops_splh_notification = { .set = set_splh_notif, .get = param_get_int, From 94bb4ccf506aeb42cbe730a5926858cb27d31fbf Mon Sep 17 00:00:00 2001 From: Gaurav Singh Date: Tue, 20 Oct 2020 15:05:24 +0530 Subject: [PATCH 051/698] defconfig: Enables RIMPS PLH interface Enables SCMI PLH protocol, SCMI client and RIMPS PLH interface. Change-Id: I837c8689e377d53ffb3fb323f2541eb1f0584f45 Signed-off-by: Gaurav Singh --- arch/arm64/configs/vendor/holi_QGKI.config | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm64/configs/vendor/holi_QGKI.config b/arch/arm64/configs/vendor/holi_QGKI.config index 9ebe6e28e4b5..8165234a54c1 100644 --- a/arch/arm64/configs/vendor/holi_QGKI.config +++ b/arch/arm64/configs/vendor/holi_QGKI.config @@ -178,6 +178,9 @@ CONFIG_QTI_HW_MEMLAT_SCMI_CLIENT=y CONFIG_SRAM=y CONFIG_QTI_HW_MEMLAT_LOG=y CONFIG_MSM_PERFORMANCE=y +CONFIG_QTI_SCMI_PLH_PROTOCOL=y +CONFIG_QTI_PLH=y +CONFIG_QTI_PLH_SCMI_CLIENT=y # CONFIG_USB_CONFIGFS_RNDIS is not set CONFIG_QCOM_INITIAL_LOGBUF=y CONFIG_QCOM_MINIDUMP_FTRACE=y From ec9cd428f261aa33b9bc2a146c05b6d8dfab8e41 Mon Sep 17 00:00:00 2001 From: Neeraj Upadhyay Date: Fri, 23 Oct 2020 23:22:30 +0530 Subject: [PATCH 052/698] soc: qcom: Conditional compile page/slub minidumps Put page owner and slub debug entries under conditional flag, to avoid compilation issues. Change-Id: I2a0c20f7bc9158e7a52e58c6a28a8f0859e83983 Signed-off-by: Neeraj Upadhyay --- drivers/soc/qcom/minidump_log.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/soc/qcom/minidump_log.c b/drivers/soc/qcom/minidump_log.c index 524f23cff353..4aaa5b894334 100644 --- a/drivers/soc/qcom/minidump_log.c +++ b/drivers/soc/qcom/minidump_log.c @@ -1248,16 +1248,20 @@ static void md_register_panic_data(void) &md_meminfo_seq_buf); md_register_panic_entries(MD_SLABINFO_PAGES, "SLABINFO", &md_slabinfo_seq_buf); +#ifdef CONFIG_PAGE_OWNER if (is_page_owner_enabled()) { md_register_memory_dump(md_pageowner_dump_size, "PAGEOWNER"); debugfs_create_file("page_owner_dump_size_mb", 0400, NULL, NULL, &proc_page_owner_dump_size_ops); } +#endif +#ifdef CONFIG_SLUB_DEBUG if (is_slub_debug_enabled()) { md_register_memory_dump(md_slabowner_dump_size, "SLABOWNER"); debugfs_create_file("slab_owner_dump_size_mb", 0400, NULL, NULL, &proc_slab_owner_dump_size_ops); } +#endif } #ifdef CONFIG_MODULES From ca6b80e3b1ada8eea2756aabd17cdd3222472965 Mon Sep 17 00:00:00 2001 From: Niranjan Reddy Dumbala Date: Fri, 6 Nov 2020 12:56:06 +0530 Subject: [PATCH 053/698] Revert "defconfig: Enables RIMPS PLH interface" This reverts commit 94bb4ccf506aeb42cbe730a5926858cb27d31fbf. Change-Id: Ib694a1cb0bf2ecce70bef10ec266a210113d059f Signed-off-by: Niranjan Reddy Dumbala --- arch/arm64/configs/vendor/holi_QGKI.config | 3 --- 1 file changed, 3 deletions(-) diff --git a/arch/arm64/configs/vendor/holi_QGKI.config b/arch/arm64/configs/vendor/holi_QGKI.config index 8165234a54c1..9ebe6e28e4b5 100644 --- a/arch/arm64/configs/vendor/holi_QGKI.config +++ b/arch/arm64/configs/vendor/holi_QGKI.config @@ -178,9 +178,6 @@ CONFIG_QTI_HW_MEMLAT_SCMI_CLIENT=y CONFIG_SRAM=y CONFIG_QTI_HW_MEMLAT_LOG=y CONFIG_MSM_PERFORMANCE=y -CONFIG_QTI_SCMI_PLH_PROTOCOL=y -CONFIG_QTI_PLH=y -CONFIG_QTI_PLH_SCMI_CLIENT=y # CONFIG_USB_CONFIGFS_RNDIS is not set CONFIG_QCOM_INITIAL_LOGBUF=y CONFIG_QCOM_MINIDUMP_FTRACE=y From acc6749297501a6c76282c994bf7a1eda0a35634 Mon Sep 17 00:00:00 2001 From: Niranjan Reddy Dumbala Date: Fri, 6 Nov 2020 12:56:32 +0530 Subject: [PATCH 054/698] Revert "drivers: soc: qcom: msm_performance: PLH interface support" This reverts commit 4d51cd653e40ab3baf8886f0bc5a4d8a50d43e7d. Change-Id: I4cf1df7070564b3bc7a29718a5d01ebe1b737929 Signed-off-by: Niranjan Reddy Dumbala --- drivers/soc/qcom/Kconfig | 9 -- drivers/soc/qcom/msm_performance.c | 184 ++--------------------------- 2 files changed, 8 insertions(+), 185 deletions(-) diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index 6f4367f19742..ac125cd94bb6 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -600,15 +600,6 @@ config MSM_PERFORMANCE fmin and fmax. The user space can request the cpu freq change by writing cpu#:freq values -config QTI_PLH - tristate "Qualcomm Technologies Inc. RIMPS PLH interface" - depends on MSM_PERFORMANCE - default n - help - Interface between RIMPS PLH and userspace, this interface is - responsible for handling the communication with RIMPS PLH - such as passing tunables and enable/disable PLH. - config QMP_DEBUGFS_CLIENT bool "Debugfs Client to communicate with AOP using QMP protocol" depends on DEBUG_FS diff --git a/drivers/soc/qcom/msm_performance.c b/drivers/soc/qcom/msm_performance.c index a2674d48d10c..3849f938126f 100644 --- a/drivers/soc/qcom/msm_performance.c +++ b/drivers/soc/qcom/msm_performance.c @@ -25,7 +25,6 @@ #include #include #include -#include /* * Sched will provide the data for every 20ms window, @@ -926,168 +925,20 @@ static const struct kernel_param_ops param_ops_game_start_pid = { module_param_cb(evnt_gplaf_pid, ¶m_ops_game_start_pid, NULL, 0644); /*******************************GFX Call************************************/ + static int splh_notif; -static struct scmi_handle *plh_handle; -void rimps_plh_init(struct scmi_handle *handle) +static void init_splh_notif(const char *buf) { - if (handle) - plh_handle = handle; -} -EXPORT_SYMBOL(rimps_plh_init); - -#ifdef CONFIG_QTI_PLH - -static int splh_init_done, plh_log_level; - -#define PLH_MIN_LOG_LEVEL 0 -#define PLH_MAX_LOG_LEVEL 0xF -#define SPLH_FPS_MAX_CNT 8 //fps supported count -#define SPLH_IPC_FREQ_VTBL_MAX_CNT 5 //ipc freq pair -#define SPLH_INIT_IPC_FREQ_TBL_PARAMS \ - (2+SPLH_FPS_MAX_CNT*(1+(2*SPLH_IPC_FREQ_VTBL_MAX_CNT))) - -static int set_plh_log_level(const char *buf, const struct kernel_param *kp) -{ - int ret, log_val_backup; - struct scmi_plh_vendor_ops *ops; - - if (!plh_handle || !plh_handle->plh_ops) - return -EINVAL; - - ops = plh_handle->plh_ops; - - log_val_backup = plh_log_level; - - ret = param_set_int(buf, kp); //Updates plh_log_level - if (ret < 0) - return ret; - - plh_log_level = max(plh_log_level, PLH_MIN_LOG_LEVEL); - plh_log_level = min(plh_log_level, PLH_MAX_LOG_LEVEL); - ret = ops->set_plh_log_level(plh_handle, plh_log_level); - if (ret < 0) { - plh_log_level = log_val_backup; - return ret; - } - return 0; -} - -static const struct kernel_param_ops param_ops_plh_log_level = { - .set = set_plh_log_level, - .get = param_get_int, -}; -module_param_cb(plh_log_level, ¶m_ops_plh_log_level, &plh_log_level, 0644); - -static int init_splh_notif(const char *buf) -{ - int i, j, ret, ntokens, nfps, n_ipc_freq_pair; - //format of cmd nfps, n_ipc_freq_pair, ,...>,... - u16 tmp[SPLH_INIT_IPC_FREQ_TBL_PARAMS]; - u16 *ptmp = tmp, tmp_valid_len = 0; - const char *cp, *cp1; - struct scmi_plh_vendor_ops *ops; - /*buf contains the init info from user*/ - if (buf == NULL || !plh_handle || !plh_handle->plh_ops) - return -EINVAL; + if (buf == NULL) + return; - cp = buf; - ntokens = 0; - while ((cp = strpbrk(cp + 1, ":"))) - ntokens++; - - cp = buf; - if (sscanf(cp, INIT ":%d", &nfps)) { - if ((nfps != ntokens-1) || (nfps > SPLH_FPS_MAX_CNT)) - return -EINVAL; - - cp = strnchr(cp, strlen(cp), ':'); //skip INIT - cp++; - cp = strnchr(cp, strlen(cp), ':'); //skip nfps - - *ptmp++ = nfps; //nfps is first cmd param - tmp_valid_len++; - cp1 = cp; - ntokens = 0; - //get count of nfps * n_ipc_freq_pair * - while ((cp1 = strpbrk(cp1 + 1, ","))) - ntokens++; - - if (ntokens % (2*nfps)) //ipc freq pair values should be multiple of nfps - return -EINVAL; - - n_ipc_freq_pair = ntokens / (2*nfps); //ipc_freq pair values for each FPS - if (n_ipc_freq_pair > SPLH_IPC_FREQ_VTBL_MAX_CNT) - return -EINVAL; - - *ptmp++ = n_ipc_freq_pair; //n_ipc_freq_pair is second cmd param - tmp_valid_len++; - cp1 = cp; - for (i = 0; i < nfps; i++) { - if (sscanf(cp1, ":%u", ptmp) != 1) - return -EINVAL; - - ptmp++; //increment after storing FPS val - tmp_valid_len++; - cp1 = strnchr(cp1, strlen(cp1), ','); //move to ,ipc - for (j = 0; j < 2*n_ipc_freq_pair; j++) { - if (sscanf(cp1, ",%u", ptmp) != 1) - return -EINVAL; - - ptmp++; //increment after storing ipc or freq - tmp_valid_len++; - cp1 = strnchr(cp1, strlen(cp1), ','); - cp1++; - if (j != (2*n_ipc_freq_pair-1)) - cp1 = strnchr(cp1, strlen(cp1), ','); //move to next - } - - if (i != (nfps-1)) - cp1 = strnchr(cp1, strlen(cp1), ':'); //move to next FPS val - - } - } else { - return -EINVAL; - } - - ops = plh_handle->plh_ops; - ret = ops->init_splh_ipc_freq_tbl(plh_handle, tmp, tmp_valid_len); - if (ret < 0) - return -EINVAL; - - pr_info("msm_perf: nfps=%d n_ipc_freq_pair=%d last_freq_val=%d len=%d\n", - nfps, n_ipc_freq_pair, *--ptmp, tmp_valid_len); - splh_init_done = 1; - return 0; + pr_debug("msm_perf:Init info for scroll :: %s\n", buf); } static void activate_splh_notif(void) { - int ret; - struct scmi_plh_vendor_ops *ops; /*received event notification here*/ - if (splh_notif) { - if (plh_handle && plh_handle->plh_ops) { - ops = plh_handle->plh_ops; - ret = ops->start_splh(plh_handle, splh_notif); //splh_notif is fps - if (ret < 0) { - pr_err("msm_perf: splh start failed, ret=%d\n", ret); - return; - } - } else { - pr_err("msm_perf: splh not supported\n"); - return; - } - } else { - if (plh_handle && plh_handle->plh_ops) { - ops = plh_handle->plh_ops; - ret = ops->stop_splh(plh_handle); - if (ret < 0) { - pr_err("msm_perf: splh stop failed, ret=%d\n", ret); - return; - } - } - } } static int set_splh_notif(const char *buf, const struct kernel_param *kp) @@ -1095,17 +946,8 @@ static int set_splh_notif(const char *buf, const struct kernel_param *kp) int ret; if (strnstr(buf, INIT, sizeof(INIT)) != NULL) { - splh_init_done = 0; - ret = init_splh_notif(buf); - if (ret < 0) - pr_err("msm_perf: splh ipc freq tbl init failed, ret=%d\n", ret); - - return ret; - } - - if (!splh_init_done) { - pr_err("msm_perf: splh ipc freq tbl not initialized\n"); - return -EINVAL; + init_splh_notif(buf); + return 0; } ret = param_set_int(buf, kp); @@ -1114,19 +956,9 @@ static int set_splh_notif(const char *buf, const struct kernel_param *kp) activate_splh_notif(); - return 0; + return ret; } -#else //!CONFIG_QTI_PLH - -static int set_splh_notif(const char *buf, const struct kernel_param *kp) -{ - pr_err("msm_perf: splh not implemented\n"); - return -EINVAL; -} - -#endif //CONFIG_QTI_PLH - static const struct kernel_param_ops param_ops_splh_notification = { .set = set_splh_notif, .get = param_get_int, From 5468caeb93ab72a1acb413924ee11cc90b8fd79e Mon Sep 17 00:00:00 2001 From: Niranjan Reddy Dumbala Date: Fri, 6 Nov 2020 12:58:46 +0530 Subject: [PATCH 055/698] Revert "drivers: soc: qcom: Initial support for plh scmi client driver" This reverts commit fa38be187b73364242acd6f3e058bbc7a2f37652. Change-Id: Ia9f57909298faccc6a5803ee1c3a6a0455e81130 Signed-off-by: Niranjan Reddy Dumbala --- drivers/soc/qcom/Kconfig | 13 ------------ drivers/soc/qcom/Makefile | 1 - drivers/soc/qcom/plh_scmi.c | 40 ------------------------------------- 3 files changed, 54 deletions(-) delete mode 100644 drivers/soc/qcom/plh_scmi.c diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index ac125cd94bb6..6f0c03b0b8f6 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -747,19 +747,6 @@ config QTI_SYSTEM_PM config QTI_SYSTEM_PM_RPM bool -config QTI_PLH_SCMI_CLIENT - tristate "Qualcomm Technologies Inc. SCMI client driver for PLH" - depends on QTI_PLH - default n - help - SCMI client driver registers itself with SCMI framework for PLH - vendor protocol, and also registers with the plh interface driver - msm_performance. - - This driver deliver the PLH vendor protocol handle to interface - driver, and interface driver will use this handle to communicate - with RIMPS PLH. - config QTI_HW_MEMLAT tristate "Qualcomm Technologies Inc. RIMPS memlat interface driver" depends on PERF_EVENTS diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile index 66207079ef97..98557a7f9b35 100644 --- a/drivers/soc/qcom/Makefile +++ b/drivers/soc/qcom/Makefile @@ -94,7 +94,6 @@ obj-$(CONFIG_MSM_RPM_SMD) += rpm-smd-debug.o endif obj-$(CONFIG_QTI_SYS_PM_VX) += sys_pm_vx.o obj-$(CONFIG_ICNSS2) += icnss2/ -obj-$(CONFIG_QTI_PLH_SCMI_CLIENT) += plh_scmi.o obj-$(CONFIG_QTI_HW_MEMLAT_SCMI_CLIENT) += memlat_scmi.o obj-$(CONFIG_QTI_HW_MEMLAT) += rimps_memlat.o obj-$(CONFIG_QTI_HW_MEMLAT_LOG) += rimps_log.o diff --git a/drivers/soc/qcom/plh_scmi.c b/drivers/soc/qcom/plh_scmi.c deleted file mode 100644 index 67ddad6413a5..000000000000 --- a/drivers/soc/qcom/plh_scmi.c +++ /dev/null @@ -1,40 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2020, The Linux Foundation. All rights reserved. - */ - -#include -#include -#include -#include -#include -#include -#include - -extern void rimps_plh_init(struct scmi_handle *handle); - -static int scmi_plh_probe(struct scmi_device *sdev) -{ - struct scmi_handle *handle = sdev->handle; - - if (!handle || !handle->plh_ops) - return -ENODEV; - - rimps_plh_init(handle); - return 0; -} - -static const struct scmi_device_id scmi_id_table[] = { - { SCMI_PROTOCOL_PLH }, -}; -MODULE_DEVICE_TABLE(scmi, scmi_id_table); - -static struct scmi_driver scmi_plh_drv = { - .name = "scmi-plh-driver", - .probe = scmi_plh_probe, - .id_table = scmi_id_table, -}; -module_scmi_driver(scmi_plh_drv); - -MODULE_DESCRIPTION("ARM SCMI PLH driver"); -MODULE_LICENSE("GPL v2"); From b98daabf685d65116a9c64037fe1b2d6df6538c5 Mon Sep 17 00:00:00 2001 From: Niranjan Reddy Dumbala Date: Fri, 6 Nov 2020 13:00:11 +0530 Subject: [PATCH 056/698] Revert "Firmware: arm_scmi: Initial support for plh vendor protocol" This reverts commit bec950f477cbbc7f4bd5f2c8c6fa73e145189a6b. Change-Id: I6207a87f556e6e3bc40b1aa33fda753de2bad3f7 Signed-off-by: Niranjan Reddy Dumbala --- drivers/firmware/Kconfig | 11 --- drivers/firmware/arm_scmi/Makefile | 1 - drivers/firmware/arm_scmi/plh_vendor.c | 126 ------------------------- include/linux/scmi_protocol.h | 26 ----- 4 files changed, 164 deletions(-) delete mode 100644 drivers/firmware/arm_scmi/plh_vendor.c diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig index cfe983d86512..e92975bc8d31 100644 --- a/drivers/firmware/Kconfig +++ b/drivers/firmware/Kconfig @@ -39,17 +39,6 @@ config QTI_SCMI_MEMLAT_PROTOCOL This driver defines the comands or message ID's used for this communication and also exposes the ops used by clients. -config QTI_SCMI_PLH_PROTOCOL - tristate "Qualcomm Technologies, Inc. SCMI PLH vendor Protocol" - depends on ARM_SCMI_PROTOCOL && QCOM_RIMPS && QGKI - help - System Control and Management Interface (SCMI) plh vendor protocol - this protocol provides interface to communicate with micro controller - which is executing the plh algorithm - - This driver defines the comands or message ID's used for this - communication and also exposes the ops used by clients. - config ARM_SCMI_POWER_DOMAIN tristate "SCMI power domain driver" depends on ARM_SCMI_PROTOCOL || (COMPILE_TEST && OF) diff --git a/drivers/firmware/arm_scmi/Makefile b/drivers/firmware/arm_scmi/Makefile index 3a463ac60fca..eeabc570042d 100644 --- a/drivers/firmware/arm_scmi/Makefile +++ b/drivers/firmware/arm_scmi/Makefile @@ -5,4 +5,3 @@ scmi-driver-y = driver.o scmi-protocols-y = base.o clock.o perf.o power.o reset.o sensors.o obj-$(CONFIG_ARM_SCMI_POWER_DOMAIN) += scmi_pm_domain.o obj-$(CONFIG_QTI_SCMI_MEMLAT_PROTOCOL) += memlat_vendor.o -obj-$(CONFIG_QTI_SCMI_PLH_PROTOCOL) += plh_vendor.o diff --git a/drivers/firmware/arm_scmi/plh_vendor.c b/drivers/firmware/arm_scmi/plh_vendor.c deleted file mode 100644 index f81b62f6281f..000000000000 --- a/drivers/firmware/arm_scmi/plh_vendor.c +++ /dev/null @@ -1,126 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2020, The Linux Foundation. All rights reserved. - */ - -#include "common.h" - -#define SCMI_MAX_TX_SIZE (100) //in bytes -#define SCMI_VENDOR_MSG_START (3) -#define SCMI_VENDOR_MSG_PLH_START (16) - -enum scmi_plh_protocol_cmd { - PERF_LOCK_SET_LOG_LEVEL = SCMI_VENDOR_MSG_START, - PERF_LOCK_SCROLL_INIT_IPC_FREQ_TBL_MSG_ID = SCMI_VENDOR_MSG_PLH_START, - PERF_LOCK_SCROLL_START_MSG_ID, - PERF_LOCK_SCROLL_STOP_MSG_ID, - PERF_LOCK_MAX_MSG_ID, -}; - - -static int scmi_plh_scroll_init_ipc_freq_tbl(const struct scmi_handle *handle, - u16 *p_init_args, u16 init_len) -{ - int ret, i = 0; - struct scmi_xfer *t; - uint16_t *msg, msg_size = init_len*sizeof(*msg); - - if (msg_size > SCMI_MAX_TX_SIZE) - return -EINVAL; - - ret = scmi_xfer_get_init(handle, PERF_LOCK_SCROLL_INIT_IPC_FREQ_TBL_MSG_ID, - SCMI_PROTOCOL_PLH, - (msg_size), sizeof(uint32_t), &t); - if (ret) - return ret; - - msg = t->tx.buf; - - for (i = 0; i < init_len; i++) { - *msg++ = cpu_to_le16(*p_init_args); - p_init_args++; - } - ret = scmi_do_xfer(handle, t); - scmi_xfer_put(handle, t); - return ret; -} - - -static int scmi_send_start_stop(const struct scmi_handle *handle, - u16 fps, u32 msg_id) -{ - int ret = 0; - struct scmi_xfer *t; - uint16_t *msg; - - ret = scmi_xfer_get_init(handle, msg_id, - SCMI_PROTOCOL_PLH, - sizeof(*msg), sizeof(uint32_t), &t); - if (ret) - return ret; - - msg = t->tx.buf; - *msg = cpu_to_le16(fps); - ret = scmi_do_xfer(handle, t); - scmi_xfer_put(handle, t); - return ret; -} - -static int scmi_plh_scroll_start_cmd(const struct scmi_handle *handle, - u16 fps) -{ - return scmi_send_start_stop(handle, fps, PERF_LOCK_SCROLL_START_MSG_ID); -} - -static int scmi_plh_scroll_stop_cmd(const struct scmi_handle *handle) -{ - return scmi_send_start_stop(handle, 0, PERF_LOCK_SCROLL_STOP_MSG_ID); -} - -static int scmi_plh_set_log_level(const struct scmi_handle *handle, - u16 val) -{ - int ret = 0; - struct scmi_xfer *t; - uint16_t *msg; - - ret = scmi_xfer_get_init(handle, PERF_LOCK_SET_LOG_LEVEL, - SCMI_PROTOCOL_PLH, sizeof(*msg), - sizeof(uint32_t), &t); - if (ret) - return ret; - - msg = t->tx.buf; - *msg = cpu_to_le16(val); - ret = scmi_do_xfer(handle, t); - scmi_xfer_put(handle, t); - return ret; -} - -static struct scmi_plh_vendor_ops plh_ops = { - .init_splh_ipc_freq_tbl = scmi_plh_scroll_init_ipc_freq_tbl, - .start_splh = scmi_plh_scroll_start_cmd, - .stop_splh = scmi_plh_scroll_stop_cmd, - .set_plh_log_level = scmi_plh_set_log_level, -}; - -static int scmi_plh_vendor_protocol_init(struct scmi_handle *handle) -{ - u32 version; - - scmi_version_get(handle, SCMI_PROTOCOL_PLH, &version); - - dev_dbg(handle->dev, "PLH version %d.%d\n", - PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version)); - - handle->plh_ops = &plh_ops; - - return 0; -} - -static int __init scmi_plh_init(void) -{ - return scmi_protocol_register(SCMI_PROTOCOL_PLH, - &scmi_plh_vendor_protocol_init); -} -subsys_initcall(scmi_plh_init); diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h index 65ebd4f01223..63c5a8edcd20 100644 --- a/include/linux/scmi_protocol.h +++ b/include/linux/scmi_protocol.h @@ -266,26 +266,6 @@ struct scmi_memlat_vendor_ops { }; #endif -#ifdef CONFIG_QTI_SCMI_PLH_PROTOCOL -/** - * struct scmi_plh_vendor_ops - represents the various operations provided - * by SCMI PLH Protocol - * - * @init_splh_ipc_freq_tbl: initialize scroll plh ipc freq voting table in rimps - * @start_splh: starts scroll plh in rimps - * @stop_splh: stops scroll plh in rimps - * @set_plh_log_level: configure the supported log_level in plh module of rimps - */ -struct scmi_plh_vendor_ops { - int (*init_splh_ipc_freq_tbl)(const struct scmi_handle *handle, - u16 *p_init_args, u16 init_len); - int (*start_splh)(const struct scmi_handle *handle, u16 fps); - int (*stop_splh)(const struct scmi_handle *handle); - int (*set_plh_log_level)(const struct scmi_handle *handle, - u16 log_level); -}; -#endif - /** * struct scmi_handle - Handle returned to ARM SCMI clients for usage. * @@ -317,9 +297,6 @@ struct scmi_handle { struct scmi_reset_ops *reset_ops; #ifdef CONFIG_QTI_SCMI_MEMLAT_PROTOCOL struct scmi_memlat_vendor_ops *memlat_ops; -#endif -#ifdef CONFIG_QTI_SCMI_PLH_PROTOCOL - struct scmi_plh_vendor_ops *plh_ops; #endif /* for protocol internal use */ void *perf_priv; @@ -340,9 +317,6 @@ enum scmi_std_protocol { #ifdef CONFIG_QTI_SCMI_MEMLAT_PROTOCOL SCMI_PROTOCOL_MEMLAT = 0x80, #endif -#ifdef CONFIG_QTI_SCMI_PLH_PROTOCOL - SCMI_PROTOCOL_PLH = 0x81, -#endif }; struct scmi_device { From 11fceaafc2e2ae8daecdbc6f37b83fb233f8afe6 Mon Sep 17 00:00:00 2001 From: Niranjan Reddy Dumbala Date: Fri, 6 Nov 2020 13:02:32 +0530 Subject: [PATCH 057/698] Revert "input: touchscreen: Enable Synaptcis tcm Modules" This reverts commit 9fb3a209fff07496aac602154d8bbf7c5cf23110. Change-Id: Ib3b0b97226d65873b311a9e3a9f1f836810d0c10 Signed-off-by: Niranjan Reddy Dumbala --- android/abi_gki_aarch64_qcom | 3 --- arch/arm64/configs/vendor/holi_GKI.config | 11 ----------- drivers/input/touchscreen/Kconfig | 12 ++++++++++++ drivers/input/touchscreen/synaptics_tcm/Kconfig | 16 +++++++++++++--- drivers/input/touchscreen/synaptics_tcm/Makefile | 3 +-- .../synaptics_tcm/synaptics_tcm_spi.c | 8 ++++---- 6 files changed, 30 insertions(+), 23 deletions(-) diff --git a/android/abi_gki_aarch64_qcom b/android/abi_gki_aarch64_qcom index 37f2500d256d..7aa6d06557aa 100644 --- a/android/abi_gki_aarch64_qcom +++ b/android/abi_gki_aarch64_qcom @@ -869,7 +869,6 @@ find_next_zero_bit find_snd_usb_substream find_vma - find_vpid finish_wait firmware_request_nowarn flow_keys_basic_dissector @@ -1659,7 +1658,6 @@ phy_start phy_stop physvirt_offset - pid_task pinconf_generic_dt_node_to_map pinctrl_dev_get_drvdata pinctrl_force_default @@ -1971,7 +1969,6 @@ sched_clock sched_setattr sched_setscheduler - sched_setscheduler_nocheck schedule schedule_timeout schedule_timeout_interruptible diff --git a/arch/arm64/configs/vendor/holi_GKI.config b/arch/arm64/configs/vendor/holi_GKI.config index 21402dacf883..4f7a3c9a9b41 100644 --- a/arch/arm64/configs/vendor/holi_GKI.config +++ b/arch/arm64/configs/vendor/holi_GKI.config @@ -126,17 +126,6 @@ CONFIG_HEADER_TEST=y CONFIG_HEADERS_INSTALL=y CONFIG_KERNEL_HEADER_TEST=y CONFIG_INPUT_TOUCHSCREEN=y -CONFIG_TOUCHSCREEN_SYNAPTICS_TCM=m -CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_SPI=m -CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_I2C=m -CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_CORE=m -CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_TOUCH=m -CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_DEVICE=m -CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_TESTING=m -CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_REFLASH=m -CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_RECOVERY=m -CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_ZEROFLASH=m -CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_DIAGNOSTICS=m CONFIG_TOUCHSCREEN_SYNAPTICS_DSX=y # CONFIG_TOUCHSCREEN_PROPERTIES is not set CONFIG_TOUCHSCREEN_USB_COMPOSITE=m diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 38830610149c..d37cd92620ec 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -1314,6 +1314,18 @@ source "drivers/input/touchscreen/st/Kconfig" source "drivers/input/touchscreen/focaltech_touch/Kconfig" +config TOUCHSCREEN_SYNAPTICS_TCM + bool "Synaptics TCM Touchscreen Driver" + depends on I2C + default y + help + Say Y here if you have a Synaptics Touchscreen. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called synaptics_tcm. + source "drivers/input/touchscreen/synaptics_tcm/Kconfig" config TOUCHSCREEN_SYNAPTICS_DSX diff --git a/drivers/input/touchscreen/synaptics_tcm/Kconfig b/drivers/input/touchscreen/synaptics_tcm/Kconfig index 6af7c9670065..78c687df4fe6 100644 --- a/drivers/input/touchscreen/synaptics_tcm/Kconfig +++ b/drivers/input/touchscreen/synaptics_tcm/Kconfig @@ -2,18 +2,21 @@ # Synaptics TCM touchscreen driver configuration # menuconfig TOUCHSCREEN_SYNAPTICS_TCM - tristate "Synaptics TCM touchscreen" + bool "Synaptics TCM touchscreen" + default y help Say Y here if you have a Synaptics TCM touchscreen connected to your system. If unsure, say N. +if TOUCHSCREEN_SYNAPTICS_TCM + choice default TOUCHSCREEN_SYNAPTICS_TCM_I2C prompt "Synaptics TCM bus module" config TOUCHSCREEN_SYNAPTICS_TCM_I2C - tristate "I2C" + bool "I2C" depends on I2C help Say Y here to use I2C bus for communication. @@ -24,7 +27,7 @@ config TOUCHSCREEN_SYNAPTICS_TCM_I2C with touch controller. config TOUCHSCREEN_SYNAPTICS_TCM_SPI - tristate "SPI" + bool "SPI" depends on SPI_MASTER help Say Y here to use SPI bus for communication. @@ -39,6 +42,7 @@ endchoice config TOUCHSCREEN_SYNAPTICS_TCM_CORE tristate "Synaptics TCM core module" depends on I2C || SPI_MASTER + default y help Say Y here to enable core functionality. @@ -50,6 +54,7 @@ config TOUCHSCREEN_SYNAPTICS_TCM_CORE config TOUCHSCREEN_SYNAPTICS_TCM_TOUCH tristate "Synaptics TCM touch module" depends on TOUCHSCREEN_SYNAPTICS_TCM_CORE + default y help Say Y here to enable support for touch reporting. @@ -61,6 +66,7 @@ config TOUCHSCREEN_SYNAPTICS_TCM_TOUCH config TOUCHSCREEN_SYNAPTICS_TCM_DEVICE tristate "Synaptics TCM device module" depends on TOUCHSCREEN_SYNAPTICS_TCM_CORE + default y help Say Y here to enable support for TCM device functionality. @@ -83,6 +89,7 @@ config TOUCHSCREEN_SYNAPTICS_TCM_TESTING config TOUCHSCREEN_SYNAPTICS_TCM_REFLASH tristate "Synaptics TCM reflash module" depends on TOUCHSCREEN_SYNAPTICS_TCM_CORE + default y help Say Y here to enable support for reflash functionality. @@ -94,6 +101,7 @@ config TOUCHSCREEN_SYNAPTICS_TCM_REFLASH config TOUCHSCREEN_SYNAPTICS_TCM_RECOVERY tristate "Synaptics TCM recovery module" depends on TOUCHSCREEN_SYNAPTICS_TCM_CORE + default y help Say Y here to enable support for recovery functionality. @@ -116,6 +124,7 @@ config TOUCHSCREEN_SYNAPTICS_TCM_ZEROFLASH config TOUCHSCREEN_SYNAPTICS_TCM_DIAGNOSTICS tristate "Synaptics TCM diagnostics module" depends on TOUCHSCREEN_SYNAPTICS_TCM_CORE + default y help Say Y here to enable support for diagnostics functionality. @@ -123,3 +132,4 @@ config TOUCHSCREEN_SYNAPTICS_TCM_DIAGNOSTICS To compile this driver as a module, choose M here: the module will be called synaptics_tcm_diagnostics. +endif diff --git a/drivers/input/touchscreen/synaptics_tcm/Makefile b/drivers/input/touchscreen/synaptics_tcm/Makefile index 3292047e442d..30db3b56516a 100644 --- a/drivers/input/touchscreen/synaptics_tcm/Makefile +++ b/drivers/input/touchscreen/synaptics_tcm/Makefile @@ -6,8 +6,7 @@ obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_SPI) += synaptics_tcm_spi.o obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_I2C) += synaptics_tcm_i2c.o -obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_CORE) += qcom_synaptics_tcm_core.o -qcom_synaptics_tcm_core-y += synaptics_tcm_core.o synaptics_tcm_i2c.o +obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_CORE) += synaptics_tcm_core.o obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_TOUCH) += synaptics_tcm_touch.o obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_DEVICE) += synaptics_tcm_device.o obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_TESTING) += synaptics_tcm_testing.o diff --git a/drivers/input/touchscreen/synaptics_tcm/synaptics_tcm_spi.c b/drivers/input/touchscreen/synaptics_tcm/synaptics_tcm_spi.c index ee8751ac52f2..e54269c0f333 100644 --- a/drivers/input/touchscreen/synaptics_tcm/synaptics_tcm_spi.c +++ b/drivers/input/touchscreen/synaptics_tcm/synaptics_tcm_spi.c @@ -649,13 +649,13 @@ static struct spi_driver syna_tcm_spi_driver = { .id_table = syna_tcm_id_table, }; -int syna_tcm_bus_init_spi(void) +int syna_tcm_bus_init(void) { return spi_register_driver(&syna_tcm_spi_driver); } -EXPORT_SYMBOL(syna_tcm_bus_init_spi); +EXPORT_SYMBOL(syna_tcm_bus_init); -void syna_tcm_bus_exit_spi(void) +void syna_tcm_bus_exit(void) { kfree(buf); @@ -663,7 +663,7 @@ void syna_tcm_bus_exit_spi(void) spi_unregister_driver(&syna_tcm_spi_driver); } -EXPORT_SYMBOL(syna_tcm_bus_exit_spi); +EXPORT_SYMBOL(syna_tcm_bus_exit); MODULE_AUTHOR("Synaptics, Inc."); MODULE_DESCRIPTION("Synaptics TCM SPI Bus Module"); From f057612d4fcbd25232d6934a2940d614fc2ae55b Mon Sep 17 00:00:00 2001 From: Ravikanth Tuniki Date: Fri, 9 Oct 2020 17:48:39 +0530 Subject: [PATCH 058/698] input: touchscreen: Enable Synaptics tcm Modules Add Synaptics Touch Driver as Modules for Holi GKI. Change-Id: I3ae42384313d1c96ffec8538c9497a6e277b8c8b Signed-off-by: Ravikanth Tuniki Signed-off-by: Niranjan Reddy Dumbala --- arch/arm64/configs/vendor/holi_GKI.config | 11 +++++++++++ drivers/input/touchscreen/Kconfig | 12 ------------ drivers/input/touchscreen/synaptics_tcm/Kconfig | 16 +++------------- drivers/input/touchscreen/synaptics_tcm/Makefile | 3 ++- .../synaptics_tcm/synaptics_tcm_core.h | 4 ++++ .../synaptics_tcm/synaptics_tcm_spi.c | 8 ++++---- 6 files changed, 24 insertions(+), 30 deletions(-) diff --git a/arch/arm64/configs/vendor/holi_GKI.config b/arch/arm64/configs/vendor/holi_GKI.config index 291a9ff05f1d..0ec68f3f69ed 100644 --- a/arch/arm64/configs/vendor/holi_GKI.config +++ b/arch/arm64/configs/vendor/holi_GKI.config @@ -126,6 +126,17 @@ CONFIG_HEADER_TEST=y CONFIG_HEADERS_INSTALL=y CONFIG_KERNEL_HEADER_TEST=y CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_SYNAPTICS_TCM=m +CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_SPI=m +CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_I2C=m +CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_CORE=m +CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_TOUCH=m +CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_DEVICE=m +CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_TESTING=m +CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_REFLASH=m +CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_RECOVERY=m +CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_ZEROFLASH=m +CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_DIAGNOSTICS=m CONFIG_TOUCHSCREEN_SYNAPTICS_DSX=y # CONFIG_TOUCHSCREEN_PROPERTIES is not set CONFIG_TOUCHSCREEN_USB_COMPOSITE=m diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index d37cd92620ec..38830610149c 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -1314,18 +1314,6 @@ source "drivers/input/touchscreen/st/Kconfig" source "drivers/input/touchscreen/focaltech_touch/Kconfig" -config TOUCHSCREEN_SYNAPTICS_TCM - bool "Synaptics TCM Touchscreen Driver" - depends on I2C - default y - help - Say Y here if you have a Synaptics Touchscreen. - - If unsure, say N. - - To compile this driver as a module, choose M here: the - module will be called synaptics_tcm. - source "drivers/input/touchscreen/synaptics_tcm/Kconfig" config TOUCHSCREEN_SYNAPTICS_DSX diff --git a/drivers/input/touchscreen/synaptics_tcm/Kconfig b/drivers/input/touchscreen/synaptics_tcm/Kconfig index 78c687df4fe6..6af7c9670065 100644 --- a/drivers/input/touchscreen/synaptics_tcm/Kconfig +++ b/drivers/input/touchscreen/synaptics_tcm/Kconfig @@ -2,21 +2,18 @@ # Synaptics TCM touchscreen driver configuration # menuconfig TOUCHSCREEN_SYNAPTICS_TCM - bool "Synaptics TCM touchscreen" - default y + tristate "Synaptics TCM touchscreen" help Say Y here if you have a Synaptics TCM touchscreen connected to your system. If unsure, say N. -if TOUCHSCREEN_SYNAPTICS_TCM - choice default TOUCHSCREEN_SYNAPTICS_TCM_I2C prompt "Synaptics TCM bus module" config TOUCHSCREEN_SYNAPTICS_TCM_I2C - bool "I2C" + tristate "I2C" depends on I2C help Say Y here to use I2C bus for communication. @@ -27,7 +24,7 @@ config TOUCHSCREEN_SYNAPTICS_TCM_I2C with touch controller. config TOUCHSCREEN_SYNAPTICS_TCM_SPI - bool "SPI" + tristate "SPI" depends on SPI_MASTER help Say Y here to use SPI bus for communication. @@ -42,7 +39,6 @@ endchoice config TOUCHSCREEN_SYNAPTICS_TCM_CORE tristate "Synaptics TCM core module" depends on I2C || SPI_MASTER - default y help Say Y here to enable core functionality. @@ -54,7 +50,6 @@ config TOUCHSCREEN_SYNAPTICS_TCM_CORE config TOUCHSCREEN_SYNAPTICS_TCM_TOUCH tristate "Synaptics TCM touch module" depends on TOUCHSCREEN_SYNAPTICS_TCM_CORE - default y help Say Y here to enable support for touch reporting. @@ -66,7 +61,6 @@ config TOUCHSCREEN_SYNAPTICS_TCM_TOUCH config TOUCHSCREEN_SYNAPTICS_TCM_DEVICE tristate "Synaptics TCM device module" depends on TOUCHSCREEN_SYNAPTICS_TCM_CORE - default y help Say Y here to enable support for TCM device functionality. @@ -89,7 +83,6 @@ config TOUCHSCREEN_SYNAPTICS_TCM_TESTING config TOUCHSCREEN_SYNAPTICS_TCM_REFLASH tristate "Synaptics TCM reflash module" depends on TOUCHSCREEN_SYNAPTICS_TCM_CORE - default y help Say Y here to enable support for reflash functionality. @@ -101,7 +94,6 @@ config TOUCHSCREEN_SYNAPTICS_TCM_REFLASH config TOUCHSCREEN_SYNAPTICS_TCM_RECOVERY tristate "Synaptics TCM recovery module" depends on TOUCHSCREEN_SYNAPTICS_TCM_CORE - default y help Say Y here to enable support for recovery functionality. @@ -124,7 +116,6 @@ config TOUCHSCREEN_SYNAPTICS_TCM_ZEROFLASH config TOUCHSCREEN_SYNAPTICS_TCM_DIAGNOSTICS tristate "Synaptics TCM diagnostics module" depends on TOUCHSCREEN_SYNAPTICS_TCM_CORE - default y help Say Y here to enable support for diagnostics functionality. @@ -132,4 +123,3 @@ config TOUCHSCREEN_SYNAPTICS_TCM_DIAGNOSTICS To compile this driver as a module, choose M here: the module will be called synaptics_tcm_diagnostics. -endif diff --git a/drivers/input/touchscreen/synaptics_tcm/Makefile b/drivers/input/touchscreen/synaptics_tcm/Makefile index 30db3b56516a..3292047e442d 100644 --- a/drivers/input/touchscreen/synaptics_tcm/Makefile +++ b/drivers/input/touchscreen/synaptics_tcm/Makefile @@ -6,7 +6,8 @@ obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_SPI) += synaptics_tcm_spi.o obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_I2C) += synaptics_tcm_i2c.o -obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_CORE) += synaptics_tcm_core.o +obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_CORE) += qcom_synaptics_tcm_core.o +qcom_synaptics_tcm_core-y += synaptics_tcm_core.o synaptics_tcm_i2c.o obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_TOUCH) += synaptics_tcm_touch.o obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_DEVICE) += synaptics_tcm_device.o obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_TESTING) += synaptics_tcm_testing.o diff --git a/drivers/input/touchscreen/synaptics_tcm/synaptics_tcm_core.h b/drivers/input/touchscreen/synaptics_tcm/synaptics_tcm_core.h index 9bbccc7d915c..62f36bdd55a4 100644 --- a/drivers/input/touchscreen/synaptics_tcm/synaptics_tcm_core.h +++ b/drivers/input/touchscreen/synaptics_tcm/synaptics_tcm_core.h @@ -528,6 +528,10 @@ int syna_tcm_bus_init(void); void syna_tcm_bus_exit(void); +int syna_tcm_bus_init_spi(void); + +void syna_tcm_bus_exit_spi(void); + int syna_tcm_add_module(struct syna_tcm_module_cb *mod_cb, bool insert); static inline int syna_tcm_rmi_read(struct syna_tcm_hcd *tcm_hcd, diff --git a/drivers/input/touchscreen/synaptics_tcm/synaptics_tcm_spi.c b/drivers/input/touchscreen/synaptics_tcm/synaptics_tcm_spi.c index e54269c0f333..ee8751ac52f2 100644 --- a/drivers/input/touchscreen/synaptics_tcm/synaptics_tcm_spi.c +++ b/drivers/input/touchscreen/synaptics_tcm/synaptics_tcm_spi.c @@ -649,13 +649,13 @@ static struct spi_driver syna_tcm_spi_driver = { .id_table = syna_tcm_id_table, }; -int syna_tcm_bus_init(void) +int syna_tcm_bus_init_spi(void) { return spi_register_driver(&syna_tcm_spi_driver); } -EXPORT_SYMBOL(syna_tcm_bus_init); +EXPORT_SYMBOL(syna_tcm_bus_init_spi); -void syna_tcm_bus_exit(void) +void syna_tcm_bus_exit_spi(void) { kfree(buf); @@ -663,7 +663,7 @@ void syna_tcm_bus_exit(void) spi_unregister_driver(&syna_tcm_spi_driver); } -EXPORT_SYMBOL(syna_tcm_bus_exit); +EXPORT_SYMBOL(syna_tcm_bus_exit_spi); MODULE_AUTHOR("Synaptics, Inc."); MODULE_DESCRIPTION("Synaptics TCM SPI Bus Module"); From d9e9e40b8ae594ca5c754ae767e030bd2f7f1efe Mon Sep 17 00:00:00 2001 From: Gaurav Singh Date: Tue, 20 Oct 2020 14:53:16 +0530 Subject: [PATCH 059/698] drivers: soc: qcom: msm_performance: plh interface support Initial support of rimps PLH interface. This interface exposes sysfs nodes required to configure PLH running in rimps. Change-Id: I3b93d97296dafa5c31ecc27447579da263e82f31 Signed-off-by: Gaurav Singh --- drivers/soc/qcom/Kconfig | 10 ++ drivers/soc/qcom/msm_performance.c | 176 +++++++++++++++++++++++++++-- 2 files changed, 175 insertions(+), 11 deletions(-) diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index ac125cd94bb6..49f75799e090 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -600,6 +600,16 @@ config MSM_PERFORMANCE fmin and fmax. The user space can request the cpu freq change by writing cpu#:freq values +config QTI_PLH + bool "Qualcomm Technologies Inc. RIMPS PLH interface" + depends on ARM_SCMI_PROTOCOL && MSM_PERFORMANCE + default n + help + Interface between RIMPS PLH and userspace. + + This interface is responsible for handling the communication + with RIMPS PLH such as passing tunables, enable and disable. + config QMP_DEBUGFS_CLIENT bool "Debugfs Client to communicate with AOP using QMP protocol" depends on DEBUG_FS diff --git a/drivers/soc/qcom/msm_performance.c b/drivers/soc/qcom/msm_performance.c index 8e088c50f4c0..d9c5047f2e4c 100644 --- a/drivers/soc/qcom/msm_performance.c +++ b/drivers/soc/qcom/msm_performance.c @@ -25,6 +25,7 @@ #include #include #include +#include /* * Sched will provide the data for every 20ms window, @@ -926,20 +927,162 @@ static const struct kernel_param_ops param_ops_game_start_pid = { module_param_cb(evnt_gplaf_pid, ¶m_ops_game_start_pid, NULL, 0644); /*******************************GFX Call************************************/ - -static int splh_notif; -static void init_splh_notif(const char *buf) +#ifdef CONFIG_QTI_PLH +static struct scmi_handle *plh_handle; +void rimps_plh_init(struct scmi_handle *handle) { - /*buf contains the init info from user*/ - if (buf == NULL) - return; + if (handle) + plh_handle = handle; +} +EXPORT_SYMBOL(rimps_plh_init); - pr_debug("msm_perf:Init info for scroll :: %s\n", buf); +static int splh_notif, splh_init_done, plh_log_level; + +#define PLH_MIN_LOG_LEVEL 0 +#define PLH_MAX_LOG_LEVEL 0xF +#define SPLH_FPS_MAX_CNT 8 +#define SPLH_IPC_FREQ_VTBL_MAX_CNT 5 /* ipc freq pair */ +#define SPLH_INIT_IPC_FREQ_TBL_PARAMS \ + (2 + SPLH_FPS_MAX_CNT * (1 + (2 * SPLH_IPC_FREQ_VTBL_MAX_CNT))) + +static int set_plh_log_level(const char *buf, const struct kernel_param *kp) +{ + int ret, log_val_backup; + struct scmi_plh_vendor_ops *ops; + + if (!plh_handle || !plh_handle->plh_ops) { + pr_err("msm_perf: plh scmi handle or vendor ops null\n"); + return -EINVAL; + } + + ops = plh_handle->plh_ops; + + log_val_backup = plh_log_level; + + ret = param_set_int(buf, kp); /* Updates plh_log_level */ + if (ret < 0) { + pr_err("msm_perf: getting new plh_log_level failed, ret=%d\n", ret); + return ret; + } + + plh_log_level = clamp(plh_log_level, PLH_MIN_LOG_LEVEL, PLH_MAX_LOG_LEVEL); + ret = ops->set_plh_log_level(plh_handle, plh_log_level); + if (ret < 0) { + plh_log_level = log_val_backup; + pr_err("msm_perf: setting new plh_log_level failed, ret=%d\n", ret); + return ret; + } + return 0; +} + +static const struct kernel_param_ops param_ops_plh_log_level = { + .set = set_plh_log_level, + .get = param_get_int, +}; +module_param_cb(plh_log_level, ¶m_ops_plh_log_level, &plh_log_level, 0644); + +static int init_splh_notif(const char *buf) +{ + int i, j, ret; + u16 tmp[SPLH_INIT_IPC_FREQ_TBL_PARAMS]; + u16 *ptmp = tmp, ntokens, nfps, n_ipc_freq_pair, tmp_valid_len = 0; + const char *cp, *cp1; + struct scmi_plh_vendor_ops *ops; + + /* buf contains the init info from user */ + if (buf == NULL || !plh_handle || !plh_handle->plh_ops) + return -EINVAL; + + cp = buf; + ntokens = 0; + while ((cp = strpbrk(cp + 1, ":"))) + ntokens++; + + /* format of cmd nfps, n_ipc_freq_pair, ,...>,... */ + cp = buf; + if (sscanf(cp, INIT ":%hu", &nfps)) { + if ((nfps != ntokens-1) || (nfps == 0) || (nfps > SPLH_FPS_MAX_CNT)) + return -EINVAL; + + cp = strnchr(cp, strlen(cp), ':'); /* skip INIT */ + cp++; + cp = strnchr(cp, strlen(cp), ':'); /* skip nfps */ + + *ptmp++ = nfps; /* nfps is first cmd param */ + tmp_valid_len++; + cp1 = cp; + ntokens = 0; + /* get count of nfps * n_ipc_freq_pair * */ + while ((cp1 = strpbrk(cp1 + 1, ","))) + ntokens++; + + if (ntokens % (2 * nfps)) /* ipc freq pair values should be multiple of nfps */ + return -EINVAL; + + n_ipc_freq_pair = ntokens / (2 * nfps); /* ipc_freq pair values for each FPS */ + if ((n_ipc_freq_pair == 0) || (n_ipc_freq_pair > SPLH_IPC_FREQ_VTBL_MAX_CNT)) + return -EINVAL; + + *ptmp++ = n_ipc_freq_pair; /* n_ipc_freq_pair is second cmd param */ + tmp_valid_len++; + cp1 = cp; + for (i = 0; i < nfps; i++) { + if (sscanf(cp1, ":%hu", ptmp) != 1) + return -EINVAL; + + ptmp++; /* increment after storing FPS val */ + tmp_valid_len++; + cp1 = strnchr(cp1, strlen(cp1), ','); /* move to ,ipc */ + for (j = 0; j < 2 * n_ipc_freq_pair; j++) { + if (sscanf(cp1, ",%hu", ptmp) != 1) + return -EINVAL; + + ptmp++; /* increment after storing ipc or freq */ + tmp_valid_len++; + cp1++; + if (j != (2 * n_ipc_freq_pair - 1)) + cp1 = strnchr(cp1, strlen(cp1), ','); /* move to next */ + } + + if (i != (nfps - 1)) + cp1 = strnchr(cp1, strlen(cp1), ':'); /* move to next FPS val */ + + } + } else { + return -EINVAL; + } + + ops = plh_handle->plh_ops; + ret = ops->init_splh_ipc_freq_tbl(plh_handle, tmp, tmp_valid_len); + if (ret < 0) + return -EINVAL; + + pr_info("msm_perf: nfps=%hu n_ipc_freq_pair=%hu last_freq_val=%hu len=%hu\n", + nfps, n_ipc_freq_pair, *--ptmp, tmp_valid_len); + splh_init_done = 1; + return 0; } static void activate_splh_notif(void) { - /*received event notification here*/ + int ret; + struct scmi_plh_vendor_ops *ops; + /* received event notification here */ + if (!plh_handle || !plh_handle->plh_ops) { + pr_err("msm_perf: splh not supported\n"); + return; + } + ops = plh_handle->plh_ops; + + if (splh_notif) + ret = ops->start_splh(plh_handle, splh_notif); /* splh_notif is fps */ + else + ret = ops->stop_splh(plh_handle); + + if (ret < 0) { + pr_err("msm_perf: splh start or stop failed, ret=%d\n", ret); + return; + } } static int set_splh_notif(const char *buf, const struct kernel_param *kp) @@ -947,8 +1090,17 @@ static int set_splh_notif(const char *buf, const struct kernel_param *kp) int ret; if (strnstr(buf, INIT, sizeof(INIT)) != NULL) { - init_splh_notif(buf); - return 0; + splh_init_done = 0; + ret = init_splh_notif(buf); + if (ret < 0) + pr_err("msm_perf: splh ipc freq tbl init failed, ret=%d\n", ret); + + return ret; + } + + if (!splh_init_done) { + pr_err("msm_perf: splh ipc freq tbl not initialized\n"); + return -EINVAL; } ret = param_set_int(buf, kp); @@ -957,7 +1109,7 @@ static int set_splh_notif(const char *buf, const struct kernel_param *kp) activate_splh_notif(); - return ret; + return 0; } static const struct kernel_param_ops param_ops_splh_notification = { @@ -965,6 +1117,8 @@ static const struct kernel_param_ops param_ops_splh_notification = { .get = param_get_int, }; module_param_cb(splh_notif, ¶m_ops_splh_notification, &splh_notif, 0644); +#endif /* CONFIG_QTI_PLH */ + static int __init msm_performance_init(void) { From 0e6c804df3aa293d56c2783e29b3117dc60ae06e Mon Sep 17 00:00:00 2001 From: Gaurav Singh Date: Tue, 20 Oct 2020 15:05:24 +0530 Subject: [PATCH 060/698] defconfig: enable rimps plh interface Enables SCMI PLH protocol, SCMI client and RIMPS PLH interface. Change-Id: Iaa6526b4977dbe025613bc6432d31d07080d51aa Signed-off-by: Gaurav Singh --- arch/arm64/configs/vendor/holi_QGKI.config | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm64/configs/vendor/holi_QGKI.config b/arch/arm64/configs/vendor/holi_QGKI.config index 4a0572eea2e5..970354799781 100644 --- a/arch/arm64/configs/vendor/holi_QGKI.config +++ b/arch/arm64/configs/vendor/holi_QGKI.config @@ -179,6 +179,9 @@ CONFIG_QTI_HW_MEMLAT_SCMI_CLIENT=y CONFIG_SRAM=y CONFIG_QTI_HW_MEMLAT_LOG=y CONFIG_MSM_PERFORMANCE=y +CONFIG_QTI_SCMI_PLH_PROTOCOL=y +CONFIG_QTI_PLH=y +CONFIG_QTI_PLH_SCMI_CLIENT=y # CONFIG_USB_CONFIGFS_RNDIS is not set CONFIG_QCOM_INITIAL_LOGBUF=y CONFIG_QCOM_MINIDUMP_FTRACE=y From a73cee6daad3411475d9c06c7df0f89e3b9a448c Mon Sep 17 00:00:00 2001 From: Hareesh Gundu Date: Tue, 20 Oct 2020 19:07:46 +0530 Subject: [PATCH 061/698] msm: kgsl: Add support for voting vdd parent supply voltage For RPM based targets which have the dedicated GFX rails requires voting of vdd parent supply. Hence add support to vote for vdd parent supply. Change-Id: I3301b9b5f07d8e928a64b7013ec40b7c54e596ca Signed-off-by: Hareesh Gundu --- drivers/gpu/msm/adreno.c | 7 +++++++ drivers/gpu/msm/kgsl_pwrctrl.c | 30 ++++++++++++++++++++++++++++-- drivers/gpu/msm/kgsl_pwrctrl.h | 4 ++++ drivers/gpu/msm/kgsl_util.c | 16 ++++++++++++++++ drivers/gpu/msm/kgsl_util.h | 12 +++++++++++- 5 files changed, 66 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c index d2e5dc10bc48..bbd27386a891 100644 --- a/drivers/gpu/msm/adreno.c +++ b/drivers/gpu/msm/adreno.c @@ -3572,9 +3572,16 @@ static void adreno_regulator_disable_poll(struct kgsl_device *device) { struct kgsl_pwrctrl *pwr = &device->pwrctrl; + /* Set the parent in retention voltage to disable CPR interrupts */ + kgsl_regulator_set_voltage(device->dev, pwr->gx_gdsc_parent, + pwr->gx_gdsc_parent_min_corner); + if (!kgsl_regulator_disable_wait(pwr->gx_gdsc, 200)) dev_err(device->dev, "Regulator vdd is stuck on\n"); + /* Remove the vote for the vdd parent supply */ + kgsl_regulator_set_voltage(device->dev, pwr->gx_gdsc_parent, 0); + if (!kgsl_regulator_disable_wait(pwr->cx_gdsc, 200)) dev_err(device->dev, "Regulator vddcx is stuck on\n"); } diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c index b6b25053ce38..88ac2285245e 100644 --- a/drivers/gpu/msm/kgsl_pwrctrl.c +++ b/drivers/gpu/msm/kgsl_pwrctrl.c @@ -14,6 +14,7 @@ #include "kgsl_pwrscale.h" #include "kgsl_sysfs.h" #include "kgsl_trace.h" +#include "kgsl_util.h" #define UPDATE_BUSY_VAL 1000000 @@ -1328,8 +1329,15 @@ static int enable_regulators(struct kgsl_device *device) return 0; ret = enable_regulator(&device->pdev->dev, pwr->cx_gdsc, "vddcx"); - if (!ret) - ret = enable_regulator(&device->pdev->dev, pwr->gx_gdsc, "vdd"); + if (!ret) { + /* Set parent in retention voltage to power up vdd supply */ + ret = kgsl_regulator_set_voltage(device->dev, + pwr->gx_gdsc_parent, + pwr->gx_gdsc_parent_min_corner); + if (!ret) + ret = enable_regulator(&device->pdev->dev, + pwr->gx_gdsc, "vdd"); + } if (ret) { clear_bit(KGSL_PWRFLAGS_POWER_ON, &pwr->power_flags); @@ -1572,6 +1580,24 @@ int kgsl_pwrctrl_init(struct kgsl_device *device) if (of_property_read_bool(pdev->dev.of_node, "vdd-supply")) pwr->gx_gdsc = devm_regulator_get(&pdev->dev, "vdd"); + if (of_property_read_bool(pdev->dev.of_node, "vdd-parent-supply")) { + pwr->gx_gdsc_parent = devm_regulator_get(&pdev->dev, + "vdd-parent"); + if (IS_ERR(pwr->gx_gdsc_parent)) { + dev_err(device->dev, + "Failed to get vdd-parent regulator:%d\n", + PTR_ERR(pwr->gx_gdsc_parent)); + return -ENODEV; + } + if (of_property_read_u32(pdev->dev.of_node, + "vdd-parent-min-corner", + &pwr->gx_gdsc_parent_min_corner)) { + dev_err(device->dev, + "vdd-parent-min-corner not found\n"); + return -ENODEV; + } + } + pwr->power_flags = 0; pm_runtime_enable(&pdev->dev); diff --git a/drivers/gpu/msm/kgsl_pwrctrl.h b/drivers/gpu/msm/kgsl_pwrctrl.h index 82763ff0c63b..85da60b12332 100644 --- a/drivers/gpu/msm/kgsl_pwrctrl.h +++ b/drivers/gpu/msm/kgsl_pwrctrl.h @@ -120,6 +120,10 @@ struct kgsl_pwrctrl { struct regulator *cx_gdsc; /** @gx_gdsc: Pointer to the GX domain regulator if applicable */ struct regulator *gx_gdsc; + /** @gx_gdsc: Pointer to the GX domain parent supply */ + struct regulator *gx_gdsc_parent; + /** @gx_gdsc_parent_min_corner: Minimum supply voltage for GX parent */ + u32 gx_gdsc_parent_min_corner; int isense_clk_indx; int isense_clk_on_level; unsigned long power_flags; diff --git a/drivers/gpu/msm/kgsl_util.c b/drivers/gpu/msm/kgsl_util.c index d7ddc602f0d4..220304b6e0ed 100644 --- a/drivers/gpu/msm/kgsl_util.c +++ b/drivers/gpu/msm/kgsl_util.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -44,3 +45,18 @@ struct clk *kgsl_of_clk_by_name(struct clk_bulk_data *clks, int count, return NULL; } + +int kgsl_regulator_set_voltage(struct device *dev, + struct regulator *reg, u32 voltage) +{ + int ret; + + if (IS_ERR_OR_NULL(reg)) + return 0; + + ret = regulator_set_voltage(reg, voltage, INT_MAX); + if (ret) + dev_err(dev, "Regulator set voltage:%d failed:%d\n", voltage, ret); + + return ret; +} diff --git a/drivers/gpu/msm/kgsl_util.h b/drivers/gpu/msm/kgsl_util.h index 839c04ffc44d..f0490baf8fd9 100644 --- a/drivers/gpu/msm/kgsl_util.h +++ b/drivers/gpu/msm/kgsl_util.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. */ #ifndef _KGSL_UTIL_H_ @@ -32,4 +32,14 @@ bool kgsl_regulator_disable_wait(struct regulator *reg, u32 timeout); */ struct clk *kgsl_of_clk_by_name(struct clk_bulk_data *clks, int count, const char *id); +/** + * kgsl_regulator_set_voltage - Set voltage level for regulator + * @dev: A &struct device pointer + * @reg: A &struct regulator handle + * @voltage: Voltage value to set regulator + * + * Return: 0 on success and negative error on failure. + */ +int kgsl_regulator_set_voltage(struct device *dev, + struct regulator *reg, u32 voltage); #endif From 73c8b4e18bbff21d10d0f042166843fce13e6416 Mon Sep 17 00:00:00 2001 From: Mayank Grover Date: Mon, 2 Nov 2020 19:23:01 +0530 Subject: [PATCH 062/698] arm64: defconfig: Disable serial console defconfig Disable serial console defconfig for GKI defconfigs. Change-Id: I2123e04b93e3c331fdb9527a34f0485805726d19 Signed-off-by: Mayank Grover --- arch/arm64/configs/vendor/holi_GKI.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/configs/vendor/holi_GKI.config b/arch/arm64/configs/vendor/holi_GKI.config index 0ec68f3f69ed..3e32f50aa037 100644 --- a/arch/arm64/configs/vendor/holi_GKI.config +++ b/arch/arm64/configs/vendor/holi_GKI.config @@ -223,4 +223,4 @@ CONFIG_SPS_SUPPORT_NDP_BAM=y # CONFIG_SPS_SUPPORT_BAMDMA is not set # CONFIG_USB_BAM is not set CONFIG_QCOM_MEMORY_DUMP_V2=m -CONFIG_SERIAL_MSM_GENI_CONSOLE=y +# CONFIG_SERIAL_MSM_GENI_CONSOLE is not set From 390469d63d58fa9dbc6d11521f472529648d698c Mon Sep 17 00:00:00 2001 From: Monika Singh Date: Tue, 3 Nov 2020 16:39:49 +0530 Subject: [PATCH 063/698] kernel: arch: Enable qcedev as gki module Enabling qcedev and msm_qce modules as gki module. Change-Id: I583363213f229ec5a166d91af4a1424548ede335 Signed-off-by: Monika Singh --- arch/arm64/configs/vendor/holi_GKI.config | 2 ++ arch/arm64/configs/vendor/holi_QGKI.config | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/configs/vendor/holi_GKI.config b/arch/arm64/configs/vendor/holi_GKI.config index 3e32f50aa037..92e7f7769eba 100644 --- a/arch/arm64/configs/vendor/holi_GKI.config +++ b/arch/arm64/configs/vendor/holi_GKI.config @@ -144,6 +144,8 @@ CONFIG_TOUCHSCREEN_FTS=m CONFIG_QCOM_MPM=m CONFIG_NFC_QTI_I2C=m CONFIG_QCOM_SMCINVOKE=m +CONFIG_CRYPTO_DEV_QCOM_MSM_QCE=m +CONFIG_CRYPTO_DEV_QCEDEV=m CONFIG_HW_RANDOM_MSM_LEGACY=m CONFIG_SCSI_UFS_CRYPTO_QTI=m CONFIG_QTI_HW_KEY_MANAGER=m diff --git a/arch/arm64/configs/vendor/holi_QGKI.config b/arch/arm64/configs/vendor/holi_QGKI.config index 970354799781..9aa95fc543b1 100644 --- a/arch/arm64/configs/vendor/holi_QGKI.config +++ b/arch/arm64/configs/vendor/holi_QGKI.config @@ -110,9 +110,7 @@ CONFIG_SPS_SUPPORT_NDP_BAM=y CONFIG_USB_BAM=y CONFIG_USB_CONFIGFS_F_QDSS=y CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y -CONFIG_CRYPTO_DEV_QCOM_MSM_QCE=y CONFIG_CRYPTO_DEV_QCRYPTO=y -CONFIG_CRYPTO_DEV_QCEDEV=y CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y CONFIG_SLIMBUS=y CONFIG_QCOM_KGSL=y From 5f7b1f51126dd3c2dcbb9459db809693c65d0907 Mon Sep 17 00:00:00 2001 From: Yuanfang Zhang Date: Tue, 3 Nov 2020 17:22:43 +0800 Subject: [PATCH 064/698] coresight: byte-cnter: Add ETR status check in bypass notifier when usb_bypass_notify is called by ush_qdss_close(), no need to response to USB_QDSS_DISCONNECT event. so add etr status check to avoid exception. Change-Id: I4ab5d7f4ba054b0d1ecc7026b5662ddc1c8b5ca1 Signed-off-by: Yuanfang Zhang --- drivers/hwtracing/coresight/coresight-byte-cntr.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/hwtracing/coresight/coresight-byte-cntr.c b/drivers/hwtracing/coresight/coresight-byte-cntr.c index aa83c3660778..4be8fbda5a10 100644 --- a/drivers/hwtracing/coresight/coresight-byte-cntr.c +++ b/drivers/hwtracing/coresight/coresight-byte-cntr.c @@ -553,10 +553,9 @@ void usb_bypass_notifier(void *priv, unsigned int event, if (!drvdata) return; - if (tmcdrvdata->out_mode != TMC_ETR_OUT_MODE_USB - || tmcdrvdata->mode == CS_MODE_DISABLED) { + if (tmcdrvdata->out_mode != TMC_ETR_OUT_MODE_USB) { dev_err(&tmcdrvdata->csdev->dev, - "%s: ETR is not USB mode, or ETR is disabled.\n", __func__); + "%s: ETR is not USB mode\n", __func__); return; } @@ -571,6 +570,11 @@ void usb_bypass_notifier(void *priv, unsigned int event, break; case USB_QDSS_DISCONNECT: + if (tmcdrvdata->mode == CS_MODE_DISABLED) { + dev_err(&tmcdrvdata->csdev->dev, + "%s: ETR is disabled.\n", __func__); + return; + } usb_bypass_stop(drvdata); flush_work(&(drvdata->read_work)); usb_qdss_free_req(tmcdrvdata->usbch); From 00eb4a021a5994e742184bb12512afdbe6cb7c30 Mon Sep 17 00:00:00 2001 From: Ravikanth Tuniki Date: Tue, 3 Nov 2020 10:13:53 +0530 Subject: [PATCH 065/698] input: touchscreen: Remove linking across different modules Remove linking and create dependency by exporting the function in synaptics touch driver. Change-Id: I494d61fafbed516a39972521b14b0bfc2337b3bd Signed-off-by: Ravikanth Tuniki --- drivers/input/touchscreen/synaptics_tcm/Makefile | 3 +-- drivers/input/touchscreen/synaptics_tcm/synaptics_tcm_i2c.c | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/input/touchscreen/synaptics_tcm/Makefile b/drivers/input/touchscreen/synaptics_tcm/Makefile index 3292047e442d..30db3b56516a 100644 --- a/drivers/input/touchscreen/synaptics_tcm/Makefile +++ b/drivers/input/touchscreen/synaptics_tcm/Makefile @@ -6,8 +6,7 @@ obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_SPI) += synaptics_tcm_spi.o obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_I2C) += synaptics_tcm_i2c.o -obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_CORE) += qcom_synaptics_tcm_core.o -qcom_synaptics_tcm_core-y += synaptics_tcm_core.o synaptics_tcm_i2c.o +obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_CORE) += synaptics_tcm_core.o obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_TOUCH) += synaptics_tcm_touch.o obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_DEVICE) += synaptics_tcm_device.o obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_TESTING) += synaptics_tcm_testing.o diff --git a/drivers/input/touchscreen/synaptics_tcm/synaptics_tcm_i2c.c b/drivers/input/touchscreen/synaptics_tcm/synaptics_tcm_i2c.c index 1754a4fb5c25..483002ea129d 100644 --- a/drivers/input/touchscreen/synaptics_tcm/synaptics_tcm_i2c.c +++ b/drivers/input/touchscreen/synaptics_tcm/synaptics_tcm_i2c.c @@ -53,7 +53,7 @@ struct drm_panel *tcm_get_panel(void) { return active_tcm_panel; } - +EXPORT_SYMBOL(tcm_get_panel); #ifdef CONFIG_OF static int parse_dt(struct device *dev, struct syna_tcm_board_data *bdata) From 09a40b77869047e3aa849882c8d23c0cb178ce29 Mon Sep 17 00:00:00 2001 From: Prakash Gupta Date: Thu, 29 Oct 2020 10:30:23 +0530 Subject: [PATCH 066/698] mm/oom_kill: defer panic_on_oom for a timeout It takes sometime for complete memory reclaimed by oom kills to be available, specifically ion allocations. This either require FDs to be closed which is not covered by oom reaper or released by another process not being kiled. So defer panic_on_oom to avoid panic trigger before memory become available. Change-Id: I9f3312c780e4d8444f58de5f781c9c8dfec9b2c7 Signed-off-by: Prakash Gupta --- mm/oom_kill.c | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/mm/oom_kill.c b/mm/oom_kill.c index b7f119359db9..827ecdf51361 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c @@ -58,6 +58,9 @@ int sysctl_oom_kill_allocating_task; int sysctl_oom_dump_tasks = 1; int sysctl_reap_mem_on_sigkill = 1; +#ifdef CONFIG_PRIORITIZE_OOM_TASKS +static unsigned long panic_on_oom_timeout; +#endif static int panic_on_adj_zero; module_param(panic_on_adj_zero, int, 0644); @@ -925,6 +928,9 @@ static void __oom_kill_process(struct task_struct *victim, const char *message) * reserves from the user space under its control. */ do_send_sig_info(SIGKILL, SEND_SIG_PRIV, victim, PIDTYPE_TGID); +#ifdef CONFIG_PRIORITIZE_OOM_TASKS + panic_on_oom_timeout = 0; +#endif mark_oom_victim(victim); pr_err("%s: Killed process %d (%s) total-vm:%lukB, anon-rss:%lukB, file-rss:%lukB, shmem-rss:%lukB, UID:%u pgtables:%lukB oom_score_adj:%hd\n", message, task_pid_nr(victim), victim->comm, K(mm->total_vm), @@ -1039,6 +1045,8 @@ static void oom_kill_process(struct oom_control *oc, const char *message) } } +#define PANIC_ON_OOM_DEFER_TIMEOUT (5*HZ) +#define PANIC_ON_OOM_DEFER_WINDOW (20*HZ) /* * Determines whether the kernel must panic because of the panic_on_oom sysctl. */ @@ -1058,6 +1066,20 @@ static void check_panic_on_oom(struct oom_control *oc) /* Do not panic for oom kills triggered by sysrq */ if (is_sysrq_oom(oc)) return; + +#ifdef CONFIG_PRIORITIZE_OOM_TASKS + if (!panic_on_oom_timeout || + time_after_eq(jiffies, panic_on_oom_timeout + + PANIC_ON_OOM_DEFER_WINDOW)) { + panic_on_oom_timeout = jiffies + PANIC_ON_OOM_DEFER_TIMEOUT; + oc->chosen = (void *)-1UL; + return; + } else if (time_before_eq(jiffies, panic_on_oom_timeout)) { + oc->chosen = (void *)-1UL; + return; + } +#endif + dump_header(oc, NULL); panic("Out of memory: %s panic_on_oom is enabled\n", sysctl_panic_on_oom == 2 ? "compulsory" : "system-wide"); @@ -1169,10 +1191,11 @@ bool out_of_memory(struct oom_control *oc) } #endif - if (!oc->chosen) { + if (!oc->chosen) check_panic_on_oom(oc); + + if (!oc->chosen) select_bad_process(oc); - } /* Found nothing?!?! */ if (!oc->chosen) { @@ -1234,6 +1257,9 @@ void add_to_oom_reaper(struct task_struct *p) get_task_struct(p); if (task_will_free_mem(p)) { __mark_oom_victim(p); +#ifdef CONFIG_PRIORITIZE_OOM_TASKS + panic_on_oom_timeout = 0; +#endif wake_oom_reaper(p); } task_unlock(p); From 9c27f23d982a188b3422da6280f2ab4e29bf671d Mon Sep 17 00:00:00 2001 From: Raghavendra Kakarla Date: Thu, 5 Nov 2020 22:12:06 +0530 Subject: [PATCH 067/698] rpmsg: rpm-smd: Add null check for irq_chip affinity callback Add the null checks for irq_chip callback while calling affinity call of glink interrupt. Change-Id: I62cec6ade0233094ef9a821185677b703d3ba1a3 Signed-off-by: Raghavendra Kakarla --- drivers/rpmsg/rpm-smd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/rpmsg/rpm-smd.c b/drivers/rpmsg/rpm-smd.c index b075062ebda1..ed1f8175b485 100644 --- a/drivers/rpmsg/rpm-smd.c +++ b/drivers/rpmsg/rpm-smd.c @@ -1465,7 +1465,7 @@ static int smd_mask_receive_interrupt(bool mask, if (mask) { irq_chip->irq_mask(irq_data); - if (cpumask) + if (cpumask && irq_chip->irq_set_affinity) irq_chip->irq_set_affinity(irq_data, cpumask, true); } else { irq_chip->irq_unmask(irq_data); From 9b084251304d57c5ce5748fdf75096b16d4cd717 Mon Sep 17 00:00:00 2001 From: Kishore Sri venkata Ganesh Bolisetty Date: Thu, 5 Nov 2020 12:04:44 -0800 Subject: [PATCH 068/698] defconfig: enable QGKI & GKI apis of msm_performance driver CONFIG_MSM_PERFORMANCE_QGKI will enable full functionality of msm_performance driver on QGKI and minimal functionality on GKI. Change-Id: Ie2a2184c9390d904532c4d659d02562c93b7e725 Signed-off-by: Kishore Sri venkata Ganesh Bolisetty --- arch/arm64/configs/vendor/holi_GKI.config | 1 + arch/arm64/configs/vendor/holi_QGKI.config | 1 + arch/arm64/configs/vendor/lahaina_GKI.config | 1 + arch/arm64/configs/vendor/lahaina_QGKI.config | 1 + 4 files changed, 4 insertions(+) diff --git a/arch/arm64/configs/vendor/holi_GKI.config b/arch/arm64/configs/vendor/holi_GKI.config index 9291f20e503f..1c637282eeb5 100644 --- a/arch/arm64/configs/vendor/holi_GKI.config +++ b/arch/arm64/configs/vendor/holi_GKI.config @@ -227,3 +227,4 @@ CONFIG_SPS_SUPPORT_NDP_BAM=y # CONFIG_USB_BAM is not set CONFIG_QCOM_MEMORY_DUMP_V2=m # CONFIG_SERIAL_MSM_GENI_CONSOLE is not set +CONFIG_MSM_PERFORMANCE=m diff --git a/arch/arm64/configs/vendor/holi_QGKI.config b/arch/arm64/configs/vendor/holi_QGKI.config index 267b0dc3b287..3a51cfef1e89 100644 --- a/arch/arm64/configs/vendor/holi_QGKI.config +++ b/arch/arm64/configs/vendor/holi_QGKI.config @@ -179,6 +179,7 @@ CONFIG_MSM_PERFORMANCE=y CONFIG_QTI_SCMI_PLH_PROTOCOL=y CONFIG_QTI_PLH=y CONFIG_QTI_PLH_SCMI_CLIENT=y +CONFIG_MSM_PERFORMANCE_QGKI=y # CONFIG_USB_CONFIGFS_RNDIS is not set CONFIG_QCOM_INITIAL_LOGBUF=y CONFIG_QCOM_MINIDUMP_FTRACE=y diff --git a/arch/arm64/configs/vendor/lahaina_GKI.config b/arch/arm64/configs/vendor/lahaina_GKI.config index d2051c538853..a77a16026da9 100644 --- a/arch/arm64/configs/vendor/lahaina_GKI.config +++ b/arch/arm64/configs/vendor/lahaina_GKI.config @@ -233,3 +233,4 @@ CONFIG_ARCH_YUPIK=y CONFIG_PINCTRL_YUPIK=m CONFIG_QCOM_QFPROM_SYS=m CONFIG_RELAY=y +CONFIG_MSM_PERFORMANCE=m diff --git a/arch/arm64/configs/vendor/lahaina_QGKI.config b/arch/arm64/configs/vendor/lahaina_QGKI.config index 2d0ac316d41d..4a530bfa0223 100644 --- a/arch/arm64/configs/vendor/lahaina_QGKI.config +++ b/arch/arm64/configs/vendor/lahaina_QGKI.config @@ -123,6 +123,7 @@ CONFIG_QTI_QMI_SENSOR=y CONFIG_QTI_BCL_PMIC5=y CONFIG_QTI_BCL_SOC_DRIVER=y CONFIG_MSM_PERFORMANCE=y +CONFIG_MSM_PERFORMANCE_QGKI=y CONFIG_QTI_QMI_COOLING_DEVICE=y CONFIG_QTI_ADC_TM=y CONFIG_QTI_CPU_ISOLATE_COOLING_DEVICE=y From f7491798de4f0ad9936f27fba71872ebb5c84cfd Mon Sep 17 00:00:00 2001 From: Vijayanand Jitta Date: Fri, 6 Nov 2020 03:23:42 +0530 Subject: [PATCH 069/698] ion: Check for valid vmids for msm system heap Add a check for valid vmids before doing an allocation for msm system heap. This check does a hyp_assign on a page, stores the vmids and mark them as valid or invalid based on hyp_assign result. If vmid is invalid it returns or if its valid then proceeds with the allocation. So, this prevents ion pages leak in cases where hyp_assign fails. Also add a check for ion_hyp_assign_sg return value to prevent leak. Change-Id: Ibbc150490daf69d27b36db0e45a3c58496e6b9bd Signed-off-by: Vijayanand Jitta --- .../android/ion/heaps/ion_msm_system_heap.c | 71 +++++++++++++++++-- 1 file changed, 64 insertions(+), 7 deletions(-) diff --git a/drivers/staging/android/ion/heaps/ion_msm_system_heap.c b/drivers/staging/android/ion/heaps/ion_msm_system_heap.c index f57918149716..b7c4d7b67a75 100644 --- a/drivers/staging/android/ion/heaps/ion_msm_system_heap.c +++ b/drivers/staging/android/ion/heaps/ion_msm_system_heap.c @@ -34,6 +34,8 @@ static gfp_t low_order_gfp_flags = GFP_HIGHUSER | __GFP_ZERO; static bool pool_auto_refill_en __read_mostly = IS_ENABLED(CONFIG_ION_POOL_AUTO_REFILL); +static bool valid_vmids[VMID_LAST]; + int order_to_index(unsigned int order) { int i; @@ -274,6 +276,42 @@ static void process_info(struct page_info *info, kfree(info); } +static bool check_valid_vmid(int dest_vmid, struct ion_msm_system_heap *sys_heap) +{ + phys_addr_t addr; + struct page *page; + int ret; + bool from_pool = true; + u32 source_vmid = VMID_HLOS; + u32 dest_perms = msm_secure_get_vmid_perms(dest_vmid); + int order_ind = order_to_index(0); + + if (valid_vmids[dest_vmid]) + return true; + + page = ion_msm_page_pool_alloc(sys_heap->uncached_pools[order_ind], + &from_pool); + if (!page) + return false; + + if (!from_pool) + ion_pages_sync_for_device(sys_heap->heap.dev, + page, PAGE_SIZE, + DMA_BIDIRECTIONAL); + addr = page_to_phys(page); + ret = hyp_assign_phys(addr, PAGE_SIZE, &source_vmid, 1, + &dest_vmid, &dest_perms, 1); + if (ret) { + ion_msm_page_pool_free(sys_heap->uncached_pools[order_ind], + page); + return false; + } + valid_vmids[dest_vmid] = true; + ion_msm_page_pool_free(sys_heap->secure_pools[dest_vmid][order_ind], + page); + return true; +} + static int ion_msm_system_heap_allocate(struct ion_heap *heap, struct ion_buffer *buffer, unsigned long size, @@ -306,6 +344,19 @@ static int ion_msm_system_heap_allocate(struct ion_heap *heap, return -EINVAL; } + /* + * check if vmid is valid and skip this + * check for trusted vm vmids (i.e; for + * vmids > VMID_LAST) assuming vmids for + * trusted vm are already validated. + */ + if (vmid > 0 && vmid < VMID_LAST && + !check_valid_vmid(vmid, sys_heap)) { + pr_err("%s: VMID: %d not valid\n", + __func__, vmid); + return -EINVAL; + } + INIT_LIST_HEAD(&pages); INIT_LIST_HEAD(&pages_from_pool); @@ -392,8 +443,10 @@ static int ion_msm_system_heap_allocate(struct ion_heap *heap, if (nents_sync) { if (vmid > 0) { ret = ion_hyp_assign_sg(&table_sync, &vmid, 1, true); - if (ret) + if (ret == -EADDRNOTAVAIL) goto err_free_sg2; + else if (ret < 0) + goto err_free; } } @@ -412,16 +465,20 @@ static int ion_msm_system_heap_allocate(struct ion_heap *heap, return 0; err_free_sg2: - /* We failed to zero buffers. Bypass pool */ - buffer->private_flags |= ION_PRIV_FLAG_SHRINKER_FREE; - if (vmid > 0) - if (ion_hyp_unassign_sg(table, &vmid, 1, true)) + if (ion_hyp_unassign_sg(&table_sync, &vmid, 1, true)) goto err_free_table_sync; - - for_each_sg(table->sgl, sg, table->nents, i) +err_free: + for_each_sg(table->sgl, sg, table->nents, i) { + if (!PagePrivate(sg_page(sg))) { + /* Pages from buddy are not zeroed. Bypass pool */ + buffer->private_flags |= ION_PRIV_FLAG_SHRINKER_FREE; + } else { + buffer->private_flags &= ~ION_PRIV_FLAG_SHRINKER_FREE; + } free_buffer_page(sys_heap, buffer, sg_page(sg), get_order(sg->length)); + } err_free_table_sync: if (nents_sync) sg_free_table(&table_sync); From edbd5eca7004dee142e1d46604e207fa33156a5d Mon Sep 17 00:00:00 2001 From: Manikandan Mohan Date: Thu, 19 Nov 2020 15:46:36 -0800 Subject: [PATCH 070/698] Revert "cnss-utils: Compile firmware service file independently" This reverts commit cdcd29a2ca80d37abdefd3f46e88425d11a77078. Change-Id: I05dec617b22b6fa7bc6b3dde6d0e4f583b4aa00b Signed-off-by: Manikandan Mohan --- drivers/net/wireless/cnss2/Kconfig | 3 +- drivers/net/wireless/cnss2/Makefile | 3 +- .../cnss2/wlan_firmware_service_v01.c | 4545 +++++++++++++++++ .../cnss2/wlan_firmware_service_v01.h | 1203 +++++ drivers/net/wireless/cnss_utils/Kconfig | 10 +- drivers/net/wireless/cnss_utils/Makefile | 1 - drivers/soc/qcom/icnss2/Kconfig | 1 - drivers/soc/qcom/icnss2/Makefile | 3 +- .../qcom/icnss2}/wlan_firmware_service_v01.c | 1058 ++-- .../qcom/icnss2}/wlan_firmware_service_v01.h | 27 +- 10 files changed, 6127 insertions(+), 727 deletions(-) create mode 100644 drivers/net/wireless/cnss2/wlan_firmware_service_v01.c create mode 100644 drivers/net/wireless/cnss2/wlan_firmware_service_v01.h rename drivers/{net/wireless/cnss_utils => soc/qcom/icnss2}/wlan_firmware_service_v01.c (79%) rename drivers/{net/wireless/cnss_utils => soc/qcom/icnss2}/wlan_firmware_service_v01.h (98%) diff --git a/drivers/net/wireless/cnss2/Kconfig b/drivers/net/wireless/cnss2/Kconfig index 3d1c448edf47..406ef18e62a4 100644 --- a/drivers/net/wireless/cnss2/Kconfig +++ b/drivers/net/wireless/cnss2/Kconfig @@ -20,7 +20,6 @@ config CNSS2_DEBUG config CNSS2_QMI bool "CNSS2 Platform Driver QMI support" - select CNSS_QMI_SVC depends on CNSS2 help CNSS2 platform driver uses QMI framework to communicate with WLAN @@ -86,4 +85,4 @@ config CNSS_QCA6490 This enables the changes from WLAN host driver that are specific to CNSS QCA6490 chipset. These changes are needed to support the new hardware architecture - for CNSS QCA6490 chipset. + for CNSS QCA6490 chipset. \ No newline at end of file diff --git a/drivers/net/wireless/cnss2/Makefile b/drivers/net/wireless/cnss2/Makefile index 225622e76a68..023dd437adec 100644 --- a/drivers/net/wireless/cnss2/Makefile +++ b/drivers/net/wireless/cnss2/Makefile @@ -2,11 +2,10 @@ obj-$(CONFIG_CNSS2) += cnss2.o -ccflags-y += -I$(srctree)/drivers/net/wireless/cnss_utils/ cnss2-y := main.o cnss2-y += bus.o cnss2-y += debug.o cnss2-y += pci.o cnss2-y += power.o cnss2-y += genl.o -cnss2-$(CONFIG_CNSS2_QMI) += qmi.o coexistence_service_v01.o ip_multimedia_subsystem_private_service_v01.o device_management_service_v01.o +cnss2-$(CONFIG_CNSS2_QMI) += qmi.o wlan_firmware_service_v01.o coexistence_service_v01.o ip_multimedia_subsystem_private_service_v01.o device_management_service_v01.o diff --git a/drivers/net/wireless/cnss2/wlan_firmware_service_v01.c b/drivers/net/wireless/cnss2/wlan_firmware_service_v01.c new file mode 100644 index 000000000000..5caf7ffea1eb --- /dev/null +++ b/drivers/net/wireless/cnss2/wlan_firmware_service_v01.c @@ -0,0 +1,4545 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. */ + +#include "wlan_firmware_service_v01.h" + +static struct qmi_elem_info wlfw_ce_tgt_pipe_cfg_s_v01_ei[] = { + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct wlfw_ce_tgt_pipe_cfg_s_v01, + pipe_num), + }, + { + .data_type = QMI_SIGNED_4_BYTE_ENUM, + .elem_len = 1, + .elem_size = sizeof(enum wlfw_pipedir_enum_v01), + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct wlfw_ce_tgt_pipe_cfg_s_v01, + pipe_dir), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct wlfw_ce_tgt_pipe_cfg_s_v01, + nentries), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct wlfw_ce_tgt_pipe_cfg_s_v01, + nbytes_max), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct wlfw_ce_tgt_pipe_cfg_s_v01, + flags), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +static struct qmi_elem_info wlfw_ce_svc_pipe_cfg_s_v01_ei[] = { + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct wlfw_ce_svc_pipe_cfg_s_v01, + service_id), + }, + { + .data_type = QMI_SIGNED_4_BYTE_ENUM, + .elem_len = 1, + .elem_size = sizeof(enum wlfw_pipedir_enum_v01), + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct wlfw_ce_svc_pipe_cfg_s_v01, + pipe_dir), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct wlfw_ce_svc_pipe_cfg_s_v01, + pipe_num), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +static struct qmi_elem_info wlfw_shadow_reg_cfg_s_v01_ei[] = { + { + .data_type = QMI_UNSIGNED_2_BYTE, + .elem_len = 1, + .elem_size = sizeof(u16), + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct wlfw_shadow_reg_cfg_s_v01, + id), + }, + { + .data_type = QMI_UNSIGNED_2_BYTE, + .elem_len = 1, + .elem_size = sizeof(u16), + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct wlfw_shadow_reg_cfg_s_v01, + offset), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +static struct qmi_elem_info wlfw_shadow_reg_v2_cfg_s_v01_ei[] = { + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct wlfw_shadow_reg_v2_cfg_s_v01, + addr), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +static struct qmi_elem_info wlfw_rri_over_ddr_cfg_s_v01_ei[] = { + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct wlfw_rri_over_ddr_cfg_s_v01, + base_addr_low), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct wlfw_rri_over_ddr_cfg_s_v01, + base_addr_high), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +static struct qmi_elem_info wlfw_msi_cfg_s_v01_ei[] = { + { + .data_type = QMI_UNSIGNED_2_BYTE, + .elem_len = 1, + .elem_size = sizeof(u16), + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct wlfw_msi_cfg_s_v01, + ce_id), + }, + { + .data_type = QMI_UNSIGNED_2_BYTE, + .elem_len = 1, + .elem_size = sizeof(u16), + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct wlfw_msi_cfg_s_v01, + msi_vector), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +static struct qmi_elem_info wlfw_memory_region_info_s_v01_ei[] = { + { + .data_type = QMI_UNSIGNED_8_BYTE, + .elem_len = 1, + .elem_size = sizeof(u64), + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct wlfw_memory_region_info_s_v01, + region_addr), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct wlfw_memory_region_info_s_v01, + size), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct wlfw_memory_region_info_s_v01, + secure_flag), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +static struct qmi_elem_info wlfw_mem_cfg_s_v01_ei[] = { + { + .data_type = QMI_UNSIGNED_8_BYTE, + .elem_len = 1, + .elem_size = sizeof(u64), + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct wlfw_mem_cfg_s_v01, + offset), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct wlfw_mem_cfg_s_v01, + size), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct wlfw_mem_cfg_s_v01, + secure_flag), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +static struct qmi_elem_info wlfw_mem_seg_s_v01_ei[] = { + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct wlfw_mem_seg_s_v01, + size), + }, + { + .data_type = QMI_SIGNED_4_BYTE_ENUM, + .elem_len = 1, + .elem_size = sizeof(enum wlfw_mem_type_enum_v01), + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct wlfw_mem_seg_s_v01, + type), + }, + { + .data_type = QMI_DATA_LEN, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct wlfw_mem_seg_s_v01, + mem_cfg_len), + }, + { + .data_type = QMI_STRUCT, + .elem_len = QMI_WLFW_MAX_NUM_MEM_CFG_V01, + .elem_size = sizeof(struct wlfw_mem_cfg_s_v01), + .array_type = VAR_LEN_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct wlfw_mem_seg_s_v01, + mem_cfg), + .ei_array = wlfw_mem_cfg_s_v01_ei, + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +static struct qmi_elem_info wlfw_mem_seg_resp_s_v01_ei[] = { + { + .data_type = QMI_UNSIGNED_8_BYTE, + .elem_len = 1, + .elem_size = sizeof(u64), + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct wlfw_mem_seg_resp_s_v01, + addr), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct wlfw_mem_seg_resp_s_v01, + size), + }, + { + .data_type = QMI_SIGNED_4_BYTE_ENUM, + .elem_len = 1, + .elem_size = sizeof(enum wlfw_mem_type_enum_v01), + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct wlfw_mem_seg_resp_s_v01, + type), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct wlfw_mem_seg_resp_s_v01, + restore), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +static struct qmi_elem_info wlfw_rf_chip_info_s_v01_ei[] = { + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct wlfw_rf_chip_info_s_v01, + chip_id), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct wlfw_rf_chip_info_s_v01, + chip_family), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +static struct qmi_elem_info wlfw_rf_board_info_s_v01_ei[] = { + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct wlfw_rf_board_info_s_v01, + board_id), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +static struct qmi_elem_info wlfw_soc_info_s_v01_ei[] = { + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct wlfw_soc_info_s_v01, + soc_id), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +static struct qmi_elem_info wlfw_fw_version_info_s_v01_ei[] = { + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct wlfw_fw_version_info_s_v01, + fw_version), + }, + { + .data_type = QMI_STRING, + .elem_len = QMI_WLFW_MAX_TIMESTAMP_LEN_V01 + 1, + .elem_size = sizeof(char), + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct wlfw_fw_version_info_s_v01, + fw_build_timestamp), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +static struct qmi_elem_info wlfw_host_ddr_range_s_v01_ei[] = { + { + .data_type = QMI_UNSIGNED_8_BYTE, + .elem_len = 1, + .elem_size = sizeof(u64), + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct wlfw_host_ddr_range_s_v01, + start), + }, + { + .data_type = QMI_UNSIGNED_8_BYTE, + .elem_len = 1, + .elem_size = sizeof(u64), + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct wlfw_host_ddr_range_s_v01, + size), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + fw_ready_enable_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + fw_ready_enable), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x11, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + initiate_cal_download_enable_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x11, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + initiate_cal_download_enable), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x12, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + initiate_cal_update_enable_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x12, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + initiate_cal_update_enable), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x13, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + msa_ready_enable_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x13, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + msa_ready_enable), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x14, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + pin_connect_result_enable_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x14, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + pin_connect_result_enable), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x15, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + client_id_valid), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0x15, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + client_id), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x16, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + request_mem_enable_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x16, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + request_mem_enable), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x17, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + fw_mem_ready_enable_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x17, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + fw_mem_ready_enable), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x18, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + fw_init_done_enable_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x18, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + fw_init_done_enable), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x19, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + rejuvenate_enable_valid), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0x19, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + rejuvenate_enable), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x1A, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + xo_cal_enable_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x1A, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + xo_cal_enable), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x1B, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + cal_done_enable_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x1B, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + cal_done_enable), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x1C, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + qdss_trace_req_mem_enable_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x1C, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + qdss_trace_req_mem_enable), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x1D, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + qdss_trace_save_enable_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x1D, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + qdss_trace_save_enable), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x1E, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + qdss_trace_free_enable_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x1E, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + qdss_trace_free_enable), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x1F, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + respond_get_info_enable_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x1F, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + respond_get_info_enable), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x20, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + m3_dump_upload_req_enable_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x20, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + m3_dump_upload_req_enable), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x21, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + wfc_call_twt_config_enable_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x21, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + wfc_call_twt_config_enable), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x22, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + qdss_mem_ready_enable_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x22, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + qdss_mem_ready_enable), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_ind_register_resp_msg_v01_ei[] = { + { + .data_type = QMI_STRUCT, + .elem_len = 1, + .elem_size = sizeof(struct qmi_response_type_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x02, + .offset = offsetof(struct + wlfw_ind_register_resp_msg_v01, + resp), + .ei_array = qmi_response_type_v01_ei, + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct + wlfw_ind_register_resp_msg_v01, + fw_status_valid), + }, + { + .data_type = QMI_UNSIGNED_8_BYTE, + .elem_len = 1, + .elem_size = sizeof(u64), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct + wlfw_ind_register_resp_msg_v01, + fw_status), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_fw_ready_ind_msg_v01_ei[] = { + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_msa_ready_ind_msg_v01_ei[] = { + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct wlfw_msa_ready_ind_msg_v01, + hang_data_addr_offset_valid), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct wlfw_msa_ready_ind_msg_v01, + hang_data_addr_offset), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x11, + .offset = offsetof(struct wlfw_msa_ready_ind_msg_v01, + hang_data_length_valid), + }, + { + .data_type = QMI_UNSIGNED_2_BYTE, + .elem_len = 1, + .elem_size = sizeof(u16), + .array_type = NO_ARRAY, + .tlv_type = 0x11, + .offset = offsetof(struct wlfw_msa_ready_ind_msg_v01, + hang_data_length), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_pin_connect_result_ind_msg_v01_ei[] = { + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct + wlfw_pin_connect_result_ind_msg_v01, + pwr_pin_result_valid), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct + wlfw_pin_connect_result_ind_msg_v01, + pwr_pin_result), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x11, + .offset = offsetof(struct + wlfw_pin_connect_result_ind_msg_v01, + phy_io_pin_result_valid), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0x11, + .offset = offsetof(struct + wlfw_pin_connect_result_ind_msg_v01, + phy_io_pin_result), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x12, + .offset = offsetof(struct + wlfw_pin_connect_result_ind_msg_v01, + rf_pin_result_valid), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0x12, + .offset = offsetof(struct + wlfw_pin_connect_result_ind_msg_v01, + rf_pin_result), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_wlan_mode_req_msg_v01_ei[] = { + { + .data_type = QMI_SIGNED_4_BYTE_ENUM, + .elem_len = 1, + .elem_size = sizeof(enum wlfw_driver_mode_enum_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x01, + .offset = offsetof(struct wlfw_wlan_mode_req_msg_v01, + mode), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct wlfw_wlan_mode_req_msg_v01, + hw_debug_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct wlfw_wlan_mode_req_msg_v01, + hw_debug), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_wlan_mode_resp_msg_v01_ei[] = { + { + .data_type = QMI_STRUCT, + .elem_len = 1, + .elem_size = sizeof(struct qmi_response_type_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x02, + .offset = offsetof(struct wlfw_wlan_mode_resp_msg_v01, + resp), + .ei_array = qmi_response_type_v01_ei, + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_wlan_cfg_req_msg_v01_ei[] = { + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, + host_version_valid), + }, + { + .data_type = QMI_STRING, + .elem_len = QMI_WLFW_MAX_STR_LEN_V01 + 1, + .elem_size = sizeof(char), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, + host_version), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x11, + .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, + tgt_cfg_valid), + }, + { + .data_type = QMI_DATA_LEN, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x11, + .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, + tgt_cfg_len), + }, + { + .data_type = QMI_STRUCT, + .elem_len = QMI_WLFW_MAX_NUM_CE_V01, + .elem_size = sizeof(struct wlfw_ce_tgt_pipe_cfg_s_v01), + .array_type = VAR_LEN_ARRAY, + .tlv_type = 0x11, + .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, + tgt_cfg), + .ei_array = wlfw_ce_tgt_pipe_cfg_s_v01_ei, + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x12, + .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, + svc_cfg_valid), + }, + { + .data_type = QMI_DATA_LEN, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x12, + .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, + svc_cfg_len), + }, + { + .data_type = QMI_STRUCT, + .elem_len = QMI_WLFW_MAX_NUM_SVC_V01, + .elem_size = sizeof(struct wlfw_ce_svc_pipe_cfg_s_v01), + .array_type = VAR_LEN_ARRAY, + .tlv_type = 0x12, + .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, + svc_cfg), + .ei_array = wlfw_ce_svc_pipe_cfg_s_v01_ei, + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x13, + .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, + shadow_reg_valid), + }, + { + .data_type = QMI_DATA_LEN, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x13, + .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, + shadow_reg_len), + }, + { + .data_type = QMI_STRUCT, + .elem_len = QMI_WLFW_MAX_NUM_SHADOW_REG_V01, + .elem_size = sizeof(struct wlfw_shadow_reg_cfg_s_v01), + .array_type = VAR_LEN_ARRAY, + .tlv_type = 0x13, + .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, + shadow_reg), + .ei_array = wlfw_shadow_reg_cfg_s_v01_ei, + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x14, + .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, + shadow_reg_v2_valid), + }, + { + .data_type = QMI_DATA_LEN, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x14, + .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, + shadow_reg_v2_len), + }, + { + .data_type = QMI_STRUCT, + .elem_len = QMI_WLFW_MAX_NUM_SHADOW_REG_V2_V01, + .elem_size = sizeof(struct wlfw_shadow_reg_v2_cfg_s_v01), + .array_type = VAR_LEN_ARRAY, + .tlv_type = 0x14, + .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, + shadow_reg_v2), + .ei_array = wlfw_shadow_reg_v2_cfg_s_v01_ei, + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x15, + .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, + rri_over_ddr_cfg_valid), + }, + { + .data_type = QMI_STRUCT, + .elem_len = 1, + .elem_size = sizeof(struct wlfw_rri_over_ddr_cfg_s_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x15, + .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, + rri_over_ddr_cfg), + .ei_array = wlfw_rri_over_ddr_cfg_s_v01_ei, + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x16, + .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, + msi_cfg_valid), + }, + { + .data_type = QMI_DATA_LEN, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x16, + .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, + msi_cfg_len), + }, + { + .data_type = QMI_STRUCT, + .elem_len = QMI_WLFW_MAX_NUM_CE_V01, + .elem_size = sizeof(struct wlfw_msi_cfg_s_v01), + .array_type = VAR_LEN_ARRAY, + .tlv_type = 0x16, + .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, + msi_cfg), + .ei_array = wlfw_msi_cfg_s_v01_ei, + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_wlan_cfg_resp_msg_v01_ei[] = { + { + .data_type = QMI_STRUCT, + .elem_len = 1, + .elem_size = sizeof(struct qmi_response_type_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x02, + .offset = offsetof(struct wlfw_wlan_cfg_resp_msg_v01, + resp), + .ei_array = qmi_response_type_v01_ei, + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_cap_req_msg_v01_ei[] = { + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[] = { + { + .data_type = QMI_STRUCT, + .elem_len = 1, + .elem_size = sizeof(struct qmi_response_type_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x02, + .offset = offsetof(struct wlfw_cap_resp_msg_v01, + resp), + .ei_array = qmi_response_type_v01_ei, + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct wlfw_cap_resp_msg_v01, + chip_info_valid), + }, + { + .data_type = QMI_STRUCT, + .elem_len = 1, + .elem_size = sizeof(struct wlfw_rf_chip_info_s_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct wlfw_cap_resp_msg_v01, + chip_info), + .ei_array = wlfw_rf_chip_info_s_v01_ei, + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x11, + .offset = offsetof(struct wlfw_cap_resp_msg_v01, + board_info_valid), + }, + { + .data_type = QMI_STRUCT, + .elem_len = 1, + .elem_size = sizeof(struct wlfw_rf_board_info_s_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x11, + .offset = offsetof(struct wlfw_cap_resp_msg_v01, + board_info), + .ei_array = wlfw_rf_board_info_s_v01_ei, + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x12, + .offset = offsetof(struct wlfw_cap_resp_msg_v01, + soc_info_valid), + }, + { + .data_type = QMI_STRUCT, + .elem_len = 1, + .elem_size = sizeof(struct wlfw_soc_info_s_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x12, + .offset = offsetof(struct wlfw_cap_resp_msg_v01, + soc_info), + .ei_array = wlfw_soc_info_s_v01_ei, + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x13, + .offset = offsetof(struct wlfw_cap_resp_msg_v01, + fw_version_info_valid), + }, + { + .data_type = QMI_STRUCT, + .elem_len = 1, + .elem_size = sizeof(struct wlfw_fw_version_info_s_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x13, + .offset = offsetof(struct wlfw_cap_resp_msg_v01, + fw_version_info), + .ei_array = wlfw_fw_version_info_s_v01_ei, + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x14, + .offset = offsetof(struct wlfw_cap_resp_msg_v01, + fw_build_id_valid), + }, + { + .data_type = QMI_STRING, + .elem_len = QMI_WLFW_MAX_BUILD_ID_LEN_V01 + 1, + .elem_size = sizeof(char), + .array_type = NO_ARRAY, + .tlv_type = 0x14, + .offset = offsetof(struct wlfw_cap_resp_msg_v01, + fw_build_id), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x15, + .offset = offsetof(struct wlfw_cap_resp_msg_v01, + num_macs_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x15, + .offset = offsetof(struct wlfw_cap_resp_msg_v01, + num_macs), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x16, + .offset = offsetof(struct wlfw_cap_resp_msg_v01, + voltage_mv_valid), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0x16, + .offset = offsetof(struct wlfw_cap_resp_msg_v01, + voltage_mv), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x17, + .offset = offsetof(struct wlfw_cap_resp_msg_v01, + time_freq_hz_valid), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0x17, + .offset = offsetof(struct wlfw_cap_resp_msg_v01, + time_freq_hz), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x18, + .offset = offsetof(struct wlfw_cap_resp_msg_v01, + otp_version_valid), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0x18, + .offset = offsetof(struct wlfw_cap_resp_msg_v01, + otp_version), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x19, + .offset = offsetof(struct wlfw_cap_resp_msg_v01, + eeprom_caldata_read_timeout_valid), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0x19, + .offset = offsetof(struct wlfw_cap_resp_msg_v01, + eeprom_caldata_read_timeout), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x1A, + .offset = offsetof(struct wlfw_cap_resp_msg_v01, + fw_caps_valid), + }, + { + .data_type = QMI_UNSIGNED_8_BYTE, + .elem_len = 1, + .elem_size = sizeof(u64), + .array_type = NO_ARRAY, + .tlv_type = 0x1A, + .offset = offsetof(struct wlfw_cap_resp_msg_v01, + fw_caps), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_bdf_download_req_msg_v01_ei[] = { + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x01, + .offset = offsetof(struct wlfw_bdf_download_req_msg_v01, + valid), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct wlfw_bdf_download_req_msg_v01, + file_id_valid), + }, + { + .data_type = QMI_SIGNED_4_BYTE_ENUM, + .elem_len = 1, + .elem_size = sizeof(enum wlfw_cal_temp_id_enum_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct wlfw_bdf_download_req_msg_v01, + file_id), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x11, + .offset = offsetof(struct wlfw_bdf_download_req_msg_v01, + total_size_valid), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0x11, + .offset = offsetof(struct wlfw_bdf_download_req_msg_v01, + total_size), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x12, + .offset = offsetof(struct wlfw_bdf_download_req_msg_v01, + seg_id_valid), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0x12, + .offset = offsetof(struct wlfw_bdf_download_req_msg_v01, + seg_id), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x13, + .offset = offsetof(struct wlfw_bdf_download_req_msg_v01, + data_valid), + }, + { + .data_type = QMI_DATA_LEN, + .elem_len = 1, + .elem_size = sizeof(u16), + .array_type = NO_ARRAY, + .tlv_type = 0x13, + .offset = offsetof(struct wlfw_bdf_download_req_msg_v01, + data_len), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = QMI_WLFW_MAX_DATA_SIZE_V01, + .elem_size = sizeof(u8), + .array_type = VAR_LEN_ARRAY, + .tlv_type = 0x13, + .offset = offsetof(struct wlfw_bdf_download_req_msg_v01, + data), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x14, + .offset = offsetof(struct wlfw_bdf_download_req_msg_v01, + end_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x14, + .offset = offsetof(struct wlfw_bdf_download_req_msg_v01, + end), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x15, + .offset = offsetof(struct wlfw_bdf_download_req_msg_v01, + bdf_type_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x15, + .offset = offsetof(struct wlfw_bdf_download_req_msg_v01, + bdf_type), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_bdf_download_resp_msg_v01_ei[] = { + { + .data_type = QMI_STRUCT, + .elem_len = 1, + .elem_size = sizeof(struct qmi_response_type_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x02, + .offset = offsetof(struct + wlfw_bdf_download_resp_msg_v01, + resp), + .ei_array = qmi_response_type_v01_ei, + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct + wlfw_bdf_download_resp_msg_v01, + host_bdf_data_valid), + }, + { + .data_type = QMI_UNSIGNED_8_BYTE, + .elem_len = 1, + .elem_size = sizeof(u64), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct + wlfw_bdf_download_resp_msg_v01, + host_bdf_data), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_cal_report_req_msg_v01_ei[] = { + { + .data_type = QMI_DATA_LEN, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x01, + .offset = offsetof(struct wlfw_cal_report_req_msg_v01, + meta_data_len), + }, + { + .data_type = QMI_SIGNED_4_BYTE_ENUM, + .elem_len = QMI_WLFW_MAX_NUM_CAL_V01, + .elem_size = sizeof(enum wlfw_cal_temp_id_enum_v01), + .array_type = VAR_LEN_ARRAY, + .tlv_type = 0x01, + .offset = offsetof(struct wlfw_cal_report_req_msg_v01, + meta_data), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct wlfw_cal_report_req_msg_v01, + xo_cal_data_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct wlfw_cal_report_req_msg_v01, + xo_cal_data), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x11, + .offset = offsetof(struct wlfw_cal_report_req_msg_v01, + cal_remove_supported_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x11, + .offset = offsetof(struct wlfw_cal_report_req_msg_v01, + cal_remove_supported), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_cal_report_resp_msg_v01_ei[] = { + { + .data_type = QMI_STRUCT, + .elem_len = 1, + .elem_size = sizeof(struct qmi_response_type_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x02, + .offset = offsetof(struct wlfw_cal_report_resp_msg_v01, + resp), + .ei_array = qmi_response_type_v01_ei, + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_initiate_cal_download_ind_msg_v01_ei[] = { + { + .data_type = QMI_SIGNED_4_BYTE_ENUM, + .elem_len = 1, + .elem_size = sizeof(enum wlfw_cal_temp_id_enum_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x01, + .offset = offsetof(struct + wlfw_initiate_cal_download_ind_msg_v01, + cal_id), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct + wlfw_initiate_cal_download_ind_msg_v01, + total_size_valid), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct + wlfw_initiate_cal_download_ind_msg_v01, + total_size), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x11, + .offset = offsetof(struct + wlfw_initiate_cal_download_ind_msg_v01, + cal_data_location_valid), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0x11, + .offset = offsetof(struct + wlfw_initiate_cal_download_ind_msg_v01, + cal_data_location), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_cal_download_req_msg_v01_ei[] = { + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x01, + .offset = offsetof(struct wlfw_cal_download_req_msg_v01, + valid), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct wlfw_cal_download_req_msg_v01, + file_id_valid), + }, + { + .data_type = QMI_SIGNED_4_BYTE_ENUM, + .elem_len = 1, + .elem_size = sizeof(enum wlfw_cal_temp_id_enum_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct wlfw_cal_download_req_msg_v01, + file_id), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x11, + .offset = offsetof(struct wlfw_cal_download_req_msg_v01, + total_size_valid), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0x11, + .offset = offsetof(struct wlfw_cal_download_req_msg_v01, + total_size), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x12, + .offset = offsetof(struct wlfw_cal_download_req_msg_v01, + seg_id_valid), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0x12, + .offset = offsetof(struct wlfw_cal_download_req_msg_v01, + seg_id), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x13, + .offset = offsetof(struct wlfw_cal_download_req_msg_v01, + data_valid), + }, + { + .data_type = QMI_DATA_LEN, + .elem_len = 1, + .elem_size = sizeof(u16), + .array_type = NO_ARRAY, + .tlv_type = 0x13, + .offset = offsetof(struct wlfw_cal_download_req_msg_v01, + data_len), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = QMI_WLFW_MAX_DATA_SIZE_V01, + .elem_size = sizeof(u8), + .array_type = VAR_LEN_ARRAY, + .tlv_type = 0x13, + .offset = offsetof(struct wlfw_cal_download_req_msg_v01, + data), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x14, + .offset = offsetof(struct wlfw_cal_download_req_msg_v01, + end_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x14, + .offset = offsetof(struct wlfw_cal_download_req_msg_v01, + end), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x15, + .offset = offsetof(struct wlfw_cal_download_req_msg_v01, + cal_data_location_valid), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0x15, + .offset = offsetof(struct wlfw_cal_download_req_msg_v01, + cal_data_location), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_cal_download_resp_msg_v01_ei[] = { + { + .data_type = QMI_STRUCT, + .elem_len = 1, + .elem_size = sizeof(struct qmi_response_type_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x02, + .offset = offsetof(struct + wlfw_cal_download_resp_msg_v01, + resp), + .ei_array = qmi_response_type_v01_ei, + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_initiate_cal_update_ind_msg_v01_ei[] = { + { + .data_type = QMI_SIGNED_4_BYTE_ENUM, + .elem_len = 1, + .elem_size = sizeof(enum wlfw_cal_temp_id_enum_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x01, + .offset = offsetof(struct + wlfw_initiate_cal_update_ind_msg_v01, + cal_id), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0x02, + .offset = offsetof(struct + wlfw_initiate_cal_update_ind_msg_v01, + total_size), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct + wlfw_initiate_cal_update_ind_msg_v01, + cal_data_location_valid), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct + wlfw_initiate_cal_update_ind_msg_v01, + cal_data_location), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_cal_update_req_msg_v01_ei[] = { + { + .data_type = QMI_SIGNED_4_BYTE_ENUM, + .elem_len = 1, + .elem_size = sizeof(enum wlfw_cal_temp_id_enum_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x01, + .offset = offsetof(struct wlfw_cal_update_req_msg_v01, + cal_id), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0x02, + .offset = offsetof(struct wlfw_cal_update_req_msg_v01, + seg_id), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_cal_update_resp_msg_v01_ei[] = { + { + .data_type = QMI_STRUCT, + .elem_len = 1, + .elem_size = sizeof(struct qmi_response_type_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x02, + .offset = offsetof(struct wlfw_cal_update_resp_msg_v01, + resp), + .ei_array = qmi_response_type_v01_ei, + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct wlfw_cal_update_resp_msg_v01, + file_id_valid), + }, + { + .data_type = QMI_SIGNED_4_BYTE_ENUM, + .elem_len = 1, + .elem_size = sizeof(enum wlfw_cal_temp_id_enum_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct wlfw_cal_update_resp_msg_v01, + file_id), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x11, + .offset = offsetof(struct wlfw_cal_update_resp_msg_v01, + total_size_valid), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0x11, + .offset = offsetof(struct wlfw_cal_update_resp_msg_v01, + total_size), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x12, + .offset = offsetof(struct wlfw_cal_update_resp_msg_v01, + seg_id_valid), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0x12, + .offset = offsetof(struct wlfw_cal_update_resp_msg_v01, + seg_id), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x13, + .offset = offsetof(struct wlfw_cal_update_resp_msg_v01, + data_valid), + }, + { + .data_type = QMI_DATA_LEN, + .elem_len = 1, + .elem_size = sizeof(u16), + .array_type = NO_ARRAY, + .tlv_type = 0x13, + .offset = offsetof(struct wlfw_cal_update_resp_msg_v01, + data_len), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = QMI_WLFW_MAX_DATA_SIZE_V01, + .elem_size = sizeof(u8), + .array_type = VAR_LEN_ARRAY, + .tlv_type = 0x13, + .offset = offsetof(struct wlfw_cal_update_resp_msg_v01, + data), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x14, + .offset = offsetof(struct wlfw_cal_update_resp_msg_v01, + end_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x14, + .offset = offsetof(struct wlfw_cal_update_resp_msg_v01, + end), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x15, + .offset = offsetof(struct wlfw_cal_update_resp_msg_v01, + cal_data_location_valid), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0x15, + .offset = offsetof(struct wlfw_cal_update_resp_msg_v01, + cal_data_location), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_msa_info_req_msg_v01_ei[] = { + { + .data_type = QMI_UNSIGNED_8_BYTE, + .elem_len = 1, + .elem_size = sizeof(u64), + .array_type = NO_ARRAY, + .tlv_type = 0x01, + .offset = offsetof(struct wlfw_msa_info_req_msg_v01, + msa_addr), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0x02, + .offset = offsetof(struct wlfw_msa_info_req_msg_v01, + size), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_msa_info_resp_msg_v01_ei[] = { + { + .data_type = QMI_STRUCT, + .elem_len = 1, + .elem_size = sizeof(struct qmi_response_type_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x02, + .offset = offsetof(struct wlfw_msa_info_resp_msg_v01, + resp), + .ei_array = qmi_response_type_v01_ei, + }, + { + .data_type = QMI_DATA_LEN, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x03, + .offset = offsetof(struct wlfw_msa_info_resp_msg_v01, + mem_region_info_len), + }, + { + .data_type = QMI_STRUCT, + .elem_len = QMI_WLFW_MAX_NUM_MEMORY_REGIONS_V01, + .elem_size = sizeof(struct wlfw_memory_region_info_s_v01), + .array_type = VAR_LEN_ARRAY, + .tlv_type = 0x03, + .offset = offsetof(struct wlfw_msa_info_resp_msg_v01, + mem_region_info), + .ei_array = wlfw_memory_region_info_s_v01_ei, + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_msa_ready_req_msg_v01_ei[] = { + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_msa_ready_resp_msg_v01_ei[] = { + { + .data_type = QMI_STRUCT, + .elem_len = 1, + .elem_size = sizeof(struct qmi_response_type_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x02, + .offset = offsetof(struct wlfw_msa_ready_resp_msg_v01, + resp), + .ei_array = qmi_response_type_v01_ei, + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_ini_req_msg_v01_ei[] = { + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct wlfw_ini_req_msg_v01, + enablefwlog_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct wlfw_ini_req_msg_v01, + enablefwlog), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_ini_resp_msg_v01_ei[] = { + { + .data_type = QMI_STRUCT, + .elem_len = 1, + .elem_size = sizeof(struct qmi_response_type_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x02, + .offset = offsetof(struct wlfw_ini_resp_msg_v01, + resp), + .ei_array = qmi_response_type_v01_ei, + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_athdiag_read_req_msg_v01_ei[] = { + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0x01, + .offset = offsetof(struct wlfw_athdiag_read_req_msg_v01, + offset), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0x02, + .offset = offsetof(struct wlfw_athdiag_read_req_msg_v01, + mem_type), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0x03, + .offset = offsetof(struct wlfw_athdiag_read_req_msg_v01, + data_len), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_athdiag_read_resp_msg_v01_ei[] = { + { + .data_type = QMI_STRUCT, + .elem_len = 1, + .elem_size = sizeof(struct qmi_response_type_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x02, + .offset = offsetof(struct + wlfw_athdiag_read_resp_msg_v01, + resp), + .ei_array = qmi_response_type_v01_ei, + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct + wlfw_athdiag_read_resp_msg_v01, + data_valid), + }, + { + .data_type = QMI_DATA_LEN, + .elem_len = 1, + .elem_size = sizeof(u16), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct + wlfw_athdiag_read_resp_msg_v01, + data_len), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = QMI_WLFW_MAX_ATHDIAG_DATA_SIZE_V01, + .elem_size = sizeof(u8), + .array_type = VAR_LEN_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct + wlfw_athdiag_read_resp_msg_v01, + data), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_athdiag_write_req_msg_v01_ei[] = { + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0x01, + .offset = offsetof(struct + wlfw_athdiag_write_req_msg_v01, + offset), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0x02, + .offset = offsetof(struct + wlfw_athdiag_write_req_msg_v01, + mem_type), + }, + { + .data_type = QMI_DATA_LEN, + .elem_len = 1, + .elem_size = sizeof(u16), + .array_type = NO_ARRAY, + .tlv_type = 0x03, + .offset = offsetof(struct + wlfw_athdiag_write_req_msg_v01, + data_len), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = QMI_WLFW_MAX_ATHDIAG_DATA_SIZE_V01, + .elem_size = sizeof(u8), + .array_type = VAR_LEN_ARRAY, + .tlv_type = 0x03, + .offset = offsetof(struct + wlfw_athdiag_write_req_msg_v01, + data), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_athdiag_write_resp_msg_v01_ei[] = { + { + .data_type = QMI_STRUCT, + .elem_len = 1, + .elem_size = sizeof(struct qmi_response_type_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x02, + .offset = offsetof(struct + wlfw_athdiag_write_resp_msg_v01, + resp), + .ei_array = qmi_response_type_v01_ei, + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_vbatt_req_msg_v01_ei[] = { + { + .data_type = QMI_UNSIGNED_8_BYTE, + .elem_len = 1, + .elem_size = sizeof(u64), + .array_type = NO_ARRAY, + .tlv_type = 0x01, + .offset = offsetof(struct wlfw_vbatt_req_msg_v01, + voltage_uv), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_vbatt_resp_msg_v01_ei[] = { + { + .data_type = QMI_STRUCT, + .elem_len = 1, + .elem_size = sizeof(struct qmi_response_type_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x02, + .offset = offsetof(struct wlfw_vbatt_resp_msg_v01, + resp), + .ei_array = qmi_response_type_v01_ei, + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_mac_addr_req_msg_v01_ei[] = { + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct wlfw_mac_addr_req_msg_v01, + mac_addr_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = QMI_WLFW_MAC_ADDR_SIZE_V01, + .elem_size = sizeof(u8), + .array_type = STATIC_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct wlfw_mac_addr_req_msg_v01, + mac_addr), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_mac_addr_resp_msg_v01_ei[] = { + { + .data_type = QMI_STRUCT, + .elem_len = 1, + .elem_size = sizeof(struct qmi_response_type_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x02, + .offset = offsetof(struct wlfw_mac_addr_resp_msg_v01, + resp), + .ei_array = qmi_response_type_v01_ei, + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + num_clients_valid), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + num_clients), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x11, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + wake_msi_valid), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0x11, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + wake_msi), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x12, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + gpios_valid), + }, + { + .data_type = QMI_DATA_LEN, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x12, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + gpios_len), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = QMI_WLFW_MAX_NUM_GPIO_V01, + .elem_size = sizeof(u32), + .array_type = VAR_LEN_ARRAY, + .tlv_type = 0x12, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + gpios), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x13, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + nm_modem_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x13, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + nm_modem), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x14, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + bdf_support_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x14, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + bdf_support), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x15, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + bdf_cache_support_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x15, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + bdf_cache_support), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x16, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + m3_support_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x16, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + m3_support), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x17, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + m3_cache_support_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x17, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + m3_cache_support), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x18, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + cal_filesys_support_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x18, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + cal_filesys_support), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x19, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + cal_cache_support_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x19, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + cal_cache_support), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x1A, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + cal_done_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x1A, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + cal_done), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x1B, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + mem_bucket_valid), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0x1B, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + mem_bucket), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x1C, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + mem_cfg_mode_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x1C, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + mem_cfg_mode), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x1D, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + cal_duration_valid), + }, + { + .data_type = QMI_UNSIGNED_2_BYTE, + .elem_len = 1, + .elem_size = sizeof(u16), + .array_type = NO_ARRAY, + .tlv_type = 0x1D, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + cal_duration), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x1E, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + platform_name_valid), + }, + { + .data_type = QMI_STRING, + .elem_len = QMI_WLFW_MAX_PLATFORM_NAME_LEN_V01 + 1, + .elem_size = sizeof(char), + .array_type = NO_ARRAY, + .tlv_type = 0x1E, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + platform_name), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x1F, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + ddr_range_valid), + }, + { + .data_type = QMI_STRUCT, + .elem_len = QMI_WLFW_MAX_HOST_DDR_RANGE_SIZE_V01, + .elem_size = sizeof(struct wlfw_host_ddr_range_s_v01), + .array_type = STATIC_ARRAY, + .tlv_type = 0x1F, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + ddr_range), + .ei_array = wlfw_host_ddr_range_s_v01_ei, + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x20, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + host_build_type_valid), + }, + { + .data_type = QMI_SIGNED_4_BYTE_ENUM, + .elem_len = 1, + .elem_size = sizeof(enum wlfw_host_build_type_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x20, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + host_build_type), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_host_cap_resp_msg_v01_ei[] = { + { + .data_type = QMI_STRUCT, + .elem_len = 1, + .elem_size = sizeof(struct qmi_response_type_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x02, + .offset = offsetof(struct wlfw_host_cap_resp_msg_v01, + resp), + .ei_array = qmi_response_type_v01_ei, + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_request_mem_ind_msg_v01_ei[] = { + { + .data_type = QMI_DATA_LEN, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x01, + .offset = offsetof(struct wlfw_request_mem_ind_msg_v01, + mem_seg_len), + }, + { + .data_type = QMI_STRUCT, + .elem_len = QMI_WLFW_MAX_NUM_MEM_SEG_V01, + .elem_size = sizeof(struct wlfw_mem_seg_s_v01), + .array_type = VAR_LEN_ARRAY, + .tlv_type = 0x01, + .offset = offsetof(struct wlfw_request_mem_ind_msg_v01, + mem_seg), + .ei_array = wlfw_mem_seg_s_v01_ei, + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_respond_mem_req_msg_v01_ei[] = { + { + .data_type = QMI_DATA_LEN, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x01, + .offset = offsetof(struct wlfw_respond_mem_req_msg_v01, + mem_seg_len), + }, + { + .data_type = QMI_STRUCT, + .elem_len = QMI_WLFW_MAX_NUM_MEM_SEG_V01, + .elem_size = sizeof(struct wlfw_mem_seg_resp_s_v01), + .array_type = VAR_LEN_ARRAY, + .tlv_type = 0x01, + .offset = offsetof(struct wlfw_respond_mem_req_msg_v01, + mem_seg), + .ei_array = wlfw_mem_seg_resp_s_v01_ei, + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_respond_mem_resp_msg_v01_ei[] = { + { + .data_type = QMI_STRUCT, + .elem_len = 1, + .elem_size = sizeof(struct qmi_response_type_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x02, + .offset = offsetof(struct wlfw_respond_mem_resp_msg_v01, + resp), + .ei_array = qmi_response_type_v01_ei, + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_fw_mem_ready_ind_msg_v01_ei[] = { + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_fw_init_done_ind_msg_v01_ei[] = { + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_rejuvenate_ind_msg_v01_ei[] = { + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct wlfw_rejuvenate_ind_msg_v01, + cause_for_rejuvenation_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct wlfw_rejuvenate_ind_msg_v01, + cause_for_rejuvenation), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x11, + .offset = offsetof(struct wlfw_rejuvenate_ind_msg_v01, + requesting_sub_system_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x11, + .offset = offsetof(struct wlfw_rejuvenate_ind_msg_v01, + requesting_sub_system), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x12, + .offset = offsetof(struct wlfw_rejuvenate_ind_msg_v01, + line_number_valid), + }, + { + .data_type = QMI_UNSIGNED_2_BYTE, + .elem_len = 1, + .elem_size = sizeof(u16), + .array_type = NO_ARRAY, + .tlv_type = 0x12, + .offset = offsetof(struct wlfw_rejuvenate_ind_msg_v01, + line_number), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x13, + .offset = offsetof(struct wlfw_rejuvenate_ind_msg_v01, + function_name_valid), + }, + { + .data_type = QMI_STRING, + .elem_len = QMI_WLFW_FUNCTION_NAME_LEN_V01 + 1, + .elem_size = sizeof(char), + .array_type = NO_ARRAY, + .tlv_type = 0x13, + .offset = offsetof(struct wlfw_rejuvenate_ind_msg_v01, + function_name), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_rejuvenate_ack_req_msg_v01_ei[] = { + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_rejuvenate_ack_resp_msg_v01_ei[] = { + { + .data_type = QMI_STRUCT, + .elem_len = 1, + .elem_size = sizeof(struct qmi_response_type_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x02, + .offset = offsetof(struct + wlfw_rejuvenate_ack_resp_msg_v01, + resp), + .ei_array = qmi_response_type_v01_ei, + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_dynamic_feature_mask_req_msg_v01_ei[] = { + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct + wlfw_dynamic_feature_mask_req_msg_v01, + mask_valid), + }, + { + .data_type = QMI_UNSIGNED_8_BYTE, + .elem_len = 1, + .elem_size = sizeof(u64), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct + wlfw_dynamic_feature_mask_req_msg_v01, + mask), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_dynamic_feature_mask_resp_msg_v01_ei[] = { + { + .data_type = QMI_STRUCT, + .elem_len = 1, + .elem_size = sizeof(struct qmi_response_type_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x02, + .offset = offsetof(struct + wlfw_dynamic_feature_mask_resp_msg_v01, + resp), + .ei_array = qmi_response_type_v01_ei, + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct + wlfw_dynamic_feature_mask_resp_msg_v01, + prev_mask_valid), + }, + { + .data_type = QMI_UNSIGNED_8_BYTE, + .elem_len = 1, + .elem_size = sizeof(u64), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct + wlfw_dynamic_feature_mask_resp_msg_v01, + prev_mask), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x11, + .offset = offsetof(struct + wlfw_dynamic_feature_mask_resp_msg_v01, + curr_mask_valid), + }, + { + .data_type = QMI_UNSIGNED_8_BYTE, + .elem_len = 1, + .elem_size = sizeof(u64), + .array_type = NO_ARRAY, + .tlv_type = 0x11, + .offset = offsetof(struct + wlfw_dynamic_feature_mask_resp_msg_v01, + curr_mask), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_m3_info_req_msg_v01_ei[] = { + { + .data_type = QMI_UNSIGNED_8_BYTE, + .elem_len = 1, + .elem_size = sizeof(u64), + .array_type = NO_ARRAY, + .tlv_type = 0x01, + .offset = offsetof(struct wlfw_m3_info_req_msg_v01, + addr), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0x02, + .offset = offsetof(struct wlfw_m3_info_req_msg_v01, + size), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_m3_info_resp_msg_v01_ei[] = { + { + .data_type = QMI_STRUCT, + .elem_len = 1, + .elem_size = sizeof(struct qmi_response_type_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x02, + .offset = offsetof(struct wlfw_m3_info_resp_msg_v01, + resp), + .ei_array = qmi_response_type_v01_ei, + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_xo_cal_ind_msg_v01_ei[] = { + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x01, + .offset = offsetof(struct wlfw_xo_cal_ind_msg_v01, + xo_cal_data), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_cal_done_ind_msg_v01_ei[] = { + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_qdss_trace_req_mem_ind_msg_v01_ei[] = { + { + .data_type = QMI_DATA_LEN, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x01, + .offset = offsetof(struct + wlfw_qdss_trace_req_mem_ind_msg_v01, + mem_seg_len), + }, + { + .data_type = QMI_STRUCT, + .elem_len = QMI_WLFW_MAX_NUM_MEM_SEG_V01, + .elem_size = sizeof(struct wlfw_mem_seg_s_v01), + .array_type = VAR_LEN_ARRAY, + .tlv_type = 0x01, + .offset = offsetof(struct + wlfw_qdss_trace_req_mem_ind_msg_v01, + mem_seg), + .ei_array = wlfw_mem_seg_s_v01_ei, + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_qdss_trace_mem_info_req_msg_v01_ei[] = { + { + .data_type = QMI_DATA_LEN, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x01, + .offset = offsetof(struct + wlfw_qdss_trace_mem_info_req_msg_v01, + mem_seg_len), + }, + { + .data_type = QMI_STRUCT, + .elem_len = QMI_WLFW_MAX_NUM_MEM_SEG_V01, + .elem_size = sizeof(struct wlfw_mem_seg_resp_s_v01), + .array_type = VAR_LEN_ARRAY, + .tlv_type = 0x01, + .offset = offsetof(struct + wlfw_qdss_trace_mem_info_req_msg_v01, + mem_seg), + .ei_array = wlfw_mem_seg_resp_s_v01_ei, + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_qdss_trace_mem_info_resp_msg_v01_ei[] = { + { + .data_type = QMI_STRUCT, + .elem_len = 1, + .elem_size = sizeof(struct qmi_response_type_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x02, + .offset = offsetof(struct + wlfw_qdss_trace_mem_info_resp_msg_v01, + resp), + .ei_array = qmi_response_type_v01_ei, + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_qdss_trace_save_ind_msg_v01_ei[] = { + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0x01, + .offset = offsetof(struct + wlfw_qdss_trace_save_ind_msg_v01, + source), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0x02, + .offset = offsetof(struct + wlfw_qdss_trace_save_ind_msg_v01, + total_size), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct + wlfw_qdss_trace_save_ind_msg_v01, + mem_seg_valid), + }, + { + .data_type = QMI_DATA_LEN, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct + wlfw_qdss_trace_save_ind_msg_v01, + mem_seg_len), + }, + { + .data_type = QMI_STRUCT, + .elem_len = QMI_WLFW_MAX_NUM_MEM_SEG_V01, + .elem_size = sizeof(struct wlfw_mem_seg_resp_s_v01), + .array_type = VAR_LEN_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct + wlfw_qdss_trace_save_ind_msg_v01, + mem_seg), + .ei_array = wlfw_mem_seg_resp_s_v01_ei, + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x11, + .offset = offsetof(struct + wlfw_qdss_trace_save_ind_msg_v01, + file_name_valid), + }, + { + .data_type = QMI_STRING, + .elem_len = QMI_WLFW_MAX_STR_LEN_V01 + 1, + .elem_size = sizeof(char), + .array_type = NO_ARRAY, + .tlv_type = 0x11, + .offset = offsetof(struct + wlfw_qdss_trace_save_ind_msg_v01, + file_name), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_qdss_trace_data_req_msg_v01_ei[] = { + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0x01, + .offset = offsetof(struct + wlfw_qdss_trace_data_req_msg_v01, + seg_id), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_qdss_trace_data_resp_msg_v01_ei[] = { + { + .data_type = QMI_STRUCT, + .elem_len = 1, + .elem_size = sizeof(struct qmi_response_type_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x02, + .offset = offsetof(struct + wlfw_qdss_trace_data_resp_msg_v01, + resp), + .ei_array = qmi_response_type_v01_ei, + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct + wlfw_qdss_trace_data_resp_msg_v01, + total_size_valid), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct + wlfw_qdss_trace_data_resp_msg_v01, + total_size), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x11, + .offset = offsetof(struct + wlfw_qdss_trace_data_resp_msg_v01, + seg_id_valid), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0x11, + .offset = offsetof(struct + wlfw_qdss_trace_data_resp_msg_v01, + seg_id), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x12, + .offset = offsetof(struct + wlfw_qdss_trace_data_resp_msg_v01, + data_valid), + }, + { + .data_type = QMI_DATA_LEN, + .elem_len = 1, + .elem_size = sizeof(u16), + .array_type = NO_ARRAY, + .tlv_type = 0x12, + .offset = offsetof(struct + wlfw_qdss_trace_data_resp_msg_v01, + data_len), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = QMI_WLFW_MAX_DATA_SIZE_V01, + .elem_size = sizeof(u8), + .array_type = VAR_LEN_ARRAY, + .tlv_type = 0x12, + .offset = offsetof(struct + wlfw_qdss_trace_data_resp_msg_v01, + data), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x13, + .offset = offsetof(struct + wlfw_qdss_trace_data_resp_msg_v01, + end_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x13, + .offset = offsetof(struct + wlfw_qdss_trace_data_resp_msg_v01, + end), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_qdss_trace_config_download_req_msg_v01_ei[] = { + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct + wlfw_qdss_trace_config_download_req_msg_v01, + total_size_valid), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct + wlfw_qdss_trace_config_download_req_msg_v01, + total_size), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x11, + .offset = offsetof(struct + wlfw_qdss_trace_config_download_req_msg_v01, + seg_id_valid), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0x11, + .offset = offsetof(struct + wlfw_qdss_trace_config_download_req_msg_v01, + seg_id), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x12, + .offset = offsetof(struct + wlfw_qdss_trace_config_download_req_msg_v01, + data_valid), + }, + { + .data_type = QMI_DATA_LEN, + .elem_len = 1, + .elem_size = sizeof(u16), + .array_type = NO_ARRAY, + .tlv_type = 0x12, + .offset = offsetof(struct + wlfw_qdss_trace_config_download_req_msg_v01, + data_len), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = QMI_WLFW_MAX_DATA_SIZE_V01, + .elem_size = sizeof(u8), + .array_type = VAR_LEN_ARRAY, + .tlv_type = 0x12, + .offset = offsetof(struct + wlfw_qdss_trace_config_download_req_msg_v01, + data), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x13, + .offset = offsetof(struct + wlfw_qdss_trace_config_download_req_msg_v01, + end_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x13, + .offset = offsetof(struct + wlfw_qdss_trace_config_download_req_msg_v01, + end), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_qdss_trace_config_download_resp_msg_v01_ei[] = { + { + .data_type = QMI_STRUCT, + .elem_len = 1, + .elem_size = sizeof(struct qmi_response_type_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x02, + .offset = offsetof(struct + wlfw_qdss_trace_config_download_resp_msg_v01, + resp), + .ei_array = qmi_response_type_v01_ei, + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_qdss_trace_mode_req_msg_v01_ei[] = { + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct + wlfw_qdss_trace_mode_req_msg_v01, + mode_valid), + }, + { + .data_type = QMI_SIGNED_4_BYTE_ENUM, + .elem_len = 1, + .elem_size = sizeof(enum wlfw_qdss_trace_mode_enum_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct + wlfw_qdss_trace_mode_req_msg_v01, + mode), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x11, + .offset = offsetof(struct + wlfw_qdss_trace_mode_req_msg_v01, + option_valid), + }, + { + .data_type = QMI_UNSIGNED_8_BYTE, + .elem_len = 1, + .elem_size = sizeof(u64), + .array_type = NO_ARRAY, + .tlv_type = 0x11, + .offset = offsetof(struct + wlfw_qdss_trace_mode_req_msg_v01, + option), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x12, + .offset = offsetof(struct + wlfw_qdss_trace_mode_req_msg_v01, + hw_trc_disable_override_valid), + }, + { + .data_type = QMI_SIGNED_4_BYTE_ENUM, + .elem_len = 1, + .elem_size = sizeof(enum wlfw_qmi_param_value_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x12, + .offset = offsetof(struct + wlfw_qdss_trace_mode_req_msg_v01, + hw_trc_disable_override), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_qdss_trace_mode_resp_msg_v01_ei[] = { + { + .data_type = QMI_STRUCT, + .elem_len = 1, + .elem_size = sizeof(struct qmi_response_type_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x02, + .offset = offsetof(struct + wlfw_qdss_trace_mode_resp_msg_v01, + resp), + .ei_array = qmi_response_type_v01_ei, + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_qdss_trace_free_ind_msg_v01_ei[] = { + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct + wlfw_qdss_trace_free_ind_msg_v01, + mem_seg_valid), + }, + { + .data_type = QMI_DATA_LEN, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct + wlfw_qdss_trace_free_ind_msg_v01, + mem_seg_len), + }, + { + .data_type = QMI_STRUCT, + .elem_len = QMI_WLFW_MAX_NUM_MEM_SEG_V01, + .elem_size = sizeof(struct wlfw_mem_seg_resp_s_v01), + .array_type = VAR_LEN_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct + wlfw_qdss_trace_free_ind_msg_v01, + mem_seg), + .ei_array = wlfw_mem_seg_resp_s_v01_ei, + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_shutdown_req_msg_v01_ei[] = { + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct wlfw_shutdown_req_msg_v01, + shutdown_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct wlfw_shutdown_req_msg_v01, + shutdown), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_shutdown_resp_msg_v01_ei[] = { + { + .data_type = QMI_STRUCT, + .elem_len = 1, + .elem_size = sizeof(struct qmi_response_type_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x02, + .offset = offsetof(struct wlfw_shutdown_resp_msg_v01, + resp), + .ei_array = qmi_response_type_v01_ei, + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_antenna_switch_req_msg_v01_ei[] = { + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_antenna_switch_resp_msg_v01_ei[] = { + { + .data_type = QMI_STRUCT, + .elem_len = 1, + .elem_size = sizeof(struct qmi_response_type_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x02, + .offset = offsetof(struct + wlfw_antenna_switch_resp_msg_v01, + resp), + .ei_array = qmi_response_type_v01_ei, + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct + wlfw_antenna_switch_resp_msg_v01, + antenna_valid), + }, + { + .data_type = QMI_UNSIGNED_8_BYTE, + .elem_len = 1, + .elem_size = sizeof(u64), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct + wlfw_antenna_switch_resp_msg_v01, + antenna), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_antenna_grant_req_msg_v01_ei[] = { + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct + wlfw_antenna_grant_req_msg_v01, + grant_valid), + }, + { + .data_type = QMI_UNSIGNED_8_BYTE, + .elem_len = 1, + .elem_size = sizeof(u64), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct + wlfw_antenna_grant_req_msg_v01, + grant), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_antenna_grant_resp_msg_v01_ei[] = { + { + .data_type = QMI_STRUCT, + .elem_len = 1, + .elem_size = sizeof(struct qmi_response_type_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x02, + .offset = offsetof(struct + wlfw_antenna_grant_resp_msg_v01, + resp), + .ei_array = qmi_response_type_v01_ei, + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_wfc_call_status_req_msg_v01_ei[] = { + { + .data_type = QMI_DATA_LEN, + .elem_len = 1, + .elem_size = sizeof(u16), + .array_type = NO_ARRAY, + .tlv_type = 0x01, + .offset = offsetof(struct + wlfw_wfc_call_status_req_msg_v01, + wfc_call_status_len), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = QMI_WLFW_MAX_WFC_CALL_STATUS_DATA_SIZE_V01, + .elem_size = sizeof(u8), + .array_type = VAR_LEN_ARRAY, + .tlv_type = 0x01, + .offset = offsetof(struct + wlfw_wfc_call_status_req_msg_v01, + wfc_call_status), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct + wlfw_wfc_call_status_req_msg_v01, + wfc_call_active_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct + wlfw_wfc_call_status_req_msg_v01, + wfc_call_active), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x11, + .offset = offsetof(struct + wlfw_wfc_call_status_req_msg_v01, + all_wfc_calls_held_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x11, + .offset = offsetof(struct + wlfw_wfc_call_status_req_msg_v01, + all_wfc_calls_held), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x12, + .offset = offsetof(struct + wlfw_wfc_call_status_req_msg_v01, + is_wfc_emergency_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x12, + .offset = offsetof(struct + wlfw_wfc_call_status_req_msg_v01, + is_wfc_emergency), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x13, + .offset = offsetof(struct + wlfw_wfc_call_status_req_msg_v01, + twt_ims_start_valid), + }, + { + .data_type = QMI_UNSIGNED_8_BYTE, + .elem_len = 1, + .elem_size = sizeof(u64), + .array_type = NO_ARRAY, + .tlv_type = 0x13, + .offset = offsetof(struct + wlfw_wfc_call_status_req_msg_v01, + twt_ims_start), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x14, + .offset = offsetof(struct + wlfw_wfc_call_status_req_msg_v01, + twt_ims_int_valid), + }, + { + .data_type = QMI_UNSIGNED_2_BYTE, + .elem_len = 1, + .elem_size = sizeof(u16), + .array_type = NO_ARRAY, + .tlv_type = 0x14, + .offset = offsetof(struct + wlfw_wfc_call_status_req_msg_v01, + twt_ims_int), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x15, + .offset = offsetof(struct + wlfw_wfc_call_status_req_msg_v01, + media_quality_valid), + }, + { + .data_type = QMI_SIGNED_4_BYTE_ENUM, + .elem_len = 1, + .elem_size = sizeof(enum wlfw_wfc_media_quality_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x15, + .offset = offsetof(struct + wlfw_wfc_call_status_req_msg_v01, + media_quality), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_wfc_call_status_resp_msg_v01_ei[] = { + { + .data_type = QMI_STRUCT, + .elem_len = 1, + .elem_size = sizeof(struct qmi_response_type_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x02, + .offset = offsetof(struct + wlfw_wfc_call_status_resp_msg_v01, + resp), + .ei_array = qmi_response_type_v01_ei, + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_get_info_req_msg_v01_ei[] = { + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x01, + .offset = offsetof(struct wlfw_get_info_req_msg_v01, + type), + }, + { + .data_type = QMI_DATA_LEN, + .elem_len = 1, + .elem_size = sizeof(u16), + .array_type = NO_ARRAY, + .tlv_type = 0x02, + .offset = offsetof(struct wlfw_get_info_req_msg_v01, + data_len), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = QMI_WLFW_MAX_DATA_SIZE_V01, + .elem_size = sizeof(u8), + .array_type = VAR_LEN_ARRAY, + .tlv_type = 0x02, + .offset = offsetof(struct wlfw_get_info_req_msg_v01, + data), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_get_info_resp_msg_v01_ei[] = { + { + .data_type = QMI_STRUCT, + .elem_len = 1, + .elem_size = sizeof(struct qmi_response_type_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x02, + .offset = offsetof(struct wlfw_get_info_resp_msg_v01, + resp), + .ei_array = qmi_response_type_v01_ei, + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_respond_get_info_ind_msg_v01_ei[] = { + { + .data_type = QMI_DATA_LEN, + .elem_len = 1, + .elem_size = sizeof(u16), + .array_type = NO_ARRAY, + .tlv_type = 0x01, + .offset = offsetof(struct + wlfw_respond_get_info_ind_msg_v01, + data_len), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = QMI_WLFW_MAX_DATA_SIZE_V01, + .elem_size = sizeof(u8), + .array_type = VAR_LEN_ARRAY, + .tlv_type = 0x01, + .offset = offsetof(struct + wlfw_respond_get_info_ind_msg_v01, + data), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct + wlfw_respond_get_info_ind_msg_v01, + type_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct + wlfw_respond_get_info_ind_msg_v01, + type), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x11, + .offset = offsetof(struct + wlfw_respond_get_info_ind_msg_v01, + is_last_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x11, + .offset = offsetof(struct + wlfw_respond_get_info_ind_msg_v01, + is_last), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x12, + .offset = offsetof(struct + wlfw_respond_get_info_ind_msg_v01, + seq_no_valid), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0x12, + .offset = offsetof(struct + wlfw_respond_get_info_ind_msg_v01, + seq_no), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_device_info_req_msg_v01_ei[] = { + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_device_info_resp_msg_v01_ei[] = { + { + .data_type = QMI_STRUCT, + .elem_len = 1, + .elem_size = sizeof(struct qmi_response_type_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x02, + .offset = offsetof(struct wlfw_device_info_resp_msg_v01, + resp), + .ei_array = qmi_response_type_v01_ei, + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct wlfw_device_info_resp_msg_v01, + bar_addr_valid), + }, + { + .data_type = QMI_UNSIGNED_8_BYTE, + .elem_len = 1, + .elem_size = sizeof(u64), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct wlfw_device_info_resp_msg_v01, + bar_addr), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x11, + .offset = offsetof(struct wlfw_device_info_resp_msg_v01, + bar_size_valid), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0x11, + .offset = offsetof(struct wlfw_device_info_resp_msg_v01, + bar_size), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_m3_dump_upload_req_ind_msg_v01_ei[] = { + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0x01, + .offset = offsetof(struct + wlfw_m3_dump_upload_req_ind_msg_v01, + pdev_id), + }, + { + .data_type = QMI_UNSIGNED_8_BYTE, + .elem_len = 1, + .elem_size = sizeof(u64), + .array_type = NO_ARRAY, + .tlv_type = 0x02, + .offset = offsetof(struct + wlfw_m3_dump_upload_req_ind_msg_v01, + addr), + }, + { + .data_type = QMI_UNSIGNED_8_BYTE, + .elem_len = 1, + .elem_size = sizeof(u64), + .array_type = NO_ARRAY, + .tlv_type = 0x03, + .offset = offsetof(struct + wlfw_m3_dump_upload_req_ind_msg_v01, + size), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_m3_dump_upload_done_req_msg_v01_ei[] = { + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0x01, + .offset = offsetof(struct + wlfw_m3_dump_upload_done_req_msg_v01, + pdev_id), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0x02, + .offset = offsetof(struct + wlfw_m3_dump_upload_done_req_msg_v01, + status), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_m3_dump_upload_done_resp_msg_v01_ei[] = { + { + .data_type = QMI_STRUCT, + .elem_len = 1, + .elem_size = sizeof(struct qmi_response_type_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x02, + .offset = offsetof(struct + wlfw_m3_dump_upload_done_resp_msg_v01, + resp), + .ei_array = qmi_response_type_v01_ei, + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_soc_wake_req_msg_v01_ei[] = { + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct + wlfw_soc_wake_req_msg_v01, + wake_valid), + }, + { + .data_type = QMI_SIGNED_4_BYTE_ENUM, + .elem_len = 1, + .elem_size = sizeof(enum wlfw_soc_wake_enum_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct wlfw_soc_wake_req_msg_v01, + wake), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_soc_wake_resp_msg_v01_ei[] = { + { + .data_type = QMI_STRUCT, + .elem_len = 1, + .elem_size = sizeof(struct qmi_response_type_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x02, + .offset = offsetof(struct wlfw_soc_wake_resp_msg_v01, + resp), + .ei_array = qmi_response_type_v01_ei, + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_exit_power_save_req_msg_v01_ei[] = { + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_exit_power_save_resp_msg_v01_ei[] = { + { + .data_type = QMI_STRUCT, + .elem_len = 1, + .elem_size = sizeof(struct qmi_response_type_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x02, + .offset = offsetof(struct + wlfw_exit_power_save_resp_msg_v01, + resp), + .ei_array = qmi_response_type_v01_ei, + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_wfc_call_twt_config_ind_msg_v01_ei[] = { + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = + offsetof(struct wlfw_wfc_call_twt_config_ind_msg_v01, + twt_sta_start_valid), + }, + { + .data_type = QMI_UNSIGNED_8_BYTE, + .elem_len = 1, + .elem_size = sizeof(u64), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = + offsetof(struct wlfw_wfc_call_twt_config_ind_msg_v01, + twt_sta_start), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x11, + .offset = + offsetof(struct wlfw_wfc_call_twt_config_ind_msg_v01, + twt_sta_int_valid), + }, + { + .data_type = QMI_UNSIGNED_2_BYTE, + .elem_len = 1, + .elem_size = sizeof(u16), + .array_type = NO_ARRAY, + .tlv_type = 0x11, + .offset = + offsetof(struct wlfw_wfc_call_twt_config_ind_msg_v01, + twt_sta_int), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x12, + .offset = + offsetof(struct wlfw_wfc_call_twt_config_ind_msg_v01, + twt_sta_upo_valid), + }, + { + .data_type = QMI_UNSIGNED_2_BYTE, + .elem_len = 1, + .elem_size = sizeof(u16), + .array_type = NO_ARRAY, + .tlv_type = 0x12, + .offset = + offsetof(struct wlfw_wfc_call_twt_config_ind_msg_v01, + twt_sta_upo), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x13, + .offset = + offsetof(struct wlfw_wfc_call_twt_config_ind_msg_v01, + twt_sta_sp_valid), + }, + { + .data_type = QMI_UNSIGNED_2_BYTE, + .elem_len = 1, + .elem_size = sizeof(u16), + .array_type = NO_ARRAY, + .tlv_type = 0x13, + .offset = + offsetof(struct wlfw_wfc_call_twt_config_ind_msg_v01, + twt_sta_sp), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x14, + .offset = + offsetof(struct wlfw_wfc_call_twt_config_ind_msg_v01, + twt_sta_dl_valid), + }, + { + .data_type = QMI_UNSIGNED_2_BYTE, + .elem_len = 1, + .elem_size = sizeof(u16), + .array_type = NO_ARRAY, + .tlv_type = 0x14, + .offset = + offsetof(struct wlfw_wfc_call_twt_config_ind_msg_v01, + twt_sta_dl), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x15, + .offset = + offsetof(struct wlfw_wfc_call_twt_config_ind_msg_v01, + twt_sta_config_changed_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x15, + .offset = + offsetof(struct wlfw_wfc_call_twt_config_ind_msg_v01, + twt_sta_config_changed), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_qdss_mem_ready_ind_msg_v01_ei[] = { + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_pcie_gen_switch_req_msg_v01_ei[] = { + { + .data_type = QMI_SIGNED_4_BYTE_ENUM, + .elem_len = 1, + .elem_size = sizeof(enum wlfw_pcie_gen_speed_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x01, + .offset = offsetof(struct + wlfw_pcie_gen_switch_req_msg_v01, + pcie_speed), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + +struct qmi_elem_info wlfw_pcie_gen_switch_resp_msg_v01_ei[] = { + { + .data_type = QMI_STRUCT, + .elem_len = 1, + .elem_size = sizeof(struct qmi_response_type_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x02, + .offset = offsetof(struct + wlfw_pcie_gen_switch_resp_msg_v01, + resp), + .ei_array = qmi_response_type_v01_ei, + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + diff --git a/drivers/net/wireless/cnss2/wlan_firmware_service_v01.h b/drivers/net/wireless/cnss2/wlan_firmware_service_v01.h new file mode 100644 index 000000000000..76cf12933cfc --- /dev/null +++ b/drivers/net/wireless/cnss2/wlan_firmware_service_v01.h @@ -0,0 +1,1203 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. */ + +#ifndef WLAN_FIRMWARE_SERVICE_V01_H +#define WLAN_FIRMWARE_SERVICE_V01_H + +#include + +#define WLFW_SERVICE_ID_V01 0x45 +#define WLFW_SERVICE_VERS_V01 0x01 + +#define QMI_WLFW_WFC_CALL_STATUS_REQ_V01 0x0049 +#define QMI_WLFW_DEVICE_INFO_RESP_V01 0x004C +#define QMI_WLFW_BDF_DOWNLOAD_REQ_V01 0x0025 +#define QMI_WLFW_FW_MEM_READY_IND_V01 0x0037 +#define QMI_WLFW_QDSS_TRACE_CONFIG_DOWNLOAD_REQ_V01 0x0044 +#define QMI_WLFW_GET_INFO_REQ_V01 0x004A +#define QMI_WLFW_INITIATE_CAL_UPDATE_IND_V01 0x002A +#define QMI_WLFW_CAL_DONE_IND_V01 0x003E +#define QMI_WLFW_M3_DUMP_UPLOAD_REQ_IND_V01 0x004D +#define QMI_WLFW_WFC_CALL_STATUS_RESP_V01 0x0049 +#define QMI_WLFW_HOST_CAP_REQ_V01 0x0034 +#define QMI_WLFW_DYNAMIC_FEATURE_MASK_RESP_V01 0x003B +#define QMI_WLFW_M3_INFO_REQ_V01 0x003C +#define QMI_WLFW_CAP_REQ_V01 0x0024 +#define QMI_WLFW_FW_INIT_DONE_IND_V01 0x0038 +#define QMI_WLFW_ANTENNA_GRANT_RESP_V01 0x0048 +#define QMI_WLFW_CAL_REPORT_REQ_V01 0x0026 +#define QMI_WLFW_RESPOND_GET_INFO_IND_V01 0x004B +#define QMI_WLFW_M3_INFO_RESP_V01 0x003C +#define QMI_WLFW_CAL_UPDATE_RESP_V01 0x0029 +#define QMI_WLFW_M3_DUMP_UPLOAD_DONE_RESP_V01 0x004E +#define QMI_WLFW_CAL_DOWNLOAD_RESP_V01 0x0027 +#define QMI_WLFW_XO_CAL_IND_V01 0x003D +#define QMI_WLFW_INI_RESP_V01 0x002F +#define QMI_WLFW_CAL_REPORT_RESP_V01 0x0026 +#define QMI_WLFW_QDSS_TRACE_MEM_INFO_REQ_V01 0x0040 +#define QMI_WLFW_ANTENNA_SWITCH_REQ_V01 0x0047 +#define QMI_WLFW_QDSS_TRACE_REQ_MEM_IND_V01 0x003F +#define QMI_WLFW_SHUTDOWN_RESP_V01 0x0043 +#define QMI_WLFW_MAC_ADDR_RESP_V01 0x0033 +#define QMI_WLFW_INITIATE_CAL_DOWNLOAD_IND_V01 0x0028 +#define QMI_WLFW_HOST_CAP_RESP_V01 0x0034 +#define QMI_WLFW_MSA_READY_IND_V01 0x002B +#define QMI_WLFW_ATHDIAG_WRITE_RESP_V01 0x0031 +#define QMI_WLFW_EXIT_POWER_SAVE_REQ_V01 0x0050 +#define QMI_WLFW_WLAN_MODE_REQ_V01 0x0022 +#define QMI_WLFW_IND_REGISTER_REQ_V01 0x0020 +#define QMI_WLFW_WLAN_CFG_RESP_V01 0x0023 +#define QMI_WLFW_QDSS_TRACE_MODE_REQ_V01 0x0045 +#define QMI_WLFW_REQUEST_MEM_IND_V01 0x0035 +#define QMI_WLFW_QDSS_TRACE_CONFIG_DOWNLOAD_RESP_V01 0x0044 +#define QMI_WLFW_SOC_WAKE_RESP_V01 0x004F +#define QMI_WLFW_REJUVENATE_IND_V01 0x0039 +#define QMI_WLFW_DYNAMIC_FEATURE_MASK_REQ_V01 0x003B +#define QMI_WLFW_ATHDIAG_WRITE_REQ_V01 0x0031 +#define QMI_WLFW_WLAN_MODE_RESP_V01 0x0022 +#define QMI_WLFW_RESPOND_MEM_REQ_V01 0x0036 +#define QMI_WLFW_GET_INFO_RESP_V01 0x004A +#define QMI_WLFW_QDSS_TRACE_MODE_RESP_V01 0x0045 +#define QMI_WLFW_PIN_CONNECT_RESULT_IND_V01 0x002C +#define QMI_WLFW_FW_READY_IND_V01 0x0021 +#define QMI_WLFW_QDSS_TRACE_SAVE_IND_V01 0x0041 +#define QMI_WLFW_QDSS_TRACE_MEM_INFO_RESP_V01 0x0040 +#define QMI_WLFW_ANTENNA_GRANT_REQ_V01 0x0048 +#define QMI_WLFW_MSA_READY_RESP_V01 0x002E +#define QMI_WLFW_QDSS_TRACE_DATA_REQ_V01 0x0042 +#define QMI_WLFW_CAL_UPDATE_REQ_V01 0x0029 +#define QMI_WLFW_INI_REQ_V01 0x002F +#define QMI_WLFW_BDF_DOWNLOAD_RESP_V01 0x0025 +#define QMI_WLFW_REJUVENATE_ACK_RESP_V01 0x003A +#define QMI_WLFW_MSA_INFO_RESP_V01 0x002D +#define QMI_WLFW_MSA_READY_REQ_V01 0x002E +#define QMI_WLFW_QDSS_TRACE_DATA_RESP_V01 0x0042 +#define QMI_WLFW_M3_DUMP_UPLOAD_DONE_REQ_V01 0x004E +#define QMI_WLFW_CAP_RESP_V01 0x0024 +#define QMI_WLFW_SOC_WAKE_REQ_V01 0x004F +#define QMI_WLFW_REJUVENATE_ACK_REQ_V01 0x003A +#define QMI_WLFW_ATHDIAG_READ_RESP_V01 0x0030 +#define QMI_WLFW_SHUTDOWN_REQ_V01 0x0043 +#define QMI_WLFW_VBATT_REQ_V01 0x0032 +#define QMI_WLFW_ANTENNA_SWITCH_RESP_V01 0x0047 +#define QMI_WLFW_DEVICE_INFO_REQ_V01 0x004C +#define QMI_WLFW_MAC_ADDR_REQ_V01 0x0033 +#define QMI_WLFW_EXIT_POWER_SAVE_RESP_V01 0x0050 +#define QMI_WLFW_RESPOND_MEM_RESP_V01 0x0036 +#define QMI_WLFW_WFC_CALL_TWT_CONFIG_IND_V01 0x0051 +#define QMI_WLFW_VBATT_RESP_V01 0x0032 +#define QMI_WLFW_MSA_INFO_REQ_V01 0x002D +#define QMI_WLFW_QDSS_TRACE_FREE_IND_V01 0x0046 +#define QMI_WLFW_CAL_DOWNLOAD_REQ_V01 0x0027 +#define QMI_WLFW_ATHDIAG_READ_REQ_V01 0x0030 +#define QMI_WLFW_WLAN_CFG_REQ_V01 0x0023 +#define QMI_WLFW_IND_REGISTER_RESP_V01 0x0020 +#define QMI_WLFW_PCIE_GEN_SWITCH_REQ_V01 0x0053 +#define QMI_WLFW_PCIE_GEN_SWITCH_RESP_V01 0x0053 +#define QMI_WLFW_QDSS_MEM_READY_IND_V01 0x0052 + +#define QMI_WLFW_MAX_NUM_MEMORY_REGIONS_V01 2 +#define QMI_WLFW_MAX_NUM_MEM_SEG_V01 32 +#define QMI_WLFW_MAX_NUM_CAL_V01 5 +#define QMI_WLFW_MAX_DATA_SIZE_V01 6144 +#define QMI_WLFW_FUNCTION_NAME_LEN_V01 128 +#define QMI_WLFW_MAX_NUM_CE_V01 12 +#define QMI_WLFW_MAX_HOST_DDR_RANGE_SIZE_V01 3 +#define QMI_WLFW_MAX_TIMESTAMP_LEN_V01 32 +#define QMI_WLFW_MAX_ATHDIAG_DATA_SIZE_V01 6144 +#define QMI_WLFW_MAX_WFC_CALL_STATUS_DATA_SIZE_V01 256 +#define QMI_WLFW_MAX_NUM_GPIO_V01 32 +#define QMI_WLFW_MAX_BUILD_ID_LEN_V01 128 +#define QMI_WLFW_MAX_NUM_MEM_CFG_V01 2 +#define QMI_WLFW_MAX_STR_LEN_V01 16 +#define QMI_WLFW_MAX_NUM_SHADOW_REG_V01 24 +#define QMI_WLFW_MAC_ADDR_SIZE_V01 6 +#define QMI_WLFW_MAX_NUM_SHADOW_REG_V2_V01 36 +#define QMI_WLFW_MAX_PLATFORM_NAME_LEN_V01 64 +#define QMI_WLFW_MAX_NUM_SVC_V01 24 + +enum wlfw_driver_mode_enum_v01 { + WLFW_DRIVER_MODE_ENUM_MIN_VAL_V01 = INT_MIN, + QMI_WLFW_MISSION_V01 = 0, + QMI_WLFW_FTM_V01 = 1, + QMI_WLFW_EPPING_V01 = 2, + QMI_WLFW_WALTEST_V01 = 3, + QMI_WLFW_OFF_V01 = 4, + QMI_WLFW_CCPM_V01 = 5, + QMI_WLFW_QVIT_V01 = 6, + QMI_WLFW_CALIBRATION_V01 = 7, + QMI_WLFW_FTM_CALIBRATION_V01 = 10, + WLFW_DRIVER_MODE_ENUM_MAX_VAL_V01 = INT_MAX, +}; + +enum wlfw_cal_temp_id_enum_v01 { + WLFW_CAL_TEMP_ID_ENUM_MIN_VAL_V01 = INT_MIN, + QMI_WLFW_CAL_TEMP_IDX_0_V01 = 0, + QMI_WLFW_CAL_TEMP_IDX_1_V01 = 1, + QMI_WLFW_CAL_TEMP_IDX_2_V01 = 2, + QMI_WLFW_CAL_TEMP_IDX_3_V01 = 3, + QMI_WLFW_CAL_TEMP_IDX_4_V01 = 4, + WLFW_CAL_TEMP_ID_ENUM_MAX_VAL_V01 = INT_MAX, +}; + +enum wlfw_pipedir_enum_v01 { + WLFW_PIPEDIR_ENUM_MIN_VAL_V01 = INT_MIN, + QMI_WLFW_PIPEDIR_NONE_V01 = 0, + QMI_WLFW_PIPEDIR_IN_V01 = 1, + QMI_WLFW_PIPEDIR_OUT_V01 = 2, + QMI_WLFW_PIPEDIR_INOUT_V01 = 3, + WLFW_PIPEDIR_ENUM_MAX_VAL_V01 = INT_MAX, +}; + +enum wlfw_mem_type_enum_v01 { + WLFW_MEM_TYPE_ENUM_MIN_VAL_V01 = INT_MIN, + QMI_WLFW_MEM_TYPE_MSA_V01 = 0, + QMI_WLFW_MEM_TYPE_DDR_V01 = 1, + QMI_WLFW_MEM_BDF_V01 = 2, + QMI_WLFW_MEM_M3_V01 = 3, + QMI_WLFW_MEM_CAL_V01 = 4, + QMI_WLFW_MEM_DPD_V01 = 5, + QMI_WLFW_MEM_QDSS_V01 = 6, + QMI_WLFW_MEM_HANG_DATA_V01 = 7, + WLFW_MEM_TYPE_ENUM_MAX_VAL_V01 = INT_MAX, +}; + +enum wlfw_qdss_trace_mode_enum_v01 { + WLFW_QDSS_TRACE_MODE_ENUM_MIN_VAL_V01 = INT_MIN, + QMI_WLFW_QDSS_TRACE_OFF_V01 = 0, + QMI_WLFW_QDSS_TRACE_ON_V01 = 1, + WLFW_QDSS_TRACE_MODE_ENUM_MAX_VAL_V01 = INT_MAX, +}; + +enum wlfw_wfc_media_quality_v01 { + WLFW_WFC_MEDIA_QUALITY_MIN_VAL_V01 = INT_MIN, + QMI_WLFW_WFC_MEDIA_QUAL_NOT_AVAILABLE_V01 = 0, + QMI_WLFW_WFC_MEDIA_QUAL_BAD_V01 = 1, + QMI_WLFW_WFC_MEDIA_QUAL_GOOD_V01 = 2, + QMI_WLFW_WFC_MEDIA_QUAL_EXCELLENT_V01 = 3, + WLFW_WFC_MEDIA_QUALITY_MAX_VAL_V01 = INT_MAX, +}; + +enum wlfw_soc_wake_enum_v01 { + WLFW_SOC_WAKE_ENUM_MIN_VAL_V01 = INT_MIN, + QMI_WLFW_WAKE_REQUEST_V01 = 0, + QMI_WLFW_WAKE_RELEASE_V01 = 1, + WLFW_SOC_WAKE_ENUM_MAX_VAL_V01 = INT_MAX, +}; + +enum wlfw_host_build_type_v01 { + WLFW_HOST_BUILD_TYPE_MIN_VAL_V01 = INT_MIN, + QMI_HOST_BUILD_TYPE_UNSPECIFIED_V01 = 0, + QMI_HOST_BUILD_TYPE_PRIMARY_V01 = 1, + QMI_HOST_BUILD_TYPE_SECONDARY_V01 = 2, + WLFW_HOST_BUILD_TYPE_MAX_VAL_V01 = INT_MAX, +}; + +enum wlfw_qmi_param_value_v01 { + WLFW_QMI_PARAM_VALUE_MIN_VAL_V01 = INT_MIN, + QMI_PARAM_INVALID_V01 = 0, + QMI_PARAM_ENABLE_V01 = 1, + QMI_PARAM_DISABLE_V01 = 2, + WLFW_QMI_PARAM_VALUE_MAX_VAL_V01 = INT_MAX, +}; + +enum wlfw_pcie_gen_speed_v01 { + WLFW_PCIE_GEN_SPEED_MIN_VAL_V01 = INT_MIN, + QMI_PCIE_GEN_SPEED_INVALID_V01 = 0, + QMI_PCIE_GEN_SPEED_1_V01 = 1, + QMI_PCIE_GEN_SPEED_2_V01 = 2, + QMI_PCIE_GEN_SPEED_3_V01 = 3, + WLFW_PCIE_GEN_SPEED_MAX_VAL_V01 = INT_MAX, +}; + +#define QMI_WLFW_CE_ATTR_FLAGS_V01 ((u32)0x00) +#define QMI_WLFW_CE_ATTR_NO_SNOOP_V01 ((u32)0x01) +#define QMI_WLFW_CE_ATTR_BYTE_SWAP_DATA_V01 ((u32)0x02) +#define QMI_WLFW_CE_ATTR_SWIZZLE_DESCRIPTORS_V01 ((u32)0x04) +#define QMI_WLFW_CE_ATTR_DISABLE_INTR_V01 ((u32)0x08) +#define QMI_WLFW_CE_ATTR_ENABLE_POLL_V01 ((u32)0x10) + +#define QMI_WLFW_ALREADY_REGISTERED_V01 ((u64)0x01ULL) +#define QMI_WLFW_FW_READY_V01 ((u64)0x02ULL) +#define QMI_WLFW_MSA_READY_V01 ((u64)0x04ULL) +#define QMI_WLFW_FW_MEM_READY_V01 ((u64)0x08ULL) +#define QMI_WLFW_FW_INIT_DONE_V01 ((u64)0x10ULL) + +#define QMI_WLFW_FW_REJUVENATE_V01 ((u64)0x01ULL) + +#define QMI_WLFW_HW_XPA_V01 ((u64)0x01ULL) +#define QMI_WLFW_CBC_FILE_DOWNLOAD_V01 ((u64)0x02ULL) + +#define QMI_WLFW_HOST_PCIE_GEN_SWITCH_V01 ((u64)0x01ULL) + +struct wlfw_ce_tgt_pipe_cfg_s_v01 { + u32 pipe_num; + enum wlfw_pipedir_enum_v01 pipe_dir; + u32 nentries; + u32 nbytes_max; + u32 flags; +}; + +struct wlfw_ce_svc_pipe_cfg_s_v01 { + u32 service_id; + enum wlfw_pipedir_enum_v01 pipe_dir; + u32 pipe_num; +}; + +struct wlfw_shadow_reg_cfg_s_v01 { + u16 id; + u16 offset; +}; + +struct wlfw_shadow_reg_v2_cfg_s_v01 { + u32 addr; +}; + +struct wlfw_rri_over_ddr_cfg_s_v01 { + u32 base_addr_low; + u32 base_addr_high; +}; + +struct wlfw_msi_cfg_s_v01 { + u16 ce_id; + u16 msi_vector; +}; + +struct wlfw_memory_region_info_s_v01 { + u64 region_addr; + u32 size; + u8 secure_flag; +}; + +struct wlfw_mem_cfg_s_v01 { + u64 offset; + u32 size; + u8 secure_flag; +}; + +struct wlfw_mem_seg_s_v01 { + u32 size; + enum wlfw_mem_type_enum_v01 type; + u32 mem_cfg_len; + struct wlfw_mem_cfg_s_v01 mem_cfg[QMI_WLFW_MAX_NUM_MEM_CFG_V01]; +}; + +struct wlfw_mem_seg_resp_s_v01 { + u64 addr; + u32 size; + enum wlfw_mem_type_enum_v01 type; + u8 restore; +}; + +struct wlfw_rf_chip_info_s_v01 { + u32 chip_id; + u32 chip_family; +}; + +struct wlfw_rf_board_info_s_v01 { + u32 board_id; +}; + +struct wlfw_soc_info_s_v01 { + u32 soc_id; +}; + +struct wlfw_fw_version_info_s_v01 { + u32 fw_version; + char fw_build_timestamp[QMI_WLFW_MAX_TIMESTAMP_LEN_V01 + 1]; +}; + +struct wlfw_host_ddr_range_s_v01 { + u64 start; + u64 size; +}; + +struct wlfw_ind_register_req_msg_v01 { + u8 fw_ready_enable_valid; + u8 fw_ready_enable; + u8 initiate_cal_download_enable_valid; + u8 initiate_cal_download_enable; + u8 initiate_cal_update_enable_valid; + u8 initiate_cal_update_enable; + u8 msa_ready_enable_valid; + u8 msa_ready_enable; + u8 pin_connect_result_enable_valid; + u8 pin_connect_result_enable; + u8 client_id_valid; + u32 client_id; + u8 request_mem_enable_valid; + u8 request_mem_enable; + u8 fw_mem_ready_enable_valid; + u8 fw_mem_ready_enable; + u8 fw_init_done_enable_valid; + u8 fw_init_done_enable; + u8 rejuvenate_enable_valid; + u32 rejuvenate_enable; + u8 xo_cal_enable_valid; + u8 xo_cal_enable; + u8 cal_done_enable_valid; + u8 cal_done_enable; + u8 qdss_trace_req_mem_enable_valid; + u8 qdss_trace_req_mem_enable; + u8 qdss_trace_save_enable_valid; + u8 qdss_trace_save_enable; + u8 qdss_trace_free_enable_valid; + u8 qdss_trace_free_enable; + u8 respond_get_info_enable_valid; + u8 respond_get_info_enable; + u8 m3_dump_upload_req_enable_valid; + u8 m3_dump_upload_req_enable; + u8 wfc_call_twt_config_enable_valid; + u8 wfc_call_twt_config_enable; + u8 qdss_mem_ready_enable_valid; + u8 qdss_mem_ready_enable; +}; + +#define WLFW_IND_REGISTER_REQ_MSG_V01_MAX_MSG_LEN 82 +extern struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[]; + +struct wlfw_ind_register_resp_msg_v01 { + struct qmi_response_type_v01 resp; + u8 fw_status_valid; + u64 fw_status; +}; + +#define WLFW_IND_REGISTER_RESP_MSG_V01_MAX_MSG_LEN 18 +extern struct qmi_elem_info wlfw_ind_register_resp_msg_v01_ei[]; + +struct wlfw_fw_ready_ind_msg_v01 { + char placeholder; +}; + +#define WLFW_FW_READY_IND_MSG_V01_MAX_MSG_LEN 0 +extern struct qmi_elem_info wlfw_fw_ready_ind_msg_v01_ei[]; + +struct wlfw_msa_ready_ind_msg_v01 { + u8 hang_data_addr_offset_valid; + u32 hang_data_addr_offset; + u8 hang_data_length_valid; + u16 hang_data_length; +}; + +#define WLFW_MSA_READY_IND_MSG_V01_MAX_MSG_LEN 12 +extern struct qmi_elem_info wlfw_msa_ready_ind_msg_v01_ei[]; + +struct wlfw_pin_connect_result_ind_msg_v01 { + u8 pwr_pin_result_valid; + u32 pwr_pin_result; + u8 phy_io_pin_result_valid; + u32 phy_io_pin_result; + u8 rf_pin_result_valid; + u32 rf_pin_result; +}; + +#define WLFW_PIN_CONNECT_RESULT_IND_MSG_V01_MAX_MSG_LEN 21 +extern struct qmi_elem_info wlfw_pin_connect_result_ind_msg_v01_ei[]; + +struct wlfw_wlan_mode_req_msg_v01 { + enum wlfw_driver_mode_enum_v01 mode; + u8 hw_debug_valid; + u8 hw_debug; +}; + +#define WLFW_WLAN_MODE_REQ_MSG_V01_MAX_MSG_LEN 11 +extern struct qmi_elem_info wlfw_wlan_mode_req_msg_v01_ei[]; + +struct wlfw_wlan_mode_resp_msg_v01 { + struct qmi_response_type_v01 resp; +}; + +#define WLFW_WLAN_MODE_RESP_MSG_V01_MAX_MSG_LEN 7 +extern struct qmi_elem_info wlfw_wlan_mode_resp_msg_v01_ei[]; + +struct wlfw_wlan_cfg_req_msg_v01 { + u8 host_version_valid; + char host_version[QMI_WLFW_MAX_STR_LEN_V01 + 1]; + u8 tgt_cfg_valid; + u32 tgt_cfg_len; + struct wlfw_ce_tgt_pipe_cfg_s_v01 tgt_cfg[QMI_WLFW_MAX_NUM_CE_V01]; + u8 svc_cfg_valid; + u32 svc_cfg_len; + struct wlfw_ce_svc_pipe_cfg_s_v01 svc_cfg[QMI_WLFW_MAX_NUM_SVC_V01]; + u8 shadow_reg_valid; + u32 shadow_reg_len; + struct wlfw_shadow_reg_cfg_s_v01 + shadow_reg[QMI_WLFW_MAX_NUM_SHADOW_REG_V01]; + u8 shadow_reg_v2_valid; + u32 shadow_reg_v2_len; + struct wlfw_shadow_reg_v2_cfg_s_v01 + shadow_reg_v2[QMI_WLFW_MAX_NUM_SHADOW_REG_V2_V01]; + u8 rri_over_ddr_cfg_valid; + struct wlfw_rri_over_ddr_cfg_s_v01 rri_over_ddr_cfg; + u8 msi_cfg_valid; + u32 msi_cfg_len; + struct wlfw_msi_cfg_s_v01 msi_cfg[QMI_WLFW_MAX_NUM_CE_V01]; +}; + +#define WLFW_WLAN_CFG_REQ_MSG_V01_MAX_MSG_LEN 866 +extern struct qmi_elem_info wlfw_wlan_cfg_req_msg_v01_ei[]; + +struct wlfw_wlan_cfg_resp_msg_v01 { + struct qmi_response_type_v01 resp; +}; + +#define WLFW_WLAN_CFG_RESP_MSG_V01_MAX_MSG_LEN 7 +extern struct qmi_elem_info wlfw_wlan_cfg_resp_msg_v01_ei[]; + +struct wlfw_cap_req_msg_v01 { + char placeholder; +}; + +#define WLFW_CAP_REQ_MSG_V01_MAX_MSG_LEN 0 +extern struct qmi_elem_info wlfw_cap_req_msg_v01_ei[]; + +struct wlfw_cap_resp_msg_v01 { + struct qmi_response_type_v01 resp; + u8 chip_info_valid; + struct wlfw_rf_chip_info_s_v01 chip_info; + u8 board_info_valid; + struct wlfw_rf_board_info_s_v01 board_info; + u8 soc_info_valid; + struct wlfw_soc_info_s_v01 soc_info; + u8 fw_version_info_valid; + struct wlfw_fw_version_info_s_v01 fw_version_info; + u8 fw_build_id_valid; + char fw_build_id[QMI_WLFW_MAX_BUILD_ID_LEN_V01 + 1]; + u8 num_macs_valid; + u8 num_macs; + u8 voltage_mv_valid; + u32 voltage_mv; + u8 time_freq_hz_valid; + u32 time_freq_hz; + u8 otp_version_valid; + u32 otp_version; + u8 eeprom_caldata_read_timeout_valid; + u32 eeprom_caldata_read_timeout; + u8 fw_caps_valid; + u64 fw_caps; +}; + +#define WLFW_CAP_RESP_MSG_V01_MAX_MSG_LEN 246 +extern struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[]; + +struct wlfw_bdf_download_req_msg_v01 { + u8 valid; + u8 file_id_valid; + enum wlfw_cal_temp_id_enum_v01 file_id; + u8 total_size_valid; + u32 total_size; + u8 seg_id_valid; + u32 seg_id; + u8 data_valid; + u32 data_len; + u8 data[QMI_WLFW_MAX_DATA_SIZE_V01]; + u8 end_valid; + u8 end; + u8 bdf_type_valid; + u8 bdf_type; +}; + +#define WLFW_BDF_DOWNLOAD_REQ_MSG_V01_MAX_MSG_LEN 6182 +extern struct qmi_elem_info wlfw_bdf_download_req_msg_v01_ei[]; + +struct wlfw_bdf_download_resp_msg_v01 { + struct qmi_response_type_v01 resp; + u8 host_bdf_data_valid; + u64 host_bdf_data; +}; + +#define WLFW_BDF_DOWNLOAD_RESP_MSG_V01_MAX_MSG_LEN 18 +extern struct qmi_elem_info wlfw_bdf_download_resp_msg_v01_ei[]; + +struct wlfw_cal_report_req_msg_v01 { + u32 meta_data_len; + enum wlfw_cal_temp_id_enum_v01 meta_data[QMI_WLFW_MAX_NUM_CAL_V01]; + u8 xo_cal_data_valid; + u8 xo_cal_data; + u8 cal_remove_supported_valid; + u8 cal_remove_supported; +}; + +#define WLFW_CAL_REPORT_REQ_MSG_V01_MAX_MSG_LEN 32 +extern struct qmi_elem_info wlfw_cal_report_req_msg_v01_ei[]; + +struct wlfw_cal_report_resp_msg_v01 { + struct qmi_response_type_v01 resp; +}; + +#define WLFW_CAL_REPORT_RESP_MSG_V01_MAX_MSG_LEN 7 +extern struct qmi_elem_info wlfw_cal_report_resp_msg_v01_ei[]; + +struct wlfw_initiate_cal_download_ind_msg_v01 { + enum wlfw_cal_temp_id_enum_v01 cal_id; + u8 total_size_valid; + u32 total_size; + u8 cal_data_location_valid; + u32 cal_data_location; +}; + +#define WLFW_INITIATE_CAL_DOWNLOAD_IND_MSG_V01_MAX_MSG_LEN 21 +extern struct qmi_elem_info wlfw_initiate_cal_download_ind_msg_v01_ei[]; + +struct wlfw_cal_download_req_msg_v01 { + u8 valid; + u8 file_id_valid; + enum wlfw_cal_temp_id_enum_v01 file_id; + u8 total_size_valid; + u32 total_size; + u8 seg_id_valid; + u32 seg_id; + u8 data_valid; + u32 data_len; + u8 data[QMI_WLFW_MAX_DATA_SIZE_V01]; + u8 end_valid; + u8 end; + u8 cal_data_location_valid; + u32 cal_data_location; +}; + +#define WLFW_CAL_DOWNLOAD_REQ_MSG_V01_MAX_MSG_LEN 6185 +extern struct qmi_elem_info wlfw_cal_download_req_msg_v01_ei[]; + +struct wlfw_cal_download_resp_msg_v01 { + struct qmi_response_type_v01 resp; +}; + +#define WLFW_CAL_DOWNLOAD_RESP_MSG_V01_MAX_MSG_LEN 7 +extern struct qmi_elem_info wlfw_cal_download_resp_msg_v01_ei[]; + +struct wlfw_initiate_cal_update_ind_msg_v01 { + enum wlfw_cal_temp_id_enum_v01 cal_id; + u32 total_size; + u8 cal_data_location_valid; + u32 cal_data_location; +}; + +#define WLFW_INITIATE_CAL_UPDATE_IND_MSG_V01_MAX_MSG_LEN 21 +extern struct qmi_elem_info wlfw_initiate_cal_update_ind_msg_v01_ei[]; + +struct wlfw_cal_update_req_msg_v01 { + enum wlfw_cal_temp_id_enum_v01 cal_id; + u32 seg_id; +}; + +#define WLFW_CAL_UPDATE_REQ_MSG_V01_MAX_MSG_LEN 14 +extern struct qmi_elem_info wlfw_cal_update_req_msg_v01_ei[]; + +struct wlfw_cal_update_resp_msg_v01 { + struct qmi_response_type_v01 resp; + u8 file_id_valid; + enum wlfw_cal_temp_id_enum_v01 file_id; + u8 total_size_valid; + u32 total_size; + u8 seg_id_valid; + u32 seg_id; + u8 data_valid; + u32 data_len; + u8 data[QMI_WLFW_MAX_DATA_SIZE_V01]; + u8 end_valid; + u8 end; + u8 cal_data_location_valid; + u32 cal_data_location; +}; + +#define WLFW_CAL_UPDATE_RESP_MSG_V01_MAX_MSG_LEN 6188 +extern struct qmi_elem_info wlfw_cal_update_resp_msg_v01_ei[]; + +struct wlfw_msa_info_req_msg_v01 { + u64 msa_addr; + u32 size; +}; + +#define WLFW_MSA_INFO_REQ_MSG_V01_MAX_MSG_LEN 18 +extern struct qmi_elem_info wlfw_msa_info_req_msg_v01_ei[]; + +struct wlfw_msa_info_resp_msg_v01 { + struct qmi_response_type_v01 resp; + u32 mem_region_info_len; + struct wlfw_memory_region_info_s_v01 + mem_region_info[QMI_WLFW_MAX_NUM_MEMORY_REGIONS_V01]; +}; + +#define WLFW_MSA_INFO_RESP_MSG_V01_MAX_MSG_LEN 37 +extern struct qmi_elem_info wlfw_msa_info_resp_msg_v01_ei[]; + +struct wlfw_msa_ready_req_msg_v01 { + char placeholder; +}; + +#define WLFW_MSA_READY_REQ_MSG_V01_MAX_MSG_LEN 0 +extern struct qmi_elem_info wlfw_msa_ready_req_msg_v01_ei[]; + +struct wlfw_msa_ready_resp_msg_v01 { + struct qmi_response_type_v01 resp; +}; + +#define WLFW_MSA_READY_RESP_MSG_V01_MAX_MSG_LEN 7 +extern struct qmi_elem_info wlfw_msa_ready_resp_msg_v01_ei[]; + +struct wlfw_ini_req_msg_v01 { + u8 enablefwlog_valid; + u8 enablefwlog; +}; + +#define WLFW_INI_REQ_MSG_V01_MAX_MSG_LEN 4 +extern struct qmi_elem_info wlfw_ini_req_msg_v01_ei[]; + +struct wlfw_ini_resp_msg_v01 { + struct qmi_response_type_v01 resp; +}; + +#define WLFW_INI_RESP_MSG_V01_MAX_MSG_LEN 7 +extern struct qmi_elem_info wlfw_ini_resp_msg_v01_ei[]; + +struct wlfw_athdiag_read_req_msg_v01 { + u32 offset; + u32 mem_type; + u32 data_len; +}; + +#define WLFW_ATHDIAG_READ_REQ_MSG_V01_MAX_MSG_LEN 21 +extern struct qmi_elem_info wlfw_athdiag_read_req_msg_v01_ei[]; + +struct wlfw_athdiag_read_resp_msg_v01 { + struct qmi_response_type_v01 resp; + u8 data_valid; + u32 data_len; + u8 data[QMI_WLFW_MAX_ATHDIAG_DATA_SIZE_V01]; +}; + +#define WLFW_ATHDIAG_READ_RESP_MSG_V01_MAX_MSG_LEN 6156 +extern struct qmi_elem_info wlfw_athdiag_read_resp_msg_v01_ei[]; + +struct wlfw_athdiag_write_req_msg_v01 { + u32 offset; + u32 mem_type; + u32 data_len; + u8 data[QMI_WLFW_MAX_ATHDIAG_DATA_SIZE_V01]; +}; + +#define WLFW_ATHDIAG_WRITE_REQ_MSG_V01_MAX_MSG_LEN 6163 +extern struct qmi_elem_info wlfw_athdiag_write_req_msg_v01_ei[]; + +struct wlfw_athdiag_write_resp_msg_v01 { + struct qmi_response_type_v01 resp; +}; + +#define WLFW_ATHDIAG_WRITE_RESP_MSG_V01_MAX_MSG_LEN 7 +extern struct qmi_elem_info wlfw_athdiag_write_resp_msg_v01_ei[]; + +struct wlfw_vbatt_req_msg_v01 { + u64 voltage_uv; +}; + +#define WLFW_VBATT_REQ_MSG_V01_MAX_MSG_LEN 11 +extern struct qmi_elem_info wlfw_vbatt_req_msg_v01_ei[]; + +struct wlfw_vbatt_resp_msg_v01 { + struct qmi_response_type_v01 resp; +}; + +#define WLFW_VBATT_RESP_MSG_V01_MAX_MSG_LEN 7 +extern struct qmi_elem_info wlfw_vbatt_resp_msg_v01_ei[]; + +struct wlfw_mac_addr_req_msg_v01 { + u8 mac_addr_valid; + u8 mac_addr[QMI_WLFW_MAC_ADDR_SIZE_V01]; +}; + +#define WLFW_MAC_ADDR_REQ_MSG_V01_MAX_MSG_LEN 9 +extern struct qmi_elem_info wlfw_mac_addr_req_msg_v01_ei[]; + +struct wlfw_mac_addr_resp_msg_v01 { + struct qmi_response_type_v01 resp; +}; + +#define WLFW_MAC_ADDR_RESP_MSG_V01_MAX_MSG_LEN 7 +extern struct qmi_elem_info wlfw_mac_addr_resp_msg_v01_ei[]; + +struct wlfw_host_cap_req_msg_v01 { + u8 num_clients_valid; + u32 num_clients; + u8 wake_msi_valid; + u32 wake_msi; + u8 gpios_valid; + u32 gpios_len; + u32 gpios[QMI_WLFW_MAX_NUM_GPIO_V01]; + u8 nm_modem_valid; + u8 nm_modem; + u8 bdf_support_valid; + u8 bdf_support; + u8 bdf_cache_support_valid; + u8 bdf_cache_support; + u8 m3_support_valid; + u8 m3_support; + u8 m3_cache_support_valid; + u8 m3_cache_support; + u8 cal_filesys_support_valid; + u8 cal_filesys_support; + u8 cal_cache_support_valid; + u8 cal_cache_support; + u8 cal_done_valid; + u8 cal_done; + u8 mem_bucket_valid; + u32 mem_bucket; + u8 mem_cfg_mode_valid; + u8 mem_cfg_mode; + u8 cal_duration_valid; + u16 cal_duration; + u8 platform_name_valid; + char platform_name[QMI_WLFW_MAX_PLATFORM_NAME_LEN_V01 + 1]; + u8 ddr_range_valid; + struct wlfw_host_ddr_range_s_v01 + ddr_range[QMI_WLFW_MAX_HOST_DDR_RANGE_SIZE_V01]; + u8 host_build_type_valid; + enum wlfw_host_build_type_v01 host_build_type; +}; + +#define WLFW_HOST_CAP_REQ_MSG_V01_MAX_MSG_LEN 319 +extern struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[]; + +struct wlfw_host_cap_resp_msg_v01 { + struct qmi_response_type_v01 resp; +}; + +#define WLFW_HOST_CAP_RESP_MSG_V01_MAX_MSG_LEN 7 +extern struct qmi_elem_info wlfw_host_cap_resp_msg_v01_ei[]; + +struct wlfw_request_mem_ind_msg_v01 { + u32 mem_seg_len; + struct wlfw_mem_seg_s_v01 mem_seg[QMI_WLFW_MAX_NUM_MEM_SEG_V01]; +}; + +#define WLFW_REQUEST_MEM_IND_MSG_V01_MAX_MSG_LEN 1124 +extern struct qmi_elem_info wlfw_request_mem_ind_msg_v01_ei[]; + +struct wlfw_respond_mem_req_msg_v01 { + u32 mem_seg_len; + struct wlfw_mem_seg_resp_s_v01 mem_seg[QMI_WLFW_MAX_NUM_MEM_SEG_V01]; +}; + +#define WLFW_RESPOND_MEM_REQ_MSG_V01_MAX_MSG_LEN 548 +extern struct qmi_elem_info wlfw_respond_mem_req_msg_v01_ei[]; + +struct wlfw_respond_mem_resp_msg_v01 { + struct qmi_response_type_v01 resp; +}; + +#define WLFW_RESPOND_MEM_RESP_MSG_V01_MAX_MSG_LEN 7 +extern struct qmi_elem_info wlfw_respond_mem_resp_msg_v01_ei[]; + +struct wlfw_fw_mem_ready_ind_msg_v01 { + char placeholder; +}; + +#define WLFW_FW_MEM_READY_IND_MSG_V01_MAX_MSG_LEN 0 +extern struct qmi_elem_info wlfw_fw_mem_ready_ind_msg_v01_ei[]; + +struct wlfw_fw_init_done_ind_msg_v01 { + char placeholder; +}; + +#define WLFW_FW_INIT_DONE_IND_MSG_V01_MAX_MSG_LEN 0 +extern struct qmi_elem_info wlfw_fw_init_done_ind_msg_v01_ei[]; + +struct wlfw_rejuvenate_ind_msg_v01 { + u8 cause_for_rejuvenation_valid; + u8 cause_for_rejuvenation; + u8 requesting_sub_system_valid; + u8 requesting_sub_system; + u8 line_number_valid; + u16 line_number; + u8 function_name_valid; + char function_name[QMI_WLFW_FUNCTION_NAME_LEN_V01 + 1]; +}; + +#define WLFW_REJUVENATE_IND_MSG_V01_MAX_MSG_LEN 144 +extern struct qmi_elem_info wlfw_rejuvenate_ind_msg_v01_ei[]; + +struct wlfw_rejuvenate_ack_req_msg_v01 { + char placeholder; +}; + +#define WLFW_REJUVENATE_ACK_REQ_MSG_V01_MAX_MSG_LEN 0 +extern struct qmi_elem_info wlfw_rejuvenate_ack_req_msg_v01_ei[]; + +struct wlfw_rejuvenate_ack_resp_msg_v01 { + struct qmi_response_type_v01 resp; +}; + +#define WLFW_REJUVENATE_ACK_RESP_MSG_V01_MAX_MSG_LEN 7 +extern struct qmi_elem_info wlfw_rejuvenate_ack_resp_msg_v01_ei[]; + +struct wlfw_dynamic_feature_mask_req_msg_v01 { + u8 mask_valid; + u64 mask; +}; + +#define WLFW_DYNAMIC_FEATURE_MASK_REQ_MSG_V01_MAX_MSG_LEN 11 +extern struct qmi_elem_info wlfw_dynamic_feature_mask_req_msg_v01_ei[]; + +struct wlfw_dynamic_feature_mask_resp_msg_v01 { + struct qmi_response_type_v01 resp; + u8 prev_mask_valid; + u64 prev_mask; + u8 curr_mask_valid; + u64 curr_mask; +}; + +#define WLFW_DYNAMIC_FEATURE_MASK_RESP_MSG_V01_MAX_MSG_LEN 29 +extern struct qmi_elem_info wlfw_dynamic_feature_mask_resp_msg_v01_ei[]; + +struct wlfw_m3_info_req_msg_v01 { + u64 addr; + u32 size; +}; + +#define WLFW_M3_INFO_REQ_MSG_V01_MAX_MSG_LEN 18 +extern struct qmi_elem_info wlfw_m3_info_req_msg_v01_ei[]; + +struct wlfw_m3_info_resp_msg_v01 { + struct qmi_response_type_v01 resp; +}; + +#define WLFW_M3_INFO_RESP_MSG_V01_MAX_MSG_LEN 7 +extern struct qmi_elem_info wlfw_m3_info_resp_msg_v01_ei[]; + +struct wlfw_xo_cal_ind_msg_v01 { + u8 xo_cal_data; +}; + +#define WLFW_XO_CAL_IND_MSG_V01_MAX_MSG_LEN 4 +extern struct qmi_elem_info wlfw_xo_cal_ind_msg_v01_ei[]; + +struct wlfw_cal_done_ind_msg_v01 { + char placeholder; +}; + +#define WLFW_CAL_DONE_IND_MSG_V01_MAX_MSG_LEN 0 +extern struct qmi_elem_info wlfw_cal_done_ind_msg_v01_ei[]; + +struct wlfw_qdss_trace_req_mem_ind_msg_v01 { + u32 mem_seg_len; + struct wlfw_mem_seg_s_v01 mem_seg[QMI_WLFW_MAX_NUM_MEM_SEG_V01]; +}; + +#define WLFW_QDSS_TRACE_REQ_MEM_IND_MSG_V01_MAX_MSG_LEN 1124 +extern struct qmi_elem_info wlfw_qdss_trace_req_mem_ind_msg_v01_ei[]; + +struct wlfw_qdss_trace_mem_info_req_msg_v01 { + u32 mem_seg_len; + struct wlfw_mem_seg_resp_s_v01 mem_seg[QMI_WLFW_MAX_NUM_MEM_SEG_V01]; +}; + +#define WLFW_QDSS_TRACE_MEM_INFO_REQ_MSG_V01_MAX_MSG_LEN 548 +extern struct qmi_elem_info wlfw_qdss_trace_mem_info_req_msg_v01_ei[]; + +struct wlfw_qdss_trace_mem_info_resp_msg_v01 { + struct qmi_response_type_v01 resp; +}; + +#define WLFW_QDSS_TRACE_MEM_INFO_RESP_MSG_V01_MAX_MSG_LEN 7 +extern struct qmi_elem_info wlfw_qdss_trace_mem_info_resp_msg_v01_ei[]; + +struct wlfw_qdss_trace_save_ind_msg_v01 { + u32 source; + u32 total_size; + u8 mem_seg_valid; + u32 mem_seg_len; + struct wlfw_mem_seg_resp_s_v01 mem_seg[QMI_WLFW_MAX_NUM_MEM_SEG_V01]; + u8 file_name_valid; + char file_name[QMI_WLFW_MAX_STR_LEN_V01 + 1]; +}; + +#define WLFW_QDSS_TRACE_SAVE_IND_MSG_V01_MAX_MSG_LEN 581 +extern struct qmi_elem_info wlfw_qdss_trace_save_ind_msg_v01_ei[]; + +struct wlfw_qdss_trace_data_req_msg_v01 { + u32 seg_id; +}; + +#define WLFW_QDSS_TRACE_DATA_REQ_MSG_V01_MAX_MSG_LEN 7 +extern struct qmi_elem_info wlfw_qdss_trace_data_req_msg_v01_ei[]; + +struct wlfw_qdss_trace_data_resp_msg_v01 { + struct qmi_response_type_v01 resp; + u8 total_size_valid; + u32 total_size; + u8 seg_id_valid; + u32 seg_id; + u8 data_valid; + u32 data_len; + u8 data[QMI_WLFW_MAX_DATA_SIZE_V01]; + u8 end_valid; + u8 end; +}; + +#define WLFW_QDSS_TRACE_DATA_RESP_MSG_V01_MAX_MSG_LEN 6174 +extern struct qmi_elem_info wlfw_qdss_trace_data_resp_msg_v01_ei[]; + +struct wlfw_qdss_trace_config_download_req_msg_v01 { + u8 total_size_valid; + u32 total_size; + u8 seg_id_valid; + u32 seg_id; + u8 data_valid; + u32 data_len; + u8 data[QMI_WLFW_MAX_DATA_SIZE_V01]; + u8 end_valid; + u8 end; +}; + +#define WLFW_QDSS_TRACE_CONFIG_DOWNLOAD_REQ_MSG_V01_MAX_MSG_LEN 6167 +extern struct qmi_elem_info wlfw_qdss_trace_config_download_req_msg_v01_ei[]; + +struct wlfw_qdss_trace_config_download_resp_msg_v01 { + struct qmi_response_type_v01 resp; +}; + +#define WLFW_QDSS_TRACE_CONFIG_DOWNLOAD_RESP_MSG_V01_MAX_MSG_LEN 7 +extern struct qmi_elem_info wlfw_qdss_trace_config_download_resp_msg_v01_ei[]; + +struct wlfw_qdss_trace_mode_req_msg_v01 { + u8 mode_valid; + enum wlfw_qdss_trace_mode_enum_v01 mode; + u8 option_valid; + u64 option; + u8 hw_trc_disable_override_valid; + enum wlfw_qmi_param_value_v01 hw_trc_disable_override; +}; + +#define WLFW_QDSS_TRACE_MODE_REQ_MSG_V01_MAX_MSG_LEN 25 +extern struct qmi_elem_info wlfw_qdss_trace_mode_req_msg_v01_ei[]; + +struct wlfw_qdss_trace_mode_resp_msg_v01 { + struct qmi_response_type_v01 resp; +}; + +#define WLFW_QDSS_TRACE_MODE_RESP_MSG_V01_MAX_MSG_LEN 7 +extern struct qmi_elem_info wlfw_qdss_trace_mode_resp_msg_v01_ei[]; + +struct wlfw_qdss_trace_free_ind_msg_v01 { + u8 mem_seg_valid; + u32 mem_seg_len; + struct wlfw_mem_seg_resp_s_v01 mem_seg[QMI_WLFW_MAX_NUM_MEM_SEG_V01]; +}; + +#define WLFW_QDSS_TRACE_FREE_IND_MSG_V01_MAX_MSG_LEN 548 +extern struct qmi_elem_info wlfw_qdss_trace_free_ind_msg_v01_ei[]; + +struct wlfw_shutdown_req_msg_v01 { + u8 shutdown_valid; + u8 shutdown; +}; + +#define WLFW_SHUTDOWN_REQ_MSG_V01_MAX_MSG_LEN 4 +extern struct qmi_elem_info wlfw_shutdown_req_msg_v01_ei[]; + +struct wlfw_shutdown_resp_msg_v01 { + struct qmi_response_type_v01 resp; +}; + +#define WLFW_SHUTDOWN_RESP_MSG_V01_MAX_MSG_LEN 7 +extern struct qmi_elem_info wlfw_shutdown_resp_msg_v01_ei[]; + +struct wlfw_antenna_switch_req_msg_v01 { + char placeholder; +}; + +#define WLFW_ANTENNA_SWITCH_REQ_MSG_V01_MAX_MSG_LEN 0 +extern struct qmi_elem_info wlfw_antenna_switch_req_msg_v01_ei[]; + +struct wlfw_antenna_switch_resp_msg_v01 { + struct qmi_response_type_v01 resp; + u8 antenna_valid; + u64 antenna; +}; + +#define WLFW_ANTENNA_SWITCH_RESP_MSG_V01_MAX_MSG_LEN 18 +extern struct qmi_elem_info wlfw_antenna_switch_resp_msg_v01_ei[]; + +struct wlfw_antenna_grant_req_msg_v01 { + u8 grant_valid; + u64 grant; +}; + +#define WLFW_ANTENNA_GRANT_REQ_MSG_V01_MAX_MSG_LEN 11 +extern struct qmi_elem_info wlfw_antenna_grant_req_msg_v01_ei[]; + +struct wlfw_antenna_grant_resp_msg_v01 { + struct qmi_response_type_v01 resp; +}; + +#define WLFW_ANTENNA_GRANT_RESP_MSG_V01_MAX_MSG_LEN 7 +extern struct qmi_elem_info wlfw_antenna_grant_resp_msg_v01_ei[]; + +struct wlfw_wfc_call_status_req_msg_v01 { + u32 wfc_call_status_len; + u8 wfc_call_status[QMI_WLFW_MAX_WFC_CALL_STATUS_DATA_SIZE_V01]; + u8 wfc_call_active_valid; + u8 wfc_call_active; + u8 all_wfc_calls_held_valid; + u8 all_wfc_calls_held; + u8 is_wfc_emergency_valid; + u8 is_wfc_emergency; + u8 twt_ims_start_valid; + u64 twt_ims_start; + u8 twt_ims_int_valid; + u16 twt_ims_int; + u8 media_quality_valid; + enum wlfw_wfc_media_quality_v01 media_quality; +}; + +#define WLFW_WFC_CALL_STATUS_REQ_MSG_V01_MAX_MSG_LEN 296 +extern struct qmi_elem_info wlfw_wfc_call_status_req_msg_v01_ei[]; + +struct wlfw_wfc_call_status_resp_msg_v01 { + struct qmi_response_type_v01 resp; +}; + +#define WLFW_WFC_CALL_STATUS_RESP_MSG_V01_MAX_MSG_LEN 7 +extern struct qmi_elem_info wlfw_wfc_call_status_resp_msg_v01_ei[]; + +struct wlfw_get_info_req_msg_v01 { + u8 type; + u32 data_len; + u8 data[QMI_WLFW_MAX_DATA_SIZE_V01]; +}; + +#define WLFW_GET_INFO_REQ_MSG_V01_MAX_MSG_LEN 6153 +extern struct qmi_elem_info wlfw_get_info_req_msg_v01_ei[]; + +struct wlfw_get_info_resp_msg_v01 { + struct qmi_response_type_v01 resp; +}; + +#define WLFW_GET_INFO_RESP_MSG_V01_MAX_MSG_LEN 7 +extern struct qmi_elem_info wlfw_get_info_resp_msg_v01_ei[]; + +struct wlfw_respond_get_info_ind_msg_v01 { + u32 data_len; + u8 data[QMI_WLFW_MAX_DATA_SIZE_V01]; + u8 type_valid; + u8 type; + u8 is_last_valid; + u8 is_last; + u8 seq_no_valid; + u32 seq_no; +}; + +#define WLFW_RESPOND_GET_INFO_IND_MSG_V01_MAX_MSG_LEN 6164 +extern struct qmi_elem_info wlfw_respond_get_info_ind_msg_v01_ei[]; + +struct wlfw_device_info_req_msg_v01 { + char placeholder; +}; + +#define WLFW_DEVICE_INFO_REQ_MSG_V01_MAX_MSG_LEN 0 +extern struct qmi_elem_info wlfw_device_info_req_msg_v01_ei[]; + +struct wlfw_device_info_resp_msg_v01 { + struct qmi_response_type_v01 resp; + u8 bar_addr_valid; + u64 bar_addr; + u8 bar_size_valid; + u32 bar_size; +}; + +#define WLFW_DEVICE_INFO_RESP_MSG_V01_MAX_MSG_LEN 25 +extern struct qmi_elem_info wlfw_device_info_resp_msg_v01_ei[]; + +struct wlfw_m3_dump_upload_req_ind_msg_v01 { + u32 pdev_id; + u64 addr; + u64 size; +}; + +#define WLFW_M3_DUMP_UPLOAD_REQ_IND_MSG_V01_MAX_MSG_LEN 29 +extern struct qmi_elem_info wlfw_m3_dump_upload_req_ind_msg_v01_ei[]; + +struct wlfw_m3_dump_upload_done_req_msg_v01 { + u32 pdev_id; + u32 status; +}; + +#define WLFW_M3_DUMP_UPLOAD_DONE_REQ_MSG_V01_MAX_MSG_LEN 14 +extern struct qmi_elem_info wlfw_m3_dump_upload_done_req_msg_v01_ei[]; + +struct wlfw_m3_dump_upload_done_resp_msg_v01 { + struct qmi_response_type_v01 resp; +}; + +#define WLFW_M3_DUMP_UPLOAD_DONE_RESP_MSG_V01_MAX_MSG_LEN 7 +extern struct qmi_elem_info wlfw_m3_dump_upload_done_resp_msg_v01_ei[]; + +struct wlfw_soc_wake_req_msg_v01 { + u8 wake_valid; + enum wlfw_soc_wake_enum_v01 wake; +}; + +#define WLFW_SOC_WAKE_REQ_MSG_V01_MAX_MSG_LEN 7 +extern struct qmi_elem_info wlfw_soc_wake_req_msg_v01_ei[]; + +struct wlfw_soc_wake_resp_msg_v01 { + struct qmi_response_type_v01 resp; +}; + +#define WLFW_SOC_WAKE_RESP_MSG_V01_MAX_MSG_LEN 7 +extern struct qmi_elem_info wlfw_soc_wake_resp_msg_v01_ei[]; + +struct wlfw_exit_power_save_req_msg_v01 { + char placeholder; +}; + +#define WLFW_EXIT_POWER_SAVE_REQ_MSG_V01_MAX_MSG_LEN 0 +extern struct qmi_elem_info wlfw_exit_power_save_req_msg_v01_ei[]; + +struct wlfw_exit_power_save_resp_msg_v01 { + struct qmi_response_type_v01 resp; +}; + +#define WLFW_EXIT_POWER_SAVE_RESP_MSG_V01_MAX_MSG_LEN 7 +extern struct qmi_elem_info wlfw_exit_power_save_resp_msg_v01_ei[]; + +struct wlfw_wfc_call_twt_config_ind_msg_v01 { + u8 twt_sta_start_valid; + u64 twt_sta_start; + u8 twt_sta_int_valid; + u16 twt_sta_int; + u8 twt_sta_upo_valid; + u16 twt_sta_upo; + u8 twt_sta_sp_valid; + u16 twt_sta_sp; + u8 twt_sta_dl_valid; + u16 twt_sta_dl; + u8 twt_sta_config_changed_valid; + u8 twt_sta_config_changed; +}; + +#define WLFW_WFC_CALL_TWT_CONFIG_IND_MSG_V01_MAX_MSG_LEN 35 +extern struct qmi_elem_info wlfw_wfc_call_twt_config_ind_msg_v01_ei[]; + +struct wlfw_qdss_mem_ready_ind_msg_v01 { + char placeholder; +}; + +#define WLFW_QDSS_MEM_READY_IND_MSG_V01_MAX_MSG_LEN 0 +extern struct qmi_elem_info wlfw_qdss_mem_ready_ind_msg_v01_ei[]; + +struct wlfw_pcie_gen_switch_req_msg_v01 { + enum wlfw_pcie_gen_speed_v01 pcie_speed; +}; + +#define WLFW_PCIE_GEN_SWITCH_REQ_MSG_V01_MAX_MSG_LEN 7 +extern struct qmi_elem_info wlfw_pcie_gen_switch_req_msg_v01_ei[]; + +struct wlfw_pcie_gen_switch_resp_msg_v01 { + struct qmi_response_type_v01 resp; +}; + +#define WLFW_PCIE_GEN_SWITCH_RESP_MSG_V01_MAX_MSG_LEN 7 +extern struct qmi_elem_info wlfw_pcie_gen_switch_resp_msg_v01_ei[]; + +#endif diff --git a/drivers/net/wireless/cnss_utils/Kconfig b/drivers/net/wireless/cnss_utils/Kconfig index 62b7129bbe17..ed1662cd4896 100644 --- a/drivers/net/wireless/cnss_utils/Kconfig +++ b/drivers/net/wireless/cnss_utils/Kconfig @@ -5,12 +5,4 @@ config CNSS_UTILS help Add CNSS utilities support for the WLAN driver module. This feature enables wlan driver to use CNSS utilities APIs to set - and get wlan related information. - -config CNSS_QMI_SVC - tristate "CNSS QMI SVC support" - help - Add CNSS QMI SVC support for the WLAN driver module. - This feature enable wlan driver to use CNSS QMI service APIs to set - and get wlan related information. - + and get wlan related information. \ No newline at end of file diff --git a/drivers/net/wireless/cnss_utils/Makefile b/drivers/net/wireless/cnss_utils/Makefile index 1b7088904d2e..aa007fd50508 100644 --- a/drivers/net/wireless/cnss_utils/Makefile +++ b/drivers/net/wireless/cnss_utils/Makefile @@ -1,4 +1,3 @@ # SPDX-License-Identifier: GPL-2.0-only obj-$(CONFIG_CNSS_UTILS) += cnss_utils.o -obj-$(CONFIG_CNSS_QMI_SVC) += wlan_firmware_service_v01.o diff --git a/drivers/soc/qcom/icnss2/Kconfig b/drivers/soc/qcom/icnss2/Kconfig index 829db44f2cd8..7e1e469dd133 100644 --- a/drivers/soc/qcom/icnss2/Kconfig +++ b/drivers/soc/qcom/icnss2/Kconfig @@ -20,7 +20,6 @@ config ICNSS2_DEBUG config ICNSS2_QMI bool "ICNSS2 Platform Driver QMI support" depends on ICNSS2 - select CNSS_QMI_SVC help Say 'Y' here to enable ICNSS QMI support. ICNSS driver will use QMI framework to communicate with WLAN FW. It will send coldboot diff --git a/drivers/soc/qcom/icnss2/Makefile b/drivers/soc/qcom/icnss2/Makefile index 735d85556b44..f0ac96742b03 100644 --- a/drivers/soc/qcom/icnss2/Makefile +++ b/drivers/soc/qcom/icnss2/Makefile @@ -2,9 +2,8 @@ obj-$(CONFIG_ICNSS2) += icnss2.o -ccflags-y += -I$(srctree)/drivers/net/wireless/cnss_utils/ icnss2-y := main.o icnss2-y += debug.o icnss2-y += power.o icnss2-y += genl.o -icnss2-$(CONFIG_ICNSS2_QMI) += qmi.o +icnss2-$(CONFIG_ICNSS2_QMI) += qmi.o wlan_firmware_service_v01.o diff --git a/drivers/net/wireless/cnss_utils/wlan_firmware_service_v01.c b/drivers/soc/qcom/icnss2/wlan_firmware_service_v01.c similarity index 79% rename from drivers/net/wireless/cnss_utils/wlan_firmware_service_v01.c rename to drivers/soc/qcom/icnss2/wlan_firmware_service_v01.c index b5d348cad289..bda8d11c05c6 100644 --- a/drivers/net/wireless/cnss_utils/wlan_firmware_service_v01.c +++ b/drivers/soc/qcom/icnss2/wlan_firmware_service_v01.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only -/* Copyright (c) 2020, The Linux Foundation. All rights reserved. */ +/* Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. */ #include "wlan_firmware_service_v01.h" @@ -10,8 +10,7 @@ static struct qmi_elem_info wlfw_ce_tgt_pipe_cfg_s_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0, - .offset = offsetof(struct - wlfw_ce_tgt_pipe_cfg_s_v01, + .offset = offsetof(struct wlfw_ce_tgt_pipe_cfg_s_v01, pipe_num), }, { @@ -20,8 +19,7 @@ static struct qmi_elem_info wlfw_ce_tgt_pipe_cfg_s_v01_ei[] = { .elem_size = sizeof(enum wlfw_pipedir_enum_v01), .array_type = NO_ARRAY, .tlv_type = 0, - .offset = offsetof(struct - wlfw_ce_tgt_pipe_cfg_s_v01, + .offset = offsetof(struct wlfw_ce_tgt_pipe_cfg_s_v01, pipe_dir), }, { @@ -30,8 +28,7 @@ static struct qmi_elem_info wlfw_ce_tgt_pipe_cfg_s_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0, - .offset = offsetof(struct - wlfw_ce_tgt_pipe_cfg_s_v01, + .offset = offsetof(struct wlfw_ce_tgt_pipe_cfg_s_v01, nentries), }, { @@ -40,8 +37,7 @@ static struct qmi_elem_info wlfw_ce_tgt_pipe_cfg_s_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0, - .offset = offsetof(struct - wlfw_ce_tgt_pipe_cfg_s_v01, + .offset = offsetof(struct wlfw_ce_tgt_pipe_cfg_s_v01, nbytes_max), }, { @@ -50,8 +46,7 @@ static struct qmi_elem_info wlfw_ce_tgt_pipe_cfg_s_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0, - .offset = offsetof(struct - wlfw_ce_tgt_pipe_cfg_s_v01, + .offset = offsetof(struct wlfw_ce_tgt_pipe_cfg_s_v01, flags), }, { @@ -68,8 +63,7 @@ static struct qmi_elem_info wlfw_ce_svc_pipe_cfg_s_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0, - .offset = offsetof(struct - wlfw_ce_svc_pipe_cfg_s_v01, + .offset = offsetof(struct wlfw_ce_svc_pipe_cfg_s_v01, service_id), }, { @@ -78,8 +72,7 @@ static struct qmi_elem_info wlfw_ce_svc_pipe_cfg_s_v01_ei[] = { .elem_size = sizeof(enum wlfw_pipedir_enum_v01), .array_type = NO_ARRAY, .tlv_type = 0, - .offset = offsetof(struct - wlfw_ce_svc_pipe_cfg_s_v01, + .offset = offsetof(struct wlfw_ce_svc_pipe_cfg_s_v01, pipe_dir), }, { @@ -88,8 +81,7 @@ static struct qmi_elem_info wlfw_ce_svc_pipe_cfg_s_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0, - .offset = offsetof(struct - wlfw_ce_svc_pipe_cfg_s_v01, + .offset = offsetof(struct wlfw_ce_svc_pipe_cfg_s_v01, pipe_num), }, { @@ -106,8 +98,7 @@ static struct qmi_elem_info wlfw_shadow_reg_cfg_s_v01_ei[] = { .elem_size = sizeof(u16), .array_type = NO_ARRAY, .tlv_type = 0, - .offset = offsetof(struct - wlfw_shadow_reg_cfg_s_v01, + .offset = offsetof(struct wlfw_shadow_reg_cfg_s_v01, id), }, { @@ -116,8 +107,7 @@ static struct qmi_elem_info wlfw_shadow_reg_cfg_s_v01_ei[] = { .elem_size = sizeof(u16), .array_type = NO_ARRAY, .tlv_type = 0, - .offset = offsetof(struct - wlfw_shadow_reg_cfg_s_v01, + .offset = offsetof(struct wlfw_shadow_reg_cfg_s_v01, offset), }, { @@ -134,8 +124,7 @@ static struct qmi_elem_info wlfw_shadow_reg_v2_cfg_s_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0, - .offset = offsetof(struct - wlfw_shadow_reg_v2_cfg_s_v01, + .offset = offsetof(struct wlfw_shadow_reg_v2_cfg_s_v01, addr), }, { @@ -152,8 +141,7 @@ static struct qmi_elem_info wlfw_rri_over_ddr_cfg_s_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0, - .offset = offsetof(struct - wlfw_rri_over_ddr_cfg_s_v01, + .offset = offsetof(struct wlfw_rri_over_ddr_cfg_s_v01, base_addr_low), }, { @@ -162,8 +150,7 @@ static struct qmi_elem_info wlfw_rri_over_ddr_cfg_s_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0, - .offset = offsetof(struct - wlfw_rri_over_ddr_cfg_s_v01, + .offset = offsetof(struct wlfw_rri_over_ddr_cfg_s_v01, base_addr_high), }, { @@ -180,8 +167,7 @@ static struct qmi_elem_info wlfw_msi_cfg_s_v01_ei[] = { .elem_size = sizeof(u16), .array_type = NO_ARRAY, .tlv_type = 0, - .offset = offsetof(struct - wlfw_msi_cfg_s_v01, + .offset = offsetof(struct wlfw_msi_cfg_s_v01, ce_id), }, { @@ -190,8 +176,7 @@ static struct qmi_elem_info wlfw_msi_cfg_s_v01_ei[] = { .elem_size = sizeof(u16), .array_type = NO_ARRAY, .tlv_type = 0, - .offset = offsetof(struct - wlfw_msi_cfg_s_v01, + .offset = offsetof(struct wlfw_msi_cfg_s_v01, msi_vector), }, { @@ -208,8 +193,7 @@ static struct qmi_elem_info wlfw_memory_region_info_s_v01_ei[] = { .elem_size = sizeof(u64), .array_type = NO_ARRAY, .tlv_type = 0, - .offset = offsetof(struct - wlfw_memory_region_info_s_v01, + .offset = offsetof(struct wlfw_memory_region_info_s_v01, region_addr), }, { @@ -218,8 +202,7 @@ static struct qmi_elem_info wlfw_memory_region_info_s_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0, - .offset = offsetof(struct - wlfw_memory_region_info_s_v01, + .offset = offsetof(struct wlfw_memory_region_info_s_v01, size), }, { @@ -228,8 +211,7 @@ static struct qmi_elem_info wlfw_memory_region_info_s_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0, - .offset = offsetof(struct - wlfw_memory_region_info_s_v01, + .offset = offsetof(struct wlfw_memory_region_info_s_v01, secure_flag), }, { @@ -246,8 +228,7 @@ static struct qmi_elem_info wlfw_mem_cfg_s_v01_ei[] = { .elem_size = sizeof(u64), .array_type = NO_ARRAY, .tlv_type = 0, - .offset = offsetof(struct - wlfw_mem_cfg_s_v01, + .offset = offsetof(struct wlfw_mem_cfg_s_v01, offset), }, { @@ -256,8 +237,7 @@ static struct qmi_elem_info wlfw_mem_cfg_s_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0, - .offset = offsetof(struct - wlfw_mem_cfg_s_v01, + .offset = offsetof(struct wlfw_mem_cfg_s_v01, size), }, { @@ -266,8 +246,7 @@ static struct qmi_elem_info wlfw_mem_cfg_s_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0, - .offset = offsetof(struct - wlfw_mem_cfg_s_v01, + .offset = offsetof(struct wlfw_mem_cfg_s_v01, secure_flag), }, { @@ -284,8 +263,7 @@ static struct qmi_elem_info wlfw_mem_seg_s_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0, - .offset = offsetof(struct - wlfw_mem_seg_s_v01, + .offset = offsetof(struct wlfw_mem_seg_s_v01, size), }, { @@ -294,8 +272,7 @@ static struct qmi_elem_info wlfw_mem_seg_s_v01_ei[] = { .elem_size = sizeof(enum wlfw_mem_type_enum_v01), .array_type = NO_ARRAY, .tlv_type = 0, - .offset = offsetof(struct - wlfw_mem_seg_s_v01, + .offset = offsetof(struct wlfw_mem_seg_s_v01, type), }, { @@ -304,8 +281,7 @@ static struct qmi_elem_info wlfw_mem_seg_s_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0, - .offset = offsetof(struct - wlfw_mem_seg_s_v01, + .offset = offsetof(struct wlfw_mem_seg_s_v01, mem_cfg_len), }, { @@ -314,8 +290,7 @@ static struct qmi_elem_info wlfw_mem_seg_s_v01_ei[] = { .elem_size = sizeof(struct wlfw_mem_cfg_s_v01), .array_type = VAR_LEN_ARRAY, .tlv_type = 0, - .offset = offsetof(struct - wlfw_mem_seg_s_v01, + .offset = offsetof(struct wlfw_mem_seg_s_v01, mem_cfg), .ei_array = wlfw_mem_cfg_s_v01_ei, }, @@ -333,8 +308,7 @@ static struct qmi_elem_info wlfw_mem_seg_resp_s_v01_ei[] = { .elem_size = sizeof(u64), .array_type = NO_ARRAY, .tlv_type = 0, - .offset = offsetof(struct - wlfw_mem_seg_resp_s_v01, + .offset = offsetof(struct wlfw_mem_seg_resp_s_v01, addr), }, { @@ -343,8 +317,7 @@ static struct qmi_elem_info wlfw_mem_seg_resp_s_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0, - .offset = offsetof(struct - wlfw_mem_seg_resp_s_v01, + .offset = offsetof(struct wlfw_mem_seg_resp_s_v01, size), }, { @@ -353,8 +326,7 @@ static struct qmi_elem_info wlfw_mem_seg_resp_s_v01_ei[] = { .elem_size = sizeof(enum wlfw_mem_type_enum_v01), .array_type = NO_ARRAY, .tlv_type = 0, - .offset = offsetof(struct - wlfw_mem_seg_resp_s_v01, + .offset = offsetof(struct wlfw_mem_seg_resp_s_v01, type), }, { @@ -363,8 +335,7 @@ static struct qmi_elem_info wlfw_mem_seg_resp_s_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0, - .offset = offsetof(struct - wlfw_mem_seg_resp_s_v01, + .offset = offsetof(struct wlfw_mem_seg_resp_s_v01, restore), }, { @@ -381,8 +352,7 @@ static struct qmi_elem_info wlfw_rf_chip_info_s_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0, - .offset = offsetof(struct - wlfw_rf_chip_info_s_v01, + .offset = offsetof(struct wlfw_rf_chip_info_s_v01, chip_id), }, { @@ -391,8 +361,7 @@ static struct qmi_elem_info wlfw_rf_chip_info_s_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0, - .offset = offsetof(struct - wlfw_rf_chip_info_s_v01, + .offset = offsetof(struct wlfw_rf_chip_info_s_v01, chip_family), }, { @@ -409,8 +378,7 @@ static struct qmi_elem_info wlfw_rf_board_info_s_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0, - .offset = offsetof(struct - wlfw_rf_board_info_s_v01, + .offset = offsetof(struct wlfw_rf_board_info_s_v01, board_id), }, { @@ -427,8 +395,7 @@ static struct qmi_elem_info wlfw_soc_info_s_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0, - .offset = offsetof(struct - wlfw_soc_info_s_v01, + .offset = offsetof(struct wlfw_soc_info_s_v01, soc_id), }, { @@ -445,8 +412,7 @@ static struct qmi_elem_info wlfw_fw_version_info_s_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0, - .offset = offsetof(struct - wlfw_fw_version_info_s_v01, + .offset = offsetof(struct wlfw_fw_version_info_s_v01, fw_version), }, { @@ -455,8 +421,7 @@ static struct qmi_elem_info wlfw_fw_version_info_s_v01_ei[] = { .elem_size = sizeof(char), .array_type = NO_ARRAY, .tlv_type = 0, - .offset = offsetof(struct - wlfw_fw_version_info_s_v01, + .offset = offsetof(struct wlfw_fw_version_info_s_v01, fw_build_timestamp), }, { @@ -473,8 +438,7 @@ static struct qmi_elem_info wlfw_host_ddr_range_s_v01_ei[] = { .elem_size = sizeof(u64), .array_type = NO_ARRAY, .tlv_type = 0, - .offset = offsetof(struct - wlfw_host_ddr_range_s_v01, + .offset = offsetof(struct wlfw_host_ddr_range_s_v01, start), }, { @@ -483,8 +447,7 @@ static struct qmi_elem_info wlfw_host_ddr_range_s_v01_ei[] = { .elem_size = sizeof(u64), .array_type = NO_ARRAY, .tlv_type = 0, - .offset = offsetof(struct - wlfw_host_ddr_range_s_v01, + .offset = offsetof(struct wlfw_host_ddr_range_s_v01, size), }, { @@ -501,8 +464,7 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x10, - .offset = offsetof(struct - wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, fw_ready_enable_valid), }, { @@ -511,8 +473,7 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x10, - .offset = offsetof(struct - wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, fw_ready_enable), }, { @@ -521,8 +482,7 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x11, - .offset = offsetof(struct - wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, initiate_cal_download_enable_valid), }, { @@ -531,8 +491,7 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x11, - .offset = offsetof(struct - wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, initiate_cal_download_enable), }, { @@ -541,8 +500,7 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x12, - .offset = offsetof(struct - wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, initiate_cal_update_enable_valid), }, { @@ -551,8 +509,7 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x12, - .offset = offsetof(struct - wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, initiate_cal_update_enable), }, { @@ -561,8 +518,7 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x13, - .offset = offsetof(struct - wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, msa_ready_enable_valid), }, { @@ -571,8 +527,7 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x13, - .offset = offsetof(struct - wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, msa_ready_enable), }, { @@ -581,8 +536,7 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x14, - .offset = offsetof(struct - wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, pin_connect_result_enable_valid), }, { @@ -591,8 +545,7 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x14, - .offset = offsetof(struct - wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, pin_connect_result_enable), }, { @@ -601,8 +554,7 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x15, - .offset = offsetof(struct - wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, client_id_valid), }, { @@ -611,8 +563,7 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0x15, - .offset = offsetof(struct - wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, client_id), }, { @@ -621,8 +572,7 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x16, - .offset = offsetof(struct - wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, request_mem_enable_valid), }, { @@ -631,8 +581,7 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x16, - .offset = offsetof(struct - wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, request_mem_enable), }, { @@ -641,8 +590,7 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x17, - .offset = offsetof(struct - wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, fw_mem_ready_enable_valid), }, { @@ -651,8 +599,7 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x17, - .offset = offsetof(struct - wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, fw_mem_ready_enable), }, { @@ -661,8 +608,7 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x18, - .offset = offsetof(struct - wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, fw_init_done_enable_valid), }, { @@ -671,8 +617,7 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x18, - .offset = offsetof(struct - wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, fw_init_done_enable), }, { @@ -681,8 +626,7 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x19, - .offset = offsetof(struct - wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, rejuvenate_enable_valid), }, { @@ -691,8 +635,7 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0x19, - .offset = offsetof(struct - wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, rejuvenate_enable), }, { @@ -701,8 +644,7 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x1A, - .offset = offsetof(struct - wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, xo_cal_enable_valid), }, { @@ -711,8 +653,7 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x1A, - .offset = offsetof(struct - wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, xo_cal_enable), }, { @@ -721,8 +662,7 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x1B, - .offset = offsetof(struct - wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, cal_done_enable_valid), }, { @@ -731,8 +671,7 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x1B, - .offset = offsetof(struct - wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, cal_done_enable), }, { @@ -741,8 +680,7 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x1C, - .offset = offsetof(struct - wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, qdss_trace_req_mem_enable_valid), }, { @@ -751,8 +689,7 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x1C, - .offset = offsetof(struct - wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, qdss_trace_req_mem_enable), }, { @@ -761,8 +698,7 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x1D, - .offset = offsetof(struct - wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, qdss_trace_save_enable_valid), }, { @@ -771,8 +707,7 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x1D, - .offset = offsetof(struct - wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, qdss_trace_save_enable), }, { @@ -781,8 +716,7 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x1E, - .offset = offsetof(struct - wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, qdss_trace_free_enable_valid), }, { @@ -791,8 +725,7 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x1E, - .offset = offsetof(struct - wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, qdss_trace_free_enable), }, { @@ -801,8 +734,7 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x1F, - .offset = offsetof(struct - wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, respond_get_info_enable_valid), }, { @@ -811,8 +743,7 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x1F, - .offset = offsetof(struct - wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, respond_get_info_enable), }, { @@ -821,8 +752,7 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x20, - .offset = offsetof(struct - wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, m3_dump_upload_req_enable_valid), }, { @@ -831,8 +761,7 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x20, - .offset = offsetof(struct - wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, m3_dump_upload_req_enable), }, { @@ -841,8 +770,7 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x21, - .offset = offsetof(struct - wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, wfc_call_twt_config_enable_valid), }, { @@ -851,8 +779,7 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x21, - .offset = offsetof(struct - wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, wfc_call_twt_config_enable), }, { @@ -861,8 +788,7 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x22, - .offset = offsetof(struct - wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, qdss_mem_ready_enable_valid), }, { @@ -871,8 +797,7 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x22, - .offset = offsetof(struct - wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct wlfw_ind_register_req_msg_v01, qdss_mem_ready_enable), }, { @@ -881,7 +806,6 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_ind_register_req_msg_v01_ei); struct qmi_elem_info wlfw_ind_register_resp_msg_v01_ei[] = { { @@ -921,7 +845,6 @@ struct qmi_elem_info wlfw_ind_register_resp_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_ind_register_resp_msg_v01_ei); struct qmi_elem_info wlfw_fw_ready_ind_msg_v01_ei[] = { { @@ -930,7 +853,6 @@ struct qmi_elem_info wlfw_fw_ready_ind_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_fw_ready_ind_msg_v01_ei); struct qmi_elem_info wlfw_msa_ready_ind_msg_v01_ei[] = { { @@ -939,8 +861,7 @@ struct qmi_elem_info wlfw_msa_ready_ind_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x10, - .offset = offsetof(struct - wlfw_msa_ready_ind_msg_v01, + .offset = offsetof(struct wlfw_msa_ready_ind_msg_v01, hang_data_addr_offset_valid), }, { @@ -949,8 +870,7 @@ struct qmi_elem_info wlfw_msa_ready_ind_msg_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0x10, - .offset = offsetof(struct - wlfw_msa_ready_ind_msg_v01, + .offset = offsetof(struct wlfw_msa_ready_ind_msg_v01, hang_data_addr_offset), }, { @@ -959,8 +879,7 @@ struct qmi_elem_info wlfw_msa_ready_ind_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x11, - .offset = offsetof(struct - wlfw_msa_ready_ind_msg_v01, + .offset = offsetof(struct wlfw_msa_ready_ind_msg_v01, hang_data_length_valid), }, { @@ -969,8 +888,7 @@ struct qmi_elem_info wlfw_msa_ready_ind_msg_v01_ei[] = { .elem_size = sizeof(u16), .array_type = NO_ARRAY, .tlv_type = 0x11, - .offset = offsetof(struct - wlfw_msa_ready_ind_msg_v01, + .offset = offsetof(struct wlfw_msa_ready_ind_msg_v01, hang_data_length), }, { @@ -979,7 +897,6 @@ struct qmi_elem_info wlfw_msa_ready_ind_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_msa_ready_ind_msg_v01_ei); struct qmi_elem_info wlfw_pin_connect_result_ind_msg_v01_ei[] = { { @@ -1048,7 +965,6 @@ struct qmi_elem_info wlfw_pin_connect_result_ind_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_pin_connect_result_ind_msg_v01_ei); struct qmi_elem_info wlfw_wlan_mode_req_msg_v01_ei[] = { { @@ -1057,8 +973,7 @@ struct qmi_elem_info wlfw_wlan_mode_req_msg_v01_ei[] = { .elem_size = sizeof(enum wlfw_driver_mode_enum_v01), .array_type = NO_ARRAY, .tlv_type = 0x01, - .offset = offsetof(struct - wlfw_wlan_mode_req_msg_v01, + .offset = offsetof(struct wlfw_wlan_mode_req_msg_v01, mode), }, { @@ -1067,8 +982,7 @@ struct qmi_elem_info wlfw_wlan_mode_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x10, - .offset = offsetof(struct - wlfw_wlan_mode_req_msg_v01, + .offset = offsetof(struct wlfw_wlan_mode_req_msg_v01, hw_debug_valid), }, { @@ -1077,8 +991,7 @@ struct qmi_elem_info wlfw_wlan_mode_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x10, - .offset = offsetof(struct - wlfw_wlan_mode_req_msg_v01, + .offset = offsetof(struct wlfw_wlan_mode_req_msg_v01, hw_debug), }, { @@ -1087,7 +1000,6 @@ struct qmi_elem_info wlfw_wlan_mode_req_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_wlan_mode_req_msg_v01_ei); struct qmi_elem_info wlfw_wlan_mode_resp_msg_v01_ei[] = { { @@ -1096,8 +1008,7 @@ struct qmi_elem_info wlfw_wlan_mode_resp_msg_v01_ei[] = { .elem_size = sizeof(struct qmi_response_type_v01), .array_type = NO_ARRAY, .tlv_type = 0x02, - .offset = offsetof(struct - wlfw_wlan_mode_resp_msg_v01, + .offset = offsetof(struct wlfw_wlan_mode_resp_msg_v01, resp), .ei_array = qmi_response_type_v01_ei, }, @@ -1107,7 +1018,6 @@ struct qmi_elem_info wlfw_wlan_mode_resp_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_wlan_mode_resp_msg_v01_ei); struct qmi_elem_info wlfw_wlan_cfg_req_msg_v01_ei[] = { { @@ -1116,8 +1026,7 @@ struct qmi_elem_info wlfw_wlan_cfg_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x10, - .offset = offsetof(struct - wlfw_wlan_cfg_req_msg_v01, + .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, host_version_valid), }, { @@ -1126,8 +1035,7 @@ struct qmi_elem_info wlfw_wlan_cfg_req_msg_v01_ei[] = { .elem_size = sizeof(char), .array_type = NO_ARRAY, .tlv_type = 0x10, - .offset = offsetof(struct - wlfw_wlan_cfg_req_msg_v01, + .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, host_version), }, { @@ -1136,8 +1044,7 @@ struct qmi_elem_info wlfw_wlan_cfg_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x11, - .offset = offsetof(struct - wlfw_wlan_cfg_req_msg_v01, + .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, tgt_cfg_valid), }, { @@ -1146,8 +1053,7 @@ struct qmi_elem_info wlfw_wlan_cfg_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x11, - .offset = offsetof(struct - wlfw_wlan_cfg_req_msg_v01, + .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, tgt_cfg_len), }, { @@ -1156,8 +1062,7 @@ struct qmi_elem_info wlfw_wlan_cfg_req_msg_v01_ei[] = { .elem_size = sizeof(struct wlfw_ce_tgt_pipe_cfg_s_v01), .array_type = VAR_LEN_ARRAY, .tlv_type = 0x11, - .offset = offsetof(struct - wlfw_wlan_cfg_req_msg_v01, + .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, tgt_cfg), .ei_array = wlfw_ce_tgt_pipe_cfg_s_v01_ei, }, @@ -1167,8 +1072,7 @@ struct qmi_elem_info wlfw_wlan_cfg_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x12, - .offset = offsetof(struct - wlfw_wlan_cfg_req_msg_v01, + .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, svc_cfg_valid), }, { @@ -1177,8 +1081,7 @@ struct qmi_elem_info wlfw_wlan_cfg_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x12, - .offset = offsetof(struct - wlfw_wlan_cfg_req_msg_v01, + .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, svc_cfg_len), }, { @@ -1187,8 +1090,7 @@ struct qmi_elem_info wlfw_wlan_cfg_req_msg_v01_ei[] = { .elem_size = sizeof(struct wlfw_ce_svc_pipe_cfg_s_v01), .array_type = VAR_LEN_ARRAY, .tlv_type = 0x12, - .offset = offsetof(struct - wlfw_wlan_cfg_req_msg_v01, + .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, svc_cfg), .ei_array = wlfw_ce_svc_pipe_cfg_s_v01_ei, }, @@ -1198,8 +1100,7 @@ struct qmi_elem_info wlfw_wlan_cfg_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x13, - .offset = offsetof(struct - wlfw_wlan_cfg_req_msg_v01, + .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, shadow_reg_valid), }, { @@ -1208,8 +1109,7 @@ struct qmi_elem_info wlfw_wlan_cfg_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x13, - .offset = offsetof(struct - wlfw_wlan_cfg_req_msg_v01, + .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, shadow_reg_len), }, { @@ -1218,8 +1118,7 @@ struct qmi_elem_info wlfw_wlan_cfg_req_msg_v01_ei[] = { .elem_size = sizeof(struct wlfw_shadow_reg_cfg_s_v01), .array_type = VAR_LEN_ARRAY, .tlv_type = 0x13, - .offset = offsetof(struct - wlfw_wlan_cfg_req_msg_v01, + .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, shadow_reg), .ei_array = wlfw_shadow_reg_cfg_s_v01_ei, }, @@ -1229,8 +1128,7 @@ struct qmi_elem_info wlfw_wlan_cfg_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x14, - .offset = offsetof(struct - wlfw_wlan_cfg_req_msg_v01, + .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, shadow_reg_v2_valid), }, { @@ -1239,8 +1137,7 @@ struct qmi_elem_info wlfw_wlan_cfg_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x14, - .offset = offsetof(struct - wlfw_wlan_cfg_req_msg_v01, + .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, shadow_reg_v2_len), }, { @@ -1249,8 +1146,7 @@ struct qmi_elem_info wlfw_wlan_cfg_req_msg_v01_ei[] = { .elem_size = sizeof(struct wlfw_shadow_reg_v2_cfg_s_v01), .array_type = VAR_LEN_ARRAY, .tlv_type = 0x14, - .offset = offsetof(struct - wlfw_wlan_cfg_req_msg_v01, + .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, shadow_reg_v2), .ei_array = wlfw_shadow_reg_v2_cfg_s_v01_ei, }, @@ -1260,8 +1156,7 @@ struct qmi_elem_info wlfw_wlan_cfg_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x15, - .offset = offsetof(struct - wlfw_wlan_cfg_req_msg_v01, + .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, rri_over_ddr_cfg_valid), }, { @@ -1270,8 +1165,7 @@ struct qmi_elem_info wlfw_wlan_cfg_req_msg_v01_ei[] = { .elem_size = sizeof(struct wlfw_rri_over_ddr_cfg_s_v01), .array_type = NO_ARRAY, .tlv_type = 0x15, - .offset = offsetof(struct - wlfw_wlan_cfg_req_msg_v01, + .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, rri_over_ddr_cfg), .ei_array = wlfw_rri_over_ddr_cfg_s_v01_ei, }, @@ -1281,8 +1175,7 @@ struct qmi_elem_info wlfw_wlan_cfg_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x16, - .offset = offsetof(struct - wlfw_wlan_cfg_req_msg_v01, + .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, msi_cfg_valid), }, { @@ -1291,8 +1184,7 @@ struct qmi_elem_info wlfw_wlan_cfg_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x16, - .offset = offsetof(struct - wlfw_wlan_cfg_req_msg_v01, + .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, msi_cfg_len), }, { @@ -1301,8 +1193,7 @@ struct qmi_elem_info wlfw_wlan_cfg_req_msg_v01_ei[] = { .elem_size = sizeof(struct wlfw_msi_cfg_s_v01), .array_type = VAR_LEN_ARRAY, .tlv_type = 0x16, - .offset = offsetof(struct - wlfw_wlan_cfg_req_msg_v01, + .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, msi_cfg), .ei_array = wlfw_msi_cfg_s_v01_ei, }, @@ -1312,7 +1203,6 @@ struct qmi_elem_info wlfw_wlan_cfg_req_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_wlan_cfg_req_msg_v01_ei); struct qmi_elem_info wlfw_wlan_cfg_resp_msg_v01_ei[] = { { @@ -1321,8 +1211,7 @@ struct qmi_elem_info wlfw_wlan_cfg_resp_msg_v01_ei[] = { .elem_size = sizeof(struct qmi_response_type_v01), .array_type = NO_ARRAY, .tlv_type = 0x02, - .offset = offsetof(struct - wlfw_wlan_cfg_resp_msg_v01, + .offset = offsetof(struct wlfw_wlan_cfg_resp_msg_v01, resp), .ei_array = qmi_response_type_v01_ei, }, @@ -1332,7 +1221,6 @@ struct qmi_elem_info wlfw_wlan_cfg_resp_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_wlan_cfg_resp_msg_v01_ei); struct qmi_elem_info wlfw_cap_req_msg_v01_ei[] = { { @@ -1341,7 +1229,6 @@ struct qmi_elem_info wlfw_cap_req_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_cap_req_msg_v01_ei); struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[] = { { @@ -1350,8 +1237,7 @@ struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[] = { .elem_size = sizeof(struct qmi_response_type_v01), .array_type = NO_ARRAY, .tlv_type = 0x02, - .offset = offsetof(struct - wlfw_cap_resp_msg_v01, + .offset = offsetof(struct wlfw_cap_resp_msg_v01, resp), .ei_array = qmi_response_type_v01_ei, }, @@ -1361,8 +1247,7 @@ struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x10, - .offset = offsetof(struct - wlfw_cap_resp_msg_v01, + .offset = offsetof(struct wlfw_cap_resp_msg_v01, chip_info_valid), }, { @@ -1371,8 +1256,7 @@ struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[] = { .elem_size = sizeof(struct wlfw_rf_chip_info_s_v01), .array_type = NO_ARRAY, .tlv_type = 0x10, - .offset = offsetof(struct - wlfw_cap_resp_msg_v01, + .offset = offsetof(struct wlfw_cap_resp_msg_v01, chip_info), .ei_array = wlfw_rf_chip_info_s_v01_ei, }, @@ -1382,8 +1266,7 @@ struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x11, - .offset = offsetof(struct - wlfw_cap_resp_msg_v01, + .offset = offsetof(struct wlfw_cap_resp_msg_v01, board_info_valid), }, { @@ -1392,8 +1275,7 @@ struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[] = { .elem_size = sizeof(struct wlfw_rf_board_info_s_v01), .array_type = NO_ARRAY, .tlv_type = 0x11, - .offset = offsetof(struct - wlfw_cap_resp_msg_v01, + .offset = offsetof(struct wlfw_cap_resp_msg_v01, board_info), .ei_array = wlfw_rf_board_info_s_v01_ei, }, @@ -1403,8 +1285,7 @@ struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x12, - .offset = offsetof(struct - wlfw_cap_resp_msg_v01, + .offset = offsetof(struct wlfw_cap_resp_msg_v01, soc_info_valid), }, { @@ -1413,8 +1294,7 @@ struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[] = { .elem_size = sizeof(struct wlfw_soc_info_s_v01), .array_type = NO_ARRAY, .tlv_type = 0x12, - .offset = offsetof(struct - wlfw_cap_resp_msg_v01, + .offset = offsetof(struct wlfw_cap_resp_msg_v01, soc_info), .ei_array = wlfw_soc_info_s_v01_ei, }, @@ -1424,8 +1304,7 @@ struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x13, - .offset = offsetof(struct - wlfw_cap_resp_msg_v01, + .offset = offsetof(struct wlfw_cap_resp_msg_v01, fw_version_info_valid), }, { @@ -1434,8 +1313,7 @@ struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[] = { .elem_size = sizeof(struct wlfw_fw_version_info_s_v01), .array_type = NO_ARRAY, .tlv_type = 0x13, - .offset = offsetof(struct - wlfw_cap_resp_msg_v01, + .offset = offsetof(struct wlfw_cap_resp_msg_v01, fw_version_info), .ei_array = wlfw_fw_version_info_s_v01_ei, }, @@ -1445,8 +1323,7 @@ struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x14, - .offset = offsetof(struct - wlfw_cap_resp_msg_v01, + .offset = offsetof(struct wlfw_cap_resp_msg_v01, fw_build_id_valid), }, { @@ -1455,8 +1332,7 @@ struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[] = { .elem_size = sizeof(char), .array_type = NO_ARRAY, .tlv_type = 0x14, - .offset = offsetof(struct - wlfw_cap_resp_msg_v01, + .offset = offsetof(struct wlfw_cap_resp_msg_v01, fw_build_id), }, { @@ -1465,8 +1341,7 @@ struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x15, - .offset = offsetof(struct - wlfw_cap_resp_msg_v01, + .offset = offsetof(struct wlfw_cap_resp_msg_v01, num_macs_valid), }, { @@ -1475,8 +1350,7 @@ struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x15, - .offset = offsetof(struct - wlfw_cap_resp_msg_v01, + .offset = offsetof(struct wlfw_cap_resp_msg_v01, num_macs), }, { @@ -1485,8 +1359,7 @@ struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x16, - .offset = offsetof(struct - wlfw_cap_resp_msg_v01, + .offset = offsetof(struct wlfw_cap_resp_msg_v01, voltage_mv_valid), }, { @@ -1495,8 +1368,7 @@ struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0x16, - .offset = offsetof(struct - wlfw_cap_resp_msg_v01, + .offset = offsetof(struct wlfw_cap_resp_msg_v01, voltage_mv), }, { @@ -1505,8 +1377,7 @@ struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x17, - .offset = offsetof(struct - wlfw_cap_resp_msg_v01, + .offset = offsetof(struct wlfw_cap_resp_msg_v01, time_freq_hz_valid), }, { @@ -1515,8 +1386,7 @@ struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0x17, - .offset = offsetof(struct - wlfw_cap_resp_msg_v01, + .offset = offsetof(struct wlfw_cap_resp_msg_v01, time_freq_hz), }, { @@ -1525,8 +1395,7 @@ struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x18, - .offset = offsetof(struct - wlfw_cap_resp_msg_v01, + .offset = offsetof(struct wlfw_cap_resp_msg_v01, otp_version_valid), }, { @@ -1535,8 +1404,7 @@ struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0x18, - .offset = offsetof(struct - wlfw_cap_resp_msg_v01, + .offset = offsetof(struct wlfw_cap_resp_msg_v01, otp_version), }, { @@ -1545,8 +1413,7 @@ struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x19, - .offset = offsetof(struct - wlfw_cap_resp_msg_v01, + .offset = offsetof(struct wlfw_cap_resp_msg_v01, eeprom_caldata_read_timeout_valid), }, { @@ -1555,8 +1422,7 @@ struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0x19, - .offset = offsetof(struct - wlfw_cap_resp_msg_v01, + .offset = offsetof(struct wlfw_cap_resp_msg_v01, eeprom_caldata_read_timeout), }, { @@ -1565,8 +1431,7 @@ struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x1A, - .offset = offsetof(struct - wlfw_cap_resp_msg_v01, + .offset = offsetof(struct wlfw_cap_resp_msg_v01, fw_caps_valid), }, { @@ -1575,8 +1440,7 @@ struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[] = { .elem_size = sizeof(u64), .array_type = NO_ARRAY, .tlv_type = 0x1A, - .offset = offsetof(struct - wlfw_cap_resp_msg_v01, + .offset = offsetof(struct wlfw_cap_resp_msg_v01, fw_caps), }, { @@ -1585,8 +1449,7 @@ struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x1B, - .offset = offsetof(struct - wlfw_cap_resp_msg_v01, + .offset = offsetof(struct wlfw_cap_resp_msg_v01, rd_card_chain_cap_valid), }, { @@ -1595,8 +1458,7 @@ struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[] = { .elem_size = sizeof(enum wlfw_rd_card_chain_cap_v01), .array_type = NO_ARRAY, .tlv_type = 0x1B, - .offset = offsetof(struct - wlfw_cap_resp_msg_v01, + .offset = offsetof(struct wlfw_cap_resp_msg_v01, rd_card_chain_cap), }, { @@ -1605,7 +1467,6 @@ struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_cap_resp_msg_v01_ei); struct qmi_elem_info wlfw_bdf_download_req_msg_v01_ei[] = { { @@ -1614,8 +1475,7 @@ struct qmi_elem_info wlfw_bdf_download_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x01, - .offset = offsetof(struct - wlfw_bdf_download_req_msg_v01, + .offset = offsetof(struct wlfw_bdf_download_req_msg_v01, valid), }, { @@ -1624,8 +1484,7 @@ struct qmi_elem_info wlfw_bdf_download_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x10, - .offset = offsetof(struct - wlfw_bdf_download_req_msg_v01, + .offset = offsetof(struct wlfw_bdf_download_req_msg_v01, file_id_valid), }, { @@ -1634,8 +1493,7 @@ struct qmi_elem_info wlfw_bdf_download_req_msg_v01_ei[] = { .elem_size = sizeof(enum wlfw_cal_temp_id_enum_v01), .array_type = NO_ARRAY, .tlv_type = 0x10, - .offset = offsetof(struct - wlfw_bdf_download_req_msg_v01, + .offset = offsetof(struct wlfw_bdf_download_req_msg_v01, file_id), }, { @@ -1644,8 +1502,7 @@ struct qmi_elem_info wlfw_bdf_download_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x11, - .offset = offsetof(struct - wlfw_bdf_download_req_msg_v01, + .offset = offsetof(struct wlfw_bdf_download_req_msg_v01, total_size_valid), }, { @@ -1654,8 +1511,7 @@ struct qmi_elem_info wlfw_bdf_download_req_msg_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0x11, - .offset = offsetof(struct - wlfw_bdf_download_req_msg_v01, + .offset = offsetof(struct wlfw_bdf_download_req_msg_v01, total_size), }, { @@ -1664,8 +1520,7 @@ struct qmi_elem_info wlfw_bdf_download_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x12, - .offset = offsetof(struct - wlfw_bdf_download_req_msg_v01, + .offset = offsetof(struct wlfw_bdf_download_req_msg_v01, seg_id_valid), }, { @@ -1674,8 +1529,7 @@ struct qmi_elem_info wlfw_bdf_download_req_msg_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0x12, - .offset = offsetof(struct - wlfw_bdf_download_req_msg_v01, + .offset = offsetof(struct wlfw_bdf_download_req_msg_v01, seg_id), }, { @@ -1684,8 +1538,7 @@ struct qmi_elem_info wlfw_bdf_download_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x13, - .offset = offsetof(struct - wlfw_bdf_download_req_msg_v01, + .offset = offsetof(struct wlfw_bdf_download_req_msg_v01, data_valid), }, { @@ -1694,8 +1547,7 @@ struct qmi_elem_info wlfw_bdf_download_req_msg_v01_ei[] = { .elem_size = sizeof(u16), .array_type = NO_ARRAY, .tlv_type = 0x13, - .offset = offsetof(struct - wlfw_bdf_download_req_msg_v01, + .offset = offsetof(struct wlfw_bdf_download_req_msg_v01, data_len), }, { @@ -1704,8 +1556,7 @@ struct qmi_elem_info wlfw_bdf_download_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = VAR_LEN_ARRAY, .tlv_type = 0x13, - .offset = offsetof(struct - wlfw_bdf_download_req_msg_v01, + .offset = offsetof(struct wlfw_bdf_download_req_msg_v01, data), }, { @@ -1714,8 +1565,7 @@ struct qmi_elem_info wlfw_bdf_download_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x14, - .offset = offsetof(struct - wlfw_bdf_download_req_msg_v01, + .offset = offsetof(struct wlfw_bdf_download_req_msg_v01, end_valid), }, { @@ -1724,8 +1574,7 @@ struct qmi_elem_info wlfw_bdf_download_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x14, - .offset = offsetof(struct - wlfw_bdf_download_req_msg_v01, + .offset = offsetof(struct wlfw_bdf_download_req_msg_v01, end), }, { @@ -1734,8 +1583,7 @@ struct qmi_elem_info wlfw_bdf_download_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x15, - .offset = offsetof(struct - wlfw_bdf_download_req_msg_v01, + .offset = offsetof(struct wlfw_bdf_download_req_msg_v01, bdf_type_valid), }, { @@ -1744,8 +1592,7 @@ struct qmi_elem_info wlfw_bdf_download_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x15, - .offset = offsetof(struct - wlfw_bdf_download_req_msg_v01, + .offset = offsetof(struct wlfw_bdf_download_req_msg_v01, bdf_type), }, { @@ -1754,7 +1601,6 @@ struct qmi_elem_info wlfw_bdf_download_req_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_bdf_download_req_msg_v01_ei); struct qmi_elem_info wlfw_bdf_download_resp_msg_v01_ei[] = { { @@ -1794,7 +1640,6 @@ struct qmi_elem_info wlfw_bdf_download_resp_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_bdf_download_resp_msg_v01_ei); struct qmi_elem_info wlfw_cal_report_req_msg_v01_ei[] = { { @@ -1803,8 +1648,7 @@ struct qmi_elem_info wlfw_cal_report_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x01, - .offset = offsetof(struct - wlfw_cal_report_req_msg_v01, + .offset = offsetof(struct wlfw_cal_report_req_msg_v01, meta_data_len), }, { @@ -1813,8 +1657,7 @@ struct qmi_elem_info wlfw_cal_report_req_msg_v01_ei[] = { .elem_size = sizeof(enum wlfw_cal_temp_id_enum_v01), .array_type = VAR_LEN_ARRAY, .tlv_type = 0x01, - .offset = offsetof(struct - wlfw_cal_report_req_msg_v01, + .offset = offsetof(struct wlfw_cal_report_req_msg_v01, meta_data), }, { @@ -1823,8 +1666,7 @@ struct qmi_elem_info wlfw_cal_report_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x10, - .offset = offsetof(struct - wlfw_cal_report_req_msg_v01, + .offset = offsetof(struct wlfw_cal_report_req_msg_v01, xo_cal_data_valid), }, { @@ -1833,8 +1675,7 @@ struct qmi_elem_info wlfw_cal_report_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x10, - .offset = offsetof(struct - wlfw_cal_report_req_msg_v01, + .offset = offsetof(struct wlfw_cal_report_req_msg_v01, xo_cal_data), }, { @@ -1843,8 +1684,7 @@ struct qmi_elem_info wlfw_cal_report_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x11, - .offset = offsetof(struct - wlfw_cal_report_req_msg_v01, + .offset = offsetof(struct wlfw_cal_report_req_msg_v01, cal_remove_supported_valid), }, { @@ -1853,8 +1693,7 @@ struct qmi_elem_info wlfw_cal_report_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x11, - .offset = offsetof(struct - wlfw_cal_report_req_msg_v01, + .offset = offsetof(struct wlfw_cal_report_req_msg_v01, cal_remove_supported), }, { @@ -1863,7 +1702,6 @@ struct qmi_elem_info wlfw_cal_report_req_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_cal_report_req_msg_v01_ei); struct qmi_elem_info wlfw_cal_report_resp_msg_v01_ei[] = { { @@ -1872,8 +1710,7 @@ struct qmi_elem_info wlfw_cal_report_resp_msg_v01_ei[] = { .elem_size = sizeof(struct qmi_response_type_v01), .array_type = NO_ARRAY, .tlv_type = 0x02, - .offset = offsetof(struct - wlfw_cal_report_resp_msg_v01, + .offset = offsetof(struct wlfw_cal_report_resp_msg_v01, resp), .ei_array = qmi_response_type_v01_ei, }, @@ -1883,7 +1720,6 @@ struct qmi_elem_info wlfw_cal_report_resp_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_cal_report_resp_msg_v01_ei); struct qmi_elem_info wlfw_initiate_cal_download_ind_msg_v01_ei[] = { { @@ -1893,8 +1729,8 @@ struct qmi_elem_info wlfw_initiate_cal_download_ind_msg_v01_ei[] = { .array_type = NO_ARRAY, .tlv_type = 0x01, .offset = offsetof(struct - wlfw_initiate_cal_download_ind_msg_v01, - cal_id), + wlfw_initiate_cal_download_ind_msg_v01, + cal_id), }, { .data_type = QMI_OPT_FLAG, @@ -1903,8 +1739,8 @@ struct qmi_elem_info wlfw_initiate_cal_download_ind_msg_v01_ei[] = { .array_type = NO_ARRAY, .tlv_type = 0x10, .offset = offsetof(struct - wlfw_initiate_cal_download_ind_msg_v01, - total_size_valid), + wlfw_initiate_cal_download_ind_msg_v01, + total_size_valid), }, { .data_type = QMI_UNSIGNED_4_BYTE, @@ -1913,8 +1749,8 @@ struct qmi_elem_info wlfw_initiate_cal_download_ind_msg_v01_ei[] = { .array_type = NO_ARRAY, .tlv_type = 0x10, .offset = offsetof(struct - wlfw_initiate_cal_download_ind_msg_v01, - total_size), + wlfw_initiate_cal_download_ind_msg_v01, + total_size), }, { .data_type = QMI_OPT_FLAG, @@ -1923,8 +1759,8 @@ struct qmi_elem_info wlfw_initiate_cal_download_ind_msg_v01_ei[] = { .array_type = NO_ARRAY, .tlv_type = 0x11, .offset = offsetof(struct - wlfw_initiate_cal_download_ind_msg_v01, - cal_data_location_valid), + wlfw_initiate_cal_download_ind_msg_v01, + cal_data_location_valid), }, { .data_type = QMI_UNSIGNED_4_BYTE, @@ -1933,8 +1769,8 @@ struct qmi_elem_info wlfw_initiate_cal_download_ind_msg_v01_ei[] = { .array_type = NO_ARRAY, .tlv_type = 0x11, .offset = offsetof(struct - wlfw_initiate_cal_download_ind_msg_v01, - cal_data_location), + wlfw_initiate_cal_download_ind_msg_v01, + cal_data_location), }, { .data_type = QMI_EOTI, @@ -1942,7 +1778,6 @@ struct qmi_elem_info wlfw_initiate_cal_download_ind_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_initiate_cal_download_ind_msg_v01_ei); struct qmi_elem_info wlfw_cal_download_req_msg_v01_ei[] = { { @@ -1951,8 +1786,7 @@ struct qmi_elem_info wlfw_cal_download_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x01, - .offset = offsetof(struct - wlfw_cal_download_req_msg_v01, + .offset = offsetof(struct wlfw_cal_download_req_msg_v01, valid), }, { @@ -1961,8 +1795,7 @@ struct qmi_elem_info wlfw_cal_download_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x10, - .offset = offsetof(struct - wlfw_cal_download_req_msg_v01, + .offset = offsetof(struct wlfw_cal_download_req_msg_v01, file_id_valid), }, { @@ -1971,8 +1804,7 @@ struct qmi_elem_info wlfw_cal_download_req_msg_v01_ei[] = { .elem_size = sizeof(enum wlfw_cal_temp_id_enum_v01), .array_type = NO_ARRAY, .tlv_type = 0x10, - .offset = offsetof(struct - wlfw_cal_download_req_msg_v01, + .offset = offsetof(struct wlfw_cal_download_req_msg_v01, file_id), }, { @@ -1981,8 +1813,7 @@ struct qmi_elem_info wlfw_cal_download_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x11, - .offset = offsetof(struct - wlfw_cal_download_req_msg_v01, + .offset = offsetof(struct wlfw_cal_download_req_msg_v01, total_size_valid), }, { @@ -1991,8 +1822,7 @@ struct qmi_elem_info wlfw_cal_download_req_msg_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0x11, - .offset = offsetof(struct - wlfw_cal_download_req_msg_v01, + .offset = offsetof(struct wlfw_cal_download_req_msg_v01, total_size), }, { @@ -2001,8 +1831,7 @@ struct qmi_elem_info wlfw_cal_download_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x12, - .offset = offsetof(struct - wlfw_cal_download_req_msg_v01, + .offset = offsetof(struct wlfw_cal_download_req_msg_v01, seg_id_valid), }, { @@ -2011,8 +1840,7 @@ struct qmi_elem_info wlfw_cal_download_req_msg_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0x12, - .offset = offsetof(struct - wlfw_cal_download_req_msg_v01, + .offset = offsetof(struct wlfw_cal_download_req_msg_v01, seg_id), }, { @@ -2021,8 +1849,7 @@ struct qmi_elem_info wlfw_cal_download_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x13, - .offset = offsetof(struct - wlfw_cal_download_req_msg_v01, + .offset = offsetof(struct wlfw_cal_download_req_msg_v01, data_valid), }, { @@ -2031,8 +1858,7 @@ struct qmi_elem_info wlfw_cal_download_req_msg_v01_ei[] = { .elem_size = sizeof(u16), .array_type = NO_ARRAY, .tlv_type = 0x13, - .offset = offsetof(struct - wlfw_cal_download_req_msg_v01, + .offset = offsetof(struct wlfw_cal_download_req_msg_v01, data_len), }, { @@ -2041,8 +1867,7 @@ struct qmi_elem_info wlfw_cal_download_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = VAR_LEN_ARRAY, .tlv_type = 0x13, - .offset = offsetof(struct - wlfw_cal_download_req_msg_v01, + .offset = offsetof(struct wlfw_cal_download_req_msg_v01, data), }, { @@ -2051,8 +1876,7 @@ struct qmi_elem_info wlfw_cal_download_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x14, - .offset = offsetof(struct - wlfw_cal_download_req_msg_v01, + .offset = offsetof(struct wlfw_cal_download_req_msg_v01, end_valid), }, { @@ -2061,8 +1885,7 @@ struct qmi_elem_info wlfw_cal_download_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x14, - .offset = offsetof(struct - wlfw_cal_download_req_msg_v01, + .offset = offsetof(struct wlfw_cal_download_req_msg_v01, end), }, { @@ -2071,8 +1894,7 @@ struct qmi_elem_info wlfw_cal_download_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x15, - .offset = offsetof(struct - wlfw_cal_download_req_msg_v01, + .offset = offsetof(struct wlfw_cal_download_req_msg_v01, cal_data_location_valid), }, { @@ -2081,8 +1903,7 @@ struct qmi_elem_info wlfw_cal_download_req_msg_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0x15, - .offset = offsetof(struct - wlfw_cal_download_req_msg_v01, + .offset = offsetof(struct wlfw_cal_download_req_msg_v01, cal_data_location), }, { @@ -2091,7 +1912,6 @@ struct qmi_elem_info wlfw_cal_download_req_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_cal_download_req_msg_v01_ei); struct qmi_elem_info wlfw_cal_download_resp_msg_v01_ei[] = { { @@ -2111,7 +1931,6 @@ struct qmi_elem_info wlfw_cal_download_resp_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_cal_download_resp_msg_v01_ei); struct qmi_elem_info wlfw_initiate_cal_update_ind_msg_v01_ei[] = { { @@ -2160,7 +1979,6 @@ struct qmi_elem_info wlfw_initiate_cal_update_ind_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_initiate_cal_update_ind_msg_v01_ei); struct qmi_elem_info wlfw_cal_update_req_msg_v01_ei[] = { { @@ -2169,8 +1987,7 @@ struct qmi_elem_info wlfw_cal_update_req_msg_v01_ei[] = { .elem_size = sizeof(enum wlfw_cal_temp_id_enum_v01), .array_type = NO_ARRAY, .tlv_type = 0x01, - .offset = offsetof(struct - wlfw_cal_update_req_msg_v01, + .offset = offsetof(struct wlfw_cal_update_req_msg_v01, cal_id), }, { @@ -2179,8 +1996,7 @@ struct qmi_elem_info wlfw_cal_update_req_msg_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0x02, - .offset = offsetof(struct - wlfw_cal_update_req_msg_v01, + .offset = offsetof(struct wlfw_cal_update_req_msg_v01, seg_id), }, { @@ -2189,7 +2005,6 @@ struct qmi_elem_info wlfw_cal_update_req_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_cal_update_req_msg_v01_ei); struct qmi_elem_info wlfw_cal_update_resp_msg_v01_ei[] = { { @@ -2198,8 +2013,7 @@ struct qmi_elem_info wlfw_cal_update_resp_msg_v01_ei[] = { .elem_size = sizeof(struct qmi_response_type_v01), .array_type = NO_ARRAY, .tlv_type = 0x02, - .offset = offsetof(struct - wlfw_cal_update_resp_msg_v01, + .offset = offsetof(struct wlfw_cal_update_resp_msg_v01, resp), .ei_array = qmi_response_type_v01_ei, }, @@ -2209,8 +2023,7 @@ struct qmi_elem_info wlfw_cal_update_resp_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x10, - .offset = offsetof(struct - wlfw_cal_update_resp_msg_v01, + .offset = offsetof(struct wlfw_cal_update_resp_msg_v01, file_id_valid), }, { @@ -2219,8 +2032,7 @@ struct qmi_elem_info wlfw_cal_update_resp_msg_v01_ei[] = { .elem_size = sizeof(enum wlfw_cal_temp_id_enum_v01), .array_type = NO_ARRAY, .tlv_type = 0x10, - .offset = offsetof(struct - wlfw_cal_update_resp_msg_v01, + .offset = offsetof(struct wlfw_cal_update_resp_msg_v01, file_id), }, { @@ -2229,8 +2041,7 @@ struct qmi_elem_info wlfw_cal_update_resp_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x11, - .offset = offsetof(struct - wlfw_cal_update_resp_msg_v01, + .offset = offsetof(struct wlfw_cal_update_resp_msg_v01, total_size_valid), }, { @@ -2239,8 +2050,7 @@ struct qmi_elem_info wlfw_cal_update_resp_msg_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0x11, - .offset = offsetof(struct - wlfw_cal_update_resp_msg_v01, + .offset = offsetof(struct wlfw_cal_update_resp_msg_v01, total_size), }, { @@ -2249,8 +2059,7 @@ struct qmi_elem_info wlfw_cal_update_resp_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x12, - .offset = offsetof(struct - wlfw_cal_update_resp_msg_v01, + .offset = offsetof(struct wlfw_cal_update_resp_msg_v01, seg_id_valid), }, { @@ -2259,8 +2068,7 @@ struct qmi_elem_info wlfw_cal_update_resp_msg_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0x12, - .offset = offsetof(struct - wlfw_cal_update_resp_msg_v01, + .offset = offsetof(struct wlfw_cal_update_resp_msg_v01, seg_id), }, { @@ -2269,8 +2077,7 @@ struct qmi_elem_info wlfw_cal_update_resp_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x13, - .offset = offsetof(struct - wlfw_cal_update_resp_msg_v01, + .offset = offsetof(struct wlfw_cal_update_resp_msg_v01, data_valid), }, { @@ -2279,8 +2086,7 @@ struct qmi_elem_info wlfw_cal_update_resp_msg_v01_ei[] = { .elem_size = sizeof(u16), .array_type = NO_ARRAY, .tlv_type = 0x13, - .offset = offsetof(struct - wlfw_cal_update_resp_msg_v01, + .offset = offsetof(struct wlfw_cal_update_resp_msg_v01, data_len), }, { @@ -2289,8 +2095,7 @@ struct qmi_elem_info wlfw_cal_update_resp_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = VAR_LEN_ARRAY, .tlv_type = 0x13, - .offset = offsetof(struct - wlfw_cal_update_resp_msg_v01, + .offset = offsetof(struct wlfw_cal_update_resp_msg_v01, data), }, { @@ -2299,8 +2104,7 @@ struct qmi_elem_info wlfw_cal_update_resp_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x14, - .offset = offsetof(struct - wlfw_cal_update_resp_msg_v01, + .offset = offsetof(struct wlfw_cal_update_resp_msg_v01, end_valid), }, { @@ -2309,8 +2113,7 @@ struct qmi_elem_info wlfw_cal_update_resp_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x14, - .offset = offsetof(struct - wlfw_cal_update_resp_msg_v01, + .offset = offsetof(struct wlfw_cal_update_resp_msg_v01, end), }, { @@ -2319,8 +2122,7 @@ struct qmi_elem_info wlfw_cal_update_resp_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x15, - .offset = offsetof(struct - wlfw_cal_update_resp_msg_v01, + .offset = offsetof(struct wlfw_cal_update_resp_msg_v01, cal_data_location_valid), }, { @@ -2329,8 +2131,7 @@ struct qmi_elem_info wlfw_cal_update_resp_msg_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0x15, - .offset = offsetof(struct - wlfw_cal_update_resp_msg_v01, + .offset = offsetof(struct wlfw_cal_update_resp_msg_v01, cal_data_location), }, { @@ -2339,7 +2140,6 @@ struct qmi_elem_info wlfw_cal_update_resp_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_cal_update_resp_msg_v01_ei); struct qmi_elem_info wlfw_msa_info_req_msg_v01_ei[] = { { @@ -2348,8 +2148,7 @@ struct qmi_elem_info wlfw_msa_info_req_msg_v01_ei[] = { .elem_size = sizeof(u64), .array_type = NO_ARRAY, .tlv_type = 0x01, - .offset = offsetof(struct - wlfw_msa_info_req_msg_v01, + .offset = offsetof(struct wlfw_msa_info_req_msg_v01, msa_addr), }, { @@ -2358,8 +2157,7 @@ struct qmi_elem_info wlfw_msa_info_req_msg_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0x02, - .offset = offsetof(struct - wlfw_msa_info_req_msg_v01, + .offset = offsetof(struct wlfw_msa_info_req_msg_v01, size), }, { @@ -2368,7 +2166,6 @@ struct qmi_elem_info wlfw_msa_info_req_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_msa_info_req_msg_v01_ei); struct qmi_elem_info wlfw_msa_info_resp_msg_v01_ei[] = { { @@ -2377,8 +2174,7 @@ struct qmi_elem_info wlfw_msa_info_resp_msg_v01_ei[] = { .elem_size = sizeof(struct qmi_response_type_v01), .array_type = NO_ARRAY, .tlv_type = 0x02, - .offset = offsetof(struct - wlfw_msa_info_resp_msg_v01, + .offset = offsetof(struct wlfw_msa_info_resp_msg_v01, resp), .ei_array = qmi_response_type_v01_ei, }, @@ -2388,8 +2184,7 @@ struct qmi_elem_info wlfw_msa_info_resp_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x03, - .offset = offsetof(struct - wlfw_msa_info_resp_msg_v01, + .offset = offsetof(struct wlfw_msa_info_resp_msg_v01, mem_region_info_len), }, { @@ -2398,8 +2193,7 @@ struct qmi_elem_info wlfw_msa_info_resp_msg_v01_ei[] = { .elem_size = sizeof(struct wlfw_memory_region_info_s_v01), .array_type = VAR_LEN_ARRAY, .tlv_type = 0x03, - .offset = offsetof(struct - wlfw_msa_info_resp_msg_v01, + .offset = offsetof(struct wlfw_msa_info_resp_msg_v01, mem_region_info), .ei_array = wlfw_memory_region_info_s_v01_ei, }, @@ -2409,7 +2203,6 @@ struct qmi_elem_info wlfw_msa_info_resp_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_msa_info_resp_msg_v01_ei); struct qmi_elem_info wlfw_msa_ready_req_msg_v01_ei[] = { { @@ -2418,7 +2211,6 @@ struct qmi_elem_info wlfw_msa_ready_req_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_msa_ready_req_msg_v01_ei); struct qmi_elem_info wlfw_msa_ready_resp_msg_v01_ei[] = { { @@ -2427,8 +2219,7 @@ struct qmi_elem_info wlfw_msa_ready_resp_msg_v01_ei[] = { .elem_size = sizeof(struct qmi_response_type_v01), .array_type = NO_ARRAY, .tlv_type = 0x02, - .offset = offsetof(struct - wlfw_msa_ready_resp_msg_v01, + .offset = offsetof(struct wlfw_msa_ready_resp_msg_v01, resp), .ei_array = qmi_response_type_v01_ei, }, @@ -2438,7 +2229,6 @@ struct qmi_elem_info wlfw_msa_ready_resp_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_msa_ready_resp_msg_v01_ei); struct qmi_elem_info wlfw_ini_req_msg_v01_ei[] = { { @@ -2447,8 +2237,7 @@ struct qmi_elem_info wlfw_ini_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x10, - .offset = offsetof(struct - wlfw_ini_req_msg_v01, + .offset = offsetof(struct wlfw_ini_req_msg_v01, enablefwlog_valid), }, { @@ -2457,8 +2246,7 @@ struct qmi_elem_info wlfw_ini_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x10, - .offset = offsetof(struct - wlfw_ini_req_msg_v01, + .offset = offsetof(struct wlfw_ini_req_msg_v01, enablefwlog), }, { @@ -2467,7 +2255,6 @@ struct qmi_elem_info wlfw_ini_req_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_ini_req_msg_v01_ei); struct qmi_elem_info wlfw_ini_resp_msg_v01_ei[] = { { @@ -2476,8 +2263,7 @@ struct qmi_elem_info wlfw_ini_resp_msg_v01_ei[] = { .elem_size = sizeof(struct qmi_response_type_v01), .array_type = NO_ARRAY, .tlv_type = 0x02, - .offset = offsetof(struct - wlfw_ini_resp_msg_v01, + .offset = offsetof(struct wlfw_ini_resp_msg_v01, resp), .ei_array = qmi_response_type_v01_ei, }, @@ -2487,7 +2273,6 @@ struct qmi_elem_info wlfw_ini_resp_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_ini_resp_msg_v01_ei); struct qmi_elem_info wlfw_athdiag_read_req_msg_v01_ei[] = { { @@ -2496,8 +2281,7 @@ struct qmi_elem_info wlfw_athdiag_read_req_msg_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0x01, - .offset = offsetof(struct - wlfw_athdiag_read_req_msg_v01, + .offset = offsetof(struct wlfw_athdiag_read_req_msg_v01, offset), }, { @@ -2506,8 +2290,7 @@ struct qmi_elem_info wlfw_athdiag_read_req_msg_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0x02, - .offset = offsetof(struct - wlfw_athdiag_read_req_msg_v01, + .offset = offsetof(struct wlfw_athdiag_read_req_msg_v01, mem_type), }, { @@ -2516,8 +2299,7 @@ struct qmi_elem_info wlfw_athdiag_read_req_msg_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0x03, - .offset = offsetof(struct - wlfw_athdiag_read_req_msg_v01, + .offset = offsetof(struct wlfw_athdiag_read_req_msg_v01, data_len), }, { @@ -2526,7 +2308,6 @@ struct qmi_elem_info wlfw_athdiag_read_req_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_athdiag_read_req_msg_v01_ei); struct qmi_elem_info wlfw_athdiag_read_resp_msg_v01_ei[] = { { @@ -2576,7 +2357,6 @@ struct qmi_elem_info wlfw_athdiag_read_resp_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_athdiag_read_resp_msg_v01_ei); struct qmi_elem_info wlfw_athdiag_write_req_msg_v01_ei[] = { { @@ -2625,7 +2405,6 @@ struct qmi_elem_info wlfw_athdiag_write_req_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_athdiag_write_req_msg_v01_ei); struct qmi_elem_info wlfw_athdiag_write_resp_msg_v01_ei[] = { { @@ -2645,7 +2424,6 @@ struct qmi_elem_info wlfw_athdiag_write_resp_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_athdiag_write_resp_msg_v01_ei); struct qmi_elem_info wlfw_vbatt_req_msg_v01_ei[] = { { @@ -2654,8 +2432,7 @@ struct qmi_elem_info wlfw_vbatt_req_msg_v01_ei[] = { .elem_size = sizeof(u64), .array_type = NO_ARRAY, .tlv_type = 0x01, - .offset = offsetof(struct - wlfw_vbatt_req_msg_v01, + .offset = offsetof(struct wlfw_vbatt_req_msg_v01, voltage_uv), }, { @@ -2664,7 +2441,6 @@ struct qmi_elem_info wlfw_vbatt_req_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_vbatt_req_msg_v01_ei); struct qmi_elem_info wlfw_vbatt_resp_msg_v01_ei[] = { { @@ -2673,8 +2449,7 @@ struct qmi_elem_info wlfw_vbatt_resp_msg_v01_ei[] = { .elem_size = sizeof(struct qmi_response_type_v01), .array_type = NO_ARRAY, .tlv_type = 0x02, - .offset = offsetof(struct - wlfw_vbatt_resp_msg_v01, + .offset = offsetof(struct wlfw_vbatt_resp_msg_v01, resp), .ei_array = qmi_response_type_v01_ei, }, @@ -2684,7 +2459,6 @@ struct qmi_elem_info wlfw_vbatt_resp_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_vbatt_resp_msg_v01_ei); struct qmi_elem_info wlfw_mac_addr_req_msg_v01_ei[] = { { @@ -2693,8 +2467,7 @@ struct qmi_elem_info wlfw_mac_addr_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x10, - .offset = offsetof(struct - wlfw_mac_addr_req_msg_v01, + .offset = offsetof(struct wlfw_mac_addr_req_msg_v01, mac_addr_valid), }, { @@ -2703,8 +2476,7 @@ struct qmi_elem_info wlfw_mac_addr_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = STATIC_ARRAY, .tlv_type = 0x10, - .offset = offsetof(struct - wlfw_mac_addr_req_msg_v01, + .offset = offsetof(struct wlfw_mac_addr_req_msg_v01, mac_addr), }, { @@ -2713,7 +2485,6 @@ struct qmi_elem_info wlfw_mac_addr_req_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_mac_addr_req_msg_v01_ei); struct qmi_elem_info wlfw_mac_addr_resp_msg_v01_ei[] = { { @@ -2722,8 +2493,7 @@ struct qmi_elem_info wlfw_mac_addr_resp_msg_v01_ei[] = { .elem_size = sizeof(struct qmi_response_type_v01), .array_type = NO_ARRAY, .tlv_type = 0x02, - .offset = offsetof(struct - wlfw_mac_addr_resp_msg_v01, + .offset = offsetof(struct wlfw_mac_addr_resp_msg_v01, resp), .ei_array = qmi_response_type_v01_ei, }, @@ -2733,7 +2503,6 @@ struct qmi_elem_info wlfw_mac_addr_resp_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_mac_addr_resp_msg_v01_ei); struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { { @@ -2742,8 +2511,7 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x10, - .offset = offsetof(struct - wlfw_host_cap_req_msg_v01, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, num_clients_valid), }, { @@ -2752,8 +2520,7 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0x10, - .offset = offsetof(struct - wlfw_host_cap_req_msg_v01, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, num_clients), }, { @@ -2762,8 +2529,7 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x11, - .offset = offsetof(struct - wlfw_host_cap_req_msg_v01, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, wake_msi_valid), }, { @@ -2772,8 +2538,7 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0x11, - .offset = offsetof(struct - wlfw_host_cap_req_msg_v01, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, wake_msi), }, { @@ -2782,8 +2547,7 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x12, - .offset = offsetof(struct - wlfw_host_cap_req_msg_v01, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, gpios_valid), }, { @@ -2792,8 +2556,7 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x12, - .offset = offsetof(struct - wlfw_host_cap_req_msg_v01, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, gpios_len), }, { @@ -2802,8 +2565,7 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { .elem_size = sizeof(u32), .array_type = VAR_LEN_ARRAY, .tlv_type = 0x12, - .offset = offsetof(struct - wlfw_host_cap_req_msg_v01, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, gpios), }, { @@ -2812,8 +2574,7 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x13, - .offset = offsetof(struct - wlfw_host_cap_req_msg_v01, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, nm_modem_valid), }, { @@ -2822,8 +2583,7 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x13, - .offset = offsetof(struct - wlfw_host_cap_req_msg_v01, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, nm_modem), }, { @@ -2832,8 +2592,7 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x14, - .offset = offsetof(struct - wlfw_host_cap_req_msg_v01, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, bdf_support_valid), }, { @@ -2842,8 +2601,7 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x14, - .offset = offsetof(struct - wlfw_host_cap_req_msg_v01, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, bdf_support), }, { @@ -2852,8 +2610,7 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x15, - .offset = offsetof(struct - wlfw_host_cap_req_msg_v01, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, bdf_cache_support_valid), }, { @@ -2862,8 +2619,7 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x15, - .offset = offsetof(struct - wlfw_host_cap_req_msg_v01, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, bdf_cache_support), }, { @@ -2872,8 +2628,7 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x16, - .offset = offsetof(struct - wlfw_host_cap_req_msg_v01, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, m3_support_valid), }, { @@ -2882,8 +2637,7 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x16, - .offset = offsetof(struct - wlfw_host_cap_req_msg_v01, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, m3_support), }, { @@ -2892,8 +2646,7 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x17, - .offset = offsetof(struct - wlfw_host_cap_req_msg_v01, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, m3_cache_support_valid), }, { @@ -2902,8 +2655,7 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x17, - .offset = offsetof(struct - wlfw_host_cap_req_msg_v01, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, m3_cache_support), }, { @@ -2912,8 +2664,7 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x18, - .offset = offsetof(struct - wlfw_host_cap_req_msg_v01, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, cal_filesys_support_valid), }, { @@ -2922,8 +2673,7 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x18, - .offset = offsetof(struct - wlfw_host_cap_req_msg_v01, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, cal_filesys_support), }, { @@ -2932,8 +2682,7 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x19, - .offset = offsetof(struct - wlfw_host_cap_req_msg_v01, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, cal_cache_support_valid), }, { @@ -2942,8 +2691,7 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x19, - .offset = offsetof(struct - wlfw_host_cap_req_msg_v01, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, cal_cache_support), }, { @@ -2952,8 +2700,7 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x1A, - .offset = offsetof(struct - wlfw_host_cap_req_msg_v01, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, cal_done_valid), }, { @@ -2962,8 +2709,7 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x1A, - .offset = offsetof(struct - wlfw_host_cap_req_msg_v01, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, cal_done), }, { @@ -2972,8 +2718,7 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x1B, - .offset = offsetof(struct - wlfw_host_cap_req_msg_v01, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, mem_bucket_valid), }, { @@ -2982,8 +2727,7 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0x1B, - .offset = offsetof(struct - wlfw_host_cap_req_msg_v01, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, mem_bucket), }, { @@ -2992,8 +2736,7 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x1C, - .offset = offsetof(struct - wlfw_host_cap_req_msg_v01, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, mem_cfg_mode_valid), }, { @@ -3002,8 +2745,7 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x1C, - .offset = offsetof(struct - wlfw_host_cap_req_msg_v01, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, mem_cfg_mode), }, { @@ -3012,8 +2754,7 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x1D, - .offset = offsetof(struct - wlfw_host_cap_req_msg_v01, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, cal_duration_valid), }, { @@ -3022,8 +2763,7 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { .elem_size = sizeof(u16), .array_type = NO_ARRAY, .tlv_type = 0x1D, - .offset = offsetof(struct - wlfw_host_cap_req_msg_v01, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, cal_duration), }, { @@ -3032,8 +2772,7 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x1E, - .offset = offsetof(struct - wlfw_host_cap_req_msg_v01, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, platform_name_valid), }, { @@ -3042,8 +2781,7 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { .elem_size = sizeof(char), .array_type = NO_ARRAY, .tlv_type = 0x1E, - .offset = offsetof(struct - wlfw_host_cap_req_msg_v01, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, platform_name), }, { @@ -3052,8 +2790,7 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x1F, - .offset = offsetof(struct - wlfw_host_cap_req_msg_v01, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, ddr_range_valid), }, { @@ -3062,8 +2799,7 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { .elem_size = sizeof(struct wlfw_host_ddr_range_s_v01), .array_type = STATIC_ARRAY, .tlv_type = 0x1F, - .offset = offsetof(struct - wlfw_host_cap_req_msg_v01, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, ddr_range), .ei_array = wlfw_host_ddr_range_s_v01_ei, }, @@ -3073,8 +2809,7 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x20, - .offset = offsetof(struct - wlfw_host_cap_req_msg_v01, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, host_build_type_valid), }, { @@ -3083,8 +2818,7 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { .elem_size = sizeof(enum wlfw_host_build_type_v01), .array_type = NO_ARRAY, .tlv_type = 0x20, - .offset = offsetof(struct - wlfw_host_cap_req_msg_v01, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, host_build_type), }, { @@ -3093,7 +2827,6 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_host_cap_req_msg_v01_ei); struct qmi_elem_info wlfw_host_cap_resp_msg_v01_ei[] = { { @@ -3102,8 +2835,7 @@ struct qmi_elem_info wlfw_host_cap_resp_msg_v01_ei[] = { .elem_size = sizeof(struct qmi_response_type_v01), .array_type = NO_ARRAY, .tlv_type = 0x02, - .offset = offsetof(struct - wlfw_host_cap_resp_msg_v01, + .offset = offsetof(struct wlfw_host_cap_resp_msg_v01, resp), .ei_array = qmi_response_type_v01_ei, }, @@ -3113,7 +2845,6 @@ struct qmi_elem_info wlfw_host_cap_resp_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_host_cap_resp_msg_v01_ei); struct qmi_elem_info wlfw_request_mem_ind_msg_v01_ei[] = { { @@ -3122,8 +2853,7 @@ struct qmi_elem_info wlfw_request_mem_ind_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x01, - .offset = offsetof(struct - wlfw_request_mem_ind_msg_v01, + .offset = offsetof(struct wlfw_request_mem_ind_msg_v01, mem_seg_len), }, { @@ -3132,8 +2862,7 @@ struct qmi_elem_info wlfw_request_mem_ind_msg_v01_ei[] = { .elem_size = sizeof(struct wlfw_mem_seg_s_v01), .array_type = VAR_LEN_ARRAY, .tlv_type = 0x01, - .offset = offsetof(struct - wlfw_request_mem_ind_msg_v01, + .offset = offsetof(struct wlfw_request_mem_ind_msg_v01, mem_seg), .ei_array = wlfw_mem_seg_s_v01_ei, }, @@ -3143,7 +2872,6 @@ struct qmi_elem_info wlfw_request_mem_ind_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_request_mem_ind_msg_v01_ei); struct qmi_elem_info wlfw_respond_mem_req_msg_v01_ei[] = { { @@ -3152,8 +2880,7 @@ struct qmi_elem_info wlfw_respond_mem_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x01, - .offset = offsetof(struct - wlfw_respond_mem_req_msg_v01, + .offset = offsetof(struct wlfw_respond_mem_req_msg_v01, mem_seg_len), }, { @@ -3162,8 +2889,7 @@ struct qmi_elem_info wlfw_respond_mem_req_msg_v01_ei[] = { .elem_size = sizeof(struct wlfw_mem_seg_resp_s_v01), .array_type = VAR_LEN_ARRAY, .tlv_type = 0x01, - .offset = offsetof(struct - wlfw_respond_mem_req_msg_v01, + .offset = offsetof(struct wlfw_respond_mem_req_msg_v01, mem_seg), .ei_array = wlfw_mem_seg_resp_s_v01_ei, }, @@ -3173,7 +2899,6 @@ struct qmi_elem_info wlfw_respond_mem_req_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_respond_mem_req_msg_v01_ei); struct qmi_elem_info wlfw_respond_mem_resp_msg_v01_ei[] = { { @@ -3182,8 +2907,7 @@ struct qmi_elem_info wlfw_respond_mem_resp_msg_v01_ei[] = { .elem_size = sizeof(struct qmi_response_type_v01), .array_type = NO_ARRAY, .tlv_type = 0x02, - .offset = offsetof(struct - wlfw_respond_mem_resp_msg_v01, + .offset = offsetof(struct wlfw_respond_mem_resp_msg_v01, resp), .ei_array = qmi_response_type_v01_ei, }, @@ -3193,7 +2917,6 @@ struct qmi_elem_info wlfw_respond_mem_resp_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_respond_mem_resp_msg_v01_ei); struct qmi_elem_info wlfw_fw_mem_ready_ind_msg_v01_ei[] = { { @@ -3202,7 +2925,6 @@ struct qmi_elem_info wlfw_fw_mem_ready_ind_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_fw_mem_ready_ind_msg_v01_ei); struct qmi_elem_info wlfw_fw_init_done_ind_msg_v01_ei[] = { { @@ -3211,7 +2933,6 @@ struct qmi_elem_info wlfw_fw_init_done_ind_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_fw_init_done_ind_msg_v01_ei); struct qmi_elem_info wlfw_rejuvenate_ind_msg_v01_ei[] = { { @@ -3220,8 +2941,7 @@ struct qmi_elem_info wlfw_rejuvenate_ind_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x10, - .offset = offsetof(struct - wlfw_rejuvenate_ind_msg_v01, + .offset = offsetof(struct wlfw_rejuvenate_ind_msg_v01, cause_for_rejuvenation_valid), }, { @@ -3230,8 +2950,7 @@ struct qmi_elem_info wlfw_rejuvenate_ind_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x10, - .offset = offsetof(struct - wlfw_rejuvenate_ind_msg_v01, + .offset = offsetof(struct wlfw_rejuvenate_ind_msg_v01, cause_for_rejuvenation), }, { @@ -3240,8 +2959,7 @@ struct qmi_elem_info wlfw_rejuvenate_ind_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x11, - .offset = offsetof(struct - wlfw_rejuvenate_ind_msg_v01, + .offset = offsetof(struct wlfw_rejuvenate_ind_msg_v01, requesting_sub_system_valid), }, { @@ -3250,8 +2968,7 @@ struct qmi_elem_info wlfw_rejuvenate_ind_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x11, - .offset = offsetof(struct - wlfw_rejuvenate_ind_msg_v01, + .offset = offsetof(struct wlfw_rejuvenate_ind_msg_v01, requesting_sub_system), }, { @@ -3260,8 +2977,7 @@ struct qmi_elem_info wlfw_rejuvenate_ind_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x12, - .offset = offsetof(struct - wlfw_rejuvenate_ind_msg_v01, + .offset = offsetof(struct wlfw_rejuvenate_ind_msg_v01, line_number_valid), }, { @@ -3270,8 +2986,7 @@ struct qmi_elem_info wlfw_rejuvenate_ind_msg_v01_ei[] = { .elem_size = sizeof(u16), .array_type = NO_ARRAY, .tlv_type = 0x12, - .offset = offsetof(struct - wlfw_rejuvenate_ind_msg_v01, + .offset = offsetof(struct wlfw_rejuvenate_ind_msg_v01, line_number), }, { @@ -3280,8 +2995,7 @@ struct qmi_elem_info wlfw_rejuvenate_ind_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x13, - .offset = offsetof(struct - wlfw_rejuvenate_ind_msg_v01, + .offset = offsetof(struct wlfw_rejuvenate_ind_msg_v01, function_name_valid), }, { @@ -3290,8 +3004,7 @@ struct qmi_elem_info wlfw_rejuvenate_ind_msg_v01_ei[] = { .elem_size = sizeof(char), .array_type = NO_ARRAY, .tlv_type = 0x13, - .offset = offsetof(struct - wlfw_rejuvenate_ind_msg_v01, + .offset = offsetof(struct wlfw_rejuvenate_ind_msg_v01, function_name), }, { @@ -3300,7 +3013,6 @@ struct qmi_elem_info wlfw_rejuvenate_ind_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_rejuvenate_ind_msg_v01_ei); struct qmi_elem_info wlfw_rejuvenate_ack_req_msg_v01_ei[] = { { @@ -3309,7 +3021,6 @@ struct qmi_elem_info wlfw_rejuvenate_ack_req_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_rejuvenate_ack_req_msg_v01_ei); struct qmi_elem_info wlfw_rejuvenate_ack_resp_msg_v01_ei[] = { { @@ -3329,7 +3040,6 @@ struct qmi_elem_info wlfw_rejuvenate_ack_resp_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_rejuvenate_ack_resp_msg_v01_ei); struct qmi_elem_info wlfw_dynamic_feature_mask_req_msg_v01_ei[] = { { @@ -3339,8 +3049,8 @@ struct qmi_elem_info wlfw_dynamic_feature_mask_req_msg_v01_ei[] = { .array_type = NO_ARRAY, .tlv_type = 0x10, .offset = offsetof(struct - wlfw_dynamic_feature_mask_req_msg_v01, - mask_valid), + wlfw_dynamic_feature_mask_req_msg_v01, + mask_valid), }, { .data_type = QMI_UNSIGNED_8_BYTE, @@ -3349,8 +3059,8 @@ struct qmi_elem_info wlfw_dynamic_feature_mask_req_msg_v01_ei[] = { .array_type = NO_ARRAY, .tlv_type = 0x10, .offset = offsetof(struct - wlfw_dynamic_feature_mask_req_msg_v01, - mask), + wlfw_dynamic_feature_mask_req_msg_v01, + mask), }, { .data_type = QMI_EOTI, @@ -3358,7 +3068,6 @@ struct qmi_elem_info wlfw_dynamic_feature_mask_req_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_dynamic_feature_mask_req_msg_v01_ei); struct qmi_elem_info wlfw_dynamic_feature_mask_resp_msg_v01_ei[] = { { @@ -3368,8 +3077,8 @@ struct qmi_elem_info wlfw_dynamic_feature_mask_resp_msg_v01_ei[] = { .array_type = NO_ARRAY, .tlv_type = 0x02, .offset = offsetof(struct - wlfw_dynamic_feature_mask_resp_msg_v01, - resp), + wlfw_dynamic_feature_mask_resp_msg_v01, + resp), .ei_array = qmi_response_type_v01_ei, }, { @@ -3379,8 +3088,8 @@ struct qmi_elem_info wlfw_dynamic_feature_mask_resp_msg_v01_ei[] = { .array_type = NO_ARRAY, .tlv_type = 0x10, .offset = offsetof(struct - wlfw_dynamic_feature_mask_resp_msg_v01, - prev_mask_valid), + wlfw_dynamic_feature_mask_resp_msg_v01, + prev_mask_valid), }, { .data_type = QMI_UNSIGNED_8_BYTE, @@ -3389,8 +3098,8 @@ struct qmi_elem_info wlfw_dynamic_feature_mask_resp_msg_v01_ei[] = { .array_type = NO_ARRAY, .tlv_type = 0x10, .offset = offsetof(struct - wlfw_dynamic_feature_mask_resp_msg_v01, - prev_mask), + wlfw_dynamic_feature_mask_resp_msg_v01, + prev_mask), }, { .data_type = QMI_OPT_FLAG, @@ -3399,8 +3108,8 @@ struct qmi_elem_info wlfw_dynamic_feature_mask_resp_msg_v01_ei[] = { .array_type = NO_ARRAY, .tlv_type = 0x11, .offset = offsetof(struct - wlfw_dynamic_feature_mask_resp_msg_v01, - curr_mask_valid), + wlfw_dynamic_feature_mask_resp_msg_v01, + curr_mask_valid), }, { .data_type = QMI_UNSIGNED_8_BYTE, @@ -3409,8 +3118,8 @@ struct qmi_elem_info wlfw_dynamic_feature_mask_resp_msg_v01_ei[] = { .array_type = NO_ARRAY, .tlv_type = 0x11, .offset = offsetof(struct - wlfw_dynamic_feature_mask_resp_msg_v01, - curr_mask), + wlfw_dynamic_feature_mask_resp_msg_v01, + curr_mask), }, { .data_type = QMI_EOTI, @@ -3418,7 +3127,6 @@ struct qmi_elem_info wlfw_dynamic_feature_mask_resp_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_dynamic_feature_mask_resp_msg_v01_ei); struct qmi_elem_info wlfw_m3_info_req_msg_v01_ei[] = { { @@ -3427,8 +3135,7 @@ struct qmi_elem_info wlfw_m3_info_req_msg_v01_ei[] = { .elem_size = sizeof(u64), .array_type = NO_ARRAY, .tlv_type = 0x01, - .offset = offsetof(struct - wlfw_m3_info_req_msg_v01, + .offset = offsetof(struct wlfw_m3_info_req_msg_v01, addr), }, { @@ -3437,8 +3144,7 @@ struct qmi_elem_info wlfw_m3_info_req_msg_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0x02, - .offset = offsetof(struct - wlfw_m3_info_req_msg_v01, + .offset = offsetof(struct wlfw_m3_info_req_msg_v01, size), }, { @@ -3447,7 +3153,6 @@ struct qmi_elem_info wlfw_m3_info_req_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_m3_info_req_msg_v01_ei); struct qmi_elem_info wlfw_m3_info_resp_msg_v01_ei[] = { { @@ -3456,8 +3161,7 @@ struct qmi_elem_info wlfw_m3_info_resp_msg_v01_ei[] = { .elem_size = sizeof(struct qmi_response_type_v01), .array_type = NO_ARRAY, .tlv_type = 0x02, - .offset = offsetof(struct - wlfw_m3_info_resp_msg_v01, + .offset = offsetof(struct wlfw_m3_info_resp_msg_v01, resp), .ei_array = qmi_response_type_v01_ei, }, @@ -3467,7 +3171,6 @@ struct qmi_elem_info wlfw_m3_info_resp_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_m3_info_resp_msg_v01_ei); struct qmi_elem_info wlfw_xo_cal_ind_msg_v01_ei[] = { { @@ -3476,8 +3179,7 @@ struct qmi_elem_info wlfw_xo_cal_ind_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x01, - .offset = offsetof(struct - wlfw_xo_cal_ind_msg_v01, + .offset = offsetof(struct wlfw_xo_cal_ind_msg_v01, xo_cal_data), }, { @@ -3486,7 +3188,6 @@ struct qmi_elem_info wlfw_xo_cal_ind_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_xo_cal_ind_msg_v01_ei); struct qmi_elem_info wlfw_cal_done_ind_msg_v01_ei[] = { { @@ -3495,7 +3196,6 @@ struct qmi_elem_info wlfw_cal_done_ind_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_cal_done_ind_msg_v01_ei); struct qmi_elem_info wlfw_qdss_trace_req_mem_ind_msg_v01_ei[] = { { @@ -3525,7 +3225,6 @@ struct qmi_elem_info wlfw_qdss_trace_req_mem_ind_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_qdss_trace_req_mem_ind_msg_v01_ei); struct qmi_elem_info wlfw_qdss_trace_mem_info_req_msg_v01_ei[] = { { @@ -3555,7 +3254,6 @@ struct qmi_elem_info wlfw_qdss_trace_mem_info_req_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_qdss_trace_mem_info_req_msg_v01_ei); struct qmi_elem_info wlfw_qdss_trace_mem_info_resp_msg_v01_ei[] = { { @@ -3565,8 +3263,8 @@ struct qmi_elem_info wlfw_qdss_trace_mem_info_resp_msg_v01_ei[] = { .array_type = NO_ARRAY, .tlv_type = 0x02, .offset = offsetof(struct - wlfw_qdss_trace_mem_info_resp_msg_v01, - resp), + wlfw_qdss_trace_mem_info_resp_msg_v01, + resp), .ei_array = qmi_response_type_v01_ei, }, { @@ -3575,7 +3273,6 @@ struct qmi_elem_info wlfw_qdss_trace_mem_info_resp_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_qdss_trace_mem_info_resp_msg_v01_ei); struct qmi_elem_info wlfw_qdss_trace_save_ind_msg_v01_ei[] = { { @@ -3655,7 +3352,6 @@ struct qmi_elem_info wlfw_qdss_trace_save_ind_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_qdss_trace_save_ind_msg_v01_ei); struct qmi_elem_info wlfw_qdss_trace_data_req_msg_v01_ei[] = { { @@ -3674,7 +3370,6 @@ struct qmi_elem_info wlfw_qdss_trace_data_req_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_qdss_trace_data_req_msg_v01_ei); struct qmi_elem_info wlfw_qdss_trace_data_resp_msg_v01_ei[] = { { @@ -3784,7 +3479,6 @@ struct qmi_elem_info wlfw_qdss_trace_data_resp_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_qdss_trace_data_resp_msg_v01_ei); struct qmi_elem_info wlfw_qdss_trace_config_download_req_msg_v01_ei[] = { { @@ -3794,8 +3488,8 @@ struct qmi_elem_info wlfw_qdss_trace_config_download_req_msg_v01_ei[] = { .array_type = NO_ARRAY, .tlv_type = 0x10, .offset = offsetof(struct - wlfw_qdss_trace_config_download_req_msg_v01, - total_size_valid), + wlfw_qdss_trace_config_download_req_msg_v01, + total_size_valid), }, { .data_type = QMI_UNSIGNED_4_BYTE, @@ -3804,8 +3498,8 @@ struct qmi_elem_info wlfw_qdss_trace_config_download_req_msg_v01_ei[] = { .array_type = NO_ARRAY, .tlv_type = 0x10, .offset = offsetof(struct - wlfw_qdss_trace_config_download_req_msg_v01, - total_size), + wlfw_qdss_trace_config_download_req_msg_v01, + total_size), }, { .data_type = QMI_OPT_FLAG, @@ -3814,8 +3508,8 @@ struct qmi_elem_info wlfw_qdss_trace_config_download_req_msg_v01_ei[] = { .array_type = NO_ARRAY, .tlv_type = 0x11, .offset = offsetof(struct - wlfw_qdss_trace_config_download_req_msg_v01, - seg_id_valid), + wlfw_qdss_trace_config_download_req_msg_v01, + seg_id_valid), }, { .data_type = QMI_UNSIGNED_4_BYTE, @@ -3824,8 +3518,8 @@ struct qmi_elem_info wlfw_qdss_trace_config_download_req_msg_v01_ei[] = { .array_type = NO_ARRAY, .tlv_type = 0x11, .offset = offsetof(struct - wlfw_qdss_trace_config_download_req_msg_v01, - seg_id), + wlfw_qdss_trace_config_download_req_msg_v01, + seg_id), }, { .data_type = QMI_OPT_FLAG, @@ -3834,8 +3528,8 @@ struct qmi_elem_info wlfw_qdss_trace_config_download_req_msg_v01_ei[] = { .array_type = NO_ARRAY, .tlv_type = 0x12, .offset = offsetof(struct - wlfw_qdss_trace_config_download_req_msg_v01, - data_valid), + wlfw_qdss_trace_config_download_req_msg_v01, + data_valid), }, { .data_type = QMI_DATA_LEN, @@ -3844,8 +3538,8 @@ struct qmi_elem_info wlfw_qdss_trace_config_download_req_msg_v01_ei[] = { .array_type = NO_ARRAY, .tlv_type = 0x12, .offset = offsetof(struct - wlfw_qdss_trace_config_download_req_msg_v01, - data_len), + wlfw_qdss_trace_config_download_req_msg_v01, + data_len), }, { .data_type = QMI_UNSIGNED_1_BYTE, @@ -3854,8 +3548,8 @@ struct qmi_elem_info wlfw_qdss_trace_config_download_req_msg_v01_ei[] = { .array_type = VAR_LEN_ARRAY, .tlv_type = 0x12, .offset = offsetof(struct - wlfw_qdss_trace_config_download_req_msg_v01, - data), + wlfw_qdss_trace_config_download_req_msg_v01, + data), }, { .data_type = QMI_OPT_FLAG, @@ -3864,8 +3558,8 @@ struct qmi_elem_info wlfw_qdss_trace_config_download_req_msg_v01_ei[] = { .array_type = NO_ARRAY, .tlv_type = 0x13, .offset = offsetof(struct - wlfw_qdss_trace_config_download_req_msg_v01, - end_valid), + wlfw_qdss_trace_config_download_req_msg_v01, + end_valid), }, { .data_type = QMI_UNSIGNED_1_BYTE, @@ -3874,8 +3568,8 @@ struct qmi_elem_info wlfw_qdss_trace_config_download_req_msg_v01_ei[] = { .array_type = NO_ARRAY, .tlv_type = 0x13, .offset = offsetof(struct - wlfw_qdss_trace_config_download_req_msg_v01, - end), + wlfw_qdss_trace_config_download_req_msg_v01, + end), }, { .data_type = QMI_EOTI, @@ -3883,7 +3577,6 @@ struct qmi_elem_info wlfw_qdss_trace_config_download_req_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_qdss_trace_config_download_req_msg_v01_ei); struct qmi_elem_info wlfw_qdss_trace_config_download_resp_msg_v01_ei[] = { { @@ -3893,8 +3586,8 @@ struct qmi_elem_info wlfw_qdss_trace_config_download_resp_msg_v01_ei[] = { .array_type = NO_ARRAY, .tlv_type = 0x02, .offset = offsetof(struct - wlfw_qdss_trace_config_download_resp_msg_v01, - resp), + wlfw_qdss_trace_config_download_resp_msg_v01, + resp), .ei_array = qmi_response_type_v01_ei, }, { @@ -3903,7 +3596,6 @@ struct qmi_elem_info wlfw_qdss_trace_config_download_resp_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_qdss_trace_config_download_resp_msg_v01_ei); struct qmi_elem_info wlfw_qdss_trace_mode_req_msg_v01_ei[] = { { @@ -3913,8 +3605,8 @@ struct qmi_elem_info wlfw_qdss_trace_mode_req_msg_v01_ei[] = { .array_type = NO_ARRAY, .tlv_type = 0x10, .offset = offsetof(struct - wlfw_qdss_trace_mode_req_msg_v01, - mode_valid), + wlfw_qdss_trace_mode_req_msg_v01, + mode_valid), }, { .data_type = QMI_SIGNED_4_BYTE_ENUM, @@ -3972,7 +3664,6 @@ struct qmi_elem_info wlfw_qdss_trace_mode_req_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_qdss_trace_mode_req_msg_v01_ei); struct qmi_elem_info wlfw_qdss_trace_mode_resp_msg_v01_ei[] = { { @@ -3992,7 +3683,6 @@ struct qmi_elem_info wlfw_qdss_trace_mode_resp_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_qdss_trace_mode_resp_msg_v01_ei); struct qmi_elem_info wlfw_qdss_trace_free_ind_msg_v01_ei[] = { { @@ -4032,7 +3722,6 @@ struct qmi_elem_info wlfw_qdss_trace_free_ind_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_qdss_trace_free_ind_msg_v01_ei); struct qmi_elem_info wlfw_shutdown_req_msg_v01_ei[] = { { @@ -4041,8 +3730,7 @@ struct qmi_elem_info wlfw_shutdown_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x10, - .offset = offsetof(struct - wlfw_shutdown_req_msg_v01, + .offset = offsetof(struct wlfw_shutdown_req_msg_v01, shutdown_valid), }, { @@ -4051,8 +3739,7 @@ struct qmi_elem_info wlfw_shutdown_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x10, - .offset = offsetof(struct - wlfw_shutdown_req_msg_v01, + .offset = offsetof(struct wlfw_shutdown_req_msg_v01, shutdown), }, { @@ -4061,7 +3748,6 @@ struct qmi_elem_info wlfw_shutdown_req_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_shutdown_req_msg_v01_ei); struct qmi_elem_info wlfw_shutdown_resp_msg_v01_ei[] = { { @@ -4070,8 +3756,7 @@ struct qmi_elem_info wlfw_shutdown_resp_msg_v01_ei[] = { .elem_size = sizeof(struct qmi_response_type_v01), .array_type = NO_ARRAY, .tlv_type = 0x02, - .offset = offsetof(struct - wlfw_shutdown_resp_msg_v01, + .offset = offsetof(struct wlfw_shutdown_resp_msg_v01, resp), .ei_array = qmi_response_type_v01_ei, }, @@ -4081,7 +3766,6 @@ struct qmi_elem_info wlfw_shutdown_resp_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_shutdown_resp_msg_v01_ei); struct qmi_elem_info wlfw_antenna_switch_req_msg_v01_ei[] = { { @@ -4090,7 +3774,6 @@ struct qmi_elem_info wlfw_antenna_switch_req_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_antenna_switch_req_msg_v01_ei); struct qmi_elem_info wlfw_antenna_switch_resp_msg_v01_ei[] = { { @@ -4130,7 +3813,6 @@ struct qmi_elem_info wlfw_antenna_switch_resp_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_antenna_switch_resp_msg_v01_ei); struct qmi_elem_info wlfw_antenna_grant_req_msg_v01_ei[] = { { @@ -4159,7 +3841,6 @@ struct qmi_elem_info wlfw_antenna_grant_req_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_antenna_grant_req_msg_v01_ei); struct qmi_elem_info wlfw_antenna_grant_resp_msg_v01_ei[] = { { @@ -4179,7 +3860,6 @@ struct qmi_elem_info wlfw_antenna_grant_resp_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_antenna_grant_resp_msg_v01_ei); struct qmi_elem_info wlfw_wfc_call_status_req_msg_v01_ei[] = { { @@ -4328,7 +4008,6 @@ struct qmi_elem_info wlfw_wfc_call_status_req_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_wfc_call_status_req_msg_v01_ei); struct qmi_elem_info wlfw_wfc_call_status_resp_msg_v01_ei[] = { { @@ -4348,7 +4027,6 @@ struct qmi_elem_info wlfw_wfc_call_status_resp_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_wfc_call_status_resp_msg_v01_ei); struct qmi_elem_info wlfw_get_info_req_msg_v01_ei[] = { { @@ -4357,8 +4035,7 @@ struct qmi_elem_info wlfw_get_info_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x01, - .offset = offsetof(struct - wlfw_get_info_req_msg_v01, + .offset = offsetof(struct wlfw_get_info_req_msg_v01, type), }, { @@ -4367,8 +4044,7 @@ struct qmi_elem_info wlfw_get_info_req_msg_v01_ei[] = { .elem_size = sizeof(u16), .array_type = NO_ARRAY, .tlv_type = 0x02, - .offset = offsetof(struct - wlfw_get_info_req_msg_v01, + .offset = offsetof(struct wlfw_get_info_req_msg_v01, data_len), }, { @@ -4377,8 +4053,7 @@ struct qmi_elem_info wlfw_get_info_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = VAR_LEN_ARRAY, .tlv_type = 0x02, - .offset = offsetof(struct - wlfw_get_info_req_msg_v01, + .offset = offsetof(struct wlfw_get_info_req_msg_v01, data), }, { @@ -4387,7 +4062,6 @@ struct qmi_elem_info wlfw_get_info_req_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_get_info_req_msg_v01_ei); struct qmi_elem_info wlfw_get_info_resp_msg_v01_ei[] = { { @@ -4396,8 +4070,7 @@ struct qmi_elem_info wlfw_get_info_resp_msg_v01_ei[] = { .elem_size = sizeof(struct qmi_response_type_v01), .array_type = NO_ARRAY, .tlv_type = 0x02, - .offset = offsetof(struct - wlfw_get_info_resp_msg_v01, + .offset = offsetof(struct wlfw_get_info_resp_msg_v01, resp), .ei_array = qmi_response_type_v01_ei, }, @@ -4407,7 +4080,6 @@ struct qmi_elem_info wlfw_get_info_resp_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_get_info_resp_msg_v01_ei); struct qmi_elem_info wlfw_respond_get_info_ind_msg_v01_ei[] = { { @@ -4496,7 +4168,6 @@ struct qmi_elem_info wlfw_respond_get_info_ind_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_respond_get_info_ind_msg_v01_ei); struct qmi_elem_info wlfw_device_info_req_msg_v01_ei[] = { { @@ -4505,7 +4176,6 @@ struct qmi_elem_info wlfw_device_info_req_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_device_info_req_msg_v01_ei); struct qmi_elem_info wlfw_device_info_resp_msg_v01_ei[] = { { @@ -4514,8 +4184,7 @@ struct qmi_elem_info wlfw_device_info_resp_msg_v01_ei[] = { .elem_size = sizeof(struct qmi_response_type_v01), .array_type = NO_ARRAY, .tlv_type = 0x02, - .offset = offsetof(struct - wlfw_device_info_resp_msg_v01, + .offset = offsetof(struct wlfw_device_info_resp_msg_v01, resp), .ei_array = qmi_response_type_v01_ei, }, @@ -4525,8 +4194,7 @@ struct qmi_elem_info wlfw_device_info_resp_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x10, - .offset = offsetof(struct - wlfw_device_info_resp_msg_v01, + .offset = offsetof(struct wlfw_device_info_resp_msg_v01, bar_addr_valid), }, { @@ -4535,8 +4203,7 @@ struct qmi_elem_info wlfw_device_info_resp_msg_v01_ei[] = { .elem_size = sizeof(u64), .array_type = NO_ARRAY, .tlv_type = 0x10, - .offset = offsetof(struct - wlfw_device_info_resp_msg_v01, + .offset = offsetof(struct wlfw_device_info_resp_msg_v01, bar_addr), }, { @@ -4545,8 +4212,7 @@ struct qmi_elem_info wlfw_device_info_resp_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x11, - .offset = offsetof(struct - wlfw_device_info_resp_msg_v01, + .offset = offsetof(struct wlfw_device_info_resp_msg_v01, bar_size_valid), }, { @@ -4555,8 +4221,7 @@ struct qmi_elem_info wlfw_device_info_resp_msg_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0x11, - .offset = offsetof(struct - wlfw_device_info_resp_msg_v01, + .offset = offsetof(struct wlfw_device_info_resp_msg_v01, bar_size), }, { @@ -4565,7 +4230,6 @@ struct qmi_elem_info wlfw_device_info_resp_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_device_info_resp_msg_v01_ei); struct qmi_elem_info wlfw_m3_dump_upload_req_ind_msg_v01_ei[] = { { @@ -4604,7 +4268,6 @@ struct qmi_elem_info wlfw_m3_dump_upload_req_ind_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_m3_dump_upload_req_ind_msg_v01_ei); struct qmi_elem_info wlfw_m3_dump_upload_done_req_msg_v01_ei[] = { { @@ -4633,7 +4296,6 @@ struct qmi_elem_info wlfw_m3_dump_upload_done_req_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_m3_dump_upload_done_req_msg_v01_ei); struct qmi_elem_info wlfw_m3_dump_upload_done_resp_msg_v01_ei[] = { { @@ -4643,8 +4305,8 @@ struct qmi_elem_info wlfw_m3_dump_upload_done_resp_msg_v01_ei[] = { .array_type = NO_ARRAY, .tlv_type = 0x02, .offset = offsetof(struct - wlfw_m3_dump_upload_done_resp_msg_v01, - resp), + wlfw_m3_dump_upload_done_resp_msg_v01, + resp), .ei_array = qmi_response_type_v01_ei, }, { @@ -4653,7 +4315,6 @@ struct qmi_elem_info wlfw_m3_dump_upload_done_resp_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_m3_dump_upload_done_resp_msg_v01_ei); struct qmi_elem_info wlfw_soc_wake_req_msg_v01_ei[] = { { @@ -4672,8 +4333,7 @@ struct qmi_elem_info wlfw_soc_wake_req_msg_v01_ei[] = { .elem_size = sizeof(enum wlfw_soc_wake_enum_v01), .array_type = NO_ARRAY, .tlv_type = 0x10, - .offset = offsetof(struct - wlfw_soc_wake_req_msg_v01, + .offset = offsetof(struct wlfw_soc_wake_req_msg_v01, wake), }, { @@ -4682,7 +4342,6 @@ struct qmi_elem_info wlfw_soc_wake_req_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_soc_wake_req_msg_v01_ei); struct qmi_elem_info wlfw_soc_wake_resp_msg_v01_ei[] = { { @@ -4691,8 +4350,7 @@ struct qmi_elem_info wlfw_soc_wake_resp_msg_v01_ei[] = { .elem_size = sizeof(struct qmi_response_type_v01), .array_type = NO_ARRAY, .tlv_type = 0x02, - .offset = offsetof(struct - wlfw_soc_wake_resp_msg_v01, + .offset = offsetof(struct wlfw_soc_wake_resp_msg_v01, resp), .ei_array = qmi_response_type_v01_ei, }, @@ -4702,7 +4360,6 @@ struct qmi_elem_info wlfw_soc_wake_resp_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_soc_wake_resp_msg_v01_ei); struct qmi_elem_info wlfw_power_save_req_msg_v01_ei[] = { { @@ -4711,8 +4368,7 @@ struct qmi_elem_info wlfw_power_save_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x10, - .offset = offsetof(struct - wlfw_power_save_req_msg_v01, + .offset = offsetof(struct wlfw_power_save_req_msg_v01, power_save_mode_valid), }, { @@ -4721,8 +4377,7 @@ struct qmi_elem_info wlfw_power_save_req_msg_v01_ei[] = { .elem_size = sizeof(enum wlfw_power_save_mode_v01), .array_type = NO_ARRAY, .tlv_type = 0x10, - .offset = offsetof(struct - wlfw_power_save_req_msg_v01, + .offset = offsetof(struct wlfw_power_save_req_msg_v01, power_save_mode), }, { @@ -4731,7 +4386,6 @@ struct qmi_elem_info wlfw_power_save_req_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_power_save_req_msg_v01_ei); struct qmi_elem_info wlfw_power_save_resp_msg_v01_ei[] = { { @@ -4740,8 +4394,7 @@ struct qmi_elem_info wlfw_power_save_resp_msg_v01_ei[] = { .elem_size = sizeof(struct qmi_response_type_v01), .array_type = NO_ARRAY, .tlv_type = 0x02, - .offset = offsetof(struct - wlfw_power_save_resp_msg_v01, + .offset = offsetof(struct wlfw_power_save_resp_msg_v01, resp), .ei_array = qmi_response_type_v01_ei, }, @@ -4751,7 +4404,6 @@ struct qmi_elem_info wlfw_power_save_resp_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_power_save_resp_msg_v01_ei); struct qmi_elem_info wlfw_wfc_call_twt_config_ind_msg_v01_ei[] = { { @@ -4760,9 +4412,9 @@ struct qmi_elem_info wlfw_wfc_call_twt_config_ind_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x10, - .offset = offsetof(struct - wlfw_wfc_call_twt_config_ind_msg_v01, - twt_sta_start_valid), + .offset = + offsetof(struct wlfw_wfc_call_twt_config_ind_msg_v01, + twt_sta_start_valid), }, { .data_type = QMI_UNSIGNED_8_BYTE, @@ -4770,9 +4422,9 @@ struct qmi_elem_info wlfw_wfc_call_twt_config_ind_msg_v01_ei[] = { .elem_size = sizeof(u64), .array_type = NO_ARRAY, .tlv_type = 0x10, - .offset = offsetof(struct - wlfw_wfc_call_twt_config_ind_msg_v01, - twt_sta_start), + .offset = + offsetof(struct wlfw_wfc_call_twt_config_ind_msg_v01, + twt_sta_start), }, { .data_type = QMI_OPT_FLAG, @@ -4780,9 +4432,9 @@ struct qmi_elem_info wlfw_wfc_call_twt_config_ind_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x11, - .offset = offsetof(struct - wlfw_wfc_call_twt_config_ind_msg_v01, - twt_sta_int_valid), + .offset = + offsetof(struct wlfw_wfc_call_twt_config_ind_msg_v01, + twt_sta_int_valid), }, { .data_type = QMI_UNSIGNED_2_BYTE, @@ -4790,9 +4442,9 @@ struct qmi_elem_info wlfw_wfc_call_twt_config_ind_msg_v01_ei[] = { .elem_size = sizeof(u16), .array_type = NO_ARRAY, .tlv_type = 0x11, - .offset = offsetof(struct - wlfw_wfc_call_twt_config_ind_msg_v01, - twt_sta_int), + .offset = + offsetof(struct wlfw_wfc_call_twt_config_ind_msg_v01, + twt_sta_int), }, { .data_type = QMI_OPT_FLAG, @@ -4800,9 +4452,9 @@ struct qmi_elem_info wlfw_wfc_call_twt_config_ind_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x12, - .offset = offsetof(struct - wlfw_wfc_call_twt_config_ind_msg_v01, - twt_sta_upo_valid), + .offset = + offsetof(struct wlfw_wfc_call_twt_config_ind_msg_v01, + twt_sta_upo_valid), }, { .data_type = QMI_UNSIGNED_2_BYTE, @@ -4810,9 +4462,9 @@ struct qmi_elem_info wlfw_wfc_call_twt_config_ind_msg_v01_ei[] = { .elem_size = sizeof(u16), .array_type = NO_ARRAY, .tlv_type = 0x12, - .offset = offsetof(struct - wlfw_wfc_call_twt_config_ind_msg_v01, - twt_sta_upo), + .offset = + offsetof(struct wlfw_wfc_call_twt_config_ind_msg_v01, + twt_sta_upo), }, { .data_type = QMI_OPT_FLAG, @@ -4820,9 +4472,9 @@ struct qmi_elem_info wlfw_wfc_call_twt_config_ind_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x13, - .offset = offsetof(struct - wlfw_wfc_call_twt_config_ind_msg_v01, - twt_sta_sp_valid), + .offset = + offsetof(struct wlfw_wfc_call_twt_config_ind_msg_v01, + twt_sta_sp_valid), }, { .data_type = QMI_UNSIGNED_2_BYTE, @@ -4830,9 +4482,9 @@ struct qmi_elem_info wlfw_wfc_call_twt_config_ind_msg_v01_ei[] = { .elem_size = sizeof(u16), .array_type = NO_ARRAY, .tlv_type = 0x13, - .offset = offsetof(struct - wlfw_wfc_call_twt_config_ind_msg_v01, - twt_sta_sp), + .offset = + offsetof(struct wlfw_wfc_call_twt_config_ind_msg_v01, + twt_sta_sp), }, { .data_type = QMI_OPT_FLAG, @@ -4840,9 +4492,9 @@ struct qmi_elem_info wlfw_wfc_call_twt_config_ind_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x14, - .offset = offsetof(struct - wlfw_wfc_call_twt_config_ind_msg_v01, - twt_sta_dl_valid), + .offset = + offsetof(struct wlfw_wfc_call_twt_config_ind_msg_v01, + twt_sta_dl_valid), }, { .data_type = QMI_UNSIGNED_2_BYTE, @@ -4850,9 +4502,9 @@ struct qmi_elem_info wlfw_wfc_call_twt_config_ind_msg_v01_ei[] = { .elem_size = sizeof(u16), .array_type = NO_ARRAY, .tlv_type = 0x14, - .offset = offsetof(struct - wlfw_wfc_call_twt_config_ind_msg_v01, - twt_sta_dl), + .offset = + offsetof(struct wlfw_wfc_call_twt_config_ind_msg_v01, + twt_sta_dl), }, { .data_type = QMI_OPT_FLAG, @@ -4860,9 +4512,9 @@ struct qmi_elem_info wlfw_wfc_call_twt_config_ind_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x15, - .offset = offsetof(struct - wlfw_wfc_call_twt_config_ind_msg_v01, - twt_sta_config_changed_valid), + .offset = + offsetof(struct wlfw_wfc_call_twt_config_ind_msg_v01, + twt_sta_config_changed_valid), }, { .data_type = QMI_UNSIGNED_1_BYTE, @@ -4870,9 +4522,9 @@ struct qmi_elem_info wlfw_wfc_call_twt_config_ind_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x15, - .offset = offsetof(struct - wlfw_wfc_call_twt_config_ind_msg_v01, - twt_sta_config_changed), + .offset = + offsetof(struct wlfw_wfc_call_twt_config_ind_msg_v01, + twt_sta_config_changed), }, { .data_type = QMI_EOTI, @@ -4880,7 +4532,6 @@ struct qmi_elem_info wlfw_wfc_call_twt_config_ind_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_wfc_call_twt_config_ind_msg_v01_ei); struct qmi_elem_info wlfw_qdss_mem_ready_ind_msg_v01_ei[] = { { @@ -4889,7 +4540,6 @@ struct qmi_elem_info wlfw_qdss_mem_ready_ind_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_qdss_mem_ready_ind_msg_v01_ei); struct qmi_elem_info wlfw_pcie_gen_switch_req_msg_v01_ei[] = { { @@ -4908,7 +4558,6 @@ struct qmi_elem_info wlfw_pcie_gen_switch_req_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_pcie_gen_switch_req_msg_v01_ei); struct qmi_elem_info wlfw_pcie_gen_switch_resp_msg_v01_ei[] = { { @@ -4928,5 +4577,4 @@ struct qmi_elem_info wlfw_pcie_gen_switch_resp_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; -EXPORT_SYMBOL(wlfw_pcie_gen_switch_resp_msg_v01_ei); diff --git a/drivers/net/wireless/cnss_utils/wlan_firmware_service_v01.h b/drivers/soc/qcom/icnss2/wlan_firmware_service_v01.h similarity index 98% rename from drivers/net/wireless/cnss_utils/wlan_firmware_service_v01.h rename to drivers/soc/qcom/icnss2/wlan_firmware_service_v01.h index cdd81b429a97..aac8403d11c3 100644 --- a/drivers/net/wireless/cnss_utils/wlan_firmware_service_v01.h +++ b/drivers/soc/qcom/icnss2/wlan_firmware_service_v01.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0-only */ -/* Copyright (c) 2020, The Linux Foundation. All rights reserved. */ +/* Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. */ #ifndef WLAN_FIRMWARE_SERVICE_V01_H #define WLAN_FIRMWARE_SERVICE_V01_H @@ -88,6 +88,10 @@ #define QMI_WLFW_XO_CAL_IND_V01 0x003D #define QMI_WLFW_SHUTDOWN_RESP_V01 0x0043 #define QMI_WLFW_ATHDIAG_READ_REQ_V01 0x0030 +#define QMI_WLFW_WLAN_CFG_REQ_V01 0x0023 +#define QMI_WLFW_IND_REGISTER_RESP_V01 0x0020 +#define QMI_WLFW_PCIE_GEN_SWITCH_REQ_V01 0x0053 +#define QMI_WLFW_PCIE_GEN_SWITCH_RESP_V01 0x0053 #define QMI_WLFW_WFC_CALL_TWT_CONFIG_IND_V01 0x0051 #define QMI_WLFW_WLAN_MODE_RESP_V01 0x0022 #define QMI_WLFW_WFC_CALL_STATUS_REQ_V01 0x0049 @@ -367,6 +371,7 @@ struct wlfw_ind_register_req_msg_v01 { u8 qdss_mem_ready_enable_valid; u8 qdss_mem_ready_enable; }; + #define WLFW_IND_REGISTER_REQ_MSG_V01_MAX_MSG_LEN 82 extern struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[]; @@ -429,10 +434,12 @@ struct wlfw_wlan_cfg_req_msg_v01 { struct wlfw_ce_svc_pipe_cfg_s_v01 svc_cfg[QMI_WLFW_MAX_NUM_SVC_V01]; u8 shadow_reg_valid; u32 shadow_reg_len; - struct wlfw_shadow_reg_cfg_s_v01 shadow_reg[QMI_WLFW_MAX_NUM_SHADOW_REG_V01]; + struct wlfw_shadow_reg_cfg_s_v01 + shadow_reg[QMI_WLFW_MAX_NUM_SHADOW_REG_V01]; u8 shadow_reg_v2_valid; u32 shadow_reg_v2_len; - struct wlfw_shadow_reg_v2_cfg_s_v01 shadow_reg_v2[QMI_WLFW_MAX_NUM_SHADOW_REG_V2_V01]; + struct wlfw_shadow_reg_v2_cfg_s_v01 + shadow_reg_v2[QMI_WLFW_MAX_NUM_SHADOW_REG_V2_V01]; u8 rri_over_ddr_cfg_valid; struct wlfw_rri_over_ddr_cfg_s_v01 rri_over_ddr_cfg; u8 msi_cfg_valid; @@ -481,6 +488,7 @@ struct wlfw_cap_resp_msg_v01 { u8 rd_card_chain_cap_valid; enum wlfw_rd_card_chain_cap_v01 rd_card_chain_cap; }; + #define WLFW_CAP_RESP_MSG_V01_MAX_MSG_LEN 253 extern struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[]; @@ -508,6 +516,7 @@ struct wlfw_bdf_download_resp_msg_v01 { u8 host_bdf_data_valid; u64 host_bdf_data; }; + #define WLFW_BDF_DOWNLOAD_RESP_MSG_V01_MAX_MSG_LEN 18 extern struct qmi_elem_info wlfw_bdf_download_resp_msg_v01_ei[]; @@ -608,7 +617,8 @@ extern struct qmi_elem_info wlfw_msa_info_req_msg_v01_ei[]; struct wlfw_msa_info_resp_msg_v01 { struct qmi_response_type_v01 resp; u32 mem_region_info_len; - struct wlfw_memory_region_info_s_v01 mem_region_info[QMI_WLFW_MAX_NUM_MEMORY_REGIONS_V01]; + struct wlfw_memory_region_info_s_v01 + mem_region_info[QMI_WLFW_MAX_NUM_MEMORY_REGIONS_V01]; }; #define WLFW_MSA_INFO_RESP_MSG_V01_MAX_MSG_LEN 37 extern struct qmi_elem_info wlfw_msa_info_resp_msg_v01_ei[]; @@ -728,7 +738,8 @@ struct wlfw_host_cap_req_msg_v01 { u8 platform_name_valid; char platform_name[QMI_WLFW_MAX_PLATFORM_NAME_LEN_V01 + 1]; u8 ddr_range_valid; - struct wlfw_host_ddr_range_s_v01 ddr_range[QMI_WLFW_MAX_HOST_DDR_RANGE_SIZE_V01]; + struct wlfw_host_ddr_range_s_v01 + ddr_range[QMI_WLFW_MAX_HOST_DDR_RANGE_SIZE_V01]; u8 host_build_type_valid; enum wlfw_host_build_type_v01 host_build_type; }; @@ -1084,12 +1095,14 @@ struct wlfw_power_save_req_msg_v01 { u8 power_save_mode_valid; enum wlfw_power_save_mode_v01 power_save_mode; }; + #define WLFW_POWER_SAVE_REQ_MSG_V01_MAX_MSG_LEN 7 extern struct qmi_elem_info wlfw_power_save_req_msg_v01_ei[]; struct wlfw_power_save_resp_msg_v01 { struct qmi_response_type_v01 resp; }; + #define WLFW_POWER_SAVE_RESP_MSG_V01_MAX_MSG_LEN 7 extern struct qmi_elem_info wlfw_power_save_resp_msg_v01_ei[]; @@ -1107,24 +1120,28 @@ struct wlfw_wfc_call_twt_config_ind_msg_v01 { u8 twt_sta_config_changed_valid; u8 twt_sta_config_changed; }; + #define WLFW_WFC_CALL_TWT_CONFIG_IND_MSG_V01_MAX_MSG_LEN 35 extern struct qmi_elem_info wlfw_wfc_call_twt_config_ind_msg_v01_ei[]; struct wlfw_qdss_mem_ready_ind_msg_v01 { char placeholder; }; + #define WLFW_QDSS_MEM_READY_IND_MSG_V01_MAX_MSG_LEN 0 extern struct qmi_elem_info wlfw_qdss_mem_ready_ind_msg_v01_ei[]; struct wlfw_pcie_gen_switch_req_msg_v01 { enum wlfw_pcie_gen_speed_v01 pcie_speed; }; + #define WLFW_PCIE_GEN_SWITCH_REQ_MSG_V01_MAX_MSG_LEN 7 extern struct qmi_elem_info wlfw_pcie_gen_switch_req_msg_v01_ei[]; struct wlfw_pcie_gen_switch_resp_msg_v01 { struct qmi_response_type_v01 resp; }; + #define WLFW_PCIE_GEN_SWITCH_RESP_MSG_V01_MAX_MSG_LEN 7 extern struct qmi_elem_info wlfw_pcie_gen_switch_resp_msg_v01_ei[]; From d481edcb6d31940ff548e5b17b711489f759fe36 Mon Sep 17 00:00:00 2001 From: Raghavendra Kakarla Date: Fri, 30 Oct 2020 19:41:33 +0530 Subject: [PATCH 071/698] lpm-levels: Disable RIMPS timer based PLL/RAIL feature timer This patch disables the RIMPS timer based PLL/RAIL trigger timer in core C4 exit so that it stops the RIMPS from ticking timer when core C4 exit happen before this timer expires. Change-Id: I74b3e2222dc3ef5ba0fdebd71b7e86201016fc42 Signed-off-by: Raghavendra Kakarla --- drivers/cpuidle/lpm-levels.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/drivers/cpuidle/lpm-levels.c b/drivers/cpuidle/lpm-levels.c index d094202bbaff..4c4e8ed6bc88 100644 --- a/drivers/cpuidle/lpm-levels.c +++ b/drivers/cpuidle/lpm-levels.c @@ -274,6 +274,23 @@ static uint32_t get_next_event(struct lpm_cpu *cpu) return ktime_to_us(ktime_sub(next_event, ktime_get())); } +static void disable_rimps_timer(struct lpm_cpu *cpu) +{ + uint32_t ctrl_val; + + if (!cpu->rimps_tmr_base) + return; + + spin_lock(&cpu->cpu_lock); + ctrl_val = readl_relaxed(cpu->rimps_tmr_base + TIMER_CTRL); + writel_relaxed(ctrl_val & ~(TIMER_CONTROL_EN), + cpu->rimps_tmr_base + TIMER_CTRL); + /* Ensure the write is complete before returning. */ + wmb(); + spin_unlock(&cpu->cpu_lock); + +} + static void program_rimps_timer(struct lpm_cpu *cpu) { uint32_t ctrl_val, next_event; @@ -1467,6 +1484,8 @@ static int lpm_cpuidle_enter(struct cpuidle_device *dev, success = (ret == 0); exit: + if (idx == cpu->nlevels - 1) + disable_rimps_timer(cpu); end_time = ktime_to_ns(ktime_get()); lpm_stats_cpu_exit(idx, end_time, success); @@ -1729,6 +1748,7 @@ static int lpm_suspend_enter(suspend_state_t state) cpu_prepare(lpm_cpu, idx, false); cluster_prepare(cluster, cpumask, idx, false, 0); + disable_rimps_timer(lpm_cpu); ret = psci_enter_sleep(lpm_cpu, idx, false); success = (ret == 0); From 50346642190c426f66bad04b9e79472593945476 Mon Sep 17 00:00:00 2001 From: Puranam V G Tejaswi Date: Wed, 11 Nov 2020 22:28:43 +0530 Subject: [PATCH 072/698] msm: kgsl: Simplify GBIF halt sequence for stall-on-fault case Currently during stall-on-fault recovery, we keep resuming SMMU and check if GBIF halt succeeded. This is done to recover from a case where a GPU block continuously initiated faulty transactions, which would keep stalling SMMU. If we set CFCFG to 0 as part of handling the first fault, all these transactions will be terminated and will not stall SMMU. This simplifies the GBIF halt sequence and avoids resuming every time. Change-Id: Iada83d6a08e5e0a4f6241b17d1b178ab680f1364 Signed-off-by: Puranam V G Tejaswi --- drivers/gpu/msm/adreno_a6xx.c | 96 +++++++++---------------------- drivers/gpu/msm/adreno_a6xx.h | 11 ---- drivers/gpu/msm/adreno_a6xx_gmu.c | 16 +++--- drivers/gpu/msm/kgsl_iommu.c | 20 +++++++ 4 files changed, 54 insertions(+), 89 deletions(-) diff --git a/drivers/gpu/msm/adreno_a6xx.c b/drivers/gpu/msm/adreno_a6xx.c index a6f08740a676..4b796166b1a9 100644 --- a/drivers/gpu/msm/adreno_a6xx.c +++ b/drivers/gpu/msm/adreno_a6xx.c @@ -1264,6 +1264,29 @@ void a6xx_gx_cpr_toggle(struct kgsl_device *device) wmb(); } +/* This is only defined for non-GMU and non-RGMU targets */ +static int a6xx_clear_pending_transactions(struct adreno_device *adreno_dev) +{ + struct kgsl_device *device = KGSL_DEVICE(adreno_dev); + int ret; + + if (adreno_is_a619_holi(adreno_dev)) { + kgsl_regwrite(device, A6XX_RBBM_GPR0_CNTL, 0x1e0); + ret = adreno_wait_for_halt_ack(device, + A6XX_RBBM_VBIF_GX_RESET_STATUS, 0xf0); + } else { + kgsl_regwrite(device, A6XX_RBBM_GBIF_HALT, + A6XX_GBIF_GX_HALT_MASK); + ret = adreno_wait_for_halt_ack(device, A6XX_RBBM_GBIF_HALT_ACK, + A6XX_GBIF_GX_HALT_MASK); + } + + if (ret) + return ret; + + return a6xx_halt_gbif(adreno_dev); +} + /** * a6xx_reset() - Helper function to reset the GPU * @device: Pointer to the KGSL device structure for the GPU @@ -1277,19 +1300,9 @@ static int a6xx_reset(struct kgsl_device *device) int ret; unsigned long flags = device->pwrctrl.ctrl_flags; - /* - * Stall on fault needs GBIF halt sequences for robust recovery. - * Because in a worst-case scenario, if any of the GPU blocks is - * generating a stream of un-ending faulting transactions, SMMU will - * process those transactions when we try to resume it and enter - * stall-on-fault mode again. GBIF halt sequences make sure that all - * GPU transactions are halted at GBIF which ensures that SMMU - * can resume safely. - */ - a6xx_do_gbif_halt(adreno_dev, A6XX_RBBM_GBIF_HALT, - A6XX_RBBM_GBIF_HALT_ACK, A6XX_GBIF_GX_HALT_MASK, "GX"); - a6xx_do_gbif_halt(adreno_dev, A6XX_GBIF_HALT, A6XX_GBIF_HALT_ACK, - A6XX_GBIF_ARB_HALT_MASK, "CX"); + ret = a6xx_clear_pending_transactions(adreno_dev); + if (ret) + return ret; /* Clear ctrl_flags to ensure clocks and regulators are turned off */ device->pwrctrl.ctrl_flags = 0; @@ -2441,63 +2454,6 @@ u64 a6xx_read_alwayson(struct adreno_device *adreno_dev) return (((u64) hi) << 32) | lo; } -void a6xx_do_gbif_halt(struct adreno_device *adreno_dev, - u32 halt_reg, u32 ack_reg, u32 mask, const char *client) -{ - struct kgsl_device *device = KGSL_DEVICE(adreno_dev); - unsigned long t; - u32 val; - - kgsl_regwrite(device, halt_reg, mask); - - t = jiffies + msecs_to_jiffies(100); - do { - kgsl_regread(device, ack_reg, &val); - if ((val & mask) == mask) - return; - - /* - * If we are attempting GBIF halt in case of stall-on-fault - * then the halt sequence will not complete as long as SMMU - * is stalled. - */ - kgsl_mmu_pagefault_resume(&device->mmu); - usleep_range(10, 100); - } while (!time_after(jiffies, t)); - - /* Check one last time */ - kgsl_mmu_pagefault_resume(&device->mmu); - - kgsl_regread(device, ack_reg, &val); - if ((val & mask) == mask) - return; - - dev_err(device->dev, "%s GBIF Halt ack timed out\n", client); -} - -/* This is only defined for non-GMU and non-RGMU targets */ -static int a6xx_clear_pending_transactions(struct adreno_device *adreno_dev) -{ - struct kgsl_device *device = KGSL_DEVICE(adreno_dev); - int ret; - - if (adreno_is_a619_holi(adreno_dev)) { - kgsl_regwrite(device, A6XX_RBBM_GPR0_CNTL, 0x1e0); - ret = adreno_wait_for_halt_ack(device, - A6XX_RBBM_VBIF_GX_RESET_STATUS, 0xf0); - } else { - kgsl_regwrite(device, A6XX_RBBM_GBIF_HALT, - A6XX_GBIF_GX_HALT_MASK); - ret = adreno_wait_for_halt_ack(device, A6XX_RBBM_GBIF_HALT_ACK, - A6XX_GBIF_GX_HALT_MASK); - } - - if (ret) - return ret; - - return a6xx_halt_gbif(adreno_dev); -} - const struct adreno_gpudev adreno_a6xx_gpudev = { .reg_offsets = a6xx_register_offsets, .probe = a6xx_probe, diff --git a/drivers/gpu/msm/adreno_a6xx.h b/drivers/gpu/msm/adreno_a6xx.h index 4c28695cbbf8..a15c1d8f401a 100644 --- a/drivers/gpu/msm/adreno_a6xx.h +++ b/drivers/gpu/msm/adreno_a6xx.h @@ -317,17 +317,6 @@ int a6xx_gmu_sptprac_enable(struct adreno_device *adreno_dev); void a6xx_gmu_sptprac_disable(struct adreno_device *adreno_dev); bool a6xx_gmu_sptprac_is_on(struct adreno_device *adreno_dev); -/** - * a6xx_do_gbif_halt - halt gbif traffic and wait for ack - * @adreno_dev: An Adreno GPU handle - * @halt_reg: reg to trigger gbif halt - * @ack_reg: status register to check for ack - * @mask: mask for ack - * @client: client name - "GX" or "CX" - */ -void a6xx_do_gbif_halt(struct adreno_device *adreno_dev, - u32 halt_reg, u32 ack_reg, u32 mask, const char *client); - /** * a6xx_read_alwayson - Read the current always on clock value * @adreno_dev: An Adreno GPU handle diff --git a/drivers/gpu/msm/adreno_a6xx_gmu.c b/drivers/gpu/msm/adreno_a6xx_gmu.c index 33bcef5d08b0..1ae6d4488b3d 100644 --- a/drivers/gpu/msm/adreno_a6xx_gmu.c +++ b/drivers/gpu/msm/adreno_a6xx_gmu.c @@ -1617,15 +1617,15 @@ static void a6xx_gmu_pwrctrl_suspend(struct adreno_device *adreno_dev) if (adreno_has_gbif(adreno_dev)) { /* Halt GX traffic */ - if (a6xx_gmu_gx_is_on(device)) - a6xx_do_gbif_halt(adreno_dev, A6XX_RBBM_GBIF_HALT, - A6XX_RBBM_GBIF_HALT_ACK, - A6XX_GBIF_GX_HALT_MASK, - "GX"); - + if (a6xx_gmu_gx_is_on(device)) { + kgsl_regwrite(device, A6XX_RBBM_GBIF_HALT, + A6XX_GBIF_GX_HALT_MASK); + adreno_wait_for_halt_ack(device, + A6XX_RBBM_GBIF_HALT_ACK, + A6XX_GBIF_GX_HALT_MASK); + } /* Halt CX traffic */ - a6xx_do_gbif_halt(adreno_dev, A6XX_GBIF_HALT, A6XX_GBIF_HALT_ACK, - A6XX_GBIF_ARB_HALT_MASK, "CX"); + a6xx_halt_gbif(adreno_dev); } if (a6xx_gmu_gx_is_on(device)) diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c index 05d05025427b..a1a4e5d151d0 100644 --- a/drivers/gpu/msm/kgsl_iommu.c +++ b/drivers/gpu/msm/kgsl_iommu.c @@ -1747,6 +1747,26 @@ static void kgsl_iommu_pagefault_resume(struct kgsl_mmu *mmu) struct kgsl_iommu_context *ctx = &iommu->user_context; if (ctx->default_pt != NULL && ctx->stalled_on_fault) { + u32 sctlr_val = KGSL_IOMMU_GET_CTX_REG(ctx, + KGSL_IOMMU_CTX_SCTLR); + + /* + * As part of recovery, GBIF halt sequence should be performed. + * In a worst case scenario, if any GPU block is generating a + * stream of un-ending faulting transactions, SMMU would enter + * stall-on-fault mode again after resuming and not let GBIF + * halt succeed. In order to avoid that situation and terminate + * those faulty transactions, set CFCFG and HUPCF to 0. + */ + sctlr_val &= ~(0x1 << KGSL_IOMMU_SCTLR_CFCFG_SHIFT); + sctlr_val &= ~(0x1 << KGSL_IOMMU_SCTLR_HUPCF_SHIFT); + KGSL_IOMMU_SET_CTX_REG(ctx, KGSL_IOMMU_CTX_SCTLR, sctlr_val); + /* + * Make sure the above register write is not reordered across + * the barrier as we use writel_relaxed to write it. + */ + wmb(); + /* * This will only clear fault bits in FSR. FSR.SS will still * be set. Writing to RESUME (below) is the only way to clear From 797ef389d0eefa6b2d3fedb3841e86f8feddb77b Mon Sep 17 00:00:00 2001 From: Puranam V G Tejaswi Date: Thu, 19 Nov 2020 00:18:49 +0530 Subject: [PATCH 073/698] msm: kgsl: Don't deassert GBIF halt for non-GMU targets During adreno_stop, GBIF halt is asserted to halt any new transaction from GPU before GPU power collapse, but in current code it is cleared immediately which can allow few GPU transactions to go through before gdsc is turned-off and can result in issues. To avoid this situation don't deassert this halt before GPU gdsc goes off. It will deassert automatically when gdsc goes off but in case gdsc doesn't toggle as it is a shared resource, it is deasserted during adreno_start to ensure wake-up doesn't fail. Change-Id: If0a892470d04a0f3a79a1ea882ee5bfd16ad24ed Signed-off-by: Puranam V G Tejaswi --- drivers/gpu/msm/adreno_a6xx_gmu.c | 10 ++++++---- drivers/gpu/msm/adreno_a6xx_hwsched.c | 2 ++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/msm/adreno_a6xx_gmu.c b/drivers/gpu/msm/adreno_a6xx_gmu.c index 1ae6d4488b3d..f90d7f2d51e6 100644 --- a/drivers/gpu/msm/adreno_a6xx_gmu.c +++ b/drivers/gpu/msm/adreno_a6xx_gmu.c @@ -1626,6 +1626,8 @@ static void a6xx_gmu_pwrctrl_suspend(struct adreno_device *adreno_dev) } /* Halt CX traffic */ a6xx_halt_gbif(adreno_dev); + /* De-assert the halts */ + kgsl_regwrite(device, A6XX_GBIF_HALT, 0x0); } if (a6xx_gmu_gx_is_on(device)) @@ -2764,9 +2766,6 @@ int a6xx_halt_gbif(struct adreno_device *adreno_dev) ret = adreno_wait_for_halt_ack(device, A6XX_GBIF_HALT_ACK, A6XX_GBIF_ARB_HALT_MASK); - /* De-assert the halts */ - kgsl_regwrite(device, A6XX_GBIF_HALT, 0x0); - return ret; } @@ -2797,8 +2796,11 @@ static int a6xx_gmu_power_off(struct adreno_device *adreno_dev) a6xx_rdpm_mx_freq_update(gmu, 0); /* Now that we are done with GMU and GPU, Clear the GBIF */ - if (!adreno_is_a630(adreno_dev)) + if (!adreno_is_a630(adreno_dev)) { ret = a6xx_halt_gbif(adreno_dev); + /* De-assert the halts */ + kgsl_regwrite(device, A6XX_GBIF_HALT, 0x0); + } a6xx_gmu_irq_disable(adreno_dev); diff --git a/drivers/gpu/msm/adreno_a6xx_hwsched.c b/drivers/gpu/msm/adreno_a6xx_hwsched.c index f83b63497408..8f40f625a3bc 100644 --- a/drivers/gpu/msm/adreno_a6xx_hwsched.c +++ b/drivers/gpu/msm/adreno_a6xx_hwsched.c @@ -373,6 +373,8 @@ static int a6xx_hwsched_gmu_power_off(struct adreno_device *adreno_dev) /* Now that we are done with GMU and GPU, Clear the GBIF */ ret = a6xx_halt_gbif(adreno_dev); + /* De-assert the halts */ + kgsl_regwrite(device, A6XX_GBIF_HALT, 0x0); a6xx_gmu_irq_disable(adreno_dev); From f6a1d90e47f3670de526d5ceac088e512ad2dd21 Mon Sep 17 00:00:00 2001 From: Puranam V G Tejaswi Date: Thu, 19 Nov 2020 00:33:34 +0530 Subject: [PATCH 074/698] msm: kgsl: Move deassert_gbif_halt to a6xx specific space deassert_gbif_halt is needed only for the a6xx targets that use clear_pending_transactions. So move deassert_gbif_halt to a6xx specific space. This helps to provide some clarity and avoid gmu and gbif related checks. Change-Id: If46fa22a54737c2dbc35205318ed75ead351760a Signed-off-by: Puranam V G Tejaswi --- drivers/gpu/msm/adreno.c | 12 ------------ drivers/gpu/msm/adreno.h | 18 ------------------ drivers/gpu/msm/adreno_a6xx.c | 28 +++++++++++++++++++++++++--- 3 files changed, 25 insertions(+), 33 deletions(-) diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c index 96342cd4b553..e2f241c369c5 100644 --- a/drivers/gpu/msm/adreno.c +++ b/drivers/gpu/msm/adreno.c @@ -2036,18 +2036,6 @@ static int _adreno_start(struct adreno_device *adreno_dev) if (regulator_left_on) _soft_reset(adreno_dev); - /* - * During adreno_stop, GBIF halt is asserted to ensure - * no further transaction can go through GPU before GPU - * headswitch is turned off. - * - * This halt is deasserted once headswitch goes off but - * incase headswitch doesn't goes off clear GBIF halt - * here to ensure GPU wake-up doesn't fail because of - * halted GPU transactions. - */ - adreno_deassert_gbif_halt(adreno_dev); - adreno_ringbuffer_set_global(adreno_dev, 0); status = kgsl_mmu_start(device); diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h index cfd574260fff..f1bec2ec0fd1 100644 --- a/drivers/gpu/msm/adreno.h +++ b/drivers/gpu/msm/adreno.h @@ -696,9 +696,7 @@ enum adreno_regs { ADRENO_REG_RBBM_PERFCTR_RBBM_0_HI, ADRENO_REG_RBBM_PERFCTR_LOAD_VALUE_LO, ADRENO_REG_RBBM_PERFCTR_LOAD_VALUE_HI, - ADRENO_REG_GBIF_HALT, ADRENO_REG_VBIF_VERSION, - ADRENO_REG_RBBM_GBIF_HALT, ADRENO_REG_GMU_AO_HOST_INTERRUPT_MASK, ADRENO_REG_GMU_AHB_FENCE_STATUS, ADRENO_REG_GMU_GMU2HOST_INTR_MASK, @@ -1692,22 +1690,6 @@ static inline int adreno_wait_for_halt_ack(struct kgsl_device *device, return 0; } -static inline void adreno_deassert_gbif_halt(struct adreno_device *adreno_dev) -{ - if (adreno_has_gbif(adreno_dev)) { - adreno_writereg(adreno_dev, ADRENO_REG_GBIF_HALT, 0x0); - - /* - * Release GBIF GX halt. For A615 family, GPU GX halt - * will be cleared automatically on reset. - */ - if (!gmu_core_gpmu_isenabled(KGSL_DEVICE(adreno_dev)) && - !adreno_is_a615_family(adreno_dev)) - adreno_writereg(adreno_dev, - ADRENO_REG_RBBM_GBIF_HALT, 0x0); - } -} - /** * adreno_move_preempt_state - Update the preemption state * @adreno_dev: An Adreno GPU device handle diff --git a/drivers/gpu/msm/adreno_a6xx.c b/drivers/gpu/msm/adreno_a6xx.c index 4b796166b1a9..4f950a8fd498 100644 --- a/drivers/gpu/msm/adreno_a6xx.c +++ b/drivers/gpu/msm/adreno_a6xx.c @@ -426,6 +426,18 @@ static void a6xx_set_secvid(struct kgsl_device *device) set = true; } +static void a6xx_deassert_gbif_halt(struct adreno_device *adreno_dev) +{ + struct kgsl_device *device = KGSL_DEVICE(adreno_dev); + + kgsl_regwrite(device, A6XX_GBIF_HALT, 0x0); + + if (adreno_is_a619_holi(adreno_dev)) + kgsl_regwrite(device, A6XX_RBBM_GPR0_CNTL, 0x0); + else + kgsl_regwrite(device, A6XX_RBBM_GBIF_HALT, 0x0); +} + /* * Some targets support marking certain transactions as always privileged which * allows us to mark more memory as privileged without having to explicitly set @@ -696,6 +708,19 @@ void a6xx_start(struct adreno_device *adreno_dev) a6xx_patch_pwrup_reglist(adreno_dev); patch_reglist = true; } + + /* + * During adreno_stop, GBIF halt is asserted to ensure + * no further transaction can go through GPU before GPU + * headswitch is turned off. + * + * This halt is deasserted once headswitch goes off but + * incase headswitch doesn't goes off clear GBIF halt + * here to ensure GPU wake-up doesn't fail because of + * halted GPU transactions. + */ + a6xx_deassert_gbif_halt(adreno_dev); + } /* Offsets into the MX/CX mapped register regions */ @@ -2300,9 +2325,6 @@ static unsigned int a6xx_register_offsets[ADRENO_REG_REGISTER_MAX] = { ADRENO_REG_DEFINE(ADRENO_REG_RBBM_PERFCTR_LOAD_VALUE_HI, A6XX_RBBM_PERFCTR_LOAD_VALUE_HI), ADRENO_REG_DEFINE(ADRENO_REG_VBIF_VERSION, A6XX_VBIF_VERSION), - ADRENO_REG_DEFINE(ADRENO_REG_RBBM_GBIF_HALT, - A6XX_RBBM_GBIF_HALT), - ADRENO_REG_DEFINE(ADRENO_REG_GBIF_HALT, A6XX_GBIF_HALT), ADRENO_REG_DEFINE(ADRENO_REG_GMU_AO_HOST_INTERRUPT_MASK, A6XX_GMU_AO_HOST_INTERRUPT_MASK), ADRENO_REG_DEFINE(ADRENO_REG_GMU_AHB_FENCE_STATUS, From 5058481c8544188bf866999641555b13d4137661 Mon Sep 17 00:00:00 2001 From: Puranam V G Tejaswi Date: Wed, 18 Nov 2020 23:22:44 +0530 Subject: [PATCH 075/698] msm: kgsl: Halt GBIF before moving to NAP state It has been observed that without gmu_clk, any active transactions will cause that transaction to be stuck in QSMMU. As of now we don't halt GBIF when moving to NAP state. So there is a possibility of transactions inflight when gmu_clk is gated. This will cause transactions to be stuck in QSMMU forever. This can eventually lead to GPU hang or TLB sync timeout. So halt GBIF before moving to NAP. Change-Id: I13bbe3b21b327d0d5c962bb2133c6d5d0f3a43c3 Signed-off-by: Puranam V G Tejaswi --- drivers/gpu/msm/adreno.c | 27 ++++++++++++++++++++++----- drivers/gpu/msm/adreno.h | 3 +-- drivers/gpu/msm/adreno_a6xx.c | 2 ++ drivers/gpu/msm/kgsl_device.h | 4 ++-- drivers/gpu/msm/kgsl_pwrctrl.c | 6 +++--- 5 files changed, 30 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c index e2f241c369c5..0c97e8bbd4d0 100644 --- a/drivers/gpu/msm/adreno.c +++ b/drivers/gpu/msm/adreno.c @@ -3510,7 +3510,7 @@ static int adreno_regulator_enable(struct kgsl_device *device) return ret; } -static bool adreno_is_hw_collapsible(struct kgsl_device *device) +static bool adreno_prepare_for_power_off(struct kgsl_device *device) { struct adreno_device *adreno_dev = ADRENO_DEVICE(device); const struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev); @@ -3524,8 +3524,16 @@ static bool adreno_is_hw_collapsible(struct kgsl_device *device) device->pwrctrl.ctrl_flags) return false; - return adreno_isidle(adreno_dev) && (gpudev->is_sptp_idle ? - gpudev->is_sptp_idle(adreno_dev) : true); + if (!adreno_isidle(adreno_dev) || !(gpudev->is_sptp_idle ? + gpudev->is_sptp_idle(adreno_dev) : true)) + return false; + + if (gpudev->clear_pending_transactions(adreno_dev)) + return false; + + adreno_dispatcher_stop_fault_timer(device); + + return true; } static void adreno_regulator_disable(struct kgsl_device *device) @@ -3732,6 +3740,15 @@ static int adreno_gpu_bus_set(struct kgsl_device *device, int level, u32 ab) return adreno_interconnect_bus_set(adreno_dev, level, ab); } +static void adreno_deassert_gbif_halt(struct kgsl_device *device) +{ + struct adreno_device *adreno_dev = ADRENO_DEVICE(device); + const struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev); + + if (gpudev->deassert_gbif_halt) + gpudev->deassert_gbif_halt(adreno_dev); +} + static const struct kgsl_functable adreno_functable = { /* Mandatory functions */ .regread = adreno_regread, @@ -3766,17 +3783,17 @@ static const struct kgsl_functable adreno_functable = { .drawctxt_sched = adreno_drawctxt_sched, .resume = adreno_dispatcher_start, .regulator_enable = adreno_regulator_enable, - .is_hw_collapsible = adreno_is_hw_collapsible, + .prepare_for_power_off = adreno_prepare_for_power_off, .regulator_disable = adreno_regulator_disable, .pwrlevel_change_settings = adreno_pwrlevel_change_settings, .regulator_disable_poll = adreno_regulator_disable_poll, .clk_set_options = adreno_clk_set_options, .gpu_model = adreno_gpu_model, - .stop_fault_timer = adreno_dispatcher_stop_fault_timer, .query_property_list = adreno_query_property_list, .is_hwcg_on = adreno_is_hwcg_on, .gpu_clock_set = adreno_gpu_clock_set, .gpu_bus_set = adreno_gpu_bus_set, + .deassert_gbif_halt = adreno_deassert_gbif_halt, }; static const struct component_master_ops adreno_ops = { diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h index f1bec2ec0fd1..a5f51cdf794c 100644 --- a/drivers/gpu/msm/adreno.h +++ b/drivers/gpu/msm/adreno.h @@ -811,6 +811,7 @@ struct adreno_gpudev { */ const struct adreno_power_ops *power_ops; int (*clear_pending_transactions)(struct adreno_device *adreno_dev); + void (*deassert_gbif_halt)(struct adreno_device *adreno_dev); }; /** @@ -1735,8 +1736,6 @@ static inline u32 adreno_get_level(u32 priority) int adreno_gmu_fenced_write(struct adreno_device *adreno_dev, enum adreno_regs offset, unsigned int val, unsigned int fence_mask); -int adreno_clear_pending_transactions(struct kgsl_device *device); - /** * adreno_get_firwmare - Load firmware into a adreno_firmware struct diff --git a/drivers/gpu/msm/adreno_a6xx.c b/drivers/gpu/msm/adreno_a6xx.c index 4f950a8fd498..fb4497cfc82d 100644 --- a/drivers/gpu/msm/adreno_a6xx.c +++ b/drivers/gpu/msm/adreno_a6xx.c @@ -2509,6 +2509,7 @@ const struct adreno_gpudev adreno_a6xx_gpudev = { .read_alwayson = a6xx_read_alwayson, .power_ops = &adreno_power_operations, .clear_pending_transactions = a6xx_clear_pending_transactions, + .deassert_gbif_halt = a6xx_deassert_gbif_halt, }; const struct adreno_gpudev adreno_a6xx_hwsched_gpudev = { @@ -2622,6 +2623,7 @@ const struct adreno_gpudev adreno_a619_holi_gpudev = { .read_alwayson = a6xx_read_alwayson, .power_ops = &adreno_power_operations, .clear_pending_transactions = a6xx_clear_pending_transactions, + .deassert_gbif_halt = a6xx_deassert_gbif_halt, }; const struct adreno_gpudev adreno_a630_gpudev = { diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h index c68d4cac981f..544cabeb3890 100644 --- a/drivers/gpu/msm/kgsl_device.h +++ b/drivers/gpu/msm/kgsl_device.h @@ -148,7 +148,7 @@ struct kgsl_functable { struct kgsl_context *context); void (*resume)(struct kgsl_device *device); int (*regulator_enable)(struct kgsl_device *device); - bool (*is_hw_collapsible)(struct kgsl_device *device); + bool (*prepare_for_power_off)(struct kgsl_device *device); void (*regulator_disable)(struct kgsl_device *device); void (*pwrlevel_change_settings)(struct kgsl_device *device, unsigned int prelevel, unsigned int postlevel, bool post); @@ -157,7 +157,6 @@ struct kgsl_functable { const char *name, struct clk *clk, bool on); void (*gpu_model)(struct kgsl_device *device, char *str, size_t bufsz); - void (*stop_fault_timer)(struct kgsl_device *device); /** * @query_property_list: query the list of properties * supported by the device. If 'list' is NULL just return the total @@ -171,6 +170,7 @@ struct kgsl_functable { int (*gpu_clock_set)(struct kgsl_device *device, u32 pwrlevel); /** @gpu_bus_set: Target specific function to set gpu bandwidth */ int (*gpu_bus_set)(struct kgsl_device *device, int bus_level, u32 ab); + void (*deassert_gbif_halt)(struct kgsl_device *device); }; struct kgsl_ioctl { diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c index 88ac2285245e..28aba03c96af 100644 --- a/drivers/gpu/msm/kgsl_pwrctrl.c +++ b/drivers/gpu/msm/kgsl_pwrctrl.c @@ -1859,6 +1859,7 @@ static int _wake(struct kgsl_device *device) /* Turn on the core clocks */ kgsl_pwrctrl_clk(device, KGSL_PWRFLAGS_ON, KGSL_STATE_ACTIVE); + device->ftbl->deassert_gbif_halt(device); /* * No need to turn on/off irq here as it no longer affects * power collapse @@ -1943,12 +1944,11 @@ _nap(struct kgsl_device *device) { switch (device->state) { case KGSL_STATE_ACTIVE: - if (!device->ftbl->is_hw_collapsible(device)) { + if (!device->ftbl->prepare_for_power_off(device)) { kgsl_pwrctrl_request_state(device, KGSL_STATE_NONE); return -EBUSY; } - device->ftbl->stop_fault_timer(device); kgsl_pwrscale_midframe_timer_cancel(device); /* @@ -2006,7 +2006,7 @@ _slumber(struct kgsl_device *device) switch (device->state) { case KGSL_STATE_ACTIVE: - if (!device->ftbl->is_hw_collapsible(device)) { + if (!device->ftbl->prepare_for_power_off(device)) { kgsl_pwrctrl_request_state(device, KGSL_STATE_NONE); return -EBUSY; } From cb3b9a8717317c073f8d4ad9817db7c5d0bc7c50 Mon Sep 17 00:00:00 2001 From: Puranam V G Tejaswi Date: Wed, 18 Nov 2020 11:49:38 +0530 Subject: [PATCH 076/698] msm: kgsl: Poll GDCSR for holi target to ensure CX collapse The regulator_is_enabled() API doesn't guarantee that CX gdsc has collapsed at hardware. There could be a vote on the GDSC from another subsystem like TZ. So poll the CX GDSCR register to ensure that CX has indeed collapsed. Change-Id: Ic07cde5ba3442689cb73b33fe57c3d4371cb9565 Signed-off-by: Puranam V G Tejaswi --- drivers/gpu/msm/adreno.c | 10 ++++------ drivers/gpu/msm/adreno.h | 1 + drivers/gpu/msm/adreno_a6xx.c | 34 ++++++++++++++++++++++++++++++++-- 3 files changed, 37 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c index 0c97e8bbd4d0..14a7c6ec8b03 100644 --- a/drivers/gpu/msm/adreno.c +++ b/drivers/gpu/msm/adreno.c @@ -3572,17 +3572,15 @@ static void adreno_clk_set_options(struct kgsl_device *device, const char *name, static void adreno_regulator_disable_poll(struct kgsl_device *device) { struct kgsl_pwrctrl *pwr = &device->pwrctrl; + const struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE( + ADRENO_DEVICE(device)); - /* Set the parent in retention voltage to disable CPR interrupts */ - kgsl_regulator_set_voltage(device->dev, pwr->gx_gdsc_parent, - pwr->gx_gdsc_parent_min_corner); + if (gpudev->regulator_disable_poll) + return gpudev->regulator_disable_poll(device); if (!kgsl_regulator_disable_wait(pwr->gx_gdsc, 200)) dev_err(device->dev, "Regulator vdd is stuck on\n"); - /* Remove the vote for the vdd parent supply */ - kgsl_regulator_set_voltage(device->dev, pwr->gx_gdsc_parent, 0); - if (!kgsl_regulator_disable_wait(pwr->cx_gdsc, 200)) dev_err(device->dev, "Regulator vddcx is stuck on\n"); } diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h index a5f51cdf794c..3d977e411805 100644 --- a/drivers/gpu/msm/adreno.h +++ b/drivers/gpu/msm/adreno.h @@ -812,6 +812,7 @@ struct adreno_gpudev { const struct adreno_power_ops *power_ops; int (*clear_pending_transactions)(struct adreno_device *adreno_dev); void (*deassert_gbif_halt)(struct adreno_device *adreno_dev); + void (*regulator_disable_poll)(struct kgsl_device *device); }; /** diff --git a/drivers/gpu/msm/adreno_a6xx.c b/drivers/gpu/msm/adreno_a6xx.c index fb4497cfc82d..657758df39bd 100644 --- a/drivers/gpu/msm/adreno_a6xx.c +++ b/drivers/gpu/msm/adreno_a6xx.c @@ -17,6 +17,7 @@ #include "adreno_pm4types.h" #include "adreno_trace.h" #include "kgsl_trace.h" +#include "kgsl_util.h" /* IFPC & Preemption static powerup restore list */ static u32 a6xx_pwrup_reglist[] = { @@ -249,6 +250,7 @@ bool a6xx_cx_regulator_disable_wait(struct regulator *reg, { ktime_t tout = ktime_add_us(ktime_get(), timeout * 1000); unsigned int val; + struct adreno_device *adreno_dev = ADRENO_DEVICE(device); if (IS_ERR_OR_NULL(reg)) return true; @@ -256,13 +258,22 @@ bool a6xx_cx_regulator_disable_wait(struct regulator *reg, regulator_disable(reg); for (;;) { - gmu_core_regread(device, A6XX_GPU_CC_CX_GDSCR, &val); + if (adreno_is_a619_holi(adreno_dev)) + adreno_read_gmu_wrapper(adreno_dev, + A6XX_GPU_CC_CX_GDSCR, &val); + else + gmu_core_regread(device, A6XX_GPU_CC_CX_GDSCR, &val); if (!(val & BIT(31))) return true; if (ktime_compare(ktime_get(), tout) > 0) { - gmu_core_regread(device, A6XX_GPU_CC_CX_GDSCR, &val); + if (adreno_is_a619_holi(adreno_dev)) + adreno_read_gmu_wrapper(adreno_dev, + A6XX_GPU_CC_CX_GDSCR, &val); + else + gmu_core_regread(device, A6XX_GPU_CC_CX_GDSCR, + &val); return (!(val & BIT(31))); } @@ -2476,6 +2487,24 @@ u64 a6xx_read_alwayson(struct adreno_device *adreno_dev) return (((u64) hi) << 32) | lo; } +static void a619_holi_regulator_disable_poll(struct kgsl_device *device) +{ + struct kgsl_pwrctrl *pwr = &device->pwrctrl; + + /* Set the parent in retention voltage to disable CPR interrupts */ + kgsl_regulator_set_voltage(device->dev, pwr->gx_gdsc_parent, + pwr->gx_gdsc_parent_min_corner); + + if (!kgsl_regulator_disable_wait(pwr->gx_gdsc, 200)) + dev_err(device->dev, "Regulator vdd is stuck on\n"); + + /* Remove the vote for the vdd parent supply */ + kgsl_regulator_set_voltage(device->dev, pwr->gx_gdsc_parent, 0); + + if (!a6xx_cx_regulator_disable_wait(pwr->cx_gdsc, device, 200)) + dev_err(device->dev, "Regulator vddcx is stuck on\n"); +} + const struct adreno_gpudev adreno_a6xx_gpudev = { .reg_offsets = a6xx_register_offsets, .probe = a6xx_probe, @@ -2624,6 +2653,7 @@ const struct adreno_gpudev adreno_a619_holi_gpudev = { .power_ops = &adreno_power_operations, .clear_pending_transactions = a6xx_clear_pending_transactions, .deassert_gbif_halt = a6xx_deassert_gbif_halt, + .regulator_disable_poll = a619_holi_regulator_disable_poll, }; const struct adreno_gpudev adreno_a630_gpudev = { From 3dec7938ff4c9a219f5648e568fe4ceb1d23cc42 Mon Sep 17 00:00:00 2001 From: Akash Asthana Date: Thu, 12 Nov 2020 11:18:45 +0530 Subject: [PATCH 077/698] platform: msm-geni-se: Correct unit for ICC optimization In older kernel target we had ICB and it use to take input in BCM units for QUP core path, whereas in recent kernel we have ICC for BW NOC voting and it accept input in KHz. So correct unit for ICC optimization code. Change-Id: Ia6c88dbd328dad1ff96c6c7ffd22c93db942d509 Signed-off-by: Akash Asthana --- drivers/platform/msm/msm-geni-se.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/platform/msm/msm-geni-se.c b/drivers/platform/msm/msm-geni-se.c index 83a25efdc62b..69b14c66df2f 100644 --- a/drivers/platform/msm/msm-geni-se.c +++ b/drivers/platform/msm/msm-geni-se.c @@ -663,7 +663,7 @@ static bool geni_se_check_bus_bw(struct geni_se_device *geni_se_dev) bool bus_bw_update = false; /* Convert agg ab into bytes per second */ unsigned long new_ab_in_hz = DEFAULT_BUS_WIDTH * - ((2*geni_se_dev->cur_ab)*10000); + KHz(geni_se_dev->cur_ab); new_bus_bw = max(geni_se_dev->cur_ib, new_ab_in_hz) / DEFAULT_BUS_WIDTH; From 47c6dbc3fd84b5be484da92d392aeed659730b1e Mon Sep 17 00:00:00 2001 From: "Isaac J. Manjarres" Date: Fri, 13 Nov 2020 14:52:32 -0800 Subject: [PATCH 078/698] iommu/dma: Fix cache maintenance in iommu_dma_map_sg() iommu_dma_map_sg() attempts to perform cache maintenance with iommu_dma_sync_sg_for_device() prior to mapping the scatter gather list to an IOVA. iommu_dma_sync_sg_for_device() uses the DMA address in the scatter gather list structure to determine if the buffer is mapped as cached or uncached by invoking iommu_is_iova_coherent(). Since the buffer has not been mapped yet, the DMA address in the scatter gather list structure will be 0. If IOVA 0 is not mapped in the client's IOMMU page tables, then iommu_is_iova_coherent() will return false, and cache maintenance will be performed on the buffer, even for clients that are io-coherent, which is not correct, as no cache maintenance is required for io-coherent clients. Ensure cache maintenance happens only after the buffer has been mapped, so that iommu_dma_sync_sg_for_device() can correctly determine if cache maintenance is required. Change-Id: Ie1cec69077eaeada00b5a2709b6d1680afdaaeba Signed-off-by: Isaac J. Manjarres --- drivers/iommu/dma-iommu.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c index f9f68da841a1..c96e296c61b2 100644 --- a/drivers/iommu/dma-iommu.c +++ b/drivers/iommu/dma-iommu.c @@ -959,6 +959,7 @@ static int iommu_dma_map_sg(struct device *dev, struct scatterlist *sg, struct iommu_dma_cookie *cookie; struct iova_domain *iovad; int prot = dma_info_to_prot(dir, is_dma_coherent(dev, attrs), attrs); + int ret; dma_addr_t iova; size_t iova_len; @@ -968,9 +969,6 @@ static int iommu_dma_map_sg(struct device *dev, struct scatterlist *sg, cookie = domain->iova_cookie; iovad = &cookie->iovad; - if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC)) - iommu_dma_sync_sg_for_device(dev, sg, nents, dir); - iova_len = iommu_dma_prepare_map_sg(dev, iovad, sg, nents); iova = iommu_dma_alloc_iova(domain, iova_len, dma_get_mask(dev), dev); @@ -984,7 +982,12 @@ static int iommu_dma_map_sg(struct device *dev, struct scatterlist *sg, if (iommu_map_sg(domain, iova, sg, nents, prot) < iova_len) goto out_free_iova; - return iommu_dma_finalise_sg(dev, sg, nents, iova); + ret = iommu_dma_finalise_sg(dev, sg, nents, iova); + + if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC)) + iommu_dma_sync_sg_for_device(dev, sg, nents, dir); + + return ret; out_free_iova: iommu_dma_free_iova(cookie, iova, iova_len); From e991174e64cc9a07078d0a748e9bd7946e9ce159 Mon Sep 17 00:00:00 2001 From: Prakash Gupta Date: Thu, 12 Nov 2020 17:00:44 +0530 Subject: [PATCH 079/698] proc/meminfo: update offline region in Memtotal When memory block is logically offlined, it is still part of System RAM but is inactive, and can be made active or Onlined anytime. Take totalram snapshot to include offlined memory in Memtotal. This method avoids taking device_hotplug lock to meminfo. Fixes: dc00b6d99a46 ("proc/meminfo: include offlined region for mem total") Change-Id: I2b69444e6f066e1c1928278707616840308b00d0 Signed-off-by: Prakash Gupta --- drivers/soc/qcom/mem-offline.c | 26 ++++++++++++++++++++++++++ fs/proc/meminfo.c | 6 +++++- include/linux/memory.h | 4 ++++ 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/drivers/soc/qcom/mem-offline.c b/drivers/soc/qcom/mem-offline.c index fec183024481..9a674e68282c 100644 --- a/drivers/soc/qcom/mem-offline.c +++ b/drivers/soc/qcom/mem-offline.c @@ -45,6 +45,7 @@ static atomic_t target_migrate_pages = ATOMIC_INIT(0); static u32 offline_granule; static bool is_rpm_controller; static bool has_pend_offline_req; +static atomic_long_t totalram_pages_with_offline = ATOMIC_INIT(0); #define MODULE_CLASS_NAME "mem-offline" #define MIGRATE_TIMEOUT_SEC (20) @@ -100,6 +101,29 @@ static void fill_movable_zone_fn(struct work_struct *work); static DECLARE_WORK(fill_movable_zone_work, fill_movable_zone_fn); static DEFINE_MUTEX(page_migrate_lock); +unsigned long get_totalram_pages_count_inc_offlined(void) +{ + struct sysinfo i; + unsigned long totalram_with_offline; + + si_meminfo(&i); + totalram_with_offline = + (unsigned long)atomic_long_read(&totalram_pages_with_offline); + + if (i.totalram < totalram_with_offline) + i.totalram = totalram_with_offline; + + return i.totalram; +} + +static void update_totalram_snapshot(void) +{ + unsigned long totalram_with_offline; + + totalram_with_offline = get_totalram_pages_count_inc_offlined(); + atomic_long_set(&totalram_pages_with_offline, totalram_with_offline); +} + static void clear_pgtable_mapping(phys_addr_t start, phys_addr_t end) { unsigned long size = end - start; @@ -670,6 +694,7 @@ static int mem_event_callback(struct notifier_block *self, break; case MEM_ONLINE: + update_totalram_snapshot(); delay = ktime_ms_delta(ktime_get(), cur); record_stat(sec_nr, delay, MEMORY_ONLINE); cur = 0; @@ -677,6 +702,7 @@ static int mem_event_callback(struct notifier_block *self, (void *)sec_nr); break; case MEM_GOING_OFFLINE: + update_totalram_snapshot(); pr_debug("mem-offline: MEM_GOING_OFFLINE : start = 0x%llx end = 0x%llx\n", start_addr, end_addr); ++mem_info[(sec_nr - start_section_nr + MEMORY_OFFLINE * diff --git a/fs/proc/meminfo.c b/fs/proc/meminfo.c index 0b10af0be77f..c69d9153f0e1 100644 --- a/fs/proc/meminfo.c +++ b/fs/proc/meminfo.c @@ -78,7 +78,11 @@ static int meminfo_proc_show(struct seq_file *m, void *v) pages[lru] = global_node_page_state(NR_LRU_BASE + lru); available = si_mem_available(); - i.totalram += get_offlined_pages_count(); + +#ifdef CONFIG_QCOM_MEM_OFFLINE + i.totalram = get_totalram_pages_count_inc_offlined(); +#endif + sreclaimable = global_node_page_state(NR_SLAB_RECLAIMABLE); sunreclaim = global_node_page_state(NR_SLAB_UNRECLAIMABLE); diff --git a/include/linux/memory.h b/include/linux/memory.h index ebda8bf060a4..cdedbd7bfef2 100644 --- a/include/linux/memory.h +++ b/include/linux/memory.h @@ -39,6 +39,10 @@ int arch_get_memory_phys_device(unsigned long start_pfn); unsigned long memory_block_size_bytes(void); int set_memory_block_size_order(unsigned int order); +#ifdef CONFIG_QCOM_MEM_OFFLINE +unsigned long get_totalram_pages_count_inc_offlined(void); +#endif + /* These states are exposed to userspace as text strings in sysfs */ #define MEM_ONLINE (1<<0) /* exposed to userspace */ #define MEM_GOING_OFFLINE (1<<1) /* exposed to userspace */ From a374ed56925a9b3367c0ea0b40ac3195cab0849e Mon Sep 17 00:00:00 2001 From: Hareesh Gundu Date: Thu, 26 Nov 2020 01:59:20 +0530 Subject: [PATCH 080/698] msm: kgsl: Poll a6x crashdumper register memory for status Use a6x crashdumper register memory end location to know the crashdumper status completion. This will avoid AHB traffic while crashdumper was active in snapshot dumping and fixes the slave timeout issue. Change-Id: Ic24e75557297c6a1a3f2ad7893f4d8d308f9943c Signed-off-by: Hareesh Gundu --- drivers/gpu/msm/adreno_a6xx_snapshot.c | 52 +++++++++++++++++++------- 1 file changed, 39 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/msm/adreno_a6xx_snapshot.c b/drivers/gpu/msm/adreno_a6xx_snapshot.c index 058d01f3400e..753a90fa48e7 100644 --- a/drivers/gpu/msm/adreno_a6xx_snapshot.c +++ b/drivers/gpu/msm/adreno_a6xx_snapshot.c @@ -574,6 +574,7 @@ static struct a6xx_shader_block a6xx_shader_blocks[] = { static struct kgsl_memdesc *a6xx_capturescript; static struct kgsl_memdesc *a6xx_crashdump_registers; static bool crash_dump_valid; +static u32 *a6xx_cd_reg_end; static struct reg_list { const unsigned int *regs; @@ -1565,7 +1566,7 @@ static size_t a6xx_snapshot_sqe(struct kgsl_device *device, u8 *buf, static void _a6xx_do_crashdump(struct kgsl_device *device) { u32 val = 0; - int ret; + ktime_t timeout; crash_dump_valid = false; @@ -1580,9 +1581,6 @@ static void _a6xx_do_crashdump(struct kgsl_device *device) if (a6xx_is_smmu_stalled(device)) return; - memset(a6xx_crashdump_registers->hostptr, 0xaa, - a6xx_crashdump_registers->size); - /* Turn on APRIV for legacy targets so we can access the buffers */ if (!ADRENO_FEATURE(ADRENO_DEVICE(device), ADRENO_APRIV)) kgsl_regwrite(device, A6XX_CP_MISC_CNTL, 1); @@ -1593,20 +1591,29 @@ static void _a6xx_do_crashdump(struct kgsl_device *device) upper_32_bits(a6xx_capturescript->gpuaddr)); kgsl_regwrite(device, A6XX_CP_CRASH_DUMP_CNTL, 1); - /* wait 100 ms before starting the loop */ - schedule_timeout_interruptible(HZ/10); + timeout = ktime_add_ms(ktime_get(), CP_CRASH_DUMPER_TIMEOUT); - /* Read every 10ms for 900ms */ - ret = readl_poll_timeout(device->reg_virt + - (A6XX_CP_CRASH_DUMP_STATUS << 2), - val, val & 0x02, 10000, 900 * 1000); - if (ret) - kgsl_regread(device, A6XX_CP_CRASH_DUMP_STATUS, &val); + might_sleep(); + + for (;;) { + /* make sure we're reading the latest value */ + rmb(); + if ((*a6xx_cd_reg_end) != 0xaaaaaaaa) + break; + + if (ktime_compare(ktime_get(), timeout) > 0) + break; + + /* Wait 1msec to avoid unnecessary looping */ + usleep_range(100, 1000); + } + + kgsl_regread(device, A6XX_CP_CRASH_DUMP_STATUS, &val); if (!ADRENO_FEATURE(ADRENO_DEVICE(device), ADRENO_APRIV)) kgsl_regwrite(device, A6XX_CP_MISC_CNTL, 0); - if (ret) { + if (!(val & 0x2)) { dev_err(device->dev, "Crash dump timed out: 0x%X\n", val); return; } @@ -1901,6 +1908,10 @@ void a6xx_snapshot(struct adreno_device *adreno_dev, /* registers dumped through DBG AHB */ a6xx_snapshot_dbgahb_regs(device, snapshot); + + if (!a6xx_is_smmu_stalled(device)) + memset(a6xx_crashdump_registers->hostptr, 0xaa, + a6xx_crashdump_registers->size); } if (adreno_is_a660(adreno_dev)) { @@ -2209,6 +2220,11 @@ void a6xx_crashdump_init(struct adreno_device *adreno_dev) sizeof(unsigned int); } + /* 16 bytes (2 qwords) for last entry in CD script */ + script_size += 16; + /* Increment data size to store last entry in CD */ + data_size += sizeof(unsigned int); + /* Now allocate the script and data buffers */ /* The script buffers needs 2 extra qwords on the end */ @@ -2271,6 +2287,16 @@ void a6xx_crashdump_init(struct adreno_device *adreno_dev) ptr += _a6xx_crashdump_init_non_ctx_dbgahb(ptr, &offset); + /* Save CD register end pointer to check CD status completion */ + a6xx_cd_reg_end = a6xx_crashdump_registers->hostptr + offset; + + memset(a6xx_crashdump_registers->hostptr, 0xaa, + a6xx_crashdump_registers->size); + + /* Program the capturescript to read the last register entry */ + *ptr++ = a6xx_crashdump_registers->gpuaddr + offset; + *ptr++ = (((uint64_t) A6XX_CP_CRASH_DUMP_STATUS) << 44) | (uint64_t) 1; + *ptr++ = 0; *ptr++ = 0; } From f03a54bd13741c21c2afed43807ac775ffd2e7a2 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Tue, 1 Sep 2020 10:50:04 +0200 Subject: [PATCH 081/698] mmc: allow setting slot index via device tree alias As with GPIO, UART and others, allow specifying the device index via the aliases node in the device tree. On embedded devices, there is often a combination of removable (e.g. SD card) and non-removable MMC devices (e.g. eMMC). Therefore the index might change depending on * host of removable device * removable card present or not This makes it difficult to hardcode the root device, if it is on the non-removable device. E.g. if SD card is present eMMC will be mmcblk1, if SD card is not present at boot, eMMC will be mmcblk0. Alternative solutions like PARTUUIDs do not cover the case where multiple mmcblk devices contain the same image. This is a common issue on devices that can boot both from eMMC (for regular boot) and SD cards (as a temporary boot medium for development). When a firmware image is installed to eMMC after a test boot via SD card, there will be no reliable way to refer to a specific device using (PART)UUIDs oder LABELs. The demand for this feature has led to multiple attempts to implement it, dating back at least to 2012 (see https://www.spinics.net/lists/linux-mmc/msg26586.html for a previous discussion from 2014). All indices defined in the aliases node will be reserved for use by the respective MMC device, moving the indices of devices that don't have an alias up into the non-reserved range. If the aliases node is not found, the driver will act as before. This is a rebased and cleaned up version of https://www.spinics.net/lists/linux-mmc/msg26588.html . Change-Id: I88c11705c8b66022e67b38a64bbc91625357a4bc Based-on-patch-by: Sascha Hauer Link: https://lkml.org/lkml/2020/8/5/194 Signed-off-by: Matthias Schiffer Signed-off-by: Ram Prakash Gupta --- drivers/mmc/core/host.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c index d026652173e5..1adb358c67ba 100644 --- a/drivers/mmc/core/host.c +++ b/drivers/mmc/core/host.c @@ -464,6 +464,20 @@ int mmc_of_parse_voltage(struct device_node *np, u32 *mask) } EXPORT_SYMBOL(mmc_of_parse_voltage); +/** + * mmc_first_nonreserved_index() - get the first index that is not reserved + */ +static int mmc_first_nonreserved_index(void) +{ + int max; + + max = of_alias_get_highest_id("sdhc"); + if (max < 0) + return 0; + + return max + 1; +} + /** * mmc_alloc_host - initialise the per-host structure. * @extra: sizeof private data structure @@ -475,6 +489,7 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev) { int err; struct mmc_host *host; + int alias_id, min_idx, max_idx; host = kzalloc(sizeof(struct mmc_host) + extra, GFP_KERNEL); if (!host) @@ -483,7 +498,16 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev) /* scanning will be enabled when we're ready */ host->rescan_disable = 1; - err = ida_simple_get(&mmc_host_ida, 0, 0, GFP_KERNEL); + alias_id = of_alias_get_id(dev->of_node, "sdhc"); + if (alias_id >= 0) { + min_idx = alias_id; + max_idx = alias_id + 1; + } else { + min_idx = mmc_first_nonreserved_index(); + max_idx = 0; + } + + err = ida_simple_get(&mmc_host_ida, min_idx, max_idx, GFP_KERNEL); if (err < 0) { kfree(host); return NULL; From 307f53caaeb797196aac6923d86563e4ab3036ee Mon Sep 17 00:00:00 2001 From: Santosh Mardi Date: Mon, 23 Nov 2020 16:31:13 +0530 Subject: [PATCH 082/698] drivers: soc: qcom: rimps_memlat: update error checks set_event will return NULL if event_id is not valid, the caller is proceeding further without proper check for NULL. Update pmu event setup function to check pevent for NULL. From the RIMPS perspective, pmu counter IDs 0 and 1 correspond to 64bit cycle counter with ID 0 representing low 32 bit and ID 1 representing high 32bit, while the counter IDs from 2 to 7 correspond to remaining PMUs. At the time of storing pmu counter values to RIMPS shared memory, the function store_event_val() stores both low and high 32bit values of cycle counter when ID 0 is passed as argument to pmu index, hence no need to handle ID 1 separately. Update logic accordingly to drop check for ID 1. Change-Id: Idd345c825572710753f18306f565043347921216 Signed-off-by: Santosh Mardi --- drivers/soc/qcom/rimps_memlat.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/drivers/soc/qcom/rimps_memlat.c b/drivers/soc/qcom/rimps_memlat.c index 8cc14f4df437..957825e959ad 100644 --- a/drivers/soc/qcom/rimps_memlat.c +++ b/drivers/soc/qcom/rimps_memlat.c @@ -481,10 +481,14 @@ static struct perf_event *set_event(int event_id, unsigned int cpu, static int setup_common_pmu_events(struct memlat_cpu_grp *cpu_grp, cpumask_t *mask, bool cpu_online) { - struct perf_event_attr *attr = alloc_attr(); + struct perf_event_attr *attr; struct perf_event *pevent; unsigned int cpu; + attr = alloc_attr(); + if (!attr) + return -ENODEV; + for_each_cpu(cpu, mask) { struct pmu_map *pmu = to_common_pmu_map(cpu_grp, cpu); struct cpu_data *cpus_data = to_cpu_data(cpu_grp, cpu); @@ -494,7 +498,7 @@ static int setup_common_pmu_events(struct memlat_cpu_grp *cpu_grp, pevent = set_event(cpu_grp->common_ev_ids[INST_IDX], cpu, attr); - if (IS_ERR(pevent)) + if (!pevent || IS_ERR(pevent)) return -ENODEV; cpus_data->common_evs[INST_IDX] = pevent; @@ -502,7 +506,7 @@ static int setup_common_pmu_events(struct memlat_cpu_grp *cpu_grp, pmu[INST_IDX].hw_cntr_idx = pevent->hw.idx + 1; pevent = set_event(cpu_grp->common_ev_ids[CYC_IDX], cpu, attr); - if (IS_ERR(pevent)) { + if (!pevent || IS_ERR(pevent)) { perf_event_release_kernel( cpus_data->common_evs[INST_IDX]); return -ENODEV; @@ -514,7 +518,7 @@ static int setup_common_pmu_events(struct memlat_cpu_grp *cpu_grp, if (cpu_grp->common_ev_ids[STALL_IDX] != INVALID_PMU_EVENT_ID) { pevent = set_event(cpu_grp->common_ev_ids[STALL_IDX], cpu, attr); - if (IS_ERR(pevent)) { + if (!pevent || IS_ERR(pevent)) { perf_event_release_kernel( cpus_data->common_evs[INST_IDX]); perf_event_release_kernel( @@ -536,10 +540,14 @@ static int setup_common_pmu_events(struct memlat_cpu_grp *cpu_grp, static int setup_mon_pmu_events(struct memlat_mon *mon, cpumask_t *mask, bool cpu_online) { - struct perf_event_attr *attr = alloc_attr(); + struct perf_event_attr *attr; struct perf_event *pevent; unsigned int cpu; + attr = alloc_attr(); + if (!attr) + return -ENODEV; + for_each_cpu(cpu, mask) { struct pmu_map *pmu = to_mon_pmu_map(mon, cpu); struct mon_data *ev_data = to_mon_ev_data(mon, cpu); @@ -548,7 +556,7 @@ static int setup_mon_pmu_events(struct memlat_mon *mon, continue; pevent = set_event(mon->mon_ev_ids[MISS_IDX], cpu, attr); - if (IS_ERR(pevent)) + if (!pevent || IS_ERR(pevent)) return -ENODEV; ev_data->mon_evs[MISS_IDX] = pevent; @@ -558,7 +566,7 @@ static int setup_mon_pmu_events(struct memlat_mon *mon, if (mon->mon_ev_ids[L2WB_IDX] != INVALID_PMU_EVENT_ID) { pevent = set_event(mon->mon_ev_ids[L2WB_IDX], cpu, attr); - if (IS_ERR(pevent)) { + if (!pevent || IS_ERR(pevent)) { perf_event_release_kernel( ev_data->mon_evs[MISS_IDX]); return -ENODEV; @@ -576,7 +584,7 @@ static int setup_mon_pmu_events(struct memlat_mon *mon, pevent = set_event(mon->mon_ev_ids[L3_ACCESS_IDX], cpu, attr); - if (IS_ERR(pevent)) { + if (!pevent || IS_ERR(pevent)) { perf_event_release_kernel( ev_data->mon_evs[MISS_IDX]); if (ev_data->mon_evs[L2WB_IDX]) @@ -605,7 +613,7 @@ static inline void store_event_val(u64 val, u8 idx, u8 cpu) if (idx == 0) { writel_relaxed((val & (0xFFFFFFFF)), &base->ccntr_lo); writel_relaxed(((val >> 32) & (0xFFFFFFFF)), &base->ccntr_hi); - } else if (idx < MAX_PMU_CNTRS_RIMPS) { + } else if ((idx > 1) && (idx < MAX_PMU_CNTRS_RIMPS)) { writel_relaxed((val & (0xFFFFFFFF)), &base->evcntr[idx - 2]); } } From 6e4ea160ca32a2cd36d5fe091a6c9595f45b45dd Mon Sep 17 00:00:00 2001 From: Santosh Mardi Date: Mon, 23 Nov 2020 20:18:56 +0530 Subject: [PATCH 083/698] drivers: soc: qcom: rimps_log: remove unused character while printing Discard character printing in ipc log buf when get_next_logbuf() returns count value less than the size argument. Change-Id: I0ba388400c76c16da423a2ccb67d961ed31e87b4 Signed-off-by: Santosh Mardi --- drivers/soc/qcom/rimps_log.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/qcom/rimps_log.c b/drivers/soc/qcom/rimps_log.c index 50d3a53d970c..0721b77186d3 100644 --- a/drivers/soc/qcom/rimps_log.c +++ b/drivers/soc/qcom/rimps_log.c @@ -126,7 +126,7 @@ static void rimps_log_work(struct work_struct *work) } } else { ipc_log_string(info->ipc_log_ctxt, - "%s\n", src, c); + "%s\n", src); } buf_start += cnt; From c53229913a1056f51ecd02e4d4ddcad600ee1fb3 Mon Sep 17 00:00:00 2001 From: Santosh Mardi Date: Mon, 23 Nov 2020 20:53:29 +0530 Subject: [PATCH 084/698] PM / devfreq: export functions to allow freeing of pmu counters Memlat and compute governors are made immutable to avoid governor switch at run time as the devices using these governors are tightly coupled with hardware features. These governors allocate pmu counters to count various events used in the algorithm. These counters are allocated exclusively for algorithm's use. This leaves limited counters available for other uses in the system such as profiling in user space using perf tool. Add and export a function in devfreq memlat governor to remove immutable flag to allow governor switch, which in turn can free pmu counters. Similarly add and export a function in rimps_memlat driver to free pmu counters. The intended use of these functions is to be called by test modules to allow freeing of pmu counters at runtime. Change-Id: I243a3201368d5a82aeaf820e775cdc1aecdfea07 Signed-off-by: Santosh Mardi --- drivers/devfreq/governor_memlat.c | 10 ++++++++++ drivers/soc/qcom/rimps_memlat.c | 15 +++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/drivers/devfreq/governor_memlat.c b/drivers/devfreq/governor_memlat.c index 57640063c643..33ce6e2765ee 100644 --- a/drivers/devfreq/governor_memlat.c +++ b/drivers/devfreq/governor_memlat.c @@ -451,6 +451,16 @@ static struct devfreq_governor devfreq_gov_compute = { .event_handler = devfreq_memlat_ev_handler, }; +void memlat_set_immutable_flag(unsigned int flag) +{ + unsigned int *memlat_ptr = (unsigned int *)&devfreq_gov_memlat.immutable; + unsigned int *compute_ptr = (unsigned int *)&devfreq_gov_compute.immutable; + + *memlat_ptr = flag; + *compute_ptr = flag; +} +EXPORT_SYMBOL(memlat_set_immutable_flag); + #define NUM_COLS 2 static struct core_dev_map *init_core_dev_map(struct device *dev, struct device_node *of_node, diff --git a/drivers/soc/qcom/rimps_memlat.c b/drivers/soc/qcom/rimps_memlat.c index 957825e959ad..1c3de9aa69fd 100644 --- a/drivers/soc/qcom/rimps_memlat.c +++ b/drivers/soc/qcom/rimps_memlat.c @@ -807,6 +807,21 @@ static int memlat_event_cpu_hp_init(void) return ret; } +void rimps_force_free_pmu_events(unsigned int flag) +{ + unsigned int cpu; + + get_online_cpus(); + for_each_possible_cpu(cpu) { + if (flag) + memlat_event_hotplug_going_down(cpu); + else + memlat_event_hotplug_coming_up(cpu); + } + put_online_cpus(); +} +EXPORT_SYMBOL(rimps_force_free_pmu_events); + static int memlat_idle_notif(struct notifier_block *nb, unsigned long action, void *data) From 31d5274a191d730c899bb38d9a620db25b665745 Mon Sep 17 00:00:00 2001 From: Raghavendra Kakarla Date: Tue, 24 Nov 2020 23:45:57 +0530 Subject: [PATCH 085/698] drivers: soc: ddr_stats: Initialize the uninitialized variable This patch can initialize the uninitialized local variables. Change-Id: I3f37a25ddaa52979657396da81830fdc8f9c2332 Signed-off-by: Raghavendra Kakarla --- drivers/soc/qcom/ddr_stats.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/qcom/ddr_stats.c b/drivers/soc/qcom/ddr_stats.c index 95d22c94a2f2..d4f1a156ae67 100644 --- a/drivers/soc/qcom/ddr_stats.c +++ b/drivers/soc/qcom/ddr_stats.c @@ -69,7 +69,7 @@ static ssize_t ddr_stats_append_data_to_buf(char *buf, int length, int *count, { u32 cp_idx = 0; u32 name; - u64 duration; + u64 duration = 0; if (accumulated_duration) { duration = data->duration * 100; From f43d459594bfeb7072e98265d140422b3213b558 Mon Sep 17 00:00:00 2001 From: Prakash Gupta Date: Tue, 24 Nov 2020 20:13:19 +0530 Subject: [PATCH 086/698] iommu: arm-smmu: defer tlbi ops Defer TLBI ops when CONFIG_QCOM_IOMMU_QUIRK_TLBI is not enabled. Change-Id: I866b4211901f71fe054bbd9f465b4df5c7dac82c Signed-off-by: Prakash Gupta --- arch/arm64/configs/vendor/holi_QGKI.config | 1 + arch/arm64/configs/vendor/lahaina_QGKI.config | 1 + drivers/iommu/Kconfig | 4 ++ drivers/iommu/arm-smmu.c | 41 +++++++++++++++++++ drivers/iommu/arm-smmu.h | 1 + 5 files changed, 48 insertions(+) diff --git a/arch/arm64/configs/vendor/holi_QGKI.config b/arch/arm64/configs/vendor/holi_QGKI.config index 6da7df3b87e7..123933c96aa9 100644 --- a/arch/arm64/configs/vendor/holi_QGKI.config +++ b/arch/arm64/configs/vendor/holi_QGKI.config @@ -1,6 +1,7 @@ CONFIG_LOCALVERSION="-qgki" # CONFIG_TRIM_UNUSED_KSYMS is not set CONFIG_QCOM_IOMMU_IO_PGTABLE_QUIRKS=y +CONFIG_QCOM_IOMMU_QUIRK_TLBI=y CONFIG_QCOM_LAZY_MAPPING=y CONFIG_DEBUG_FS=y CONFIG_IOMMU_DYNAMIC_DOMAINS=y diff --git a/arch/arm64/configs/vendor/lahaina_QGKI.config b/arch/arm64/configs/vendor/lahaina_QGKI.config index c8a1efff3d68..5c1f32355e65 100644 --- a/arch/arm64/configs/vendor/lahaina_QGKI.config +++ b/arch/arm64/configs/vendor/lahaina_QGKI.config @@ -1,6 +1,7 @@ CONFIG_LOCALVERSION="-qgki" # CONFIG_TRIM_UNUSED_KSYMS is not set CONFIG_QCOM_IOMMU_IO_PGTABLE_QUIRKS=y +CONFIG_QCOM_IOMMU_QUIRK_TLBI=y CONFIG_QCOM_LAZY_MAPPING=y CONFIG_QCOM_SECURE_BUFFER=y CONFIG_DMABUF_DESTRUCTOR_SUPPORT=y diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig index a30f891a391e..f5e744ed890d 100644 --- a/drivers/iommu/Kconfig +++ b/drivers/iommu/Kconfig @@ -693,6 +693,10 @@ config IOMMU_TESTS endif # IOMMU_DEBUG +config QCOM_IOMMU_QUIRK_TLBI + bool "Qualcomm IOMMU Quirks for TLB invalidation" + depends on ARM_SMMU + config QCOM_IOMMU # Note: iommu drivers cannot (yet?) be built as modules bool "Qualcomm IOMMU Support" diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index fc6aa7448c3d..0ba526324673 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -970,6 +970,11 @@ static void arm_smmu_tlb_inv_walk(unsigned long iova, size_t size, struct arm_smmu_domain *smmu_domain = cookie; const struct arm_smmu_flush_ops *ops = smmu_domain->flush_ops; + if (!IS_ENABLED(CONFIG_QCOM_IOMMU_QUIRK_TLBI)){ + smmu_domain->defer_flush = true; + return; + } + ops->tlb_inv_range(iova, size, granule, false, cookie); ops->tlb_sync(cookie); } @@ -980,6 +985,11 @@ static void arm_smmu_tlb_inv_leaf(unsigned long iova, size_t size, struct arm_smmu_domain *smmu_domain = cookie; const struct arm_smmu_flush_ops *ops = smmu_domain->flush_ops; + if (!IS_ENABLED(CONFIG_QCOM_IOMMU_QUIRK_TLBI)){ + smmu_domain->defer_flush = true; + return; + } + ops->tlb_inv_range(iova, size, granule, true, cookie); ops->tlb_sync(cookie); } @@ -991,6 +1001,11 @@ static void arm_smmu_tlb_add_page(struct iommu_iotlb_gather *gather, struct arm_smmu_domain *smmu_domain = cookie; const struct arm_smmu_flush_ops *ops = smmu_domain->flush_ops; + if (!IS_ENABLED(CONFIG_QCOM_IOMMU_QUIRK_TLBI)){ + smmu_domain->defer_flush = true; + return; + } + ops->tlb_inv_range(iova, granule, granule, true, cookie); } @@ -3183,6 +3198,12 @@ static int arm_smmu_map(struct iommu_domain *domain, unsigned long iova, arm_smmu_rpm_get(smmu); spin_lock_irqsave(&smmu_domain->cb_lock, flags); ret = ops->map(ops, iova, paddr, size, prot); + + if (smmu_domain->defer_flush) { + smmu_domain->flush_ops->tlb.tlb_flush_all(smmu_domain); + smmu_domain->defer_flush = false; + } + spin_unlock_irqrestore(&smmu_domain->cb_lock, flags); arm_smmu_rpm_put(smmu); @@ -3197,6 +3218,10 @@ static int arm_smmu_map(struct iommu_domain *domain, unsigned long iova, list_splice_init(&nonsecure_pool, &smmu_domain->nonsecure_pool); ret = ops->map(ops, iova, paddr, size, prot); list_splice_init(&smmu_domain->nonsecure_pool, &nonsecure_pool); + if (smmu_domain->defer_flush) { + smmu_domain->flush_ops->tlb.tlb_flush_all(smmu_domain); + smmu_domain->defer_flush = false; + } spin_unlock_irqrestore(&smmu_domain->cb_lock, flags); arm_smmu_rpm_put(smmu); arm_smmu_release_prealloc_memory(smmu_domain, &nonsecure_pool); @@ -3256,6 +3281,12 @@ static size_t arm_smmu_unmap(struct iommu_domain *domain, unsigned long iova, arm_smmu_rpm_get(smmu); spin_lock_irqsave(&smmu_domain->cb_lock, flags); ret = ops->unmap(ops, iova, size, gather); + + if (smmu_domain->defer_flush) { + smmu_domain->flush_ops->tlb.tlb_flush_all(smmu_domain); + smmu_domain->defer_flush = false; + } + spin_unlock_irqrestore(&smmu_domain->cb_lock, flags); arm_smmu_rpm_put(smmu); @@ -3358,6 +3389,12 @@ static size_t arm_smmu_map_sg(struct iommu_domain *domain, unsigned long iova, spin_lock_irqsave(&smmu_domain->cb_lock, flags); ret = pgtbl_info->map_sg(ops, iova, sg_start, idx_end - idx_start, prot, &size); + + if (smmu_domain->defer_flush) { + smmu_domain->flush_ops->tlb.tlb_flush_all(smmu_domain); + smmu_domain->defer_flush = false; + } + spin_unlock_irqrestore(&smmu_domain->cb_lock, flags); if (ret == -ENOMEM) { @@ -3377,6 +3414,10 @@ static size_t arm_smmu_map_sg(struct iommu_domain *domain, unsigned long iova, &size); list_splice_init(&smmu_domain->nonsecure_pool, &nonsecure_pool); + if (smmu_domain->defer_flush) { + smmu_domain->flush_ops->tlb.tlb_flush_all(smmu_domain); + smmu_domain->defer_flush = false; + } spin_unlock_irqrestore(&smmu_domain->cb_lock, flags); arm_smmu_release_prealloc_memory(smmu_domain, &nonsecure_pool); diff --git a/drivers/iommu/arm-smmu.h b/drivers/iommu/arm-smmu.h index d8a0a1115238..4f8127b2ee45 100644 --- a/drivers/iommu/arm-smmu.h +++ b/drivers/iommu/arm-smmu.h @@ -492,6 +492,7 @@ struct arm_smmu_domain { struct list_head nonsecure_pool; struct iommu_debug_attachment *logger; struct msm_iommu_domain domain; + bool defer_flush; }; From e41d3d98829e6fc1272be085a71e01d119bfcb95 Mon Sep 17 00:00:00 2001 From: Niranjan Reddy Dumbala Date: Wed, 9 Dec 2020 23:34:16 +0530 Subject: [PATCH 087/698] Revert "iommu: arm-smmu: defer tlbi ops" This reverts commit f43d459594bfeb7072e98265d140422b3213b558. Change-Id: I8e920929bf7c60a10ca5732aebe9edbd1982c18d Signed-off-by: Niranjan Reddy Dumbala --- arch/arm64/configs/vendor/holi_QGKI.config | 1 - arch/arm64/configs/vendor/lahaina_QGKI.config | 1 - drivers/iommu/Kconfig | 4 -- drivers/iommu/arm-smmu.c | 41 ------------------- drivers/iommu/arm-smmu.h | 1 - 5 files changed, 48 deletions(-) diff --git a/arch/arm64/configs/vendor/holi_QGKI.config b/arch/arm64/configs/vendor/holi_QGKI.config index 123933c96aa9..6da7df3b87e7 100644 --- a/arch/arm64/configs/vendor/holi_QGKI.config +++ b/arch/arm64/configs/vendor/holi_QGKI.config @@ -1,7 +1,6 @@ CONFIG_LOCALVERSION="-qgki" # CONFIG_TRIM_UNUSED_KSYMS is not set CONFIG_QCOM_IOMMU_IO_PGTABLE_QUIRKS=y -CONFIG_QCOM_IOMMU_QUIRK_TLBI=y CONFIG_QCOM_LAZY_MAPPING=y CONFIG_DEBUG_FS=y CONFIG_IOMMU_DYNAMIC_DOMAINS=y diff --git a/arch/arm64/configs/vendor/lahaina_QGKI.config b/arch/arm64/configs/vendor/lahaina_QGKI.config index 5c1f32355e65..c8a1efff3d68 100644 --- a/arch/arm64/configs/vendor/lahaina_QGKI.config +++ b/arch/arm64/configs/vendor/lahaina_QGKI.config @@ -1,7 +1,6 @@ CONFIG_LOCALVERSION="-qgki" # CONFIG_TRIM_UNUSED_KSYMS is not set CONFIG_QCOM_IOMMU_IO_PGTABLE_QUIRKS=y -CONFIG_QCOM_IOMMU_QUIRK_TLBI=y CONFIG_QCOM_LAZY_MAPPING=y CONFIG_QCOM_SECURE_BUFFER=y CONFIG_DMABUF_DESTRUCTOR_SUPPORT=y diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig index f5e744ed890d..a30f891a391e 100644 --- a/drivers/iommu/Kconfig +++ b/drivers/iommu/Kconfig @@ -693,10 +693,6 @@ config IOMMU_TESTS endif # IOMMU_DEBUG -config QCOM_IOMMU_QUIRK_TLBI - bool "Qualcomm IOMMU Quirks for TLB invalidation" - depends on ARM_SMMU - config QCOM_IOMMU # Note: iommu drivers cannot (yet?) be built as modules bool "Qualcomm IOMMU Support" diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 0ba526324673..fc6aa7448c3d 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -970,11 +970,6 @@ static void arm_smmu_tlb_inv_walk(unsigned long iova, size_t size, struct arm_smmu_domain *smmu_domain = cookie; const struct arm_smmu_flush_ops *ops = smmu_domain->flush_ops; - if (!IS_ENABLED(CONFIG_QCOM_IOMMU_QUIRK_TLBI)){ - smmu_domain->defer_flush = true; - return; - } - ops->tlb_inv_range(iova, size, granule, false, cookie); ops->tlb_sync(cookie); } @@ -985,11 +980,6 @@ static void arm_smmu_tlb_inv_leaf(unsigned long iova, size_t size, struct arm_smmu_domain *smmu_domain = cookie; const struct arm_smmu_flush_ops *ops = smmu_domain->flush_ops; - if (!IS_ENABLED(CONFIG_QCOM_IOMMU_QUIRK_TLBI)){ - smmu_domain->defer_flush = true; - return; - } - ops->tlb_inv_range(iova, size, granule, true, cookie); ops->tlb_sync(cookie); } @@ -1001,11 +991,6 @@ static void arm_smmu_tlb_add_page(struct iommu_iotlb_gather *gather, struct arm_smmu_domain *smmu_domain = cookie; const struct arm_smmu_flush_ops *ops = smmu_domain->flush_ops; - if (!IS_ENABLED(CONFIG_QCOM_IOMMU_QUIRK_TLBI)){ - smmu_domain->defer_flush = true; - return; - } - ops->tlb_inv_range(iova, granule, granule, true, cookie); } @@ -3198,12 +3183,6 @@ static int arm_smmu_map(struct iommu_domain *domain, unsigned long iova, arm_smmu_rpm_get(smmu); spin_lock_irqsave(&smmu_domain->cb_lock, flags); ret = ops->map(ops, iova, paddr, size, prot); - - if (smmu_domain->defer_flush) { - smmu_domain->flush_ops->tlb.tlb_flush_all(smmu_domain); - smmu_domain->defer_flush = false; - } - spin_unlock_irqrestore(&smmu_domain->cb_lock, flags); arm_smmu_rpm_put(smmu); @@ -3218,10 +3197,6 @@ static int arm_smmu_map(struct iommu_domain *domain, unsigned long iova, list_splice_init(&nonsecure_pool, &smmu_domain->nonsecure_pool); ret = ops->map(ops, iova, paddr, size, prot); list_splice_init(&smmu_domain->nonsecure_pool, &nonsecure_pool); - if (smmu_domain->defer_flush) { - smmu_domain->flush_ops->tlb.tlb_flush_all(smmu_domain); - smmu_domain->defer_flush = false; - } spin_unlock_irqrestore(&smmu_domain->cb_lock, flags); arm_smmu_rpm_put(smmu); arm_smmu_release_prealloc_memory(smmu_domain, &nonsecure_pool); @@ -3281,12 +3256,6 @@ static size_t arm_smmu_unmap(struct iommu_domain *domain, unsigned long iova, arm_smmu_rpm_get(smmu); spin_lock_irqsave(&smmu_domain->cb_lock, flags); ret = ops->unmap(ops, iova, size, gather); - - if (smmu_domain->defer_flush) { - smmu_domain->flush_ops->tlb.tlb_flush_all(smmu_domain); - smmu_domain->defer_flush = false; - } - spin_unlock_irqrestore(&smmu_domain->cb_lock, flags); arm_smmu_rpm_put(smmu); @@ -3389,12 +3358,6 @@ static size_t arm_smmu_map_sg(struct iommu_domain *domain, unsigned long iova, spin_lock_irqsave(&smmu_domain->cb_lock, flags); ret = pgtbl_info->map_sg(ops, iova, sg_start, idx_end - idx_start, prot, &size); - - if (smmu_domain->defer_flush) { - smmu_domain->flush_ops->tlb.tlb_flush_all(smmu_domain); - smmu_domain->defer_flush = false; - } - spin_unlock_irqrestore(&smmu_domain->cb_lock, flags); if (ret == -ENOMEM) { @@ -3414,10 +3377,6 @@ static size_t arm_smmu_map_sg(struct iommu_domain *domain, unsigned long iova, &size); list_splice_init(&smmu_domain->nonsecure_pool, &nonsecure_pool); - if (smmu_domain->defer_flush) { - smmu_domain->flush_ops->tlb.tlb_flush_all(smmu_domain); - smmu_domain->defer_flush = false; - } spin_unlock_irqrestore(&smmu_domain->cb_lock, flags); arm_smmu_release_prealloc_memory(smmu_domain, &nonsecure_pool); diff --git a/drivers/iommu/arm-smmu.h b/drivers/iommu/arm-smmu.h index 4f8127b2ee45..d8a0a1115238 100644 --- a/drivers/iommu/arm-smmu.h +++ b/drivers/iommu/arm-smmu.h @@ -492,7 +492,6 @@ struct arm_smmu_domain { struct list_head nonsecure_pool; struct iommu_debug_attachment *logger; struct msm_iommu_domain domain; - bool defer_flush; }; From 857008ac690f161a63d46f467e3a7bae1214e73f Mon Sep 17 00:00:00 2001 From: Prakash Gupta Date: Tue, 24 Nov 2020 20:13:19 +0530 Subject: [PATCH 088/698] iommu: arm-smmu: defer tlbi invalidation With QCOM quirks, the invalidations are agrregated to reduce map/unmap time. In absenence of CONFIG_QCOM_IOMMU_TLBI_QUIRKS enabled, the map/unmap latency impact time critical usecases. Hence defer TLB invalidation when CONFIG_QCOM_IOMMU_TLBI_QUIRKS is not enabled. Change-Id: Idfd18b9e528804f2a7813685998b83a3f5e80843 Signed-off-by: Prakash Gupta --- arch/arm64/configs/vendor/holi_QGKI.config | 1 + arch/arm64/configs/vendor/lahaina_QGKI.config | 1 + drivers/iommu/Kconfig | 11 ++++++ drivers/iommu/arm-smmu.c | 35 +++++++++++++++++++ drivers/iommu/arm-smmu.h | 1 + 5 files changed, 49 insertions(+) diff --git a/arch/arm64/configs/vendor/holi_QGKI.config b/arch/arm64/configs/vendor/holi_QGKI.config index 6da7df3b87e7..d273e2cf696c 100644 --- a/arch/arm64/configs/vendor/holi_QGKI.config +++ b/arch/arm64/configs/vendor/holi_QGKI.config @@ -1,6 +1,7 @@ CONFIG_LOCALVERSION="-qgki" # CONFIG_TRIM_UNUSED_KSYMS is not set CONFIG_QCOM_IOMMU_IO_PGTABLE_QUIRKS=y +CONFIG_QCOM_IOMMU_TLBI_QUIRKS=y CONFIG_QCOM_LAZY_MAPPING=y CONFIG_DEBUG_FS=y CONFIG_IOMMU_DYNAMIC_DOMAINS=y diff --git a/arch/arm64/configs/vendor/lahaina_QGKI.config b/arch/arm64/configs/vendor/lahaina_QGKI.config index c8a1efff3d68..06a46fd0cb04 100644 --- a/arch/arm64/configs/vendor/lahaina_QGKI.config +++ b/arch/arm64/configs/vendor/lahaina_QGKI.config @@ -1,6 +1,7 @@ CONFIG_LOCALVERSION="-qgki" # CONFIG_TRIM_UNUSED_KSYMS is not set CONFIG_QCOM_IOMMU_IO_PGTABLE_QUIRKS=y +CONFIG_QCOM_IOMMU_TLBI_QUIRKS=y CONFIG_QCOM_LAZY_MAPPING=y CONFIG_QCOM_SECURE_BUFFER=y CONFIG_DMABUF_DESTRUCTOR_SUPPORT=y diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig index a30f891a391e..1908f570b3b8 100644 --- a/drivers/iommu/Kconfig +++ b/drivers/iommu/Kconfig @@ -693,6 +693,17 @@ config IOMMU_TESTS endif # IOMMU_DEBUG +config QCOM_IOMMU_TLBI_QUIRKS + bool "QCOM IOMMU Quirks for TLB invalidation" + depends on ARM_SMMU + depends on QGKI + help + Enables some quirks that are used when performing TLBI for faster + invalidation. The quirks that are supported deal with allowing + defer tlbi and perform tlbiasid at the end of unmap. + + If unsure, say N here. + config QCOM_IOMMU # Note: iommu drivers cannot (yet?) be built as modules bool "Qualcomm IOMMU Support" diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index fc6aa7448c3d..ebca72dec632 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -970,6 +970,11 @@ static void arm_smmu_tlb_inv_walk(unsigned long iova, size_t size, struct arm_smmu_domain *smmu_domain = cookie; const struct arm_smmu_flush_ops *ops = smmu_domain->flush_ops; + if (!IS_ENABLED(CONFIG_QCOM_IOMMU_TLBI_QUIRKS)) { + smmu_domain->defer_flush = true; + return; + } + ops->tlb_inv_range(iova, size, granule, false, cookie); ops->tlb_sync(cookie); } @@ -980,6 +985,11 @@ static void arm_smmu_tlb_inv_leaf(unsigned long iova, size_t size, struct arm_smmu_domain *smmu_domain = cookie; const struct arm_smmu_flush_ops *ops = smmu_domain->flush_ops; + if (!IS_ENABLED(CONFIG_QCOM_IOMMU_TLBI_QUIRKS)) { + smmu_domain->defer_flush = true; + return; + } + ops->tlb_inv_range(iova, size, granule, true, cookie); ops->tlb_sync(cookie); } @@ -991,6 +1001,11 @@ static void arm_smmu_tlb_add_page(struct iommu_iotlb_gather *gather, struct arm_smmu_domain *smmu_domain = cookie; const struct arm_smmu_flush_ops *ops = smmu_domain->flush_ops; + if (!IS_ENABLED(CONFIG_QCOM_IOMMU_TLBI_QUIRKS)) { + smmu_domain->defer_flush = true; + return; + } + ops->tlb_inv_range(iova, granule, granule, true, cookie); } @@ -1161,6 +1176,19 @@ static const struct arm_smmu_flush_ops arm_smmu_s2_tlb_ops_v1 = { .tlb_sync = arm_smmu_tlb_sync_vmid, }; +static void arm_smmu_deferred_flush(struct arm_smmu_domain *smmu_domain) +{ + /* + * This checks for deferred invalidations, and perform flush all. + * Deferred invalidations helps replace multiple invalidations with + * single flush + */ + if (smmu_domain->defer_flush) { + smmu_domain->flush_ops->tlb.tlb_flush_all(smmu_domain); + smmu_domain->defer_flush = false; + } +} + static void print_ctx_regs(struct arm_smmu_device *smmu, struct arm_smmu_cfg *cfg, unsigned int fsr) { @@ -3183,6 +3211,9 @@ static int arm_smmu_map(struct iommu_domain *domain, unsigned long iova, arm_smmu_rpm_get(smmu); spin_lock_irqsave(&smmu_domain->cb_lock, flags); ret = ops->map(ops, iova, paddr, size, prot); + + arm_smmu_deferred_flush(smmu_domain); + spin_unlock_irqrestore(&smmu_domain->cb_lock, flags); arm_smmu_rpm_put(smmu); @@ -3197,6 +3228,7 @@ static int arm_smmu_map(struct iommu_domain *domain, unsigned long iova, list_splice_init(&nonsecure_pool, &smmu_domain->nonsecure_pool); ret = ops->map(ops, iova, paddr, size, prot); list_splice_init(&smmu_domain->nonsecure_pool, &nonsecure_pool); + arm_smmu_deferred_flush(smmu_domain); spin_unlock_irqrestore(&smmu_domain->cb_lock, flags); arm_smmu_rpm_put(smmu); arm_smmu_release_prealloc_memory(smmu_domain, &nonsecure_pool); @@ -3256,6 +3288,7 @@ static size_t arm_smmu_unmap(struct iommu_domain *domain, unsigned long iova, arm_smmu_rpm_get(smmu); spin_lock_irqsave(&smmu_domain->cb_lock, flags); ret = ops->unmap(ops, iova, size, gather); + arm_smmu_deferred_flush(smmu_domain); spin_unlock_irqrestore(&smmu_domain->cb_lock, flags); arm_smmu_rpm_put(smmu); @@ -3358,6 +3391,7 @@ static size_t arm_smmu_map_sg(struct iommu_domain *domain, unsigned long iova, spin_lock_irqsave(&smmu_domain->cb_lock, flags); ret = pgtbl_info->map_sg(ops, iova, sg_start, idx_end - idx_start, prot, &size); + arm_smmu_deferred_flush(smmu_domain); spin_unlock_irqrestore(&smmu_domain->cb_lock, flags); if (ret == -ENOMEM) { @@ -3377,6 +3411,7 @@ static size_t arm_smmu_map_sg(struct iommu_domain *domain, unsigned long iova, &size); list_splice_init(&smmu_domain->nonsecure_pool, &nonsecure_pool); + arm_smmu_deferred_flush(smmu_domain); spin_unlock_irqrestore(&smmu_domain->cb_lock, flags); arm_smmu_release_prealloc_memory(smmu_domain, &nonsecure_pool); diff --git a/drivers/iommu/arm-smmu.h b/drivers/iommu/arm-smmu.h index d8a0a1115238..4f8127b2ee45 100644 --- a/drivers/iommu/arm-smmu.h +++ b/drivers/iommu/arm-smmu.h @@ -492,6 +492,7 @@ struct arm_smmu_domain { struct list_head nonsecure_pool; struct iommu_debug_attachment *logger; struct msm_iommu_domain domain; + bool defer_flush; }; From 82c7bee23d992538b565883bc8e63ca367a9e553 Mon Sep 17 00:00:00 2001 From: Tapas Dey Date: Tue, 24 Nov 2020 20:16:10 +0530 Subject: [PATCH 089/698] NFC: Fix possible NULL pointer dereference issue Due to possible NULL pointer dereference kw issues are seen. Modify code and add proper NULL check to avoid NULL pointer dereference. Change-Id: Ie9f19fa9ac57a108575c08bdc123313eea3df49c Signed-off-by: Tapas Dey --- drivers/nfc/qti/nfc_common.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/nfc/qti/nfc_common.c b/drivers/nfc/qti/nfc_common.c index 12a34d3c8dd2..9b593f8bd51d 100644 --- a/drivers/nfc/qti/nfc_common.c +++ b/drivers/nfc/qti/nfc_common.c @@ -369,10 +369,14 @@ void read_cold_reset_rsp(struct nfc_dev *nfc_dev, char *header) __func__); goto error; } - } else { + } else if (header) { /* For I3C driver, header is read by the worker thread */ memcpy(cold_reset_rsp, header, NCI_HDR_LEN); + + } else { + pr_err("%s: - invalid or NULL header\n", __func__); + goto error; } if ((cold_reset_rsp[0] != COLD_RESET_RSP_GID) From 96c35474416c0d898f2ec99990dfd0fd2cd4f0f7 Mon Sep 17 00:00:00 2001 From: Vinayak Menon Date: Wed, 2 Dec 2020 13:22:01 +0530 Subject: [PATCH 090/698] drivers: staging: ion: mark secure page private check_valid_vmid does not mark page private when releasing the page to secure pool. Do it. Change-Id: I258561421c520a7b8b50dbf9421bc0aea459dfee Fixes: cae595f476e4 ("ion: Check for valid vmids for msm system heap") Signed-off-by: Vinayak Menon --- drivers/staging/android/ion/heaps/ion_msm_system_heap.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/staging/android/ion/heaps/ion_msm_system_heap.c b/drivers/staging/android/ion/heaps/ion_msm_system_heap.c index b7c4d7b67a75..c2a751653b12 100644 --- a/drivers/staging/android/ion/heaps/ion_msm_system_heap.c +++ b/drivers/staging/android/ion/heaps/ion_msm_system_heap.c @@ -307,6 +307,7 @@ static bool check_valid_vmid(int dest_vmid, struct ion_msm_system_heap *sys_heap return false; } valid_vmids[dest_vmid] = true; + SetPagePrivate(page); ion_msm_page_pool_free(sys_heap->secure_pools[dest_vmid][order_ind], page); return true; From 585e167b41ca8e6a6bf8e5be342d7b0ecac7d069 Mon Sep 17 00:00:00 2001 From: Hareesh Gundu Date: Mon, 30 Nov 2020 13:29:52 +0530 Subject: [PATCH 091/698] msm: kgsl: Don't access addr_mode_cntl registers for holi through host Sometimes probably crashdump timeout scenarios accessing addr_mode_cntl registers through the host path resulting to slave timeout issue. Hence revert this commit 'fca32c53c237("msm: kgsl: Add addr_mode_cntl registers for legacy snapshot for holi gpu")'. Change-Id: I771d9aecad69dd03d7e2ab771aee164c1cdfeabd Signed-off-by: Hareesh Gundu --- drivers/gpu/msm/adreno_a6xx_snapshot.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/drivers/gpu/msm/adreno_a6xx_snapshot.c b/drivers/gpu/msm/adreno_a6xx_snapshot.c index 753a90fa48e7..3bba78d461d2 100644 --- a/drivers/gpu/msm/adreno_a6xx_snapshot.c +++ b/drivers/gpu/msm/adreno_a6xx_snapshot.c @@ -304,10 +304,6 @@ static const unsigned int a660_registers[] = { 0x0B00, 0x0B40, 0x0B80, 0x0B83, }; -static const unsigned int a619_holi_registers[] = { - /* HLSQ, SP, TPL1 */ - 0xAE00, 0xAE01, 0xBE04, 0xBE05, 0xB600, 0xB601, -}; /* * Set of registers to dump for A6XX before actually triggering crash dumper. * Registers in pairs - first value is the start offset, second @@ -1837,12 +1833,6 @@ void a6xx_snapshot(struct adreno_device *adreno_dev, snapshot, a6xx_snapshot_registers, &a6xx_reg_list[i]); } - if (adreno_is_a619_holi(adreno_dev) && !crash_dump_valid) { - adreno_snapshot_registers(device, snapshot, - a619_holi_registers, - ARRAY_SIZE(a619_holi_registers) / 2); - } - /* CP_SQE indexed registers */ kgsl_snapshot_indexed_registers(device, snapshot, A6XX_CP_SQE_STAT_ADDR, A6XX_CP_SQE_STAT_DATA, 0, 0x33); From 06fbf6e01eaa0d1480ae4a21fef62eac428e2212 Mon Sep 17 00:00:00 2001 From: Jeya R Date: Wed, 2 Dec 2020 10:25:15 +0530 Subject: [PATCH 092/698] msm: ADSPRPC: Handle Null pointer De-reference Retrieved tgid from current process instead of mapping for naming the minidump region. Change-Id: I598606577c63794f495c9ca92adc951c088046be Acked-by: Krishnaiah Tadakamalla Acked-by: Gururaj Chalgeri Signed-off-by: Jeya R --- drivers/char/adsprpc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c index f31e1441fd6d..940fb5c1cebb 100644 --- a/drivers/char/adsprpc.c +++ b/drivers/char/adsprpc.c @@ -1164,14 +1164,14 @@ static void fastrpc_mmap_free(struct fastrpc_mmap *map, uint32_t flags) return; } if (msm_minidump_enabled()) { - scnprintf(md_entry.name, sizeof(md_entry.name), "CMA_%d", fl->tgid); + scnprintf(md_entry.name, sizeof(md_entry.name), "CMA_%d", current->tgid); md_entry.virt_addr = map->va; md_entry.phys_addr = map->phys; md_entry.size = map->size; if (msm_minidump_remove_region(&md_entry) < 0) { ADSPRPC_ERR( "Failed to remove CMA from Minidump for tgid: %d, phys: 0x%llx, size: %zu\n", - fl->tgid, map->phys, map->size); + current->tgid, map->phys, map->size); } } trace_fastrpc_dma_free(-1, map->phys, map->size); From a9bef89466fa7874311665413e79488570de38cc Mon Sep 17 00:00:00 2001 From: Prudhvi Yarlagadda Date: Wed, 21 Oct 2020 22:47:31 +0530 Subject: [PATCH 093/698] serial: msm_geni_serial: Pull RFR before stop_rx for uart Pull the RFR line before doing stop_rx in uart driver. This is to prevent any rx data to come into the uart rx fifo when stop_rx is being executed. Remove the rx length zero check in handling dma rx to prevent race conditions with EOT and DMA_DONE interrupt bits. Issue scenarios could be that during baud rate change/ runtime suspend or any other place where stop_rx is used, there might be a race between rx data entering uart rx fifo and availability of dma buffers in uart driver. In this scenarios there will be interrupt storm with rx water mark interrupt. Change-Id: I92163c4997c1709269dce67a1d492533f710abfb Signed-off-by: Prudhvi Yarlagadda --- drivers/tty/serial/msm_geni_serial.c | 71 +++++++++++++++++++++------- 1 file changed, 55 insertions(+), 16 deletions(-) diff --git a/drivers/tty/serial/msm_geni_serial.c b/drivers/tty/serial/msm_geni_serial.c index 6d7e6fd35397..de9cef364dd2 100644 --- a/drivers/tty/serial/msm_geni_serial.c +++ b/drivers/tty/serial/msm_geni_serial.c @@ -101,6 +101,8 @@ #define UART_OVERSAMPLING (32) #define STALE_TIMEOUT (16) +#define STALE_COUNT (DEFAULT_BITS_PER_CHAR * STALE_TIMEOUT) +#define SEC_TO_USEC (1000000) #define DEFAULT_BITS_PER_CHAR (10) #define GENI_UART_NR_PORTS (6) #define GENI_UART_CONS_PORTS (1) @@ -1397,8 +1399,11 @@ static void msm_geni_serial_set_manual_flow(bool enable, SE_UART_MANUAL_RFR); /* Ensure that the manual flow off writes go through */ mb(); + uart_manual_rfr = geni_read_reg_nolog(port->uport.membase, + SE_UART_MANUAL_RFR); IPC_LOG_MSG(port->ipc_log_misc, - "%s: Manual Flow Disabled, HW Flow ON\n", __func__); + "%s: Manual Flow Disabled, HW Flow ON rfr = 0x%x\n", + __func__, uart_manual_rfr); } } @@ -1409,6 +1414,7 @@ static int stop_rx_sequencer(struct uart_port *uport) struct msm_geni_serial_port *port = GET_DEV_PORT(uport); unsigned long flags = 0; bool is_rx_active; + unsigned int stale_delay; IPC_LOG_MSG(port->ipc_log_misc, "%s\n", __func__); @@ -1421,9 +1427,18 @@ static int stop_rx_sequencer(struct uart_port *uport) return 0; } - port->s_cmd_done = false; - port->s_cmd = true; - reinit_completion(&port->s_cmd_timeout); + if (!uart_console(uport)) { + msm_geni_serial_set_manual_flow(false, port); + /* + * Wait for the stale timeout to happen if there + * is any data pending in the rx fifo. + * Have a safety factor of 2 to include the interrupt + * and system latencies. + */ + stale_delay = (STALE_COUNT * SEC_TO_USEC) / port->cur_baud; + stale_delay = (2 * stale_delay); + udelay(stale_delay); + } IPC_LOG_MSG(port->ipc_log_misc, "%s: Start 0x%x\n", __func__, geni_status); @@ -1432,6 +1447,11 @@ static int stop_rx_sequencer(struct uart_port *uport) * cancel command as this might be in an atomic context. */ is_irq_masked = msm_serial_try_disable_interrupts(uport); + + port->s_cmd_done = false; + port->s_cmd = true; + reinit_completion(&port->s_cmd_timeout); + geni_cancel_s_cmd(uport->membase); /* @@ -1494,6 +1514,9 @@ static int stop_rx_sequencer(struct uart_port *uport) port->s_cmd = false; exit_rx_seq: + if (!uart_console(uport)) + msm_geni_serial_set_manual_flow(true, port); + 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); @@ -1889,7 +1912,6 @@ static bool handle_tx_dma_xfer(u32 m_irq_status, struct uart_port *uport) static bool handle_rx_dma_xfer(u32 s_irq_status, struct uart_port *uport) { - u32 rx_dma_len; bool ret = false; bool drop_rx = false; struct msm_geni_serial_port *msm_port = GET_DEV_PORT(uport); @@ -1926,16 +1948,13 @@ static bool handle_rx_dma_xfer(u32 s_irq_status, struct uart_port *uport) dma_rx_status & RX_DMA_DONE) { msm_geni_serial_handle_dma_rx(uport, drop_rx); - rx_dma_len = - geni_read_reg_nolog(uport->membase, - SE_DMA_RX_LEN_IN); - if (rx_dma_len != 0) { + if (!(dma_rx_status & RX_GENI_CANCEL_IRQ)) { geni_se_rx_dma_start(uport->membase, DMA_RX_BUF_SIZE, &msm_port->rx_dma); } else { IPC_LOG_MSG(msm_port->ipc_log_misc, - "%s.stop dma Rx 0x%x\n", - __func__, dma_rx_status); + "%s. not mapping rx dma\n", + __func__); } } if (dma_rx_status & RX_SBE) { @@ -2174,7 +2193,7 @@ static int msm_geni_serial_port_setup(struct uart_port *uport) struct msm_geni_serial_port *msm_port = GET_DEV_PORT(uport); unsigned long cfg0, cfg1; dma_addr_t dma_address; - unsigned int rxstale = DEFAULT_BITS_PER_CHAR * STALE_TIMEOUT; + unsigned int rxstale = STALE_COUNT; set_rfr_wm(msm_port); geni_write_reg_nolog(rxstale, uport->membase, SE_UART_RX_STALE_CNT); @@ -2465,7 +2484,6 @@ static void msm_geni_serial_set_termios(struct uart_port *uport, __func__, ret); return; } - msm_geni_serial_set_manual_flow(false, port); } msm_geni_serial_stop_rx(uport); /* baud rate */ @@ -2512,9 +2530,6 @@ static void msm_geni_serial_set_termios(struct uart_port *uport, msm_geni_serial_termios_cfg(uport, termios); IPC_LOG_MSG(port->ipc_log_misc, "%s: baud %d\n", __func__, baud); exit_set_termios: - if (!uart_console(uport)) - msm_geni_serial_set_manual_flow(true, port); - msm_geni_serial_start_rx(uport); if (!uart_console(uport)) msm_geni_serial_power_off(uport); @@ -3197,6 +3212,23 @@ static int msm_geni_serial_remove(struct platform_device *pdev) return 0; } +static void msm_geni_serial_allow_rx(struct msm_geni_serial_port *port) +{ + u32 uart_manual_rfr; + + uart_manual_rfr = (UART_MANUAL_RFR_EN | UART_RFR_READY); + geni_write_reg_nolog(uart_manual_rfr, port->uport.membase, + SE_UART_MANUAL_RFR); + /* Ensure that the manual flow off writes go through */ + mb(); + uart_manual_rfr = geni_read_reg_nolog(port->uport.membase, + SE_UART_MANUAL_RFR); + IPC_LOG_MSG(port->ipc_log_misc, "%s(): rfr = 0x%x\n", + __func__, uart_manual_rfr); + + /* To give control of RFR back to HW */ + msm_geni_serial_set_manual_flow(true, port); +} #ifdef CONFIG_PM static int msm_geni_serial_runtime_suspend(struct device *dev) @@ -3226,6 +3258,13 @@ static int msm_geni_serial_runtime_suspend(struct device *dev) stop_tx_sequencer(&port->uport); disable_irq(port->uport.irq); + + /* + * Above stop_rx disabled the flow so we need to enable it here + * Make sure wake up interrupt is enabled before RFR is made low + */ + msm_geni_serial_allow_rx(port); + ret = se_geni_resources_off(&port->serial_rsc); if (ret) { dev_err(dev, "%s: Error ret %d\n", __func__, ret); From 5921d184a633bdac72028114e7ae587c8d678ce9 Mon Sep 17 00:00:00 2001 From: Prudhvi Yarlagadda Date: Wed, 25 Nov 2020 18:43:05 +0530 Subject: [PATCH 094/698] serial: msm_geni_serial: Correct start rx sequence Correct start_rx sequence to keep the dma buffers available before starting rx engine. This is needed to handle rx data which might come between starting of rx engine and having dma buffer available. Change-Id: I194890ba8f51d6a917d6b1682f6b21ca443ca38b Signed-off-by: Prudhvi Yarlagadda --- drivers/tty/serial/msm_geni_serial.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/tty/serial/msm_geni_serial.c b/drivers/tty/serial/msm_geni_serial.c index 6d7e6fd35397..e2d94c714226 100644 --- a/drivers/tty/serial/msm_geni_serial.c +++ b/drivers/tty/serial/msm_geni_serial.c @@ -1342,14 +1342,14 @@ static void start_rx_sequencer(struct uart_port *uport) msm_geni_serial_stop_rx(uport); } - /* Start RX with the RFR_OPEN to keep RFR in always ready state */ - msm_geni_serial_enable_interrupts(uport); - geni_setup_s_cmd(uport->membase, UART_START_READ, geni_se_param); - if (port->xfer_mode == SE_DMA) geni_se_rx_dma_start(uport->membase, DMA_RX_BUF_SIZE, &port->rx_dma); + /* Start RX with the RFR_OPEN to keep RFR in always ready state */ + geni_setup_s_cmd(uport->membase, UART_START_READ, geni_se_param); + msm_geni_serial_enable_interrupts(uport); + /* Ensure that the above writes go through */ mb(); geni_status = geni_read_reg_nolog(uport->membase, SE_GENI_STATUS); From b5b877e1a5afe29c1e52a9c4d416075bebb2b412 Mon Sep 17 00:00:00 2001 From: Prakash Gupta Date: Fri, 4 Dec 2020 00:20:32 +0530 Subject: [PATCH 095/698] iommu: arm-smmu: skip tlb flush during unmap With fragmented physical memory, mappings are generated of lower granule. This increases the unmap latency of large buffers. When not supporting demand paging in smmu, unmap can defer the invalidation till next map. This change aggregates invalidations across multiple unmaps till a new mapping is created on that context. The new mapping can be using an iova previously unmapped hence the stale TLB can cause issue. Hence invalidate the TLB during map. Change-Id: I1d64227ca075067a43075729ba26be684126d679 Signed-off-by: Prakash Gupta --- drivers/iommu/arm-smmu.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index ebca72dec632..aa609e0ec4e7 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -3288,7 +3288,6 @@ static size_t arm_smmu_unmap(struct iommu_domain *domain, unsigned long iova, arm_smmu_rpm_get(smmu); spin_lock_irqsave(&smmu_domain->cb_lock, flags); ret = ops->unmap(ops, iova, size, gather); - arm_smmu_deferred_flush(smmu_domain); spin_unlock_irqrestore(&smmu_domain->cb_lock, flags); arm_smmu_rpm_put(smmu); From fd72ed900f62e5b20d88b872f848d796a95fbad5 Mon Sep 17 00:00:00 2001 From: Prakash Gupta Date: Wed, 9 Dec 2020 22:43:19 +0530 Subject: [PATCH 096/698] ion: use correct section map size for LPAE Use correct section map size for LPAE. At present ion use CONFIG_IOMMU_IO_PGTABLE_ARMV7S to determine whether to use LPAE or short descriptor section size. This is insufficient. Check for CONFIG_64bit and CONFIG_LPAE as well to decide correct section size. Change-Id: If730d98da110ebb338f7f1affccaae28c0c58a9e Signed-off-by: Prakash Gupta --- drivers/staging/android/ion/heaps/ion_msm_system_heap.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/android/ion/heaps/ion_msm_system_heap.h b/drivers/staging/android/ion/heaps/ion_msm_system_heap.h index 4e1986ae8916..1afca71e213c 100644 --- a/drivers/staging/android/ion/heaps/ion_msm_system_heap.h +++ b/drivers/staging/android/ion/heaps/ion_msm_system_heap.h @@ -9,7 +9,7 @@ #define _ION_MSM_SYSTEM_HEAP_H #ifndef CONFIG_ALLOC_BUFFERS_IN_4K_CHUNKS -#if defined(CONFIG_IOMMU_IO_PGTABLE_ARMV7S) +#if defined(CONFIG_IOMMU_IO_PGTABLE_ARMV7S) && !defined(CONFIG_64BIT) && !defined(CONFIG_ARM_LPAE) static const unsigned int orders[] = {8, 4, 0}; #else static const unsigned int orders[] = {9, 4, 0}; From 3adaf5d918a21af89f24a08fb7054d938238f440 Mon Sep 17 00:00:00 2001 From: Chandana Kishori Chiluveru Date: Thu, 10 Dec 2020 20:25:56 +0530 Subject: [PATCH 097/698] Revert "serial: msm_geni_serial: Pull RFR before stop_rx for uart" This reverts commit 7cd5c82cbdb7851043f15028179f2e604eabed22. Change-Id: I8d0d8b933b2893fcff68fe9f43af08651a7d576a Signed-off-by: Chandana Kishori Chiluveru --- drivers/tty/serial/msm_geni_serial.c | 71 +++++++--------------------- 1 file changed, 16 insertions(+), 55 deletions(-) diff --git a/drivers/tty/serial/msm_geni_serial.c b/drivers/tty/serial/msm_geni_serial.c index 00f34c0cd901..e2d94c714226 100644 --- a/drivers/tty/serial/msm_geni_serial.c +++ b/drivers/tty/serial/msm_geni_serial.c @@ -101,8 +101,6 @@ #define UART_OVERSAMPLING (32) #define STALE_TIMEOUT (16) -#define STALE_COUNT (DEFAULT_BITS_PER_CHAR * STALE_TIMEOUT) -#define SEC_TO_USEC (1000000) #define DEFAULT_BITS_PER_CHAR (10) #define GENI_UART_NR_PORTS (6) #define GENI_UART_CONS_PORTS (1) @@ -1399,11 +1397,8 @@ static void msm_geni_serial_set_manual_flow(bool enable, SE_UART_MANUAL_RFR); /* Ensure that the manual flow off writes go through */ mb(); - uart_manual_rfr = geni_read_reg_nolog(port->uport.membase, - SE_UART_MANUAL_RFR); IPC_LOG_MSG(port->ipc_log_misc, - "%s: Manual Flow Disabled, HW Flow ON rfr = 0x%x\n", - __func__, uart_manual_rfr); + "%s: Manual Flow Disabled, HW Flow ON\n", __func__); } } @@ -1414,7 +1409,6 @@ static int stop_rx_sequencer(struct uart_port *uport) struct msm_geni_serial_port *port = GET_DEV_PORT(uport); unsigned long flags = 0; bool is_rx_active; - unsigned int stale_delay; IPC_LOG_MSG(port->ipc_log_misc, "%s\n", __func__); @@ -1427,18 +1421,9 @@ static int stop_rx_sequencer(struct uart_port *uport) return 0; } - if (!uart_console(uport)) { - msm_geni_serial_set_manual_flow(false, port); - /* - * Wait for the stale timeout to happen if there - * is any data pending in the rx fifo. - * Have a safety factor of 2 to include the interrupt - * and system latencies. - */ - stale_delay = (STALE_COUNT * SEC_TO_USEC) / port->cur_baud; - stale_delay = (2 * stale_delay); - udelay(stale_delay); - } + port->s_cmd_done = false; + port->s_cmd = true; + reinit_completion(&port->s_cmd_timeout); IPC_LOG_MSG(port->ipc_log_misc, "%s: Start 0x%x\n", __func__, geni_status); @@ -1447,11 +1432,6 @@ static int stop_rx_sequencer(struct uart_port *uport) * cancel command as this might be in an atomic context. */ is_irq_masked = msm_serial_try_disable_interrupts(uport); - - port->s_cmd_done = false; - port->s_cmd = true; - reinit_completion(&port->s_cmd_timeout); - geni_cancel_s_cmd(uport->membase); /* @@ -1514,9 +1494,6 @@ static int stop_rx_sequencer(struct uart_port *uport) port->s_cmd = false; exit_rx_seq: - if (!uart_console(uport)) - msm_geni_serial_set_manual_flow(true, port); - 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); @@ -1912,6 +1889,7 @@ static bool handle_tx_dma_xfer(u32 m_irq_status, struct uart_port *uport) static bool handle_rx_dma_xfer(u32 s_irq_status, struct uart_port *uport) { + u32 rx_dma_len; bool ret = false; bool drop_rx = false; struct msm_geni_serial_port *msm_port = GET_DEV_PORT(uport); @@ -1948,13 +1926,16 @@ static bool handle_rx_dma_xfer(u32 s_irq_status, struct uart_port *uport) dma_rx_status & RX_DMA_DONE) { msm_geni_serial_handle_dma_rx(uport, drop_rx); - if (!(dma_rx_status & RX_GENI_CANCEL_IRQ)) { + rx_dma_len = + geni_read_reg_nolog(uport->membase, + SE_DMA_RX_LEN_IN); + if (rx_dma_len != 0) { geni_se_rx_dma_start(uport->membase, DMA_RX_BUF_SIZE, &msm_port->rx_dma); } else { IPC_LOG_MSG(msm_port->ipc_log_misc, - "%s. not mapping rx dma\n", - __func__); + "%s.stop dma Rx 0x%x\n", + __func__, dma_rx_status); } } if (dma_rx_status & RX_SBE) { @@ -2193,7 +2174,7 @@ static int msm_geni_serial_port_setup(struct uart_port *uport) struct msm_geni_serial_port *msm_port = GET_DEV_PORT(uport); unsigned long cfg0, cfg1; dma_addr_t dma_address; - unsigned int rxstale = STALE_COUNT; + unsigned int rxstale = DEFAULT_BITS_PER_CHAR * STALE_TIMEOUT; set_rfr_wm(msm_port); geni_write_reg_nolog(rxstale, uport->membase, SE_UART_RX_STALE_CNT); @@ -2484,6 +2465,7 @@ static void msm_geni_serial_set_termios(struct uart_port *uport, __func__, ret); return; } + msm_geni_serial_set_manual_flow(false, port); } msm_geni_serial_stop_rx(uport); /* baud rate */ @@ -2530,6 +2512,9 @@ static void msm_geni_serial_set_termios(struct uart_port *uport, msm_geni_serial_termios_cfg(uport, termios); IPC_LOG_MSG(port->ipc_log_misc, "%s: baud %d\n", __func__, baud); exit_set_termios: + if (!uart_console(uport)) + msm_geni_serial_set_manual_flow(true, port); + msm_geni_serial_start_rx(uport); if (!uart_console(uport)) msm_geni_serial_power_off(uport); @@ -3212,23 +3197,6 @@ static int msm_geni_serial_remove(struct platform_device *pdev) return 0; } -static void msm_geni_serial_allow_rx(struct msm_geni_serial_port *port) -{ - u32 uart_manual_rfr; - - uart_manual_rfr = (UART_MANUAL_RFR_EN | UART_RFR_READY); - geni_write_reg_nolog(uart_manual_rfr, port->uport.membase, - SE_UART_MANUAL_RFR); - /* Ensure that the manual flow off writes go through */ - mb(); - uart_manual_rfr = geni_read_reg_nolog(port->uport.membase, - SE_UART_MANUAL_RFR); - IPC_LOG_MSG(port->ipc_log_misc, "%s(): rfr = 0x%x\n", - __func__, uart_manual_rfr); - - /* To give control of RFR back to HW */ - msm_geni_serial_set_manual_flow(true, port); -} #ifdef CONFIG_PM static int msm_geni_serial_runtime_suspend(struct device *dev) @@ -3258,13 +3226,6 @@ static int msm_geni_serial_runtime_suspend(struct device *dev) stop_tx_sequencer(&port->uport); disable_irq(port->uport.irq); - - /* - * Above stop_rx disabled the flow so we need to enable it here - * Make sure wake up interrupt is enabled before RFR is made low - */ - msm_geni_serial_allow_rx(port); - ret = se_geni_resources_off(&port->serial_rsc); if (ret) { dev_err(dev, "%s: Error ret %d\n", __func__, ret); From cde50e6cdf2f06ccc621bc405484203f683ffce0 Mon Sep 17 00:00:00 2001 From: Chandana Kishori Chiluveru Date: Thu, 10 Dec 2020 20:26:25 +0530 Subject: [PATCH 098/698] Revert "serial: msm_geni_serial: Don't queue the rx dma buffer in stop rx" This reverts commit 152e037894308445f891630f1f847ebfb3f2ccb6. Change-Id: I71de3c524ecbb79f88e531b0f2854dc051c68b80 Signed-off-by: Chandana Kishori Chiluveru --- drivers/tty/serial/msm_geni_serial.c | 45 +++++++--------------------- 1 file changed, 11 insertions(+), 34 deletions(-) diff --git a/drivers/tty/serial/msm_geni_serial.c b/drivers/tty/serial/msm_geni_serial.c index e2d94c714226..bce893cdf919 100644 --- a/drivers/tty/serial/msm_geni_serial.c +++ b/drivers/tty/serial/msm_geni_serial.c @@ -1402,13 +1402,12 @@ static void msm_geni_serial_set_manual_flow(bool enable, } } -static int stop_rx_sequencer(struct uart_port *uport) +static void stop_rx_sequencer(struct uart_port *uport) { unsigned int geni_status; bool timeout, is_irq_masked; struct msm_geni_serial_port *port = GET_DEV_PORT(uport); unsigned long flags = 0; - bool is_rx_active; IPC_LOG_MSG(port->ipc_log_misc, "%s\n", __func__); @@ -1418,7 +1417,7 @@ static int 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); - return 0; + return; } port->s_cmd_done = false; @@ -1441,6 +1440,8 @@ static int stop_rx_sequencer(struct uart_port *uport) mb(); timeout = geni_wait_for_cmd_done(uport, is_irq_masked); if (timeout) { + bool is_rx_active; + geni_status = geni_read_reg_nolog(uport->membase, SE_GENI_STATUS); /* @@ -1497,28 +1498,18 @@ exit_rx_seq: 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); - - is_rx_active = geni_status & S_GENI_CMD_ACTIVE; - if (is_rx_active) - return -EBUSY; - else - return 0; } static void msm_geni_serial_stop_rx(struct uart_port *uport) { struct msm_geni_serial_port *port = GET_DEV_PORT(uport); - int ret; if (!uart_console(uport) && device_pending_suspend(uport)) { IPC_LOG_MSG(port->ipc_log_misc, "%s.Device is suspended.\n", __func__); return; } - ret = stop_rx_sequencer(uport); - if (ret) - IPC_LOG_MSG(port->ipc_log_misc, "%s: stop rx failed %d\n", - __func__, ret); + stop_rx_sequencer(uport); } static int handle_rx_hs(struct uart_port *uport, @@ -1889,7 +1880,6 @@ static bool handle_tx_dma_xfer(u32 m_irq_status, struct uart_port *uport) static bool handle_rx_dma_xfer(u32 s_irq_status, struct uart_port *uport) { - u32 rx_dma_len; bool ret = false; bool drop_rx = false; struct msm_geni_serial_port *msm_port = GET_DEV_PORT(uport); @@ -1922,22 +1912,14 @@ static bool handle_rx_dma_xfer(u32 s_irq_status, struct uart_port *uport) uport->icount.brk); } - if (dma_rx_status & RX_EOT || - dma_rx_status & RX_DMA_DONE) { - msm_geni_serial_handle_dma_rx(uport, - drop_rx); - rx_dma_len = - geni_read_reg_nolog(uport->membase, - SE_DMA_RX_LEN_IN); - if (rx_dma_len != 0) { + if (dma_rx_status & RX_EOT || dma_rx_status & RX_DMA_DONE) { + msm_geni_serial_handle_dma_rx(uport, drop_rx); + if (!(dma_rx_status & RX_GENI_CANCEL_IRQ)) { geni_se_rx_dma_start(uport->membase, - DMA_RX_BUF_SIZE, &msm_port->rx_dma); - } else { - IPC_LOG_MSG(msm_port->ipc_log_misc, - "%s.stop dma Rx 0x%x\n", - __func__, dma_rx_status); + DMA_RX_BUF_SIZE, &msm_port->rx_dma); } } + if (dma_rx_status & RX_SBE) { IPC_LOG_MSG(msm_port->ipc_log_misc, "%s.Rx Errors. 0x%x\n", @@ -3214,12 +3196,7 @@ static int msm_geni_serial_runtime_suspend(struct device *dev) * Disable Interrupt * Resources off */ - ret = stop_rx_sequencer(&port->uport); - if (ret) { - IPC_LOG_MSG(port->ipc_log_pwr, "%s: stop rx failed %d\n", - __func__, ret); - return -EBUSY; - } + stop_rx_sequencer(&port->uport); geni_status = geni_read_reg_nolog(port->uport.membase, SE_GENI_STATUS); if ((geni_status & M_GENI_CMD_ACTIVE)) From fe353a4e28a93b026950c25e12237b130e5c34db Mon Sep 17 00:00:00 2001 From: Niranjan Reddy Dumbala Date: Tue, 22 Dec 2020 12:01:04 +0530 Subject: [PATCH 099/698] Revert "Revert "cnss-utils: Compile firmware service file independently"" This reverts commit edbd5eca7004dee142e1d46604e207fa33156a5d. Change-Id: Ia6a0d8e353952bf9d33d90409e366b755647cd7f Signed-off-by: Niranjan Reddy Dumbala --- drivers/net/wireless/cnss2/Kconfig | 3 +- drivers/net/wireless/cnss2/Makefile | 3 +- .../cnss2/wlan_firmware_service_v01.c | 4545 ----------------- .../cnss2/wlan_firmware_service_v01.h | 1203 ----- drivers/net/wireless/cnss_utils/Kconfig | 10 +- drivers/net/wireless/cnss_utils/Makefile | 1 + .../cnss_utils}/wlan_firmware_service_v01.c | 1302 +++-- .../cnss_utils}/wlan_firmware_service_v01.h | 27 +- drivers/soc/qcom/icnss2/Kconfig | 1 + drivers/soc/qcom/icnss2/Makefile | 3 +- 10 files changed, 849 insertions(+), 6249 deletions(-) delete mode 100644 drivers/net/wireless/cnss2/wlan_firmware_service_v01.c delete mode 100644 drivers/net/wireless/cnss2/wlan_firmware_service_v01.h rename drivers/{soc/qcom/icnss2 => net/wireless/cnss_utils}/wlan_firmware_service_v01.c (79%) rename drivers/{soc/qcom/icnss2 => net/wireless/cnss_utils}/wlan_firmware_service_v01.h (98%) diff --git a/drivers/net/wireless/cnss2/Kconfig b/drivers/net/wireless/cnss2/Kconfig index 406ef18e62a4..3d1c448edf47 100644 --- a/drivers/net/wireless/cnss2/Kconfig +++ b/drivers/net/wireless/cnss2/Kconfig @@ -20,6 +20,7 @@ config CNSS2_DEBUG config CNSS2_QMI bool "CNSS2 Platform Driver QMI support" + select CNSS_QMI_SVC depends on CNSS2 help CNSS2 platform driver uses QMI framework to communicate with WLAN @@ -85,4 +86,4 @@ config CNSS_QCA6490 This enables the changes from WLAN host driver that are specific to CNSS QCA6490 chipset. These changes are needed to support the new hardware architecture - for CNSS QCA6490 chipset. \ No newline at end of file + for CNSS QCA6490 chipset. diff --git a/drivers/net/wireless/cnss2/Makefile b/drivers/net/wireless/cnss2/Makefile index 023dd437adec..225622e76a68 100644 --- a/drivers/net/wireless/cnss2/Makefile +++ b/drivers/net/wireless/cnss2/Makefile @@ -2,10 +2,11 @@ obj-$(CONFIG_CNSS2) += cnss2.o +ccflags-y += -I$(srctree)/drivers/net/wireless/cnss_utils/ cnss2-y := main.o cnss2-y += bus.o cnss2-y += debug.o cnss2-y += pci.o cnss2-y += power.o cnss2-y += genl.o -cnss2-$(CONFIG_CNSS2_QMI) += qmi.o wlan_firmware_service_v01.o coexistence_service_v01.o ip_multimedia_subsystem_private_service_v01.o device_management_service_v01.o +cnss2-$(CONFIG_CNSS2_QMI) += qmi.o coexistence_service_v01.o ip_multimedia_subsystem_private_service_v01.o device_management_service_v01.o diff --git a/drivers/net/wireless/cnss2/wlan_firmware_service_v01.c b/drivers/net/wireless/cnss2/wlan_firmware_service_v01.c deleted file mode 100644 index 5caf7ffea1eb..000000000000 --- a/drivers/net/wireless/cnss2/wlan_firmware_service_v01.c +++ /dev/null @@ -1,4545 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. */ - -#include "wlan_firmware_service_v01.h" - -static struct qmi_elem_info wlfw_ce_tgt_pipe_cfg_s_v01_ei[] = { - { - .data_type = QMI_UNSIGNED_4_BYTE, - .elem_len = 1, - .elem_size = sizeof(u32), - .array_type = NO_ARRAY, - .tlv_type = 0, - .offset = offsetof(struct wlfw_ce_tgt_pipe_cfg_s_v01, - pipe_num), - }, - { - .data_type = QMI_SIGNED_4_BYTE_ENUM, - .elem_len = 1, - .elem_size = sizeof(enum wlfw_pipedir_enum_v01), - .array_type = NO_ARRAY, - .tlv_type = 0, - .offset = offsetof(struct wlfw_ce_tgt_pipe_cfg_s_v01, - pipe_dir), - }, - { - .data_type = QMI_UNSIGNED_4_BYTE, - .elem_len = 1, - .elem_size = sizeof(u32), - .array_type = NO_ARRAY, - .tlv_type = 0, - .offset = offsetof(struct wlfw_ce_tgt_pipe_cfg_s_v01, - nentries), - }, - { - .data_type = QMI_UNSIGNED_4_BYTE, - .elem_len = 1, - .elem_size = sizeof(u32), - .array_type = NO_ARRAY, - .tlv_type = 0, - .offset = offsetof(struct wlfw_ce_tgt_pipe_cfg_s_v01, - nbytes_max), - }, - { - .data_type = QMI_UNSIGNED_4_BYTE, - .elem_len = 1, - .elem_size = sizeof(u32), - .array_type = NO_ARRAY, - .tlv_type = 0, - .offset = offsetof(struct wlfw_ce_tgt_pipe_cfg_s_v01, - flags), - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -static struct qmi_elem_info wlfw_ce_svc_pipe_cfg_s_v01_ei[] = { - { - .data_type = QMI_UNSIGNED_4_BYTE, - .elem_len = 1, - .elem_size = sizeof(u32), - .array_type = NO_ARRAY, - .tlv_type = 0, - .offset = offsetof(struct wlfw_ce_svc_pipe_cfg_s_v01, - service_id), - }, - { - .data_type = QMI_SIGNED_4_BYTE_ENUM, - .elem_len = 1, - .elem_size = sizeof(enum wlfw_pipedir_enum_v01), - .array_type = NO_ARRAY, - .tlv_type = 0, - .offset = offsetof(struct wlfw_ce_svc_pipe_cfg_s_v01, - pipe_dir), - }, - { - .data_type = QMI_UNSIGNED_4_BYTE, - .elem_len = 1, - .elem_size = sizeof(u32), - .array_type = NO_ARRAY, - .tlv_type = 0, - .offset = offsetof(struct wlfw_ce_svc_pipe_cfg_s_v01, - pipe_num), - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -static struct qmi_elem_info wlfw_shadow_reg_cfg_s_v01_ei[] = { - { - .data_type = QMI_UNSIGNED_2_BYTE, - .elem_len = 1, - .elem_size = sizeof(u16), - .array_type = NO_ARRAY, - .tlv_type = 0, - .offset = offsetof(struct wlfw_shadow_reg_cfg_s_v01, - id), - }, - { - .data_type = QMI_UNSIGNED_2_BYTE, - .elem_len = 1, - .elem_size = sizeof(u16), - .array_type = NO_ARRAY, - .tlv_type = 0, - .offset = offsetof(struct wlfw_shadow_reg_cfg_s_v01, - offset), - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -static struct qmi_elem_info wlfw_shadow_reg_v2_cfg_s_v01_ei[] = { - { - .data_type = QMI_UNSIGNED_4_BYTE, - .elem_len = 1, - .elem_size = sizeof(u32), - .array_type = NO_ARRAY, - .tlv_type = 0, - .offset = offsetof(struct wlfw_shadow_reg_v2_cfg_s_v01, - addr), - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -static struct qmi_elem_info wlfw_rri_over_ddr_cfg_s_v01_ei[] = { - { - .data_type = QMI_UNSIGNED_4_BYTE, - .elem_len = 1, - .elem_size = sizeof(u32), - .array_type = NO_ARRAY, - .tlv_type = 0, - .offset = offsetof(struct wlfw_rri_over_ddr_cfg_s_v01, - base_addr_low), - }, - { - .data_type = QMI_UNSIGNED_4_BYTE, - .elem_len = 1, - .elem_size = sizeof(u32), - .array_type = NO_ARRAY, - .tlv_type = 0, - .offset = offsetof(struct wlfw_rri_over_ddr_cfg_s_v01, - base_addr_high), - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -static struct qmi_elem_info wlfw_msi_cfg_s_v01_ei[] = { - { - .data_type = QMI_UNSIGNED_2_BYTE, - .elem_len = 1, - .elem_size = sizeof(u16), - .array_type = NO_ARRAY, - .tlv_type = 0, - .offset = offsetof(struct wlfw_msi_cfg_s_v01, - ce_id), - }, - { - .data_type = QMI_UNSIGNED_2_BYTE, - .elem_len = 1, - .elem_size = sizeof(u16), - .array_type = NO_ARRAY, - .tlv_type = 0, - .offset = offsetof(struct wlfw_msi_cfg_s_v01, - msi_vector), - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -static struct qmi_elem_info wlfw_memory_region_info_s_v01_ei[] = { - { - .data_type = QMI_UNSIGNED_8_BYTE, - .elem_len = 1, - .elem_size = sizeof(u64), - .array_type = NO_ARRAY, - .tlv_type = 0, - .offset = offsetof(struct wlfw_memory_region_info_s_v01, - region_addr), - }, - { - .data_type = QMI_UNSIGNED_4_BYTE, - .elem_len = 1, - .elem_size = sizeof(u32), - .array_type = NO_ARRAY, - .tlv_type = 0, - .offset = offsetof(struct wlfw_memory_region_info_s_v01, - size), - }, - { - .data_type = QMI_UNSIGNED_1_BYTE, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0, - .offset = offsetof(struct wlfw_memory_region_info_s_v01, - secure_flag), - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -static struct qmi_elem_info wlfw_mem_cfg_s_v01_ei[] = { - { - .data_type = QMI_UNSIGNED_8_BYTE, - .elem_len = 1, - .elem_size = sizeof(u64), - .array_type = NO_ARRAY, - .tlv_type = 0, - .offset = offsetof(struct wlfw_mem_cfg_s_v01, - offset), - }, - { - .data_type = QMI_UNSIGNED_4_BYTE, - .elem_len = 1, - .elem_size = sizeof(u32), - .array_type = NO_ARRAY, - .tlv_type = 0, - .offset = offsetof(struct wlfw_mem_cfg_s_v01, - size), - }, - { - .data_type = QMI_UNSIGNED_1_BYTE, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0, - .offset = offsetof(struct wlfw_mem_cfg_s_v01, - secure_flag), - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -static struct qmi_elem_info wlfw_mem_seg_s_v01_ei[] = { - { - .data_type = QMI_UNSIGNED_4_BYTE, - .elem_len = 1, - .elem_size = sizeof(u32), - .array_type = NO_ARRAY, - .tlv_type = 0, - .offset = offsetof(struct wlfw_mem_seg_s_v01, - size), - }, - { - .data_type = QMI_SIGNED_4_BYTE_ENUM, - .elem_len = 1, - .elem_size = sizeof(enum wlfw_mem_type_enum_v01), - .array_type = NO_ARRAY, - .tlv_type = 0, - .offset = offsetof(struct wlfw_mem_seg_s_v01, - type), - }, - { - .data_type = QMI_DATA_LEN, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0, - .offset = offsetof(struct wlfw_mem_seg_s_v01, - mem_cfg_len), - }, - { - .data_type = QMI_STRUCT, - .elem_len = QMI_WLFW_MAX_NUM_MEM_CFG_V01, - .elem_size = sizeof(struct wlfw_mem_cfg_s_v01), - .array_type = VAR_LEN_ARRAY, - .tlv_type = 0, - .offset = offsetof(struct wlfw_mem_seg_s_v01, - mem_cfg), - .ei_array = wlfw_mem_cfg_s_v01_ei, - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -static struct qmi_elem_info wlfw_mem_seg_resp_s_v01_ei[] = { - { - .data_type = QMI_UNSIGNED_8_BYTE, - .elem_len = 1, - .elem_size = sizeof(u64), - .array_type = NO_ARRAY, - .tlv_type = 0, - .offset = offsetof(struct wlfw_mem_seg_resp_s_v01, - addr), - }, - { - .data_type = QMI_UNSIGNED_4_BYTE, - .elem_len = 1, - .elem_size = sizeof(u32), - .array_type = NO_ARRAY, - .tlv_type = 0, - .offset = offsetof(struct wlfw_mem_seg_resp_s_v01, - size), - }, - { - .data_type = QMI_SIGNED_4_BYTE_ENUM, - .elem_len = 1, - .elem_size = sizeof(enum wlfw_mem_type_enum_v01), - .array_type = NO_ARRAY, - .tlv_type = 0, - .offset = offsetof(struct wlfw_mem_seg_resp_s_v01, - type), - }, - { - .data_type = QMI_UNSIGNED_1_BYTE, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0, - .offset = offsetof(struct wlfw_mem_seg_resp_s_v01, - restore), - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -static struct qmi_elem_info wlfw_rf_chip_info_s_v01_ei[] = { - { - .data_type = QMI_UNSIGNED_4_BYTE, - .elem_len = 1, - .elem_size = sizeof(u32), - .array_type = NO_ARRAY, - .tlv_type = 0, - .offset = offsetof(struct wlfw_rf_chip_info_s_v01, - chip_id), - }, - { - .data_type = QMI_UNSIGNED_4_BYTE, - .elem_len = 1, - .elem_size = sizeof(u32), - .array_type = NO_ARRAY, - .tlv_type = 0, - .offset = offsetof(struct wlfw_rf_chip_info_s_v01, - chip_family), - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -static struct qmi_elem_info wlfw_rf_board_info_s_v01_ei[] = { - { - .data_type = QMI_UNSIGNED_4_BYTE, - .elem_len = 1, - .elem_size = sizeof(u32), - .array_type = NO_ARRAY, - .tlv_type = 0, - .offset = offsetof(struct wlfw_rf_board_info_s_v01, - board_id), - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -static struct qmi_elem_info wlfw_soc_info_s_v01_ei[] = { - { - .data_type = QMI_UNSIGNED_4_BYTE, - .elem_len = 1, - .elem_size = sizeof(u32), - .array_type = NO_ARRAY, - .tlv_type = 0, - .offset = offsetof(struct wlfw_soc_info_s_v01, - soc_id), - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -static struct qmi_elem_info wlfw_fw_version_info_s_v01_ei[] = { - { - .data_type = QMI_UNSIGNED_4_BYTE, - .elem_len = 1, - .elem_size = sizeof(u32), - .array_type = NO_ARRAY, - .tlv_type = 0, - .offset = offsetof(struct wlfw_fw_version_info_s_v01, - fw_version), - }, - { - .data_type = QMI_STRING, - .elem_len = QMI_WLFW_MAX_TIMESTAMP_LEN_V01 + 1, - .elem_size = sizeof(char), - .array_type = NO_ARRAY, - .tlv_type = 0, - .offset = offsetof(struct wlfw_fw_version_info_s_v01, - fw_build_timestamp), - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -static struct qmi_elem_info wlfw_host_ddr_range_s_v01_ei[] = { - { - .data_type = QMI_UNSIGNED_8_BYTE, - .elem_len = 1, - .elem_size = sizeof(u64), - .array_type = NO_ARRAY, - .tlv_type = 0, - .offset = offsetof(struct wlfw_host_ddr_range_s_v01, - start), - }, - { - .data_type = QMI_UNSIGNED_8_BYTE, - .elem_len = 1, - .elem_size = sizeof(u64), - .array_type = NO_ARRAY, - .tlv_type = 0, - .offset = offsetof(struct wlfw_host_ddr_range_s_v01, - size), - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, - fw_ready_enable_valid), - }, - { - .data_type = QMI_UNSIGNED_1_BYTE, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, - fw_ready_enable), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x11, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, - initiate_cal_download_enable_valid), - }, - { - .data_type = QMI_UNSIGNED_1_BYTE, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x11, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, - initiate_cal_download_enable), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x12, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, - initiate_cal_update_enable_valid), - }, - { - .data_type = QMI_UNSIGNED_1_BYTE, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x12, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, - initiate_cal_update_enable), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x13, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, - msa_ready_enable_valid), - }, - { - .data_type = QMI_UNSIGNED_1_BYTE, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x13, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, - msa_ready_enable), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x14, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, - pin_connect_result_enable_valid), - }, - { - .data_type = QMI_UNSIGNED_1_BYTE, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x14, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, - pin_connect_result_enable), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x15, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, - client_id_valid), - }, - { - .data_type = QMI_UNSIGNED_4_BYTE, - .elem_len = 1, - .elem_size = sizeof(u32), - .array_type = NO_ARRAY, - .tlv_type = 0x15, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, - client_id), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x16, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, - request_mem_enable_valid), - }, - { - .data_type = QMI_UNSIGNED_1_BYTE, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x16, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, - request_mem_enable), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x17, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, - fw_mem_ready_enable_valid), - }, - { - .data_type = QMI_UNSIGNED_1_BYTE, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x17, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, - fw_mem_ready_enable), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x18, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, - fw_init_done_enable_valid), - }, - { - .data_type = QMI_UNSIGNED_1_BYTE, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x18, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, - fw_init_done_enable), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x19, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, - rejuvenate_enable_valid), - }, - { - .data_type = QMI_UNSIGNED_4_BYTE, - .elem_len = 1, - .elem_size = sizeof(u32), - .array_type = NO_ARRAY, - .tlv_type = 0x19, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, - rejuvenate_enable), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x1A, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, - xo_cal_enable_valid), - }, - { - .data_type = QMI_UNSIGNED_1_BYTE, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x1A, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, - xo_cal_enable), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x1B, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, - cal_done_enable_valid), - }, - { - .data_type = QMI_UNSIGNED_1_BYTE, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x1B, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, - cal_done_enable), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x1C, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, - qdss_trace_req_mem_enable_valid), - }, - { - .data_type = QMI_UNSIGNED_1_BYTE, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x1C, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, - qdss_trace_req_mem_enable), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x1D, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, - qdss_trace_save_enable_valid), - }, - { - .data_type = QMI_UNSIGNED_1_BYTE, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x1D, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, - qdss_trace_save_enable), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x1E, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, - qdss_trace_free_enable_valid), - }, - { - .data_type = QMI_UNSIGNED_1_BYTE, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x1E, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, - qdss_trace_free_enable), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x1F, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, - respond_get_info_enable_valid), - }, - { - .data_type = QMI_UNSIGNED_1_BYTE, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x1F, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, - respond_get_info_enable), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x20, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, - m3_dump_upload_req_enable_valid), - }, - { - .data_type = QMI_UNSIGNED_1_BYTE, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x20, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, - m3_dump_upload_req_enable), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x21, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, - wfc_call_twt_config_enable_valid), - }, - { - .data_type = QMI_UNSIGNED_1_BYTE, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x21, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, - wfc_call_twt_config_enable), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x22, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, - qdss_mem_ready_enable_valid), - }, - { - .data_type = QMI_UNSIGNED_1_BYTE, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x22, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, - qdss_mem_ready_enable), - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_ind_register_resp_msg_v01_ei[] = { - { - .data_type = QMI_STRUCT, - .elem_len = 1, - .elem_size = sizeof(struct qmi_response_type_v01), - .array_type = NO_ARRAY, - .tlv_type = 0x02, - .offset = offsetof(struct - wlfw_ind_register_resp_msg_v01, - resp), - .ei_array = qmi_response_type_v01_ei, - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct - wlfw_ind_register_resp_msg_v01, - fw_status_valid), - }, - { - .data_type = QMI_UNSIGNED_8_BYTE, - .elem_len = 1, - .elem_size = sizeof(u64), - .array_type = NO_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct - wlfw_ind_register_resp_msg_v01, - fw_status), - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_fw_ready_ind_msg_v01_ei[] = { - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_msa_ready_ind_msg_v01_ei[] = { - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct wlfw_msa_ready_ind_msg_v01, - hang_data_addr_offset_valid), - }, - { - .data_type = QMI_UNSIGNED_4_BYTE, - .elem_len = 1, - .elem_size = sizeof(u32), - .array_type = NO_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct wlfw_msa_ready_ind_msg_v01, - hang_data_addr_offset), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x11, - .offset = offsetof(struct wlfw_msa_ready_ind_msg_v01, - hang_data_length_valid), - }, - { - .data_type = QMI_UNSIGNED_2_BYTE, - .elem_len = 1, - .elem_size = sizeof(u16), - .array_type = NO_ARRAY, - .tlv_type = 0x11, - .offset = offsetof(struct wlfw_msa_ready_ind_msg_v01, - hang_data_length), - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_pin_connect_result_ind_msg_v01_ei[] = { - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct - wlfw_pin_connect_result_ind_msg_v01, - pwr_pin_result_valid), - }, - { - .data_type = QMI_UNSIGNED_4_BYTE, - .elem_len = 1, - .elem_size = sizeof(u32), - .array_type = NO_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct - wlfw_pin_connect_result_ind_msg_v01, - pwr_pin_result), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x11, - .offset = offsetof(struct - wlfw_pin_connect_result_ind_msg_v01, - phy_io_pin_result_valid), - }, - { - .data_type = QMI_UNSIGNED_4_BYTE, - .elem_len = 1, - .elem_size = sizeof(u32), - .array_type = NO_ARRAY, - .tlv_type = 0x11, - .offset = offsetof(struct - wlfw_pin_connect_result_ind_msg_v01, - phy_io_pin_result), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x12, - .offset = offsetof(struct - wlfw_pin_connect_result_ind_msg_v01, - rf_pin_result_valid), - }, - { - .data_type = QMI_UNSIGNED_4_BYTE, - .elem_len = 1, - .elem_size = sizeof(u32), - .array_type = NO_ARRAY, - .tlv_type = 0x12, - .offset = offsetof(struct - wlfw_pin_connect_result_ind_msg_v01, - rf_pin_result), - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_wlan_mode_req_msg_v01_ei[] = { - { - .data_type = QMI_SIGNED_4_BYTE_ENUM, - .elem_len = 1, - .elem_size = sizeof(enum wlfw_driver_mode_enum_v01), - .array_type = NO_ARRAY, - .tlv_type = 0x01, - .offset = offsetof(struct wlfw_wlan_mode_req_msg_v01, - mode), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct wlfw_wlan_mode_req_msg_v01, - hw_debug_valid), - }, - { - .data_type = QMI_UNSIGNED_1_BYTE, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct wlfw_wlan_mode_req_msg_v01, - hw_debug), - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_wlan_mode_resp_msg_v01_ei[] = { - { - .data_type = QMI_STRUCT, - .elem_len = 1, - .elem_size = sizeof(struct qmi_response_type_v01), - .array_type = NO_ARRAY, - .tlv_type = 0x02, - .offset = offsetof(struct wlfw_wlan_mode_resp_msg_v01, - resp), - .ei_array = qmi_response_type_v01_ei, - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_wlan_cfg_req_msg_v01_ei[] = { - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, - host_version_valid), - }, - { - .data_type = QMI_STRING, - .elem_len = QMI_WLFW_MAX_STR_LEN_V01 + 1, - .elem_size = sizeof(char), - .array_type = NO_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, - host_version), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x11, - .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, - tgt_cfg_valid), - }, - { - .data_type = QMI_DATA_LEN, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x11, - .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, - tgt_cfg_len), - }, - { - .data_type = QMI_STRUCT, - .elem_len = QMI_WLFW_MAX_NUM_CE_V01, - .elem_size = sizeof(struct wlfw_ce_tgt_pipe_cfg_s_v01), - .array_type = VAR_LEN_ARRAY, - .tlv_type = 0x11, - .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, - tgt_cfg), - .ei_array = wlfw_ce_tgt_pipe_cfg_s_v01_ei, - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x12, - .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, - svc_cfg_valid), - }, - { - .data_type = QMI_DATA_LEN, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x12, - .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, - svc_cfg_len), - }, - { - .data_type = QMI_STRUCT, - .elem_len = QMI_WLFW_MAX_NUM_SVC_V01, - .elem_size = sizeof(struct wlfw_ce_svc_pipe_cfg_s_v01), - .array_type = VAR_LEN_ARRAY, - .tlv_type = 0x12, - .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, - svc_cfg), - .ei_array = wlfw_ce_svc_pipe_cfg_s_v01_ei, - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x13, - .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, - shadow_reg_valid), - }, - { - .data_type = QMI_DATA_LEN, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x13, - .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, - shadow_reg_len), - }, - { - .data_type = QMI_STRUCT, - .elem_len = QMI_WLFW_MAX_NUM_SHADOW_REG_V01, - .elem_size = sizeof(struct wlfw_shadow_reg_cfg_s_v01), - .array_type = VAR_LEN_ARRAY, - .tlv_type = 0x13, - .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, - shadow_reg), - .ei_array = wlfw_shadow_reg_cfg_s_v01_ei, - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x14, - .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, - shadow_reg_v2_valid), - }, - { - .data_type = QMI_DATA_LEN, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x14, - .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, - shadow_reg_v2_len), - }, - { - .data_type = QMI_STRUCT, - .elem_len = QMI_WLFW_MAX_NUM_SHADOW_REG_V2_V01, - .elem_size = sizeof(struct wlfw_shadow_reg_v2_cfg_s_v01), - .array_type = VAR_LEN_ARRAY, - .tlv_type = 0x14, - .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, - shadow_reg_v2), - .ei_array = wlfw_shadow_reg_v2_cfg_s_v01_ei, - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x15, - .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, - rri_over_ddr_cfg_valid), - }, - { - .data_type = QMI_STRUCT, - .elem_len = 1, - .elem_size = sizeof(struct wlfw_rri_over_ddr_cfg_s_v01), - .array_type = NO_ARRAY, - .tlv_type = 0x15, - .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, - rri_over_ddr_cfg), - .ei_array = wlfw_rri_over_ddr_cfg_s_v01_ei, - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x16, - .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, - msi_cfg_valid), - }, - { - .data_type = QMI_DATA_LEN, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x16, - .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, - msi_cfg_len), - }, - { - .data_type = QMI_STRUCT, - .elem_len = QMI_WLFW_MAX_NUM_CE_V01, - .elem_size = sizeof(struct wlfw_msi_cfg_s_v01), - .array_type = VAR_LEN_ARRAY, - .tlv_type = 0x16, - .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, - msi_cfg), - .ei_array = wlfw_msi_cfg_s_v01_ei, - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_wlan_cfg_resp_msg_v01_ei[] = { - { - .data_type = QMI_STRUCT, - .elem_len = 1, - .elem_size = sizeof(struct qmi_response_type_v01), - .array_type = NO_ARRAY, - .tlv_type = 0x02, - .offset = offsetof(struct wlfw_wlan_cfg_resp_msg_v01, - resp), - .ei_array = qmi_response_type_v01_ei, - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_cap_req_msg_v01_ei[] = { - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[] = { - { - .data_type = QMI_STRUCT, - .elem_len = 1, - .elem_size = sizeof(struct qmi_response_type_v01), - .array_type = NO_ARRAY, - .tlv_type = 0x02, - .offset = offsetof(struct wlfw_cap_resp_msg_v01, - resp), - .ei_array = qmi_response_type_v01_ei, - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct wlfw_cap_resp_msg_v01, - chip_info_valid), - }, - { - .data_type = QMI_STRUCT, - .elem_len = 1, - .elem_size = sizeof(struct wlfw_rf_chip_info_s_v01), - .array_type = NO_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct wlfw_cap_resp_msg_v01, - chip_info), - .ei_array = wlfw_rf_chip_info_s_v01_ei, - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x11, - .offset = offsetof(struct wlfw_cap_resp_msg_v01, - board_info_valid), - }, - { - .data_type = QMI_STRUCT, - .elem_len = 1, - .elem_size = sizeof(struct wlfw_rf_board_info_s_v01), - .array_type = NO_ARRAY, - .tlv_type = 0x11, - .offset = offsetof(struct wlfw_cap_resp_msg_v01, - board_info), - .ei_array = wlfw_rf_board_info_s_v01_ei, - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x12, - .offset = offsetof(struct wlfw_cap_resp_msg_v01, - soc_info_valid), - }, - { - .data_type = QMI_STRUCT, - .elem_len = 1, - .elem_size = sizeof(struct wlfw_soc_info_s_v01), - .array_type = NO_ARRAY, - .tlv_type = 0x12, - .offset = offsetof(struct wlfw_cap_resp_msg_v01, - soc_info), - .ei_array = wlfw_soc_info_s_v01_ei, - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x13, - .offset = offsetof(struct wlfw_cap_resp_msg_v01, - fw_version_info_valid), - }, - { - .data_type = QMI_STRUCT, - .elem_len = 1, - .elem_size = sizeof(struct wlfw_fw_version_info_s_v01), - .array_type = NO_ARRAY, - .tlv_type = 0x13, - .offset = offsetof(struct wlfw_cap_resp_msg_v01, - fw_version_info), - .ei_array = wlfw_fw_version_info_s_v01_ei, - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x14, - .offset = offsetof(struct wlfw_cap_resp_msg_v01, - fw_build_id_valid), - }, - { - .data_type = QMI_STRING, - .elem_len = QMI_WLFW_MAX_BUILD_ID_LEN_V01 + 1, - .elem_size = sizeof(char), - .array_type = NO_ARRAY, - .tlv_type = 0x14, - .offset = offsetof(struct wlfw_cap_resp_msg_v01, - fw_build_id), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x15, - .offset = offsetof(struct wlfw_cap_resp_msg_v01, - num_macs_valid), - }, - { - .data_type = QMI_UNSIGNED_1_BYTE, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x15, - .offset = offsetof(struct wlfw_cap_resp_msg_v01, - num_macs), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x16, - .offset = offsetof(struct wlfw_cap_resp_msg_v01, - voltage_mv_valid), - }, - { - .data_type = QMI_UNSIGNED_4_BYTE, - .elem_len = 1, - .elem_size = sizeof(u32), - .array_type = NO_ARRAY, - .tlv_type = 0x16, - .offset = offsetof(struct wlfw_cap_resp_msg_v01, - voltage_mv), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x17, - .offset = offsetof(struct wlfw_cap_resp_msg_v01, - time_freq_hz_valid), - }, - { - .data_type = QMI_UNSIGNED_4_BYTE, - .elem_len = 1, - .elem_size = sizeof(u32), - .array_type = NO_ARRAY, - .tlv_type = 0x17, - .offset = offsetof(struct wlfw_cap_resp_msg_v01, - time_freq_hz), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x18, - .offset = offsetof(struct wlfw_cap_resp_msg_v01, - otp_version_valid), - }, - { - .data_type = QMI_UNSIGNED_4_BYTE, - .elem_len = 1, - .elem_size = sizeof(u32), - .array_type = NO_ARRAY, - .tlv_type = 0x18, - .offset = offsetof(struct wlfw_cap_resp_msg_v01, - otp_version), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x19, - .offset = offsetof(struct wlfw_cap_resp_msg_v01, - eeprom_caldata_read_timeout_valid), - }, - { - .data_type = QMI_UNSIGNED_4_BYTE, - .elem_len = 1, - .elem_size = sizeof(u32), - .array_type = NO_ARRAY, - .tlv_type = 0x19, - .offset = offsetof(struct wlfw_cap_resp_msg_v01, - eeprom_caldata_read_timeout), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x1A, - .offset = offsetof(struct wlfw_cap_resp_msg_v01, - fw_caps_valid), - }, - { - .data_type = QMI_UNSIGNED_8_BYTE, - .elem_len = 1, - .elem_size = sizeof(u64), - .array_type = NO_ARRAY, - .tlv_type = 0x1A, - .offset = offsetof(struct wlfw_cap_resp_msg_v01, - fw_caps), - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_bdf_download_req_msg_v01_ei[] = { - { - .data_type = QMI_UNSIGNED_1_BYTE, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x01, - .offset = offsetof(struct wlfw_bdf_download_req_msg_v01, - valid), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct wlfw_bdf_download_req_msg_v01, - file_id_valid), - }, - { - .data_type = QMI_SIGNED_4_BYTE_ENUM, - .elem_len = 1, - .elem_size = sizeof(enum wlfw_cal_temp_id_enum_v01), - .array_type = NO_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct wlfw_bdf_download_req_msg_v01, - file_id), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x11, - .offset = offsetof(struct wlfw_bdf_download_req_msg_v01, - total_size_valid), - }, - { - .data_type = QMI_UNSIGNED_4_BYTE, - .elem_len = 1, - .elem_size = sizeof(u32), - .array_type = NO_ARRAY, - .tlv_type = 0x11, - .offset = offsetof(struct wlfw_bdf_download_req_msg_v01, - total_size), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x12, - .offset = offsetof(struct wlfw_bdf_download_req_msg_v01, - seg_id_valid), - }, - { - .data_type = QMI_UNSIGNED_4_BYTE, - .elem_len = 1, - .elem_size = sizeof(u32), - .array_type = NO_ARRAY, - .tlv_type = 0x12, - .offset = offsetof(struct wlfw_bdf_download_req_msg_v01, - seg_id), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x13, - .offset = offsetof(struct wlfw_bdf_download_req_msg_v01, - data_valid), - }, - { - .data_type = QMI_DATA_LEN, - .elem_len = 1, - .elem_size = sizeof(u16), - .array_type = NO_ARRAY, - .tlv_type = 0x13, - .offset = offsetof(struct wlfw_bdf_download_req_msg_v01, - data_len), - }, - { - .data_type = QMI_UNSIGNED_1_BYTE, - .elem_len = QMI_WLFW_MAX_DATA_SIZE_V01, - .elem_size = sizeof(u8), - .array_type = VAR_LEN_ARRAY, - .tlv_type = 0x13, - .offset = offsetof(struct wlfw_bdf_download_req_msg_v01, - data), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x14, - .offset = offsetof(struct wlfw_bdf_download_req_msg_v01, - end_valid), - }, - { - .data_type = QMI_UNSIGNED_1_BYTE, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x14, - .offset = offsetof(struct wlfw_bdf_download_req_msg_v01, - end), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x15, - .offset = offsetof(struct wlfw_bdf_download_req_msg_v01, - bdf_type_valid), - }, - { - .data_type = QMI_UNSIGNED_1_BYTE, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x15, - .offset = offsetof(struct wlfw_bdf_download_req_msg_v01, - bdf_type), - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_bdf_download_resp_msg_v01_ei[] = { - { - .data_type = QMI_STRUCT, - .elem_len = 1, - .elem_size = sizeof(struct qmi_response_type_v01), - .array_type = NO_ARRAY, - .tlv_type = 0x02, - .offset = offsetof(struct - wlfw_bdf_download_resp_msg_v01, - resp), - .ei_array = qmi_response_type_v01_ei, - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct - wlfw_bdf_download_resp_msg_v01, - host_bdf_data_valid), - }, - { - .data_type = QMI_UNSIGNED_8_BYTE, - .elem_len = 1, - .elem_size = sizeof(u64), - .array_type = NO_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct - wlfw_bdf_download_resp_msg_v01, - host_bdf_data), - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_cal_report_req_msg_v01_ei[] = { - { - .data_type = QMI_DATA_LEN, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x01, - .offset = offsetof(struct wlfw_cal_report_req_msg_v01, - meta_data_len), - }, - { - .data_type = QMI_SIGNED_4_BYTE_ENUM, - .elem_len = QMI_WLFW_MAX_NUM_CAL_V01, - .elem_size = sizeof(enum wlfw_cal_temp_id_enum_v01), - .array_type = VAR_LEN_ARRAY, - .tlv_type = 0x01, - .offset = offsetof(struct wlfw_cal_report_req_msg_v01, - meta_data), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct wlfw_cal_report_req_msg_v01, - xo_cal_data_valid), - }, - { - .data_type = QMI_UNSIGNED_1_BYTE, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct wlfw_cal_report_req_msg_v01, - xo_cal_data), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x11, - .offset = offsetof(struct wlfw_cal_report_req_msg_v01, - cal_remove_supported_valid), - }, - { - .data_type = QMI_UNSIGNED_1_BYTE, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x11, - .offset = offsetof(struct wlfw_cal_report_req_msg_v01, - cal_remove_supported), - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_cal_report_resp_msg_v01_ei[] = { - { - .data_type = QMI_STRUCT, - .elem_len = 1, - .elem_size = sizeof(struct qmi_response_type_v01), - .array_type = NO_ARRAY, - .tlv_type = 0x02, - .offset = offsetof(struct wlfw_cal_report_resp_msg_v01, - resp), - .ei_array = qmi_response_type_v01_ei, - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_initiate_cal_download_ind_msg_v01_ei[] = { - { - .data_type = QMI_SIGNED_4_BYTE_ENUM, - .elem_len = 1, - .elem_size = sizeof(enum wlfw_cal_temp_id_enum_v01), - .array_type = NO_ARRAY, - .tlv_type = 0x01, - .offset = offsetof(struct - wlfw_initiate_cal_download_ind_msg_v01, - cal_id), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct - wlfw_initiate_cal_download_ind_msg_v01, - total_size_valid), - }, - { - .data_type = QMI_UNSIGNED_4_BYTE, - .elem_len = 1, - .elem_size = sizeof(u32), - .array_type = NO_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct - wlfw_initiate_cal_download_ind_msg_v01, - total_size), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x11, - .offset = offsetof(struct - wlfw_initiate_cal_download_ind_msg_v01, - cal_data_location_valid), - }, - { - .data_type = QMI_UNSIGNED_4_BYTE, - .elem_len = 1, - .elem_size = sizeof(u32), - .array_type = NO_ARRAY, - .tlv_type = 0x11, - .offset = offsetof(struct - wlfw_initiate_cal_download_ind_msg_v01, - cal_data_location), - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_cal_download_req_msg_v01_ei[] = { - { - .data_type = QMI_UNSIGNED_1_BYTE, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x01, - .offset = offsetof(struct wlfw_cal_download_req_msg_v01, - valid), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct wlfw_cal_download_req_msg_v01, - file_id_valid), - }, - { - .data_type = QMI_SIGNED_4_BYTE_ENUM, - .elem_len = 1, - .elem_size = sizeof(enum wlfw_cal_temp_id_enum_v01), - .array_type = NO_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct wlfw_cal_download_req_msg_v01, - file_id), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x11, - .offset = offsetof(struct wlfw_cal_download_req_msg_v01, - total_size_valid), - }, - { - .data_type = QMI_UNSIGNED_4_BYTE, - .elem_len = 1, - .elem_size = sizeof(u32), - .array_type = NO_ARRAY, - .tlv_type = 0x11, - .offset = offsetof(struct wlfw_cal_download_req_msg_v01, - total_size), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x12, - .offset = offsetof(struct wlfw_cal_download_req_msg_v01, - seg_id_valid), - }, - { - .data_type = QMI_UNSIGNED_4_BYTE, - .elem_len = 1, - .elem_size = sizeof(u32), - .array_type = NO_ARRAY, - .tlv_type = 0x12, - .offset = offsetof(struct wlfw_cal_download_req_msg_v01, - seg_id), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x13, - .offset = offsetof(struct wlfw_cal_download_req_msg_v01, - data_valid), - }, - { - .data_type = QMI_DATA_LEN, - .elem_len = 1, - .elem_size = sizeof(u16), - .array_type = NO_ARRAY, - .tlv_type = 0x13, - .offset = offsetof(struct wlfw_cal_download_req_msg_v01, - data_len), - }, - { - .data_type = QMI_UNSIGNED_1_BYTE, - .elem_len = QMI_WLFW_MAX_DATA_SIZE_V01, - .elem_size = sizeof(u8), - .array_type = VAR_LEN_ARRAY, - .tlv_type = 0x13, - .offset = offsetof(struct wlfw_cal_download_req_msg_v01, - data), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x14, - .offset = offsetof(struct wlfw_cal_download_req_msg_v01, - end_valid), - }, - { - .data_type = QMI_UNSIGNED_1_BYTE, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x14, - .offset = offsetof(struct wlfw_cal_download_req_msg_v01, - end), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x15, - .offset = offsetof(struct wlfw_cal_download_req_msg_v01, - cal_data_location_valid), - }, - { - .data_type = QMI_UNSIGNED_4_BYTE, - .elem_len = 1, - .elem_size = sizeof(u32), - .array_type = NO_ARRAY, - .tlv_type = 0x15, - .offset = offsetof(struct wlfw_cal_download_req_msg_v01, - cal_data_location), - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_cal_download_resp_msg_v01_ei[] = { - { - .data_type = QMI_STRUCT, - .elem_len = 1, - .elem_size = sizeof(struct qmi_response_type_v01), - .array_type = NO_ARRAY, - .tlv_type = 0x02, - .offset = offsetof(struct - wlfw_cal_download_resp_msg_v01, - resp), - .ei_array = qmi_response_type_v01_ei, - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_initiate_cal_update_ind_msg_v01_ei[] = { - { - .data_type = QMI_SIGNED_4_BYTE_ENUM, - .elem_len = 1, - .elem_size = sizeof(enum wlfw_cal_temp_id_enum_v01), - .array_type = NO_ARRAY, - .tlv_type = 0x01, - .offset = offsetof(struct - wlfw_initiate_cal_update_ind_msg_v01, - cal_id), - }, - { - .data_type = QMI_UNSIGNED_4_BYTE, - .elem_len = 1, - .elem_size = sizeof(u32), - .array_type = NO_ARRAY, - .tlv_type = 0x02, - .offset = offsetof(struct - wlfw_initiate_cal_update_ind_msg_v01, - total_size), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct - wlfw_initiate_cal_update_ind_msg_v01, - cal_data_location_valid), - }, - { - .data_type = QMI_UNSIGNED_4_BYTE, - .elem_len = 1, - .elem_size = sizeof(u32), - .array_type = NO_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct - wlfw_initiate_cal_update_ind_msg_v01, - cal_data_location), - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_cal_update_req_msg_v01_ei[] = { - { - .data_type = QMI_SIGNED_4_BYTE_ENUM, - .elem_len = 1, - .elem_size = sizeof(enum wlfw_cal_temp_id_enum_v01), - .array_type = NO_ARRAY, - .tlv_type = 0x01, - .offset = offsetof(struct wlfw_cal_update_req_msg_v01, - cal_id), - }, - { - .data_type = QMI_UNSIGNED_4_BYTE, - .elem_len = 1, - .elem_size = sizeof(u32), - .array_type = NO_ARRAY, - .tlv_type = 0x02, - .offset = offsetof(struct wlfw_cal_update_req_msg_v01, - seg_id), - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_cal_update_resp_msg_v01_ei[] = { - { - .data_type = QMI_STRUCT, - .elem_len = 1, - .elem_size = sizeof(struct qmi_response_type_v01), - .array_type = NO_ARRAY, - .tlv_type = 0x02, - .offset = offsetof(struct wlfw_cal_update_resp_msg_v01, - resp), - .ei_array = qmi_response_type_v01_ei, - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct wlfw_cal_update_resp_msg_v01, - file_id_valid), - }, - { - .data_type = QMI_SIGNED_4_BYTE_ENUM, - .elem_len = 1, - .elem_size = sizeof(enum wlfw_cal_temp_id_enum_v01), - .array_type = NO_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct wlfw_cal_update_resp_msg_v01, - file_id), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x11, - .offset = offsetof(struct wlfw_cal_update_resp_msg_v01, - total_size_valid), - }, - { - .data_type = QMI_UNSIGNED_4_BYTE, - .elem_len = 1, - .elem_size = sizeof(u32), - .array_type = NO_ARRAY, - .tlv_type = 0x11, - .offset = offsetof(struct wlfw_cal_update_resp_msg_v01, - total_size), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x12, - .offset = offsetof(struct wlfw_cal_update_resp_msg_v01, - seg_id_valid), - }, - { - .data_type = QMI_UNSIGNED_4_BYTE, - .elem_len = 1, - .elem_size = sizeof(u32), - .array_type = NO_ARRAY, - .tlv_type = 0x12, - .offset = offsetof(struct wlfw_cal_update_resp_msg_v01, - seg_id), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x13, - .offset = offsetof(struct wlfw_cal_update_resp_msg_v01, - data_valid), - }, - { - .data_type = QMI_DATA_LEN, - .elem_len = 1, - .elem_size = sizeof(u16), - .array_type = NO_ARRAY, - .tlv_type = 0x13, - .offset = offsetof(struct wlfw_cal_update_resp_msg_v01, - data_len), - }, - { - .data_type = QMI_UNSIGNED_1_BYTE, - .elem_len = QMI_WLFW_MAX_DATA_SIZE_V01, - .elem_size = sizeof(u8), - .array_type = VAR_LEN_ARRAY, - .tlv_type = 0x13, - .offset = offsetof(struct wlfw_cal_update_resp_msg_v01, - data), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x14, - .offset = offsetof(struct wlfw_cal_update_resp_msg_v01, - end_valid), - }, - { - .data_type = QMI_UNSIGNED_1_BYTE, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x14, - .offset = offsetof(struct wlfw_cal_update_resp_msg_v01, - end), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x15, - .offset = offsetof(struct wlfw_cal_update_resp_msg_v01, - cal_data_location_valid), - }, - { - .data_type = QMI_UNSIGNED_4_BYTE, - .elem_len = 1, - .elem_size = sizeof(u32), - .array_type = NO_ARRAY, - .tlv_type = 0x15, - .offset = offsetof(struct wlfw_cal_update_resp_msg_v01, - cal_data_location), - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_msa_info_req_msg_v01_ei[] = { - { - .data_type = QMI_UNSIGNED_8_BYTE, - .elem_len = 1, - .elem_size = sizeof(u64), - .array_type = NO_ARRAY, - .tlv_type = 0x01, - .offset = offsetof(struct wlfw_msa_info_req_msg_v01, - msa_addr), - }, - { - .data_type = QMI_UNSIGNED_4_BYTE, - .elem_len = 1, - .elem_size = sizeof(u32), - .array_type = NO_ARRAY, - .tlv_type = 0x02, - .offset = offsetof(struct wlfw_msa_info_req_msg_v01, - size), - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_msa_info_resp_msg_v01_ei[] = { - { - .data_type = QMI_STRUCT, - .elem_len = 1, - .elem_size = sizeof(struct qmi_response_type_v01), - .array_type = NO_ARRAY, - .tlv_type = 0x02, - .offset = offsetof(struct wlfw_msa_info_resp_msg_v01, - resp), - .ei_array = qmi_response_type_v01_ei, - }, - { - .data_type = QMI_DATA_LEN, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x03, - .offset = offsetof(struct wlfw_msa_info_resp_msg_v01, - mem_region_info_len), - }, - { - .data_type = QMI_STRUCT, - .elem_len = QMI_WLFW_MAX_NUM_MEMORY_REGIONS_V01, - .elem_size = sizeof(struct wlfw_memory_region_info_s_v01), - .array_type = VAR_LEN_ARRAY, - .tlv_type = 0x03, - .offset = offsetof(struct wlfw_msa_info_resp_msg_v01, - mem_region_info), - .ei_array = wlfw_memory_region_info_s_v01_ei, - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_msa_ready_req_msg_v01_ei[] = { - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_msa_ready_resp_msg_v01_ei[] = { - { - .data_type = QMI_STRUCT, - .elem_len = 1, - .elem_size = sizeof(struct qmi_response_type_v01), - .array_type = NO_ARRAY, - .tlv_type = 0x02, - .offset = offsetof(struct wlfw_msa_ready_resp_msg_v01, - resp), - .ei_array = qmi_response_type_v01_ei, - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_ini_req_msg_v01_ei[] = { - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct wlfw_ini_req_msg_v01, - enablefwlog_valid), - }, - { - .data_type = QMI_UNSIGNED_1_BYTE, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct wlfw_ini_req_msg_v01, - enablefwlog), - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_ini_resp_msg_v01_ei[] = { - { - .data_type = QMI_STRUCT, - .elem_len = 1, - .elem_size = sizeof(struct qmi_response_type_v01), - .array_type = NO_ARRAY, - .tlv_type = 0x02, - .offset = offsetof(struct wlfw_ini_resp_msg_v01, - resp), - .ei_array = qmi_response_type_v01_ei, - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_athdiag_read_req_msg_v01_ei[] = { - { - .data_type = QMI_UNSIGNED_4_BYTE, - .elem_len = 1, - .elem_size = sizeof(u32), - .array_type = NO_ARRAY, - .tlv_type = 0x01, - .offset = offsetof(struct wlfw_athdiag_read_req_msg_v01, - offset), - }, - { - .data_type = QMI_UNSIGNED_4_BYTE, - .elem_len = 1, - .elem_size = sizeof(u32), - .array_type = NO_ARRAY, - .tlv_type = 0x02, - .offset = offsetof(struct wlfw_athdiag_read_req_msg_v01, - mem_type), - }, - { - .data_type = QMI_UNSIGNED_4_BYTE, - .elem_len = 1, - .elem_size = sizeof(u32), - .array_type = NO_ARRAY, - .tlv_type = 0x03, - .offset = offsetof(struct wlfw_athdiag_read_req_msg_v01, - data_len), - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_athdiag_read_resp_msg_v01_ei[] = { - { - .data_type = QMI_STRUCT, - .elem_len = 1, - .elem_size = sizeof(struct qmi_response_type_v01), - .array_type = NO_ARRAY, - .tlv_type = 0x02, - .offset = offsetof(struct - wlfw_athdiag_read_resp_msg_v01, - resp), - .ei_array = qmi_response_type_v01_ei, - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct - wlfw_athdiag_read_resp_msg_v01, - data_valid), - }, - { - .data_type = QMI_DATA_LEN, - .elem_len = 1, - .elem_size = sizeof(u16), - .array_type = NO_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct - wlfw_athdiag_read_resp_msg_v01, - data_len), - }, - { - .data_type = QMI_UNSIGNED_1_BYTE, - .elem_len = QMI_WLFW_MAX_ATHDIAG_DATA_SIZE_V01, - .elem_size = sizeof(u8), - .array_type = VAR_LEN_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct - wlfw_athdiag_read_resp_msg_v01, - data), - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_athdiag_write_req_msg_v01_ei[] = { - { - .data_type = QMI_UNSIGNED_4_BYTE, - .elem_len = 1, - .elem_size = sizeof(u32), - .array_type = NO_ARRAY, - .tlv_type = 0x01, - .offset = offsetof(struct - wlfw_athdiag_write_req_msg_v01, - offset), - }, - { - .data_type = QMI_UNSIGNED_4_BYTE, - .elem_len = 1, - .elem_size = sizeof(u32), - .array_type = NO_ARRAY, - .tlv_type = 0x02, - .offset = offsetof(struct - wlfw_athdiag_write_req_msg_v01, - mem_type), - }, - { - .data_type = QMI_DATA_LEN, - .elem_len = 1, - .elem_size = sizeof(u16), - .array_type = NO_ARRAY, - .tlv_type = 0x03, - .offset = offsetof(struct - wlfw_athdiag_write_req_msg_v01, - data_len), - }, - { - .data_type = QMI_UNSIGNED_1_BYTE, - .elem_len = QMI_WLFW_MAX_ATHDIAG_DATA_SIZE_V01, - .elem_size = sizeof(u8), - .array_type = VAR_LEN_ARRAY, - .tlv_type = 0x03, - .offset = offsetof(struct - wlfw_athdiag_write_req_msg_v01, - data), - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_athdiag_write_resp_msg_v01_ei[] = { - { - .data_type = QMI_STRUCT, - .elem_len = 1, - .elem_size = sizeof(struct qmi_response_type_v01), - .array_type = NO_ARRAY, - .tlv_type = 0x02, - .offset = offsetof(struct - wlfw_athdiag_write_resp_msg_v01, - resp), - .ei_array = qmi_response_type_v01_ei, - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_vbatt_req_msg_v01_ei[] = { - { - .data_type = QMI_UNSIGNED_8_BYTE, - .elem_len = 1, - .elem_size = sizeof(u64), - .array_type = NO_ARRAY, - .tlv_type = 0x01, - .offset = offsetof(struct wlfw_vbatt_req_msg_v01, - voltage_uv), - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_vbatt_resp_msg_v01_ei[] = { - { - .data_type = QMI_STRUCT, - .elem_len = 1, - .elem_size = sizeof(struct qmi_response_type_v01), - .array_type = NO_ARRAY, - .tlv_type = 0x02, - .offset = offsetof(struct wlfw_vbatt_resp_msg_v01, - resp), - .ei_array = qmi_response_type_v01_ei, - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_mac_addr_req_msg_v01_ei[] = { - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct wlfw_mac_addr_req_msg_v01, - mac_addr_valid), - }, - { - .data_type = QMI_UNSIGNED_1_BYTE, - .elem_len = QMI_WLFW_MAC_ADDR_SIZE_V01, - .elem_size = sizeof(u8), - .array_type = STATIC_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct wlfw_mac_addr_req_msg_v01, - mac_addr), - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_mac_addr_resp_msg_v01_ei[] = { - { - .data_type = QMI_STRUCT, - .elem_len = 1, - .elem_size = sizeof(struct qmi_response_type_v01), - .array_type = NO_ARRAY, - .tlv_type = 0x02, - .offset = offsetof(struct wlfw_mac_addr_resp_msg_v01, - resp), - .ei_array = qmi_response_type_v01_ei, - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct wlfw_host_cap_req_msg_v01, - num_clients_valid), - }, - { - .data_type = QMI_UNSIGNED_4_BYTE, - .elem_len = 1, - .elem_size = sizeof(u32), - .array_type = NO_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct wlfw_host_cap_req_msg_v01, - num_clients), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x11, - .offset = offsetof(struct wlfw_host_cap_req_msg_v01, - wake_msi_valid), - }, - { - .data_type = QMI_UNSIGNED_4_BYTE, - .elem_len = 1, - .elem_size = sizeof(u32), - .array_type = NO_ARRAY, - .tlv_type = 0x11, - .offset = offsetof(struct wlfw_host_cap_req_msg_v01, - wake_msi), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x12, - .offset = offsetof(struct wlfw_host_cap_req_msg_v01, - gpios_valid), - }, - { - .data_type = QMI_DATA_LEN, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x12, - .offset = offsetof(struct wlfw_host_cap_req_msg_v01, - gpios_len), - }, - { - .data_type = QMI_UNSIGNED_4_BYTE, - .elem_len = QMI_WLFW_MAX_NUM_GPIO_V01, - .elem_size = sizeof(u32), - .array_type = VAR_LEN_ARRAY, - .tlv_type = 0x12, - .offset = offsetof(struct wlfw_host_cap_req_msg_v01, - gpios), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x13, - .offset = offsetof(struct wlfw_host_cap_req_msg_v01, - nm_modem_valid), - }, - { - .data_type = QMI_UNSIGNED_1_BYTE, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x13, - .offset = offsetof(struct wlfw_host_cap_req_msg_v01, - nm_modem), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x14, - .offset = offsetof(struct wlfw_host_cap_req_msg_v01, - bdf_support_valid), - }, - { - .data_type = QMI_UNSIGNED_1_BYTE, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x14, - .offset = offsetof(struct wlfw_host_cap_req_msg_v01, - bdf_support), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x15, - .offset = offsetof(struct wlfw_host_cap_req_msg_v01, - bdf_cache_support_valid), - }, - { - .data_type = QMI_UNSIGNED_1_BYTE, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x15, - .offset = offsetof(struct wlfw_host_cap_req_msg_v01, - bdf_cache_support), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x16, - .offset = offsetof(struct wlfw_host_cap_req_msg_v01, - m3_support_valid), - }, - { - .data_type = QMI_UNSIGNED_1_BYTE, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x16, - .offset = offsetof(struct wlfw_host_cap_req_msg_v01, - m3_support), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x17, - .offset = offsetof(struct wlfw_host_cap_req_msg_v01, - m3_cache_support_valid), - }, - { - .data_type = QMI_UNSIGNED_1_BYTE, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x17, - .offset = offsetof(struct wlfw_host_cap_req_msg_v01, - m3_cache_support), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x18, - .offset = offsetof(struct wlfw_host_cap_req_msg_v01, - cal_filesys_support_valid), - }, - { - .data_type = QMI_UNSIGNED_1_BYTE, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x18, - .offset = offsetof(struct wlfw_host_cap_req_msg_v01, - cal_filesys_support), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x19, - .offset = offsetof(struct wlfw_host_cap_req_msg_v01, - cal_cache_support_valid), - }, - { - .data_type = QMI_UNSIGNED_1_BYTE, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x19, - .offset = offsetof(struct wlfw_host_cap_req_msg_v01, - cal_cache_support), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x1A, - .offset = offsetof(struct wlfw_host_cap_req_msg_v01, - cal_done_valid), - }, - { - .data_type = QMI_UNSIGNED_1_BYTE, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x1A, - .offset = offsetof(struct wlfw_host_cap_req_msg_v01, - cal_done), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x1B, - .offset = offsetof(struct wlfw_host_cap_req_msg_v01, - mem_bucket_valid), - }, - { - .data_type = QMI_UNSIGNED_4_BYTE, - .elem_len = 1, - .elem_size = sizeof(u32), - .array_type = NO_ARRAY, - .tlv_type = 0x1B, - .offset = offsetof(struct wlfw_host_cap_req_msg_v01, - mem_bucket), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x1C, - .offset = offsetof(struct wlfw_host_cap_req_msg_v01, - mem_cfg_mode_valid), - }, - { - .data_type = QMI_UNSIGNED_1_BYTE, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x1C, - .offset = offsetof(struct wlfw_host_cap_req_msg_v01, - mem_cfg_mode), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x1D, - .offset = offsetof(struct wlfw_host_cap_req_msg_v01, - cal_duration_valid), - }, - { - .data_type = QMI_UNSIGNED_2_BYTE, - .elem_len = 1, - .elem_size = sizeof(u16), - .array_type = NO_ARRAY, - .tlv_type = 0x1D, - .offset = offsetof(struct wlfw_host_cap_req_msg_v01, - cal_duration), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x1E, - .offset = offsetof(struct wlfw_host_cap_req_msg_v01, - platform_name_valid), - }, - { - .data_type = QMI_STRING, - .elem_len = QMI_WLFW_MAX_PLATFORM_NAME_LEN_V01 + 1, - .elem_size = sizeof(char), - .array_type = NO_ARRAY, - .tlv_type = 0x1E, - .offset = offsetof(struct wlfw_host_cap_req_msg_v01, - platform_name), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x1F, - .offset = offsetof(struct wlfw_host_cap_req_msg_v01, - ddr_range_valid), - }, - { - .data_type = QMI_STRUCT, - .elem_len = QMI_WLFW_MAX_HOST_DDR_RANGE_SIZE_V01, - .elem_size = sizeof(struct wlfw_host_ddr_range_s_v01), - .array_type = STATIC_ARRAY, - .tlv_type = 0x1F, - .offset = offsetof(struct wlfw_host_cap_req_msg_v01, - ddr_range), - .ei_array = wlfw_host_ddr_range_s_v01_ei, - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x20, - .offset = offsetof(struct wlfw_host_cap_req_msg_v01, - host_build_type_valid), - }, - { - .data_type = QMI_SIGNED_4_BYTE_ENUM, - .elem_len = 1, - .elem_size = sizeof(enum wlfw_host_build_type_v01), - .array_type = NO_ARRAY, - .tlv_type = 0x20, - .offset = offsetof(struct wlfw_host_cap_req_msg_v01, - host_build_type), - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_host_cap_resp_msg_v01_ei[] = { - { - .data_type = QMI_STRUCT, - .elem_len = 1, - .elem_size = sizeof(struct qmi_response_type_v01), - .array_type = NO_ARRAY, - .tlv_type = 0x02, - .offset = offsetof(struct wlfw_host_cap_resp_msg_v01, - resp), - .ei_array = qmi_response_type_v01_ei, - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_request_mem_ind_msg_v01_ei[] = { - { - .data_type = QMI_DATA_LEN, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x01, - .offset = offsetof(struct wlfw_request_mem_ind_msg_v01, - mem_seg_len), - }, - { - .data_type = QMI_STRUCT, - .elem_len = QMI_WLFW_MAX_NUM_MEM_SEG_V01, - .elem_size = sizeof(struct wlfw_mem_seg_s_v01), - .array_type = VAR_LEN_ARRAY, - .tlv_type = 0x01, - .offset = offsetof(struct wlfw_request_mem_ind_msg_v01, - mem_seg), - .ei_array = wlfw_mem_seg_s_v01_ei, - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_respond_mem_req_msg_v01_ei[] = { - { - .data_type = QMI_DATA_LEN, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x01, - .offset = offsetof(struct wlfw_respond_mem_req_msg_v01, - mem_seg_len), - }, - { - .data_type = QMI_STRUCT, - .elem_len = QMI_WLFW_MAX_NUM_MEM_SEG_V01, - .elem_size = sizeof(struct wlfw_mem_seg_resp_s_v01), - .array_type = VAR_LEN_ARRAY, - .tlv_type = 0x01, - .offset = offsetof(struct wlfw_respond_mem_req_msg_v01, - mem_seg), - .ei_array = wlfw_mem_seg_resp_s_v01_ei, - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_respond_mem_resp_msg_v01_ei[] = { - { - .data_type = QMI_STRUCT, - .elem_len = 1, - .elem_size = sizeof(struct qmi_response_type_v01), - .array_type = NO_ARRAY, - .tlv_type = 0x02, - .offset = offsetof(struct wlfw_respond_mem_resp_msg_v01, - resp), - .ei_array = qmi_response_type_v01_ei, - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_fw_mem_ready_ind_msg_v01_ei[] = { - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_fw_init_done_ind_msg_v01_ei[] = { - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_rejuvenate_ind_msg_v01_ei[] = { - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct wlfw_rejuvenate_ind_msg_v01, - cause_for_rejuvenation_valid), - }, - { - .data_type = QMI_UNSIGNED_1_BYTE, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct wlfw_rejuvenate_ind_msg_v01, - cause_for_rejuvenation), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x11, - .offset = offsetof(struct wlfw_rejuvenate_ind_msg_v01, - requesting_sub_system_valid), - }, - { - .data_type = QMI_UNSIGNED_1_BYTE, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x11, - .offset = offsetof(struct wlfw_rejuvenate_ind_msg_v01, - requesting_sub_system), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x12, - .offset = offsetof(struct wlfw_rejuvenate_ind_msg_v01, - line_number_valid), - }, - { - .data_type = QMI_UNSIGNED_2_BYTE, - .elem_len = 1, - .elem_size = sizeof(u16), - .array_type = NO_ARRAY, - .tlv_type = 0x12, - .offset = offsetof(struct wlfw_rejuvenate_ind_msg_v01, - line_number), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x13, - .offset = offsetof(struct wlfw_rejuvenate_ind_msg_v01, - function_name_valid), - }, - { - .data_type = QMI_STRING, - .elem_len = QMI_WLFW_FUNCTION_NAME_LEN_V01 + 1, - .elem_size = sizeof(char), - .array_type = NO_ARRAY, - .tlv_type = 0x13, - .offset = offsetof(struct wlfw_rejuvenate_ind_msg_v01, - function_name), - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_rejuvenate_ack_req_msg_v01_ei[] = { - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_rejuvenate_ack_resp_msg_v01_ei[] = { - { - .data_type = QMI_STRUCT, - .elem_len = 1, - .elem_size = sizeof(struct qmi_response_type_v01), - .array_type = NO_ARRAY, - .tlv_type = 0x02, - .offset = offsetof(struct - wlfw_rejuvenate_ack_resp_msg_v01, - resp), - .ei_array = qmi_response_type_v01_ei, - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_dynamic_feature_mask_req_msg_v01_ei[] = { - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct - wlfw_dynamic_feature_mask_req_msg_v01, - mask_valid), - }, - { - .data_type = QMI_UNSIGNED_8_BYTE, - .elem_len = 1, - .elem_size = sizeof(u64), - .array_type = NO_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct - wlfw_dynamic_feature_mask_req_msg_v01, - mask), - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_dynamic_feature_mask_resp_msg_v01_ei[] = { - { - .data_type = QMI_STRUCT, - .elem_len = 1, - .elem_size = sizeof(struct qmi_response_type_v01), - .array_type = NO_ARRAY, - .tlv_type = 0x02, - .offset = offsetof(struct - wlfw_dynamic_feature_mask_resp_msg_v01, - resp), - .ei_array = qmi_response_type_v01_ei, - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct - wlfw_dynamic_feature_mask_resp_msg_v01, - prev_mask_valid), - }, - { - .data_type = QMI_UNSIGNED_8_BYTE, - .elem_len = 1, - .elem_size = sizeof(u64), - .array_type = NO_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct - wlfw_dynamic_feature_mask_resp_msg_v01, - prev_mask), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x11, - .offset = offsetof(struct - wlfw_dynamic_feature_mask_resp_msg_v01, - curr_mask_valid), - }, - { - .data_type = QMI_UNSIGNED_8_BYTE, - .elem_len = 1, - .elem_size = sizeof(u64), - .array_type = NO_ARRAY, - .tlv_type = 0x11, - .offset = offsetof(struct - wlfw_dynamic_feature_mask_resp_msg_v01, - curr_mask), - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_m3_info_req_msg_v01_ei[] = { - { - .data_type = QMI_UNSIGNED_8_BYTE, - .elem_len = 1, - .elem_size = sizeof(u64), - .array_type = NO_ARRAY, - .tlv_type = 0x01, - .offset = offsetof(struct wlfw_m3_info_req_msg_v01, - addr), - }, - { - .data_type = QMI_UNSIGNED_4_BYTE, - .elem_len = 1, - .elem_size = sizeof(u32), - .array_type = NO_ARRAY, - .tlv_type = 0x02, - .offset = offsetof(struct wlfw_m3_info_req_msg_v01, - size), - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_m3_info_resp_msg_v01_ei[] = { - { - .data_type = QMI_STRUCT, - .elem_len = 1, - .elem_size = sizeof(struct qmi_response_type_v01), - .array_type = NO_ARRAY, - .tlv_type = 0x02, - .offset = offsetof(struct wlfw_m3_info_resp_msg_v01, - resp), - .ei_array = qmi_response_type_v01_ei, - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_xo_cal_ind_msg_v01_ei[] = { - { - .data_type = QMI_UNSIGNED_1_BYTE, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x01, - .offset = offsetof(struct wlfw_xo_cal_ind_msg_v01, - xo_cal_data), - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_cal_done_ind_msg_v01_ei[] = { - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_qdss_trace_req_mem_ind_msg_v01_ei[] = { - { - .data_type = QMI_DATA_LEN, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x01, - .offset = offsetof(struct - wlfw_qdss_trace_req_mem_ind_msg_v01, - mem_seg_len), - }, - { - .data_type = QMI_STRUCT, - .elem_len = QMI_WLFW_MAX_NUM_MEM_SEG_V01, - .elem_size = sizeof(struct wlfw_mem_seg_s_v01), - .array_type = VAR_LEN_ARRAY, - .tlv_type = 0x01, - .offset = offsetof(struct - wlfw_qdss_trace_req_mem_ind_msg_v01, - mem_seg), - .ei_array = wlfw_mem_seg_s_v01_ei, - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_qdss_trace_mem_info_req_msg_v01_ei[] = { - { - .data_type = QMI_DATA_LEN, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x01, - .offset = offsetof(struct - wlfw_qdss_trace_mem_info_req_msg_v01, - mem_seg_len), - }, - { - .data_type = QMI_STRUCT, - .elem_len = QMI_WLFW_MAX_NUM_MEM_SEG_V01, - .elem_size = sizeof(struct wlfw_mem_seg_resp_s_v01), - .array_type = VAR_LEN_ARRAY, - .tlv_type = 0x01, - .offset = offsetof(struct - wlfw_qdss_trace_mem_info_req_msg_v01, - mem_seg), - .ei_array = wlfw_mem_seg_resp_s_v01_ei, - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_qdss_trace_mem_info_resp_msg_v01_ei[] = { - { - .data_type = QMI_STRUCT, - .elem_len = 1, - .elem_size = sizeof(struct qmi_response_type_v01), - .array_type = NO_ARRAY, - .tlv_type = 0x02, - .offset = offsetof(struct - wlfw_qdss_trace_mem_info_resp_msg_v01, - resp), - .ei_array = qmi_response_type_v01_ei, - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_qdss_trace_save_ind_msg_v01_ei[] = { - { - .data_type = QMI_UNSIGNED_4_BYTE, - .elem_len = 1, - .elem_size = sizeof(u32), - .array_type = NO_ARRAY, - .tlv_type = 0x01, - .offset = offsetof(struct - wlfw_qdss_trace_save_ind_msg_v01, - source), - }, - { - .data_type = QMI_UNSIGNED_4_BYTE, - .elem_len = 1, - .elem_size = sizeof(u32), - .array_type = NO_ARRAY, - .tlv_type = 0x02, - .offset = offsetof(struct - wlfw_qdss_trace_save_ind_msg_v01, - total_size), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct - wlfw_qdss_trace_save_ind_msg_v01, - mem_seg_valid), - }, - { - .data_type = QMI_DATA_LEN, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct - wlfw_qdss_trace_save_ind_msg_v01, - mem_seg_len), - }, - { - .data_type = QMI_STRUCT, - .elem_len = QMI_WLFW_MAX_NUM_MEM_SEG_V01, - .elem_size = sizeof(struct wlfw_mem_seg_resp_s_v01), - .array_type = VAR_LEN_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct - wlfw_qdss_trace_save_ind_msg_v01, - mem_seg), - .ei_array = wlfw_mem_seg_resp_s_v01_ei, - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x11, - .offset = offsetof(struct - wlfw_qdss_trace_save_ind_msg_v01, - file_name_valid), - }, - { - .data_type = QMI_STRING, - .elem_len = QMI_WLFW_MAX_STR_LEN_V01 + 1, - .elem_size = sizeof(char), - .array_type = NO_ARRAY, - .tlv_type = 0x11, - .offset = offsetof(struct - wlfw_qdss_trace_save_ind_msg_v01, - file_name), - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_qdss_trace_data_req_msg_v01_ei[] = { - { - .data_type = QMI_UNSIGNED_4_BYTE, - .elem_len = 1, - .elem_size = sizeof(u32), - .array_type = NO_ARRAY, - .tlv_type = 0x01, - .offset = offsetof(struct - wlfw_qdss_trace_data_req_msg_v01, - seg_id), - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_qdss_trace_data_resp_msg_v01_ei[] = { - { - .data_type = QMI_STRUCT, - .elem_len = 1, - .elem_size = sizeof(struct qmi_response_type_v01), - .array_type = NO_ARRAY, - .tlv_type = 0x02, - .offset = offsetof(struct - wlfw_qdss_trace_data_resp_msg_v01, - resp), - .ei_array = qmi_response_type_v01_ei, - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct - wlfw_qdss_trace_data_resp_msg_v01, - total_size_valid), - }, - { - .data_type = QMI_UNSIGNED_4_BYTE, - .elem_len = 1, - .elem_size = sizeof(u32), - .array_type = NO_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct - wlfw_qdss_trace_data_resp_msg_v01, - total_size), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x11, - .offset = offsetof(struct - wlfw_qdss_trace_data_resp_msg_v01, - seg_id_valid), - }, - { - .data_type = QMI_UNSIGNED_4_BYTE, - .elem_len = 1, - .elem_size = sizeof(u32), - .array_type = NO_ARRAY, - .tlv_type = 0x11, - .offset = offsetof(struct - wlfw_qdss_trace_data_resp_msg_v01, - seg_id), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x12, - .offset = offsetof(struct - wlfw_qdss_trace_data_resp_msg_v01, - data_valid), - }, - { - .data_type = QMI_DATA_LEN, - .elem_len = 1, - .elem_size = sizeof(u16), - .array_type = NO_ARRAY, - .tlv_type = 0x12, - .offset = offsetof(struct - wlfw_qdss_trace_data_resp_msg_v01, - data_len), - }, - { - .data_type = QMI_UNSIGNED_1_BYTE, - .elem_len = QMI_WLFW_MAX_DATA_SIZE_V01, - .elem_size = sizeof(u8), - .array_type = VAR_LEN_ARRAY, - .tlv_type = 0x12, - .offset = offsetof(struct - wlfw_qdss_trace_data_resp_msg_v01, - data), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x13, - .offset = offsetof(struct - wlfw_qdss_trace_data_resp_msg_v01, - end_valid), - }, - { - .data_type = QMI_UNSIGNED_1_BYTE, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x13, - .offset = offsetof(struct - wlfw_qdss_trace_data_resp_msg_v01, - end), - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_qdss_trace_config_download_req_msg_v01_ei[] = { - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct - wlfw_qdss_trace_config_download_req_msg_v01, - total_size_valid), - }, - { - .data_type = QMI_UNSIGNED_4_BYTE, - .elem_len = 1, - .elem_size = sizeof(u32), - .array_type = NO_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct - wlfw_qdss_trace_config_download_req_msg_v01, - total_size), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x11, - .offset = offsetof(struct - wlfw_qdss_trace_config_download_req_msg_v01, - seg_id_valid), - }, - { - .data_type = QMI_UNSIGNED_4_BYTE, - .elem_len = 1, - .elem_size = sizeof(u32), - .array_type = NO_ARRAY, - .tlv_type = 0x11, - .offset = offsetof(struct - wlfw_qdss_trace_config_download_req_msg_v01, - seg_id), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x12, - .offset = offsetof(struct - wlfw_qdss_trace_config_download_req_msg_v01, - data_valid), - }, - { - .data_type = QMI_DATA_LEN, - .elem_len = 1, - .elem_size = sizeof(u16), - .array_type = NO_ARRAY, - .tlv_type = 0x12, - .offset = offsetof(struct - wlfw_qdss_trace_config_download_req_msg_v01, - data_len), - }, - { - .data_type = QMI_UNSIGNED_1_BYTE, - .elem_len = QMI_WLFW_MAX_DATA_SIZE_V01, - .elem_size = sizeof(u8), - .array_type = VAR_LEN_ARRAY, - .tlv_type = 0x12, - .offset = offsetof(struct - wlfw_qdss_trace_config_download_req_msg_v01, - data), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x13, - .offset = offsetof(struct - wlfw_qdss_trace_config_download_req_msg_v01, - end_valid), - }, - { - .data_type = QMI_UNSIGNED_1_BYTE, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x13, - .offset = offsetof(struct - wlfw_qdss_trace_config_download_req_msg_v01, - end), - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_qdss_trace_config_download_resp_msg_v01_ei[] = { - { - .data_type = QMI_STRUCT, - .elem_len = 1, - .elem_size = sizeof(struct qmi_response_type_v01), - .array_type = NO_ARRAY, - .tlv_type = 0x02, - .offset = offsetof(struct - wlfw_qdss_trace_config_download_resp_msg_v01, - resp), - .ei_array = qmi_response_type_v01_ei, - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_qdss_trace_mode_req_msg_v01_ei[] = { - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct - wlfw_qdss_trace_mode_req_msg_v01, - mode_valid), - }, - { - .data_type = QMI_SIGNED_4_BYTE_ENUM, - .elem_len = 1, - .elem_size = sizeof(enum wlfw_qdss_trace_mode_enum_v01), - .array_type = NO_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct - wlfw_qdss_trace_mode_req_msg_v01, - mode), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x11, - .offset = offsetof(struct - wlfw_qdss_trace_mode_req_msg_v01, - option_valid), - }, - { - .data_type = QMI_UNSIGNED_8_BYTE, - .elem_len = 1, - .elem_size = sizeof(u64), - .array_type = NO_ARRAY, - .tlv_type = 0x11, - .offset = offsetof(struct - wlfw_qdss_trace_mode_req_msg_v01, - option), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x12, - .offset = offsetof(struct - wlfw_qdss_trace_mode_req_msg_v01, - hw_trc_disable_override_valid), - }, - { - .data_type = QMI_SIGNED_4_BYTE_ENUM, - .elem_len = 1, - .elem_size = sizeof(enum wlfw_qmi_param_value_v01), - .array_type = NO_ARRAY, - .tlv_type = 0x12, - .offset = offsetof(struct - wlfw_qdss_trace_mode_req_msg_v01, - hw_trc_disable_override), - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_qdss_trace_mode_resp_msg_v01_ei[] = { - { - .data_type = QMI_STRUCT, - .elem_len = 1, - .elem_size = sizeof(struct qmi_response_type_v01), - .array_type = NO_ARRAY, - .tlv_type = 0x02, - .offset = offsetof(struct - wlfw_qdss_trace_mode_resp_msg_v01, - resp), - .ei_array = qmi_response_type_v01_ei, - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_qdss_trace_free_ind_msg_v01_ei[] = { - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct - wlfw_qdss_trace_free_ind_msg_v01, - mem_seg_valid), - }, - { - .data_type = QMI_DATA_LEN, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct - wlfw_qdss_trace_free_ind_msg_v01, - mem_seg_len), - }, - { - .data_type = QMI_STRUCT, - .elem_len = QMI_WLFW_MAX_NUM_MEM_SEG_V01, - .elem_size = sizeof(struct wlfw_mem_seg_resp_s_v01), - .array_type = VAR_LEN_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct - wlfw_qdss_trace_free_ind_msg_v01, - mem_seg), - .ei_array = wlfw_mem_seg_resp_s_v01_ei, - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_shutdown_req_msg_v01_ei[] = { - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct wlfw_shutdown_req_msg_v01, - shutdown_valid), - }, - { - .data_type = QMI_UNSIGNED_1_BYTE, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct wlfw_shutdown_req_msg_v01, - shutdown), - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_shutdown_resp_msg_v01_ei[] = { - { - .data_type = QMI_STRUCT, - .elem_len = 1, - .elem_size = sizeof(struct qmi_response_type_v01), - .array_type = NO_ARRAY, - .tlv_type = 0x02, - .offset = offsetof(struct wlfw_shutdown_resp_msg_v01, - resp), - .ei_array = qmi_response_type_v01_ei, - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_antenna_switch_req_msg_v01_ei[] = { - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_antenna_switch_resp_msg_v01_ei[] = { - { - .data_type = QMI_STRUCT, - .elem_len = 1, - .elem_size = sizeof(struct qmi_response_type_v01), - .array_type = NO_ARRAY, - .tlv_type = 0x02, - .offset = offsetof(struct - wlfw_antenna_switch_resp_msg_v01, - resp), - .ei_array = qmi_response_type_v01_ei, - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct - wlfw_antenna_switch_resp_msg_v01, - antenna_valid), - }, - { - .data_type = QMI_UNSIGNED_8_BYTE, - .elem_len = 1, - .elem_size = sizeof(u64), - .array_type = NO_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct - wlfw_antenna_switch_resp_msg_v01, - antenna), - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_antenna_grant_req_msg_v01_ei[] = { - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct - wlfw_antenna_grant_req_msg_v01, - grant_valid), - }, - { - .data_type = QMI_UNSIGNED_8_BYTE, - .elem_len = 1, - .elem_size = sizeof(u64), - .array_type = NO_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct - wlfw_antenna_grant_req_msg_v01, - grant), - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_antenna_grant_resp_msg_v01_ei[] = { - { - .data_type = QMI_STRUCT, - .elem_len = 1, - .elem_size = sizeof(struct qmi_response_type_v01), - .array_type = NO_ARRAY, - .tlv_type = 0x02, - .offset = offsetof(struct - wlfw_antenna_grant_resp_msg_v01, - resp), - .ei_array = qmi_response_type_v01_ei, - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_wfc_call_status_req_msg_v01_ei[] = { - { - .data_type = QMI_DATA_LEN, - .elem_len = 1, - .elem_size = sizeof(u16), - .array_type = NO_ARRAY, - .tlv_type = 0x01, - .offset = offsetof(struct - wlfw_wfc_call_status_req_msg_v01, - wfc_call_status_len), - }, - { - .data_type = QMI_UNSIGNED_1_BYTE, - .elem_len = QMI_WLFW_MAX_WFC_CALL_STATUS_DATA_SIZE_V01, - .elem_size = sizeof(u8), - .array_type = VAR_LEN_ARRAY, - .tlv_type = 0x01, - .offset = offsetof(struct - wlfw_wfc_call_status_req_msg_v01, - wfc_call_status), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct - wlfw_wfc_call_status_req_msg_v01, - wfc_call_active_valid), - }, - { - .data_type = QMI_UNSIGNED_1_BYTE, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct - wlfw_wfc_call_status_req_msg_v01, - wfc_call_active), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x11, - .offset = offsetof(struct - wlfw_wfc_call_status_req_msg_v01, - all_wfc_calls_held_valid), - }, - { - .data_type = QMI_UNSIGNED_1_BYTE, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x11, - .offset = offsetof(struct - wlfw_wfc_call_status_req_msg_v01, - all_wfc_calls_held), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x12, - .offset = offsetof(struct - wlfw_wfc_call_status_req_msg_v01, - is_wfc_emergency_valid), - }, - { - .data_type = QMI_UNSIGNED_1_BYTE, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x12, - .offset = offsetof(struct - wlfw_wfc_call_status_req_msg_v01, - is_wfc_emergency), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x13, - .offset = offsetof(struct - wlfw_wfc_call_status_req_msg_v01, - twt_ims_start_valid), - }, - { - .data_type = QMI_UNSIGNED_8_BYTE, - .elem_len = 1, - .elem_size = sizeof(u64), - .array_type = NO_ARRAY, - .tlv_type = 0x13, - .offset = offsetof(struct - wlfw_wfc_call_status_req_msg_v01, - twt_ims_start), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x14, - .offset = offsetof(struct - wlfw_wfc_call_status_req_msg_v01, - twt_ims_int_valid), - }, - { - .data_type = QMI_UNSIGNED_2_BYTE, - .elem_len = 1, - .elem_size = sizeof(u16), - .array_type = NO_ARRAY, - .tlv_type = 0x14, - .offset = offsetof(struct - wlfw_wfc_call_status_req_msg_v01, - twt_ims_int), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x15, - .offset = offsetof(struct - wlfw_wfc_call_status_req_msg_v01, - media_quality_valid), - }, - { - .data_type = QMI_SIGNED_4_BYTE_ENUM, - .elem_len = 1, - .elem_size = sizeof(enum wlfw_wfc_media_quality_v01), - .array_type = NO_ARRAY, - .tlv_type = 0x15, - .offset = offsetof(struct - wlfw_wfc_call_status_req_msg_v01, - media_quality), - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_wfc_call_status_resp_msg_v01_ei[] = { - { - .data_type = QMI_STRUCT, - .elem_len = 1, - .elem_size = sizeof(struct qmi_response_type_v01), - .array_type = NO_ARRAY, - .tlv_type = 0x02, - .offset = offsetof(struct - wlfw_wfc_call_status_resp_msg_v01, - resp), - .ei_array = qmi_response_type_v01_ei, - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_get_info_req_msg_v01_ei[] = { - { - .data_type = QMI_UNSIGNED_1_BYTE, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x01, - .offset = offsetof(struct wlfw_get_info_req_msg_v01, - type), - }, - { - .data_type = QMI_DATA_LEN, - .elem_len = 1, - .elem_size = sizeof(u16), - .array_type = NO_ARRAY, - .tlv_type = 0x02, - .offset = offsetof(struct wlfw_get_info_req_msg_v01, - data_len), - }, - { - .data_type = QMI_UNSIGNED_1_BYTE, - .elem_len = QMI_WLFW_MAX_DATA_SIZE_V01, - .elem_size = sizeof(u8), - .array_type = VAR_LEN_ARRAY, - .tlv_type = 0x02, - .offset = offsetof(struct wlfw_get_info_req_msg_v01, - data), - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_get_info_resp_msg_v01_ei[] = { - { - .data_type = QMI_STRUCT, - .elem_len = 1, - .elem_size = sizeof(struct qmi_response_type_v01), - .array_type = NO_ARRAY, - .tlv_type = 0x02, - .offset = offsetof(struct wlfw_get_info_resp_msg_v01, - resp), - .ei_array = qmi_response_type_v01_ei, - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_respond_get_info_ind_msg_v01_ei[] = { - { - .data_type = QMI_DATA_LEN, - .elem_len = 1, - .elem_size = sizeof(u16), - .array_type = NO_ARRAY, - .tlv_type = 0x01, - .offset = offsetof(struct - wlfw_respond_get_info_ind_msg_v01, - data_len), - }, - { - .data_type = QMI_UNSIGNED_1_BYTE, - .elem_len = QMI_WLFW_MAX_DATA_SIZE_V01, - .elem_size = sizeof(u8), - .array_type = VAR_LEN_ARRAY, - .tlv_type = 0x01, - .offset = offsetof(struct - wlfw_respond_get_info_ind_msg_v01, - data), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct - wlfw_respond_get_info_ind_msg_v01, - type_valid), - }, - { - .data_type = QMI_UNSIGNED_1_BYTE, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct - wlfw_respond_get_info_ind_msg_v01, - type), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x11, - .offset = offsetof(struct - wlfw_respond_get_info_ind_msg_v01, - is_last_valid), - }, - { - .data_type = QMI_UNSIGNED_1_BYTE, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x11, - .offset = offsetof(struct - wlfw_respond_get_info_ind_msg_v01, - is_last), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x12, - .offset = offsetof(struct - wlfw_respond_get_info_ind_msg_v01, - seq_no_valid), - }, - { - .data_type = QMI_UNSIGNED_4_BYTE, - .elem_len = 1, - .elem_size = sizeof(u32), - .array_type = NO_ARRAY, - .tlv_type = 0x12, - .offset = offsetof(struct - wlfw_respond_get_info_ind_msg_v01, - seq_no), - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_device_info_req_msg_v01_ei[] = { - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_device_info_resp_msg_v01_ei[] = { - { - .data_type = QMI_STRUCT, - .elem_len = 1, - .elem_size = sizeof(struct qmi_response_type_v01), - .array_type = NO_ARRAY, - .tlv_type = 0x02, - .offset = offsetof(struct wlfw_device_info_resp_msg_v01, - resp), - .ei_array = qmi_response_type_v01_ei, - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct wlfw_device_info_resp_msg_v01, - bar_addr_valid), - }, - { - .data_type = QMI_UNSIGNED_8_BYTE, - .elem_len = 1, - .elem_size = sizeof(u64), - .array_type = NO_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct wlfw_device_info_resp_msg_v01, - bar_addr), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x11, - .offset = offsetof(struct wlfw_device_info_resp_msg_v01, - bar_size_valid), - }, - { - .data_type = QMI_UNSIGNED_4_BYTE, - .elem_len = 1, - .elem_size = sizeof(u32), - .array_type = NO_ARRAY, - .tlv_type = 0x11, - .offset = offsetof(struct wlfw_device_info_resp_msg_v01, - bar_size), - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_m3_dump_upload_req_ind_msg_v01_ei[] = { - { - .data_type = QMI_UNSIGNED_4_BYTE, - .elem_len = 1, - .elem_size = sizeof(u32), - .array_type = NO_ARRAY, - .tlv_type = 0x01, - .offset = offsetof(struct - wlfw_m3_dump_upload_req_ind_msg_v01, - pdev_id), - }, - { - .data_type = QMI_UNSIGNED_8_BYTE, - .elem_len = 1, - .elem_size = sizeof(u64), - .array_type = NO_ARRAY, - .tlv_type = 0x02, - .offset = offsetof(struct - wlfw_m3_dump_upload_req_ind_msg_v01, - addr), - }, - { - .data_type = QMI_UNSIGNED_8_BYTE, - .elem_len = 1, - .elem_size = sizeof(u64), - .array_type = NO_ARRAY, - .tlv_type = 0x03, - .offset = offsetof(struct - wlfw_m3_dump_upload_req_ind_msg_v01, - size), - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_m3_dump_upload_done_req_msg_v01_ei[] = { - { - .data_type = QMI_UNSIGNED_4_BYTE, - .elem_len = 1, - .elem_size = sizeof(u32), - .array_type = NO_ARRAY, - .tlv_type = 0x01, - .offset = offsetof(struct - wlfw_m3_dump_upload_done_req_msg_v01, - pdev_id), - }, - { - .data_type = QMI_UNSIGNED_4_BYTE, - .elem_len = 1, - .elem_size = sizeof(u32), - .array_type = NO_ARRAY, - .tlv_type = 0x02, - .offset = offsetof(struct - wlfw_m3_dump_upload_done_req_msg_v01, - status), - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_m3_dump_upload_done_resp_msg_v01_ei[] = { - { - .data_type = QMI_STRUCT, - .elem_len = 1, - .elem_size = sizeof(struct qmi_response_type_v01), - .array_type = NO_ARRAY, - .tlv_type = 0x02, - .offset = offsetof(struct - wlfw_m3_dump_upload_done_resp_msg_v01, - resp), - .ei_array = qmi_response_type_v01_ei, - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_soc_wake_req_msg_v01_ei[] = { - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct - wlfw_soc_wake_req_msg_v01, - wake_valid), - }, - { - .data_type = QMI_SIGNED_4_BYTE_ENUM, - .elem_len = 1, - .elem_size = sizeof(enum wlfw_soc_wake_enum_v01), - .array_type = NO_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct wlfw_soc_wake_req_msg_v01, - wake), - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_soc_wake_resp_msg_v01_ei[] = { - { - .data_type = QMI_STRUCT, - .elem_len = 1, - .elem_size = sizeof(struct qmi_response_type_v01), - .array_type = NO_ARRAY, - .tlv_type = 0x02, - .offset = offsetof(struct wlfw_soc_wake_resp_msg_v01, - resp), - .ei_array = qmi_response_type_v01_ei, - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_exit_power_save_req_msg_v01_ei[] = { - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_exit_power_save_resp_msg_v01_ei[] = { - { - .data_type = QMI_STRUCT, - .elem_len = 1, - .elem_size = sizeof(struct qmi_response_type_v01), - .array_type = NO_ARRAY, - .tlv_type = 0x02, - .offset = offsetof(struct - wlfw_exit_power_save_resp_msg_v01, - resp), - .ei_array = qmi_response_type_v01_ei, - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_wfc_call_twt_config_ind_msg_v01_ei[] = { - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x10, - .offset = - offsetof(struct wlfw_wfc_call_twt_config_ind_msg_v01, - twt_sta_start_valid), - }, - { - .data_type = QMI_UNSIGNED_8_BYTE, - .elem_len = 1, - .elem_size = sizeof(u64), - .array_type = NO_ARRAY, - .tlv_type = 0x10, - .offset = - offsetof(struct wlfw_wfc_call_twt_config_ind_msg_v01, - twt_sta_start), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x11, - .offset = - offsetof(struct wlfw_wfc_call_twt_config_ind_msg_v01, - twt_sta_int_valid), - }, - { - .data_type = QMI_UNSIGNED_2_BYTE, - .elem_len = 1, - .elem_size = sizeof(u16), - .array_type = NO_ARRAY, - .tlv_type = 0x11, - .offset = - offsetof(struct wlfw_wfc_call_twt_config_ind_msg_v01, - twt_sta_int), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x12, - .offset = - offsetof(struct wlfw_wfc_call_twt_config_ind_msg_v01, - twt_sta_upo_valid), - }, - { - .data_type = QMI_UNSIGNED_2_BYTE, - .elem_len = 1, - .elem_size = sizeof(u16), - .array_type = NO_ARRAY, - .tlv_type = 0x12, - .offset = - offsetof(struct wlfw_wfc_call_twt_config_ind_msg_v01, - twt_sta_upo), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x13, - .offset = - offsetof(struct wlfw_wfc_call_twt_config_ind_msg_v01, - twt_sta_sp_valid), - }, - { - .data_type = QMI_UNSIGNED_2_BYTE, - .elem_len = 1, - .elem_size = sizeof(u16), - .array_type = NO_ARRAY, - .tlv_type = 0x13, - .offset = - offsetof(struct wlfw_wfc_call_twt_config_ind_msg_v01, - twt_sta_sp), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x14, - .offset = - offsetof(struct wlfw_wfc_call_twt_config_ind_msg_v01, - twt_sta_dl_valid), - }, - { - .data_type = QMI_UNSIGNED_2_BYTE, - .elem_len = 1, - .elem_size = sizeof(u16), - .array_type = NO_ARRAY, - .tlv_type = 0x14, - .offset = - offsetof(struct wlfw_wfc_call_twt_config_ind_msg_v01, - twt_sta_dl), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x15, - .offset = - offsetof(struct wlfw_wfc_call_twt_config_ind_msg_v01, - twt_sta_config_changed_valid), - }, - { - .data_type = QMI_UNSIGNED_1_BYTE, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x15, - .offset = - offsetof(struct wlfw_wfc_call_twt_config_ind_msg_v01, - twt_sta_config_changed), - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_qdss_mem_ready_ind_msg_v01_ei[] = { - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_pcie_gen_switch_req_msg_v01_ei[] = { - { - .data_type = QMI_SIGNED_4_BYTE_ENUM, - .elem_len = 1, - .elem_size = sizeof(enum wlfw_pcie_gen_speed_v01), - .array_type = NO_ARRAY, - .tlv_type = 0x01, - .offset = offsetof(struct - wlfw_pcie_gen_switch_req_msg_v01, - pcie_speed), - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_pcie_gen_switch_resp_msg_v01_ei[] = { - { - .data_type = QMI_STRUCT, - .elem_len = 1, - .elem_size = sizeof(struct qmi_response_type_v01), - .array_type = NO_ARRAY, - .tlv_type = 0x02, - .offset = offsetof(struct - wlfw_pcie_gen_switch_resp_msg_v01, - resp), - .ei_array = qmi_response_type_v01_ei, - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - diff --git a/drivers/net/wireless/cnss2/wlan_firmware_service_v01.h b/drivers/net/wireless/cnss2/wlan_firmware_service_v01.h deleted file mode 100644 index 76cf12933cfc..000000000000 --- a/drivers/net/wireless/cnss2/wlan_firmware_service_v01.h +++ /dev/null @@ -1,1203 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. */ - -#ifndef WLAN_FIRMWARE_SERVICE_V01_H -#define WLAN_FIRMWARE_SERVICE_V01_H - -#include - -#define WLFW_SERVICE_ID_V01 0x45 -#define WLFW_SERVICE_VERS_V01 0x01 - -#define QMI_WLFW_WFC_CALL_STATUS_REQ_V01 0x0049 -#define QMI_WLFW_DEVICE_INFO_RESP_V01 0x004C -#define QMI_WLFW_BDF_DOWNLOAD_REQ_V01 0x0025 -#define QMI_WLFW_FW_MEM_READY_IND_V01 0x0037 -#define QMI_WLFW_QDSS_TRACE_CONFIG_DOWNLOAD_REQ_V01 0x0044 -#define QMI_WLFW_GET_INFO_REQ_V01 0x004A -#define QMI_WLFW_INITIATE_CAL_UPDATE_IND_V01 0x002A -#define QMI_WLFW_CAL_DONE_IND_V01 0x003E -#define QMI_WLFW_M3_DUMP_UPLOAD_REQ_IND_V01 0x004D -#define QMI_WLFW_WFC_CALL_STATUS_RESP_V01 0x0049 -#define QMI_WLFW_HOST_CAP_REQ_V01 0x0034 -#define QMI_WLFW_DYNAMIC_FEATURE_MASK_RESP_V01 0x003B -#define QMI_WLFW_M3_INFO_REQ_V01 0x003C -#define QMI_WLFW_CAP_REQ_V01 0x0024 -#define QMI_WLFW_FW_INIT_DONE_IND_V01 0x0038 -#define QMI_WLFW_ANTENNA_GRANT_RESP_V01 0x0048 -#define QMI_WLFW_CAL_REPORT_REQ_V01 0x0026 -#define QMI_WLFW_RESPOND_GET_INFO_IND_V01 0x004B -#define QMI_WLFW_M3_INFO_RESP_V01 0x003C -#define QMI_WLFW_CAL_UPDATE_RESP_V01 0x0029 -#define QMI_WLFW_M3_DUMP_UPLOAD_DONE_RESP_V01 0x004E -#define QMI_WLFW_CAL_DOWNLOAD_RESP_V01 0x0027 -#define QMI_WLFW_XO_CAL_IND_V01 0x003D -#define QMI_WLFW_INI_RESP_V01 0x002F -#define QMI_WLFW_CAL_REPORT_RESP_V01 0x0026 -#define QMI_WLFW_QDSS_TRACE_MEM_INFO_REQ_V01 0x0040 -#define QMI_WLFW_ANTENNA_SWITCH_REQ_V01 0x0047 -#define QMI_WLFW_QDSS_TRACE_REQ_MEM_IND_V01 0x003F -#define QMI_WLFW_SHUTDOWN_RESP_V01 0x0043 -#define QMI_WLFW_MAC_ADDR_RESP_V01 0x0033 -#define QMI_WLFW_INITIATE_CAL_DOWNLOAD_IND_V01 0x0028 -#define QMI_WLFW_HOST_CAP_RESP_V01 0x0034 -#define QMI_WLFW_MSA_READY_IND_V01 0x002B -#define QMI_WLFW_ATHDIAG_WRITE_RESP_V01 0x0031 -#define QMI_WLFW_EXIT_POWER_SAVE_REQ_V01 0x0050 -#define QMI_WLFW_WLAN_MODE_REQ_V01 0x0022 -#define QMI_WLFW_IND_REGISTER_REQ_V01 0x0020 -#define QMI_WLFW_WLAN_CFG_RESP_V01 0x0023 -#define QMI_WLFW_QDSS_TRACE_MODE_REQ_V01 0x0045 -#define QMI_WLFW_REQUEST_MEM_IND_V01 0x0035 -#define QMI_WLFW_QDSS_TRACE_CONFIG_DOWNLOAD_RESP_V01 0x0044 -#define QMI_WLFW_SOC_WAKE_RESP_V01 0x004F -#define QMI_WLFW_REJUVENATE_IND_V01 0x0039 -#define QMI_WLFW_DYNAMIC_FEATURE_MASK_REQ_V01 0x003B -#define QMI_WLFW_ATHDIAG_WRITE_REQ_V01 0x0031 -#define QMI_WLFW_WLAN_MODE_RESP_V01 0x0022 -#define QMI_WLFW_RESPOND_MEM_REQ_V01 0x0036 -#define QMI_WLFW_GET_INFO_RESP_V01 0x004A -#define QMI_WLFW_QDSS_TRACE_MODE_RESP_V01 0x0045 -#define QMI_WLFW_PIN_CONNECT_RESULT_IND_V01 0x002C -#define QMI_WLFW_FW_READY_IND_V01 0x0021 -#define QMI_WLFW_QDSS_TRACE_SAVE_IND_V01 0x0041 -#define QMI_WLFW_QDSS_TRACE_MEM_INFO_RESP_V01 0x0040 -#define QMI_WLFW_ANTENNA_GRANT_REQ_V01 0x0048 -#define QMI_WLFW_MSA_READY_RESP_V01 0x002E -#define QMI_WLFW_QDSS_TRACE_DATA_REQ_V01 0x0042 -#define QMI_WLFW_CAL_UPDATE_REQ_V01 0x0029 -#define QMI_WLFW_INI_REQ_V01 0x002F -#define QMI_WLFW_BDF_DOWNLOAD_RESP_V01 0x0025 -#define QMI_WLFW_REJUVENATE_ACK_RESP_V01 0x003A -#define QMI_WLFW_MSA_INFO_RESP_V01 0x002D -#define QMI_WLFW_MSA_READY_REQ_V01 0x002E -#define QMI_WLFW_QDSS_TRACE_DATA_RESP_V01 0x0042 -#define QMI_WLFW_M3_DUMP_UPLOAD_DONE_REQ_V01 0x004E -#define QMI_WLFW_CAP_RESP_V01 0x0024 -#define QMI_WLFW_SOC_WAKE_REQ_V01 0x004F -#define QMI_WLFW_REJUVENATE_ACK_REQ_V01 0x003A -#define QMI_WLFW_ATHDIAG_READ_RESP_V01 0x0030 -#define QMI_WLFW_SHUTDOWN_REQ_V01 0x0043 -#define QMI_WLFW_VBATT_REQ_V01 0x0032 -#define QMI_WLFW_ANTENNA_SWITCH_RESP_V01 0x0047 -#define QMI_WLFW_DEVICE_INFO_REQ_V01 0x004C -#define QMI_WLFW_MAC_ADDR_REQ_V01 0x0033 -#define QMI_WLFW_EXIT_POWER_SAVE_RESP_V01 0x0050 -#define QMI_WLFW_RESPOND_MEM_RESP_V01 0x0036 -#define QMI_WLFW_WFC_CALL_TWT_CONFIG_IND_V01 0x0051 -#define QMI_WLFW_VBATT_RESP_V01 0x0032 -#define QMI_WLFW_MSA_INFO_REQ_V01 0x002D -#define QMI_WLFW_QDSS_TRACE_FREE_IND_V01 0x0046 -#define QMI_WLFW_CAL_DOWNLOAD_REQ_V01 0x0027 -#define QMI_WLFW_ATHDIAG_READ_REQ_V01 0x0030 -#define QMI_WLFW_WLAN_CFG_REQ_V01 0x0023 -#define QMI_WLFW_IND_REGISTER_RESP_V01 0x0020 -#define QMI_WLFW_PCIE_GEN_SWITCH_REQ_V01 0x0053 -#define QMI_WLFW_PCIE_GEN_SWITCH_RESP_V01 0x0053 -#define QMI_WLFW_QDSS_MEM_READY_IND_V01 0x0052 - -#define QMI_WLFW_MAX_NUM_MEMORY_REGIONS_V01 2 -#define QMI_WLFW_MAX_NUM_MEM_SEG_V01 32 -#define QMI_WLFW_MAX_NUM_CAL_V01 5 -#define QMI_WLFW_MAX_DATA_SIZE_V01 6144 -#define QMI_WLFW_FUNCTION_NAME_LEN_V01 128 -#define QMI_WLFW_MAX_NUM_CE_V01 12 -#define QMI_WLFW_MAX_HOST_DDR_RANGE_SIZE_V01 3 -#define QMI_WLFW_MAX_TIMESTAMP_LEN_V01 32 -#define QMI_WLFW_MAX_ATHDIAG_DATA_SIZE_V01 6144 -#define QMI_WLFW_MAX_WFC_CALL_STATUS_DATA_SIZE_V01 256 -#define QMI_WLFW_MAX_NUM_GPIO_V01 32 -#define QMI_WLFW_MAX_BUILD_ID_LEN_V01 128 -#define QMI_WLFW_MAX_NUM_MEM_CFG_V01 2 -#define QMI_WLFW_MAX_STR_LEN_V01 16 -#define QMI_WLFW_MAX_NUM_SHADOW_REG_V01 24 -#define QMI_WLFW_MAC_ADDR_SIZE_V01 6 -#define QMI_WLFW_MAX_NUM_SHADOW_REG_V2_V01 36 -#define QMI_WLFW_MAX_PLATFORM_NAME_LEN_V01 64 -#define QMI_WLFW_MAX_NUM_SVC_V01 24 - -enum wlfw_driver_mode_enum_v01 { - WLFW_DRIVER_MODE_ENUM_MIN_VAL_V01 = INT_MIN, - QMI_WLFW_MISSION_V01 = 0, - QMI_WLFW_FTM_V01 = 1, - QMI_WLFW_EPPING_V01 = 2, - QMI_WLFW_WALTEST_V01 = 3, - QMI_WLFW_OFF_V01 = 4, - QMI_WLFW_CCPM_V01 = 5, - QMI_WLFW_QVIT_V01 = 6, - QMI_WLFW_CALIBRATION_V01 = 7, - QMI_WLFW_FTM_CALIBRATION_V01 = 10, - WLFW_DRIVER_MODE_ENUM_MAX_VAL_V01 = INT_MAX, -}; - -enum wlfw_cal_temp_id_enum_v01 { - WLFW_CAL_TEMP_ID_ENUM_MIN_VAL_V01 = INT_MIN, - QMI_WLFW_CAL_TEMP_IDX_0_V01 = 0, - QMI_WLFW_CAL_TEMP_IDX_1_V01 = 1, - QMI_WLFW_CAL_TEMP_IDX_2_V01 = 2, - QMI_WLFW_CAL_TEMP_IDX_3_V01 = 3, - QMI_WLFW_CAL_TEMP_IDX_4_V01 = 4, - WLFW_CAL_TEMP_ID_ENUM_MAX_VAL_V01 = INT_MAX, -}; - -enum wlfw_pipedir_enum_v01 { - WLFW_PIPEDIR_ENUM_MIN_VAL_V01 = INT_MIN, - QMI_WLFW_PIPEDIR_NONE_V01 = 0, - QMI_WLFW_PIPEDIR_IN_V01 = 1, - QMI_WLFW_PIPEDIR_OUT_V01 = 2, - QMI_WLFW_PIPEDIR_INOUT_V01 = 3, - WLFW_PIPEDIR_ENUM_MAX_VAL_V01 = INT_MAX, -}; - -enum wlfw_mem_type_enum_v01 { - WLFW_MEM_TYPE_ENUM_MIN_VAL_V01 = INT_MIN, - QMI_WLFW_MEM_TYPE_MSA_V01 = 0, - QMI_WLFW_MEM_TYPE_DDR_V01 = 1, - QMI_WLFW_MEM_BDF_V01 = 2, - QMI_WLFW_MEM_M3_V01 = 3, - QMI_WLFW_MEM_CAL_V01 = 4, - QMI_WLFW_MEM_DPD_V01 = 5, - QMI_WLFW_MEM_QDSS_V01 = 6, - QMI_WLFW_MEM_HANG_DATA_V01 = 7, - WLFW_MEM_TYPE_ENUM_MAX_VAL_V01 = INT_MAX, -}; - -enum wlfw_qdss_trace_mode_enum_v01 { - WLFW_QDSS_TRACE_MODE_ENUM_MIN_VAL_V01 = INT_MIN, - QMI_WLFW_QDSS_TRACE_OFF_V01 = 0, - QMI_WLFW_QDSS_TRACE_ON_V01 = 1, - WLFW_QDSS_TRACE_MODE_ENUM_MAX_VAL_V01 = INT_MAX, -}; - -enum wlfw_wfc_media_quality_v01 { - WLFW_WFC_MEDIA_QUALITY_MIN_VAL_V01 = INT_MIN, - QMI_WLFW_WFC_MEDIA_QUAL_NOT_AVAILABLE_V01 = 0, - QMI_WLFW_WFC_MEDIA_QUAL_BAD_V01 = 1, - QMI_WLFW_WFC_MEDIA_QUAL_GOOD_V01 = 2, - QMI_WLFW_WFC_MEDIA_QUAL_EXCELLENT_V01 = 3, - WLFW_WFC_MEDIA_QUALITY_MAX_VAL_V01 = INT_MAX, -}; - -enum wlfw_soc_wake_enum_v01 { - WLFW_SOC_WAKE_ENUM_MIN_VAL_V01 = INT_MIN, - QMI_WLFW_WAKE_REQUEST_V01 = 0, - QMI_WLFW_WAKE_RELEASE_V01 = 1, - WLFW_SOC_WAKE_ENUM_MAX_VAL_V01 = INT_MAX, -}; - -enum wlfw_host_build_type_v01 { - WLFW_HOST_BUILD_TYPE_MIN_VAL_V01 = INT_MIN, - QMI_HOST_BUILD_TYPE_UNSPECIFIED_V01 = 0, - QMI_HOST_BUILD_TYPE_PRIMARY_V01 = 1, - QMI_HOST_BUILD_TYPE_SECONDARY_V01 = 2, - WLFW_HOST_BUILD_TYPE_MAX_VAL_V01 = INT_MAX, -}; - -enum wlfw_qmi_param_value_v01 { - WLFW_QMI_PARAM_VALUE_MIN_VAL_V01 = INT_MIN, - QMI_PARAM_INVALID_V01 = 0, - QMI_PARAM_ENABLE_V01 = 1, - QMI_PARAM_DISABLE_V01 = 2, - WLFW_QMI_PARAM_VALUE_MAX_VAL_V01 = INT_MAX, -}; - -enum wlfw_pcie_gen_speed_v01 { - WLFW_PCIE_GEN_SPEED_MIN_VAL_V01 = INT_MIN, - QMI_PCIE_GEN_SPEED_INVALID_V01 = 0, - QMI_PCIE_GEN_SPEED_1_V01 = 1, - QMI_PCIE_GEN_SPEED_2_V01 = 2, - QMI_PCIE_GEN_SPEED_3_V01 = 3, - WLFW_PCIE_GEN_SPEED_MAX_VAL_V01 = INT_MAX, -}; - -#define QMI_WLFW_CE_ATTR_FLAGS_V01 ((u32)0x00) -#define QMI_WLFW_CE_ATTR_NO_SNOOP_V01 ((u32)0x01) -#define QMI_WLFW_CE_ATTR_BYTE_SWAP_DATA_V01 ((u32)0x02) -#define QMI_WLFW_CE_ATTR_SWIZZLE_DESCRIPTORS_V01 ((u32)0x04) -#define QMI_WLFW_CE_ATTR_DISABLE_INTR_V01 ((u32)0x08) -#define QMI_WLFW_CE_ATTR_ENABLE_POLL_V01 ((u32)0x10) - -#define QMI_WLFW_ALREADY_REGISTERED_V01 ((u64)0x01ULL) -#define QMI_WLFW_FW_READY_V01 ((u64)0x02ULL) -#define QMI_WLFW_MSA_READY_V01 ((u64)0x04ULL) -#define QMI_WLFW_FW_MEM_READY_V01 ((u64)0x08ULL) -#define QMI_WLFW_FW_INIT_DONE_V01 ((u64)0x10ULL) - -#define QMI_WLFW_FW_REJUVENATE_V01 ((u64)0x01ULL) - -#define QMI_WLFW_HW_XPA_V01 ((u64)0x01ULL) -#define QMI_WLFW_CBC_FILE_DOWNLOAD_V01 ((u64)0x02ULL) - -#define QMI_WLFW_HOST_PCIE_GEN_SWITCH_V01 ((u64)0x01ULL) - -struct wlfw_ce_tgt_pipe_cfg_s_v01 { - u32 pipe_num; - enum wlfw_pipedir_enum_v01 pipe_dir; - u32 nentries; - u32 nbytes_max; - u32 flags; -}; - -struct wlfw_ce_svc_pipe_cfg_s_v01 { - u32 service_id; - enum wlfw_pipedir_enum_v01 pipe_dir; - u32 pipe_num; -}; - -struct wlfw_shadow_reg_cfg_s_v01 { - u16 id; - u16 offset; -}; - -struct wlfw_shadow_reg_v2_cfg_s_v01 { - u32 addr; -}; - -struct wlfw_rri_over_ddr_cfg_s_v01 { - u32 base_addr_low; - u32 base_addr_high; -}; - -struct wlfw_msi_cfg_s_v01 { - u16 ce_id; - u16 msi_vector; -}; - -struct wlfw_memory_region_info_s_v01 { - u64 region_addr; - u32 size; - u8 secure_flag; -}; - -struct wlfw_mem_cfg_s_v01 { - u64 offset; - u32 size; - u8 secure_flag; -}; - -struct wlfw_mem_seg_s_v01 { - u32 size; - enum wlfw_mem_type_enum_v01 type; - u32 mem_cfg_len; - struct wlfw_mem_cfg_s_v01 mem_cfg[QMI_WLFW_MAX_NUM_MEM_CFG_V01]; -}; - -struct wlfw_mem_seg_resp_s_v01 { - u64 addr; - u32 size; - enum wlfw_mem_type_enum_v01 type; - u8 restore; -}; - -struct wlfw_rf_chip_info_s_v01 { - u32 chip_id; - u32 chip_family; -}; - -struct wlfw_rf_board_info_s_v01 { - u32 board_id; -}; - -struct wlfw_soc_info_s_v01 { - u32 soc_id; -}; - -struct wlfw_fw_version_info_s_v01 { - u32 fw_version; - char fw_build_timestamp[QMI_WLFW_MAX_TIMESTAMP_LEN_V01 + 1]; -}; - -struct wlfw_host_ddr_range_s_v01 { - u64 start; - u64 size; -}; - -struct wlfw_ind_register_req_msg_v01 { - u8 fw_ready_enable_valid; - u8 fw_ready_enable; - u8 initiate_cal_download_enable_valid; - u8 initiate_cal_download_enable; - u8 initiate_cal_update_enable_valid; - u8 initiate_cal_update_enable; - u8 msa_ready_enable_valid; - u8 msa_ready_enable; - u8 pin_connect_result_enable_valid; - u8 pin_connect_result_enable; - u8 client_id_valid; - u32 client_id; - u8 request_mem_enable_valid; - u8 request_mem_enable; - u8 fw_mem_ready_enable_valid; - u8 fw_mem_ready_enable; - u8 fw_init_done_enable_valid; - u8 fw_init_done_enable; - u8 rejuvenate_enable_valid; - u32 rejuvenate_enable; - u8 xo_cal_enable_valid; - u8 xo_cal_enable; - u8 cal_done_enable_valid; - u8 cal_done_enable; - u8 qdss_trace_req_mem_enable_valid; - u8 qdss_trace_req_mem_enable; - u8 qdss_trace_save_enable_valid; - u8 qdss_trace_save_enable; - u8 qdss_trace_free_enable_valid; - u8 qdss_trace_free_enable; - u8 respond_get_info_enable_valid; - u8 respond_get_info_enable; - u8 m3_dump_upload_req_enable_valid; - u8 m3_dump_upload_req_enable; - u8 wfc_call_twt_config_enable_valid; - u8 wfc_call_twt_config_enable; - u8 qdss_mem_ready_enable_valid; - u8 qdss_mem_ready_enable; -}; - -#define WLFW_IND_REGISTER_REQ_MSG_V01_MAX_MSG_LEN 82 -extern struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[]; - -struct wlfw_ind_register_resp_msg_v01 { - struct qmi_response_type_v01 resp; - u8 fw_status_valid; - u64 fw_status; -}; - -#define WLFW_IND_REGISTER_RESP_MSG_V01_MAX_MSG_LEN 18 -extern struct qmi_elem_info wlfw_ind_register_resp_msg_v01_ei[]; - -struct wlfw_fw_ready_ind_msg_v01 { - char placeholder; -}; - -#define WLFW_FW_READY_IND_MSG_V01_MAX_MSG_LEN 0 -extern struct qmi_elem_info wlfw_fw_ready_ind_msg_v01_ei[]; - -struct wlfw_msa_ready_ind_msg_v01 { - u8 hang_data_addr_offset_valid; - u32 hang_data_addr_offset; - u8 hang_data_length_valid; - u16 hang_data_length; -}; - -#define WLFW_MSA_READY_IND_MSG_V01_MAX_MSG_LEN 12 -extern struct qmi_elem_info wlfw_msa_ready_ind_msg_v01_ei[]; - -struct wlfw_pin_connect_result_ind_msg_v01 { - u8 pwr_pin_result_valid; - u32 pwr_pin_result; - u8 phy_io_pin_result_valid; - u32 phy_io_pin_result; - u8 rf_pin_result_valid; - u32 rf_pin_result; -}; - -#define WLFW_PIN_CONNECT_RESULT_IND_MSG_V01_MAX_MSG_LEN 21 -extern struct qmi_elem_info wlfw_pin_connect_result_ind_msg_v01_ei[]; - -struct wlfw_wlan_mode_req_msg_v01 { - enum wlfw_driver_mode_enum_v01 mode; - u8 hw_debug_valid; - u8 hw_debug; -}; - -#define WLFW_WLAN_MODE_REQ_MSG_V01_MAX_MSG_LEN 11 -extern struct qmi_elem_info wlfw_wlan_mode_req_msg_v01_ei[]; - -struct wlfw_wlan_mode_resp_msg_v01 { - struct qmi_response_type_v01 resp; -}; - -#define WLFW_WLAN_MODE_RESP_MSG_V01_MAX_MSG_LEN 7 -extern struct qmi_elem_info wlfw_wlan_mode_resp_msg_v01_ei[]; - -struct wlfw_wlan_cfg_req_msg_v01 { - u8 host_version_valid; - char host_version[QMI_WLFW_MAX_STR_LEN_V01 + 1]; - u8 tgt_cfg_valid; - u32 tgt_cfg_len; - struct wlfw_ce_tgt_pipe_cfg_s_v01 tgt_cfg[QMI_WLFW_MAX_NUM_CE_V01]; - u8 svc_cfg_valid; - u32 svc_cfg_len; - struct wlfw_ce_svc_pipe_cfg_s_v01 svc_cfg[QMI_WLFW_MAX_NUM_SVC_V01]; - u8 shadow_reg_valid; - u32 shadow_reg_len; - struct wlfw_shadow_reg_cfg_s_v01 - shadow_reg[QMI_WLFW_MAX_NUM_SHADOW_REG_V01]; - u8 shadow_reg_v2_valid; - u32 shadow_reg_v2_len; - struct wlfw_shadow_reg_v2_cfg_s_v01 - shadow_reg_v2[QMI_WLFW_MAX_NUM_SHADOW_REG_V2_V01]; - u8 rri_over_ddr_cfg_valid; - struct wlfw_rri_over_ddr_cfg_s_v01 rri_over_ddr_cfg; - u8 msi_cfg_valid; - u32 msi_cfg_len; - struct wlfw_msi_cfg_s_v01 msi_cfg[QMI_WLFW_MAX_NUM_CE_V01]; -}; - -#define WLFW_WLAN_CFG_REQ_MSG_V01_MAX_MSG_LEN 866 -extern struct qmi_elem_info wlfw_wlan_cfg_req_msg_v01_ei[]; - -struct wlfw_wlan_cfg_resp_msg_v01 { - struct qmi_response_type_v01 resp; -}; - -#define WLFW_WLAN_CFG_RESP_MSG_V01_MAX_MSG_LEN 7 -extern struct qmi_elem_info wlfw_wlan_cfg_resp_msg_v01_ei[]; - -struct wlfw_cap_req_msg_v01 { - char placeholder; -}; - -#define WLFW_CAP_REQ_MSG_V01_MAX_MSG_LEN 0 -extern struct qmi_elem_info wlfw_cap_req_msg_v01_ei[]; - -struct wlfw_cap_resp_msg_v01 { - struct qmi_response_type_v01 resp; - u8 chip_info_valid; - struct wlfw_rf_chip_info_s_v01 chip_info; - u8 board_info_valid; - struct wlfw_rf_board_info_s_v01 board_info; - u8 soc_info_valid; - struct wlfw_soc_info_s_v01 soc_info; - u8 fw_version_info_valid; - struct wlfw_fw_version_info_s_v01 fw_version_info; - u8 fw_build_id_valid; - char fw_build_id[QMI_WLFW_MAX_BUILD_ID_LEN_V01 + 1]; - u8 num_macs_valid; - u8 num_macs; - u8 voltage_mv_valid; - u32 voltage_mv; - u8 time_freq_hz_valid; - u32 time_freq_hz; - u8 otp_version_valid; - u32 otp_version; - u8 eeprom_caldata_read_timeout_valid; - u32 eeprom_caldata_read_timeout; - u8 fw_caps_valid; - u64 fw_caps; -}; - -#define WLFW_CAP_RESP_MSG_V01_MAX_MSG_LEN 246 -extern struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[]; - -struct wlfw_bdf_download_req_msg_v01 { - u8 valid; - u8 file_id_valid; - enum wlfw_cal_temp_id_enum_v01 file_id; - u8 total_size_valid; - u32 total_size; - u8 seg_id_valid; - u32 seg_id; - u8 data_valid; - u32 data_len; - u8 data[QMI_WLFW_MAX_DATA_SIZE_V01]; - u8 end_valid; - u8 end; - u8 bdf_type_valid; - u8 bdf_type; -}; - -#define WLFW_BDF_DOWNLOAD_REQ_MSG_V01_MAX_MSG_LEN 6182 -extern struct qmi_elem_info wlfw_bdf_download_req_msg_v01_ei[]; - -struct wlfw_bdf_download_resp_msg_v01 { - struct qmi_response_type_v01 resp; - u8 host_bdf_data_valid; - u64 host_bdf_data; -}; - -#define WLFW_BDF_DOWNLOAD_RESP_MSG_V01_MAX_MSG_LEN 18 -extern struct qmi_elem_info wlfw_bdf_download_resp_msg_v01_ei[]; - -struct wlfw_cal_report_req_msg_v01 { - u32 meta_data_len; - enum wlfw_cal_temp_id_enum_v01 meta_data[QMI_WLFW_MAX_NUM_CAL_V01]; - u8 xo_cal_data_valid; - u8 xo_cal_data; - u8 cal_remove_supported_valid; - u8 cal_remove_supported; -}; - -#define WLFW_CAL_REPORT_REQ_MSG_V01_MAX_MSG_LEN 32 -extern struct qmi_elem_info wlfw_cal_report_req_msg_v01_ei[]; - -struct wlfw_cal_report_resp_msg_v01 { - struct qmi_response_type_v01 resp; -}; - -#define WLFW_CAL_REPORT_RESP_MSG_V01_MAX_MSG_LEN 7 -extern struct qmi_elem_info wlfw_cal_report_resp_msg_v01_ei[]; - -struct wlfw_initiate_cal_download_ind_msg_v01 { - enum wlfw_cal_temp_id_enum_v01 cal_id; - u8 total_size_valid; - u32 total_size; - u8 cal_data_location_valid; - u32 cal_data_location; -}; - -#define WLFW_INITIATE_CAL_DOWNLOAD_IND_MSG_V01_MAX_MSG_LEN 21 -extern struct qmi_elem_info wlfw_initiate_cal_download_ind_msg_v01_ei[]; - -struct wlfw_cal_download_req_msg_v01 { - u8 valid; - u8 file_id_valid; - enum wlfw_cal_temp_id_enum_v01 file_id; - u8 total_size_valid; - u32 total_size; - u8 seg_id_valid; - u32 seg_id; - u8 data_valid; - u32 data_len; - u8 data[QMI_WLFW_MAX_DATA_SIZE_V01]; - u8 end_valid; - u8 end; - u8 cal_data_location_valid; - u32 cal_data_location; -}; - -#define WLFW_CAL_DOWNLOAD_REQ_MSG_V01_MAX_MSG_LEN 6185 -extern struct qmi_elem_info wlfw_cal_download_req_msg_v01_ei[]; - -struct wlfw_cal_download_resp_msg_v01 { - struct qmi_response_type_v01 resp; -}; - -#define WLFW_CAL_DOWNLOAD_RESP_MSG_V01_MAX_MSG_LEN 7 -extern struct qmi_elem_info wlfw_cal_download_resp_msg_v01_ei[]; - -struct wlfw_initiate_cal_update_ind_msg_v01 { - enum wlfw_cal_temp_id_enum_v01 cal_id; - u32 total_size; - u8 cal_data_location_valid; - u32 cal_data_location; -}; - -#define WLFW_INITIATE_CAL_UPDATE_IND_MSG_V01_MAX_MSG_LEN 21 -extern struct qmi_elem_info wlfw_initiate_cal_update_ind_msg_v01_ei[]; - -struct wlfw_cal_update_req_msg_v01 { - enum wlfw_cal_temp_id_enum_v01 cal_id; - u32 seg_id; -}; - -#define WLFW_CAL_UPDATE_REQ_MSG_V01_MAX_MSG_LEN 14 -extern struct qmi_elem_info wlfw_cal_update_req_msg_v01_ei[]; - -struct wlfw_cal_update_resp_msg_v01 { - struct qmi_response_type_v01 resp; - u8 file_id_valid; - enum wlfw_cal_temp_id_enum_v01 file_id; - u8 total_size_valid; - u32 total_size; - u8 seg_id_valid; - u32 seg_id; - u8 data_valid; - u32 data_len; - u8 data[QMI_WLFW_MAX_DATA_SIZE_V01]; - u8 end_valid; - u8 end; - u8 cal_data_location_valid; - u32 cal_data_location; -}; - -#define WLFW_CAL_UPDATE_RESP_MSG_V01_MAX_MSG_LEN 6188 -extern struct qmi_elem_info wlfw_cal_update_resp_msg_v01_ei[]; - -struct wlfw_msa_info_req_msg_v01 { - u64 msa_addr; - u32 size; -}; - -#define WLFW_MSA_INFO_REQ_MSG_V01_MAX_MSG_LEN 18 -extern struct qmi_elem_info wlfw_msa_info_req_msg_v01_ei[]; - -struct wlfw_msa_info_resp_msg_v01 { - struct qmi_response_type_v01 resp; - u32 mem_region_info_len; - struct wlfw_memory_region_info_s_v01 - mem_region_info[QMI_WLFW_MAX_NUM_MEMORY_REGIONS_V01]; -}; - -#define WLFW_MSA_INFO_RESP_MSG_V01_MAX_MSG_LEN 37 -extern struct qmi_elem_info wlfw_msa_info_resp_msg_v01_ei[]; - -struct wlfw_msa_ready_req_msg_v01 { - char placeholder; -}; - -#define WLFW_MSA_READY_REQ_MSG_V01_MAX_MSG_LEN 0 -extern struct qmi_elem_info wlfw_msa_ready_req_msg_v01_ei[]; - -struct wlfw_msa_ready_resp_msg_v01 { - struct qmi_response_type_v01 resp; -}; - -#define WLFW_MSA_READY_RESP_MSG_V01_MAX_MSG_LEN 7 -extern struct qmi_elem_info wlfw_msa_ready_resp_msg_v01_ei[]; - -struct wlfw_ini_req_msg_v01 { - u8 enablefwlog_valid; - u8 enablefwlog; -}; - -#define WLFW_INI_REQ_MSG_V01_MAX_MSG_LEN 4 -extern struct qmi_elem_info wlfw_ini_req_msg_v01_ei[]; - -struct wlfw_ini_resp_msg_v01 { - struct qmi_response_type_v01 resp; -}; - -#define WLFW_INI_RESP_MSG_V01_MAX_MSG_LEN 7 -extern struct qmi_elem_info wlfw_ini_resp_msg_v01_ei[]; - -struct wlfw_athdiag_read_req_msg_v01 { - u32 offset; - u32 mem_type; - u32 data_len; -}; - -#define WLFW_ATHDIAG_READ_REQ_MSG_V01_MAX_MSG_LEN 21 -extern struct qmi_elem_info wlfw_athdiag_read_req_msg_v01_ei[]; - -struct wlfw_athdiag_read_resp_msg_v01 { - struct qmi_response_type_v01 resp; - u8 data_valid; - u32 data_len; - u8 data[QMI_WLFW_MAX_ATHDIAG_DATA_SIZE_V01]; -}; - -#define WLFW_ATHDIAG_READ_RESP_MSG_V01_MAX_MSG_LEN 6156 -extern struct qmi_elem_info wlfw_athdiag_read_resp_msg_v01_ei[]; - -struct wlfw_athdiag_write_req_msg_v01 { - u32 offset; - u32 mem_type; - u32 data_len; - u8 data[QMI_WLFW_MAX_ATHDIAG_DATA_SIZE_V01]; -}; - -#define WLFW_ATHDIAG_WRITE_REQ_MSG_V01_MAX_MSG_LEN 6163 -extern struct qmi_elem_info wlfw_athdiag_write_req_msg_v01_ei[]; - -struct wlfw_athdiag_write_resp_msg_v01 { - struct qmi_response_type_v01 resp; -}; - -#define WLFW_ATHDIAG_WRITE_RESP_MSG_V01_MAX_MSG_LEN 7 -extern struct qmi_elem_info wlfw_athdiag_write_resp_msg_v01_ei[]; - -struct wlfw_vbatt_req_msg_v01 { - u64 voltage_uv; -}; - -#define WLFW_VBATT_REQ_MSG_V01_MAX_MSG_LEN 11 -extern struct qmi_elem_info wlfw_vbatt_req_msg_v01_ei[]; - -struct wlfw_vbatt_resp_msg_v01 { - struct qmi_response_type_v01 resp; -}; - -#define WLFW_VBATT_RESP_MSG_V01_MAX_MSG_LEN 7 -extern struct qmi_elem_info wlfw_vbatt_resp_msg_v01_ei[]; - -struct wlfw_mac_addr_req_msg_v01 { - u8 mac_addr_valid; - u8 mac_addr[QMI_WLFW_MAC_ADDR_SIZE_V01]; -}; - -#define WLFW_MAC_ADDR_REQ_MSG_V01_MAX_MSG_LEN 9 -extern struct qmi_elem_info wlfw_mac_addr_req_msg_v01_ei[]; - -struct wlfw_mac_addr_resp_msg_v01 { - struct qmi_response_type_v01 resp; -}; - -#define WLFW_MAC_ADDR_RESP_MSG_V01_MAX_MSG_LEN 7 -extern struct qmi_elem_info wlfw_mac_addr_resp_msg_v01_ei[]; - -struct wlfw_host_cap_req_msg_v01 { - u8 num_clients_valid; - u32 num_clients; - u8 wake_msi_valid; - u32 wake_msi; - u8 gpios_valid; - u32 gpios_len; - u32 gpios[QMI_WLFW_MAX_NUM_GPIO_V01]; - u8 nm_modem_valid; - u8 nm_modem; - u8 bdf_support_valid; - u8 bdf_support; - u8 bdf_cache_support_valid; - u8 bdf_cache_support; - u8 m3_support_valid; - u8 m3_support; - u8 m3_cache_support_valid; - u8 m3_cache_support; - u8 cal_filesys_support_valid; - u8 cal_filesys_support; - u8 cal_cache_support_valid; - u8 cal_cache_support; - u8 cal_done_valid; - u8 cal_done; - u8 mem_bucket_valid; - u32 mem_bucket; - u8 mem_cfg_mode_valid; - u8 mem_cfg_mode; - u8 cal_duration_valid; - u16 cal_duration; - u8 platform_name_valid; - char platform_name[QMI_WLFW_MAX_PLATFORM_NAME_LEN_V01 + 1]; - u8 ddr_range_valid; - struct wlfw_host_ddr_range_s_v01 - ddr_range[QMI_WLFW_MAX_HOST_DDR_RANGE_SIZE_V01]; - u8 host_build_type_valid; - enum wlfw_host_build_type_v01 host_build_type; -}; - -#define WLFW_HOST_CAP_REQ_MSG_V01_MAX_MSG_LEN 319 -extern struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[]; - -struct wlfw_host_cap_resp_msg_v01 { - struct qmi_response_type_v01 resp; -}; - -#define WLFW_HOST_CAP_RESP_MSG_V01_MAX_MSG_LEN 7 -extern struct qmi_elem_info wlfw_host_cap_resp_msg_v01_ei[]; - -struct wlfw_request_mem_ind_msg_v01 { - u32 mem_seg_len; - struct wlfw_mem_seg_s_v01 mem_seg[QMI_WLFW_MAX_NUM_MEM_SEG_V01]; -}; - -#define WLFW_REQUEST_MEM_IND_MSG_V01_MAX_MSG_LEN 1124 -extern struct qmi_elem_info wlfw_request_mem_ind_msg_v01_ei[]; - -struct wlfw_respond_mem_req_msg_v01 { - u32 mem_seg_len; - struct wlfw_mem_seg_resp_s_v01 mem_seg[QMI_WLFW_MAX_NUM_MEM_SEG_V01]; -}; - -#define WLFW_RESPOND_MEM_REQ_MSG_V01_MAX_MSG_LEN 548 -extern struct qmi_elem_info wlfw_respond_mem_req_msg_v01_ei[]; - -struct wlfw_respond_mem_resp_msg_v01 { - struct qmi_response_type_v01 resp; -}; - -#define WLFW_RESPOND_MEM_RESP_MSG_V01_MAX_MSG_LEN 7 -extern struct qmi_elem_info wlfw_respond_mem_resp_msg_v01_ei[]; - -struct wlfw_fw_mem_ready_ind_msg_v01 { - char placeholder; -}; - -#define WLFW_FW_MEM_READY_IND_MSG_V01_MAX_MSG_LEN 0 -extern struct qmi_elem_info wlfw_fw_mem_ready_ind_msg_v01_ei[]; - -struct wlfw_fw_init_done_ind_msg_v01 { - char placeholder; -}; - -#define WLFW_FW_INIT_DONE_IND_MSG_V01_MAX_MSG_LEN 0 -extern struct qmi_elem_info wlfw_fw_init_done_ind_msg_v01_ei[]; - -struct wlfw_rejuvenate_ind_msg_v01 { - u8 cause_for_rejuvenation_valid; - u8 cause_for_rejuvenation; - u8 requesting_sub_system_valid; - u8 requesting_sub_system; - u8 line_number_valid; - u16 line_number; - u8 function_name_valid; - char function_name[QMI_WLFW_FUNCTION_NAME_LEN_V01 + 1]; -}; - -#define WLFW_REJUVENATE_IND_MSG_V01_MAX_MSG_LEN 144 -extern struct qmi_elem_info wlfw_rejuvenate_ind_msg_v01_ei[]; - -struct wlfw_rejuvenate_ack_req_msg_v01 { - char placeholder; -}; - -#define WLFW_REJUVENATE_ACK_REQ_MSG_V01_MAX_MSG_LEN 0 -extern struct qmi_elem_info wlfw_rejuvenate_ack_req_msg_v01_ei[]; - -struct wlfw_rejuvenate_ack_resp_msg_v01 { - struct qmi_response_type_v01 resp; -}; - -#define WLFW_REJUVENATE_ACK_RESP_MSG_V01_MAX_MSG_LEN 7 -extern struct qmi_elem_info wlfw_rejuvenate_ack_resp_msg_v01_ei[]; - -struct wlfw_dynamic_feature_mask_req_msg_v01 { - u8 mask_valid; - u64 mask; -}; - -#define WLFW_DYNAMIC_FEATURE_MASK_REQ_MSG_V01_MAX_MSG_LEN 11 -extern struct qmi_elem_info wlfw_dynamic_feature_mask_req_msg_v01_ei[]; - -struct wlfw_dynamic_feature_mask_resp_msg_v01 { - struct qmi_response_type_v01 resp; - u8 prev_mask_valid; - u64 prev_mask; - u8 curr_mask_valid; - u64 curr_mask; -}; - -#define WLFW_DYNAMIC_FEATURE_MASK_RESP_MSG_V01_MAX_MSG_LEN 29 -extern struct qmi_elem_info wlfw_dynamic_feature_mask_resp_msg_v01_ei[]; - -struct wlfw_m3_info_req_msg_v01 { - u64 addr; - u32 size; -}; - -#define WLFW_M3_INFO_REQ_MSG_V01_MAX_MSG_LEN 18 -extern struct qmi_elem_info wlfw_m3_info_req_msg_v01_ei[]; - -struct wlfw_m3_info_resp_msg_v01 { - struct qmi_response_type_v01 resp; -}; - -#define WLFW_M3_INFO_RESP_MSG_V01_MAX_MSG_LEN 7 -extern struct qmi_elem_info wlfw_m3_info_resp_msg_v01_ei[]; - -struct wlfw_xo_cal_ind_msg_v01 { - u8 xo_cal_data; -}; - -#define WLFW_XO_CAL_IND_MSG_V01_MAX_MSG_LEN 4 -extern struct qmi_elem_info wlfw_xo_cal_ind_msg_v01_ei[]; - -struct wlfw_cal_done_ind_msg_v01 { - char placeholder; -}; - -#define WLFW_CAL_DONE_IND_MSG_V01_MAX_MSG_LEN 0 -extern struct qmi_elem_info wlfw_cal_done_ind_msg_v01_ei[]; - -struct wlfw_qdss_trace_req_mem_ind_msg_v01 { - u32 mem_seg_len; - struct wlfw_mem_seg_s_v01 mem_seg[QMI_WLFW_MAX_NUM_MEM_SEG_V01]; -}; - -#define WLFW_QDSS_TRACE_REQ_MEM_IND_MSG_V01_MAX_MSG_LEN 1124 -extern struct qmi_elem_info wlfw_qdss_trace_req_mem_ind_msg_v01_ei[]; - -struct wlfw_qdss_trace_mem_info_req_msg_v01 { - u32 mem_seg_len; - struct wlfw_mem_seg_resp_s_v01 mem_seg[QMI_WLFW_MAX_NUM_MEM_SEG_V01]; -}; - -#define WLFW_QDSS_TRACE_MEM_INFO_REQ_MSG_V01_MAX_MSG_LEN 548 -extern struct qmi_elem_info wlfw_qdss_trace_mem_info_req_msg_v01_ei[]; - -struct wlfw_qdss_trace_mem_info_resp_msg_v01 { - struct qmi_response_type_v01 resp; -}; - -#define WLFW_QDSS_TRACE_MEM_INFO_RESP_MSG_V01_MAX_MSG_LEN 7 -extern struct qmi_elem_info wlfw_qdss_trace_mem_info_resp_msg_v01_ei[]; - -struct wlfw_qdss_trace_save_ind_msg_v01 { - u32 source; - u32 total_size; - u8 mem_seg_valid; - u32 mem_seg_len; - struct wlfw_mem_seg_resp_s_v01 mem_seg[QMI_WLFW_MAX_NUM_MEM_SEG_V01]; - u8 file_name_valid; - char file_name[QMI_WLFW_MAX_STR_LEN_V01 + 1]; -}; - -#define WLFW_QDSS_TRACE_SAVE_IND_MSG_V01_MAX_MSG_LEN 581 -extern struct qmi_elem_info wlfw_qdss_trace_save_ind_msg_v01_ei[]; - -struct wlfw_qdss_trace_data_req_msg_v01 { - u32 seg_id; -}; - -#define WLFW_QDSS_TRACE_DATA_REQ_MSG_V01_MAX_MSG_LEN 7 -extern struct qmi_elem_info wlfw_qdss_trace_data_req_msg_v01_ei[]; - -struct wlfw_qdss_trace_data_resp_msg_v01 { - struct qmi_response_type_v01 resp; - u8 total_size_valid; - u32 total_size; - u8 seg_id_valid; - u32 seg_id; - u8 data_valid; - u32 data_len; - u8 data[QMI_WLFW_MAX_DATA_SIZE_V01]; - u8 end_valid; - u8 end; -}; - -#define WLFW_QDSS_TRACE_DATA_RESP_MSG_V01_MAX_MSG_LEN 6174 -extern struct qmi_elem_info wlfw_qdss_trace_data_resp_msg_v01_ei[]; - -struct wlfw_qdss_trace_config_download_req_msg_v01 { - u8 total_size_valid; - u32 total_size; - u8 seg_id_valid; - u32 seg_id; - u8 data_valid; - u32 data_len; - u8 data[QMI_WLFW_MAX_DATA_SIZE_V01]; - u8 end_valid; - u8 end; -}; - -#define WLFW_QDSS_TRACE_CONFIG_DOWNLOAD_REQ_MSG_V01_MAX_MSG_LEN 6167 -extern struct qmi_elem_info wlfw_qdss_trace_config_download_req_msg_v01_ei[]; - -struct wlfw_qdss_trace_config_download_resp_msg_v01 { - struct qmi_response_type_v01 resp; -}; - -#define WLFW_QDSS_TRACE_CONFIG_DOWNLOAD_RESP_MSG_V01_MAX_MSG_LEN 7 -extern struct qmi_elem_info wlfw_qdss_trace_config_download_resp_msg_v01_ei[]; - -struct wlfw_qdss_trace_mode_req_msg_v01 { - u8 mode_valid; - enum wlfw_qdss_trace_mode_enum_v01 mode; - u8 option_valid; - u64 option; - u8 hw_trc_disable_override_valid; - enum wlfw_qmi_param_value_v01 hw_trc_disable_override; -}; - -#define WLFW_QDSS_TRACE_MODE_REQ_MSG_V01_MAX_MSG_LEN 25 -extern struct qmi_elem_info wlfw_qdss_trace_mode_req_msg_v01_ei[]; - -struct wlfw_qdss_trace_mode_resp_msg_v01 { - struct qmi_response_type_v01 resp; -}; - -#define WLFW_QDSS_TRACE_MODE_RESP_MSG_V01_MAX_MSG_LEN 7 -extern struct qmi_elem_info wlfw_qdss_trace_mode_resp_msg_v01_ei[]; - -struct wlfw_qdss_trace_free_ind_msg_v01 { - u8 mem_seg_valid; - u32 mem_seg_len; - struct wlfw_mem_seg_resp_s_v01 mem_seg[QMI_WLFW_MAX_NUM_MEM_SEG_V01]; -}; - -#define WLFW_QDSS_TRACE_FREE_IND_MSG_V01_MAX_MSG_LEN 548 -extern struct qmi_elem_info wlfw_qdss_trace_free_ind_msg_v01_ei[]; - -struct wlfw_shutdown_req_msg_v01 { - u8 shutdown_valid; - u8 shutdown; -}; - -#define WLFW_SHUTDOWN_REQ_MSG_V01_MAX_MSG_LEN 4 -extern struct qmi_elem_info wlfw_shutdown_req_msg_v01_ei[]; - -struct wlfw_shutdown_resp_msg_v01 { - struct qmi_response_type_v01 resp; -}; - -#define WLFW_SHUTDOWN_RESP_MSG_V01_MAX_MSG_LEN 7 -extern struct qmi_elem_info wlfw_shutdown_resp_msg_v01_ei[]; - -struct wlfw_antenna_switch_req_msg_v01 { - char placeholder; -}; - -#define WLFW_ANTENNA_SWITCH_REQ_MSG_V01_MAX_MSG_LEN 0 -extern struct qmi_elem_info wlfw_antenna_switch_req_msg_v01_ei[]; - -struct wlfw_antenna_switch_resp_msg_v01 { - struct qmi_response_type_v01 resp; - u8 antenna_valid; - u64 antenna; -}; - -#define WLFW_ANTENNA_SWITCH_RESP_MSG_V01_MAX_MSG_LEN 18 -extern struct qmi_elem_info wlfw_antenna_switch_resp_msg_v01_ei[]; - -struct wlfw_antenna_grant_req_msg_v01 { - u8 grant_valid; - u64 grant; -}; - -#define WLFW_ANTENNA_GRANT_REQ_MSG_V01_MAX_MSG_LEN 11 -extern struct qmi_elem_info wlfw_antenna_grant_req_msg_v01_ei[]; - -struct wlfw_antenna_grant_resp_msg_v01 { - struct qmi_response_type_v01 resp; -}; - -#define WLFW_ANTENNA_GRANT_RESP_MSG_V01_MAX_MSG_LEN 7 -extern struct qmi_elem_info wlfw_antenna_grant_resp_msg_v01_ei[]; - -struct wlfw_wfc_call_status_req_msg_v01 { - u32 wfc_call_status_len; - u8 wfc_call_status[QMI_WLFW_MAX_WFC_CALL_STATUS_DATA_SIZE_V01]; - u8 wfc_call_active_valid; - u8 wfc_call_active; - u8 all_wfc_calls_held_valid; - u8 all_wfc_calls_held; - u8 is_wfc_emergency_valid; - u8 is_wfc_emergency; - u8 twt_ims_start_valid; - u64 twt_ims_start; - u8 twt_ims_int_valid; - u16 twt_ims_int; - u8 media_quality_valid; - enum wlfw_wfc_media_quality_v01 media_quality; -}; - -#define WLFW_WFC_CALL_STATUS_REQ_MSG_V01_MAX_MSG_LEN 296 -extern struct qmi_elem_info wlfw_wfc_call_status_req_msg_v01_ei[]; - -struct wlfw_wfc_call_status_resp_msg_v01 { - struct qmi_response_type_v01 resp; -}; - -#define WLFW_WFC_CALL_STATUS_RESP_MSG_V01_MAX_MSG_LEN 7 -extern struct qmi_elem_info wlfw_wfc_call_status_resp_msg_v01_ei[]; - -struct wlfw_get_info_req_msg_v01 { - u8 type; - u32 data_len; - u8 data[QMI_WLFW_MAX_DATA_SIZE_V01]; -}; - -#define WLFW_GET_INFO_REQ_MSG_V01_MAX_MSG_LEN 6153 -extern struct qmi_elem_info wlfw_get_info_req_msg_v01_ei[]; - -struct wlfw_get_info_resp_msg_v01 { - struct qmi_response_type_v01 resp; -}; - -#define WLFW_GET_INFO_RESP_MSG_V01_MAX_MSG_LEN 7 -extern struct qmi_elem_info wlfw_get_info_resp_msg_v01_ei[]; - -struct wlfw_respond_get_info_ind_msg_v01 { - u32 data_len; - u8 data[QMI_WLFW_MAX_DATA_SIZE_V01]; - u8 type_valid; - u8 type; - u8 is_last_valid; - u8 is_last; - u8 seq_no_valid; - u32 seq_no; -}; - -#define WLFW_RESPOND_GET_INFO_IND_MSG_V01_MAX_MSG_LEN 6164 -extern struct qmi_elem_info wlfw_respond_get_info_ind_msg_v01_ei[]; - -struct wlfw_device_info_req_msg_v01 { - char placeholder; -}; - -#define WLFW_DEVICE_INFO_REQ_MSG_V01_MAX_MSG_LEN 0 -extern struct qmi_elem_info wlfw_device_info_req_msg_v01_ei[]; - -struct wlfw_device_info_resp_msg_v01 { - struct qmi_response_type_v01 resp; - u8 bar_addr_valid; - u64 bar_addr; - u8 bar_size_valid; - u32 bar_size; -}; - -#define WLFW_DEVICE_INFO_RESP_MSG_V01_MAX_MSG_LEN 25 -extern struct qmi_elem_info wlfw_device_info_resp_msg_v01_ei[]; - -struct wlfw_m3_dump_upload_req_ind_msg_v01 { - u32 pdev_id; - u64 addr; - u64 size; -}; - -#define WLFW_M3_DUMP_UPLOAD_REQ_IND_MSG_V01_MAX_MSG_LEN 29 -extern struct qmi_elem_info wlfw_m3_dump_upload_req_ind_msg_v01_ei[]; - -struct wlfw_m3_dump_upload_done_req_msg_v01 { - u32 pdev_id; - u32 status; -}; - -#define WLFW_M3_DUMP_UPLOAD_DONE_REQ_MSG_V01_MAX_MSG_LEN 14 -extern struct qmi_elem_info wlfw_m3_dump_upload_done_req_msg_v01_ei[]; - -struct wlfw_m3_dump_upload_done_resp_msg_v01 { - struct qmi_response_type_v01 resp; -}; - -#define WLFW_M3_DUMP_UPLOAD_DONE_RESP_MSG_V01_MAX_MSG_LEN 7 -extern struct qmi_elem_info wlfw_m3_dump_upload_done_resp_msg_v01_ei[]; - -struct wlfw_soc_wake_req_msg_v01 { - u8 wake_valid; - enum wlfw_soc_wake_enum_v01 wake; -}; - -#define WLFW_SOC_WAKE_REQ_MSG_V01_MAX_MSG_LEN 7 -extern struct qmi_elem_info wlfw_soc_wake_req_msg_v01_ei[]; - -struct wlfw_soc_wake_resp_msg_v01 { - struct qmi_response_type_v01 resp; -}; - -#define WLFW_SOC_WAKE_RESP_MSG_V01_MAX_MSG_LEN 7 -extern struct qmi_elem_info wlfw_soc_wake_resp_msg_v01_ei[]; - -struct wlfw_exit_power_save_req_msg_v01 { - char placeholder; -}; - -#define WLFW_EXIT_POWER_SAVE_REQ_MSG_V01_MAX_MSG_LEN 0 -extern struct qmi_elem_info wlfw_exit_power_save_req_msg_v01_ei[]; - -struct wlfw_exit_power_save_resp_msg_v01 { - struct qmi_response_type_v01 resp; -}; - -#define WLFW_EXIT_POWER_SAVE_RESP_MSG_V01_MAX_MSG_LEN 7 -extern struct qmi_elem_info wlfw_exit_power_save_resp_msg_v01_ei[]; - -struct wlfw_wfc_call_twt_config_ind_msg_v01 { - u8 twt_sta_start_valid; - u64 twt_sta_start; - u8 twt_sta_int_valid; - u16 twt_sta_int; - u8 twt_sta_upo_valid; - u16 twt_sta_upo; - u8 twt_sta_sp_valid; - u16 twt_sta_sp; - u8 twt_sta_dl_valid; - u16 twt_sta_dl; - u8 twt_sta_config_changed_valid; - u8 twt_sta_config_changed; -}; - -#define WLFW_WFC_CALL_TWT_CONFIG_IND_MSG_V01_MAX_MSG_LEN 35 -extern struct qmi_elem_info wlfw_wfc_call_twt_config_ind_msg_v01_ei[]; - -struct wlfw_qdss_mem_ready_ind_msg_v01 { - char placeholder; -}; - -#define WLFW_QDSS_MEM_READY_IND_MSG_V01_MAX_MSG_LEN 0 -extern struct qmi_elem_info wlfw_qdss_mem_ready_ind_msg_v01_ei[]; - -struct wlfw_pcie_gen_switch_req_msg_v01 { - enum wlfw_pcie_gen_speed_v01 pcie_speed; -}; - -#define WLFW_PCIE_GEN_SWITCH_REQ_MSG_V01_MAX_MSG_LEN 7 -extern struct qmi_elem_info wlfw_pcie_gen_switch_req_msg_v01_ei[]; - -struct wlfw_pcie_gen_switch_resp_msg_v01 { - struct qmi_response_type_v01 resp; -}; - -#define WLFW_PCIE_GEN_SWITCH_RESP_MSG_V01_MAX_MSG_LEN 7 -extern struct qmi_elem_info wlfw_pcie_gen_switch_resp_msg_v01_ei[]; - -#endif diff --git a/drivers/net/wireless/cnss_utils/Kconfig b/drivers/net/wireless/cnss_utils/Kconfig index ed1662cd4896..62b7129bbe17 100644 --- a/drivers/net/wireless/cnss_utils/Kconfig +++ b/drivers/net/wireless/cnss_utils/Kconfig @@ -5,4 +5,12 @@ config CNSS_UTILS help Add CNSS utilities support for the WLAN driver module. This feature enables wlan driver to use CNSS utilities APIs to set - and get wlan related information. \ No newline at end of file + and get wlan related information. + +config CNSS_QMI_SVC + tristate "CNSS QMI SVC support" + help + Add CNSS QMI SVC support for the WLAN driver module. + This feature enable wlan driver to use CNSS QMI service APIs to set + and get wlan related information. + diff --git a/drivers/net/wireless/cnss_utils/Makefile b/drivers/net/wireless/cnss_utils/Makefile index aa007fd50508..1b7088904d2e 100644 --- a/drivers/net/wireless/cnss_utils/Makefile +++ b/drivers/net/wireless/cnss_utils/Makefile @@ -1,3 +1,4 @@ # SPDX-License-Identifier: GPL-2.0-only obj-$(CONFIG_CNSS_UTILS) += cnss_utils.o +obj-$(CONFIG_CNSS_QMI_SVC) += wlan_firmware_service_v01.o diff --git a/drivers/soc/qcom/icnss2/wlan_firmware_service_v01.c b/drivers/net/wireless/cnss_utils/wlan_firmware_service_v01.c similarity index 79% rename from drivers/soc/qcom/icnss2/wlan_firmware_service_v01.c rename to drivers/net/wireless/cnss_utils/wlan_firmware_service_v01.c index bda8d11c05c6..b5d348cad289 100644 --- a/drivers/soc/qcom/icnss2/wlan_firmware_service_v01.c +++ b/drivers/net/wireless/cnss_utils/wlan_firmware_service_v01.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only -/* Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. */ +/* Copyright (c) 2020, The Linux Foundation. All rights reserved. */ #include "wlan_firmware_service_v01.h" @@ -10,7 +10,8 @@ static struct qmi_elem_info wlfw_ce_tgt_pipe_cfg_s_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0, - .offset = offsetof(struct wlfw_ce_tgt_pipe_cfg_s_v01, + .offset = offsetof(struct + wlfw_ce_tgt_pipe_cfg_s_v01, pipe_num), }, { @@ -19,7 +20,8 @@ static struct qmi_elem_info wlfw_ce_tgt_pipe_cfg_s_v01_ei[] = { .elem_size = sizeof(enum wlfw_pipedir_enum_v01), .array_type = NO_ARRAY, .tlv_type = 0, - .offset = offsetof(struct wlfw_ce_tgt_pipe_cfg_s_v01, + .offset = offsetof(struct + wlfw_ce_tgt_pipe_cfg_s_v01, pipe_dir), }, { @@ -28,7 +30,8 @@ static struct qmi_elem_info wlfw_ce_tgt_pipe_cfg_s_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0, - .offset = offsetof(struct wlfw_ce_tgt_pipe_cfg_s_v01, + .offset = offsetof(struct + wlfw_ce_tgt_pipe_cfg_s_v01, nentries), }, { @@ -37,7 +40,8 @@ static struct qmi_elem_info wlfw_ce_tgt_pipe_cfg_s_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0, - .offset = offsetof(struct wlfw_ce_tgt_pipe_cfg_s_v01, + .offset = offsetof(struct + wlfw_ce_tgt_pipe_cfg_s_v01, nbytes_max), }, { @@ -46,7 +50,8 @@ static struct qmi_elem_info wlfw_ce_tgt_pipe_cfg_s_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0, - .offset = offsetof(struct wlfw_ce_tgt_pipe_cfg_s_v01, + .offset = offsetof(struct + wlfw_ce_tgt_pipe_cfg_s_v01, flags), }, { @@ -63,7 +68,8 @@ static struct qmi_elem_info wlfw_ce_svc_pipe_cfg_s_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0, - .offset = offsetof(struct wlfw_ce_svc_pipe_cfg_s_v01, + .offset = offsetof(struct + wlfw_ce_svc_pipe_cfg_s_v01, service_id), }, { @@ -72,7 +78,8 @@ static struct qmi_elem_info wlfw_ce_svc_pipe_cfg_s_v01_ei[] = { .elem_size = sizeof(enum wlfw_pipedir_enum_v01), .array_type = NO_ARRAY, .tlv_type = 0, - .offset = offsetof(struct wlfw_ce_svc_pipe_cfg_s_v01, + .offset = offsetof(struct + wlfw_ce_svc_pipe_cfg_s_v01, pipe_dir), }, { @@ -81,7 +88,8 @@ static struct qmi_elem_info wlfw_ce_svc_pipe_cfg_s_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0, - .offset = offsetof(struct wlfw_ce_svc_pipe_cfg_s_v01, + .offset = offsetof(struct + wlfw_ce_svc_pipe_cfg_s_v01, pipe_num), }, { @@ -98,7 +106,8 @@ static struct qmi_elem_info wlfw_shadow_reg_cfg_s_v01_ei[] = { .elem_size = sizeof(u16), .array_type = NO_ARRAY, .tlv_type = 0, - .offset = offsetof(struct wlfw_shadow_reg_cfg_s_v01, + .offset = offsetof(struct + wlfw_shadow_reg_cfg_s_v01, id), }, { @@ -107,7 +116,8 @@ static struct qmi_elem_info wlfw_shadow_reg_cfg_s_v01_ei[] = { .elem_size = sizeof(u16), .array_type = NO_ARRAY, .tlv_type = 0, - .offset = offsetof(struct wlfw_shadow_reg_cfg_s_v01, + .offset = offsetof(struct + wlfw_shadow_reg_cfg_s_v01, offset), }, { @@ -124,7 +134,8 @@ static struct qmi_elem_info wlfw_shadow_reg_v2_cfg_s_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0, - .offset = offsetof(struct wlfw_shadow_reg_v2_cfg_s_v01, + .offset = offsetof(struct + wlfw_shadow_reg_v2_cfg_s_v01, addr), }, { @@ -141,7 +152,8 @@ static struct qmi_elem_info wlfw_rri_over_ddr_cfg_s_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0, - .offset = offsetof(struct wlfw_rri_over_ddr_cfg_s_v01, + .offset = offsetof(struct + wlfw_rri_over_ddr_cfg_s_v01, base_addr_low), }, { @@ -150,7 +162,8 @@ static struct qmi_elem_info wlfw_rri_over_ddr_cfg_s_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0, - .offset = offsetof(struct wlfw_rri_over_ddr_cfg_s_v01, + .offset = offsetof(struct + wlfw_rri_over_ddr_cfg_s_v01, base_addr_high), }, { @@ -167,7 +180,8 @@ static struct qmi_elem_info wlfw_msi_cfg_s_v01_ei[] = { .elem_size = sizeof(u16), .array_type = NO_ARRAY, .tlv_type = 0, - .offset = offsetof(struct wlfw_msi_cfg_s_v01, + .offset = offsetof(struct + wlfw_msi_cfg_s_v01, ce_id), }, { @@ -176,7 +190,8 @@ static struct qmi_elem_info wlfw_msi_cfg_s_v01_ei[] = { .elem_size = sizeof(u16), .array_type = NO_ARRAY, .tlv_type = 0, - .offset = offsetof(struct wlfw_msi_cfg_s_v01, + .offset = offsetof(struct + wlfw_msi_cfg_s_v01, msi_vector), }, { @@ -193,7 +208,8 @@ static struct qmi_elem_info wlfw_memory_region_info_s_v01_ei[] = { .elem_size = sizeof(u64), .array_type = NO_ARRAY, .tlv_type = 0, - .offset = offsetof(struct wlfw_memory_region_info_s_v01, + .offset = offsetof(struct + wlfw_memory_region_info_s_v01, region_addr), }, { @@ -202,7 +218,8 @@ static struct qmi_elem_info wlfw_memory_region_info_s_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0, - .offset = offsetof(struct wlfw_memory_region_info_s_v01, + .offset = offsetof(struct + wlfw_memory_region_info_s_v01, size), }, { @@ -211,7 +228,8 @@ static struct qmi_elem_info wlfw_memory_region_info_s_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0, - .offset = offsetof(struct wlfw_memory_region_info_s_v01, + .offset = offsetof(struct + wlfw_memory_region_info_s_v01, secure_flag), }, { @@ -228,7 +246,8 @@ static struct qmi_elem_info wlfw_mem_cfg_s_v01_ei[] = { .elem_size = sizeof(u64), .array_type = NO_ARRAY, .tlv_type = 0, - .offset = offsetof(struct wlfw_mem_cfg_s_v01, + .offset = offsetof(struct + wlfw_mem_cfg_s_v01, offset), }, { @@ -237,7 +256,8 @@ static struct qmi_elem_info wlfw_mem_cfg_s_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0, - .offset = offsetof(struct wlfw_mem_cfg_s_v01, + .offset = offsetof(struct + wlfw_mem_cfg_s_v01, size), }, { @@ -246,7 +266,8 @@ static struct qmi_elem_info wlfw_mem_cfg_s_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0, - .offset = offsetof(struct wlfw_mem_cfg_s_v01, + .offset = offsetof(struct + wlfw_mem_cfg_s_v01, secure_flag), }, { @@ -263,7 +284,8 @@ static struct qmi_elem_info wlfw_mem_seg_s_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0, - .offset = offsetof(struct wlfw_mem_seg_s_v01, + .offset = offsetof(struct + wlfw_mem_seg_s_v01, size), }, { @@ -272,7 +294,8 @@ static struct qmi_elem_info wlfw_mem_seg_s_v01_ei[] = { .elem_size = sizeof(enum wlfw_mem_type_enum_v01), .array_type = NO_ARRAY, .tlv_type = 0, - .offset = offsetof(struct wlfw_mem_seg_s_v01, + .offset = offsetof(struct + wlfw_mem_seg_s_v01, type), }, { @@ -281,7 +304,8 @@ static struct qmi_elem_info wlfw_mem_seg_s_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0, - .offset = offsetof(struct wlfw_mem_seg_s_v01, + .offset = offsetof(struct + wlfw_mem_seg_s_v01, mem_cfg_len), }, { @@ -290,7 +314,8 @@ static struct qmi_elem_info wlfw_mem_seg_s_v01_ei[] = { .elem_size = sizeof(struct wlfw_mem_cfg_s_v01), .array_type = VAR_LEN_ARRAY, .tlv_type = 0, - .offset = offsetof(struct wlfw_mem_seg_s_v01, + .offset = offsetof(struct + wlfw_mem_seg_s_v01, mem_cfg), .ei_array = wlfw_mem_cfg_s_v01_ei, }, @@ -308,7 +333,8 @@ static struct qmi_elem_info wlfw_mem_seg_resp_s_v01_ei[] = { .elem_size = sizeof(u64), .array_type = NO_ARRAY, .tlv_type = 0, - .offset = offsetof(struct wlfw_mem_seg_resp_s_v01, + .offset = offsetof(struct + wlfw_mem_seg_resp_s_v01, addr), }, { @@ -317,7 +343,8 @@ static struct qmi_elem_info wlfw_mem_seg_resp_s_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0, - .offset = offsetof(struct wlfw_mem_seg_resp_s_v01, + .offset = offsetof(struct + wlfw_mem_seg_resp_s_v01, size), }, { @@ -326,7 +353,8 @@ static struct qmi_elem_info wlfw_mem_seg_resp_s_v01_ei[] = { .elem_size = sizeof(enum wlfw_mem_type_enum_v01), .array_type = NO_ARRAY, .tlv_type = 0, - .offset = offsetof(struct wlfw_mem_seg_resp_s_v01, + .offset = offsetof(struct + wlfw_mem_seg_resp_s_v01, type), }, { @@ -335,7 +363,8 @@ static struct qmi_elem_info wlfw_mem_seg_resp_s_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0, - .offset = offsetof(struct wlfw_mem_seg_resp_s_v01, + .offset = offsetof(struct + wlfw_mem_seg_resp_s_v01, restore), }, { @@ -352,7 +381,8 @@ static struct qmi_elem_info wlfw_rf_chip_info_s_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0, - .offset = offsetof(struct wlfw_rf_chip_info_s_v01, + .offset = offsetof(struct + wlfw_rf_chip_info_s_v01, chip_id), }, { @@ -361,7 +391,8 @@ static struct qmi_elem_info wlfw_rf_chip_info_s_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0, - .offset = offsetof(struct wlfw_rf_chip_info_s_v01, + .offset = offsetof(struct + wlfw_rf_chip_info_s_v01, chip_family), }, { @@ -378,7 +409,8 @@ static struct qmi_elem_info wlfw_rf_board_info_s_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0, - .offset = offsetof(struct wlfw_rf_board_info_s_v01, + .offset = offsetof(struct + wlfw_rf_board_info_s_v01, board_id), }, { @@ -395,7 +427,8 @@ static struct qmi_elem_info wlfw_soc_info_s_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0, - .offset = offsetof(struct wlfw_soc_info_s_v01, + .offset = offsetof(struct + wlfw_soc_info_s_v01, soc_id), }, { @@ -412,7 +445,8 @@ static struct qmi_elem_info wlfw_fw_version_info_s_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0, - .offset = offsetof(struct wlfw_fw_version_info_s_v01, + .offset = offsetof(struct + wlfw_fw_version_info_s_v01, fw_version), }, { @@ -421,7 +455,8 @@ static struct qmi_elem_info wlfw_fw_version_info_s_v01_ei[] = { .elem_size = sizeof(char), .array_type = NO_ARRAY, .tlv_type = 0, - .offset = offsetof(struct wlfw_fw_version_info_s_v01, + .offset = offsetof(struct + wlfw_fw_version_info_s_v01, fw_build_timestamp), }, { @@ -438,7 +473,8 @@ static struct qmi_elem_info wlfw_host_ddr_range_s_v01_ei[] = { .elem_size = sizeof(u64), .array_type = NO_ARRAY, .tlv_type = 0, - .offset = offsetof(struct wlfw_host_ddr_range_s_v01, + .offset = offsetof(struct + wlfw_host_ddr_range_s_v01, start), }, { @@ -447,7 +483,8 @@ static struct qmi_elem_info wlfw_host_ddr_range_s_v01_ei[] = { .elem_size = sizeof(u64), .array_type = NO_ARRAY, .tlv_type = 0, - .offset = offsetof(struct wlfw_host_ddr_range_s_v01, + .offset = offsetof(struct + wlfw_host_ddr_range_s_v01, size), }, { @@ -464,7 +501,8 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x10, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct + wlfw_ind_register_req_msg_v01, fw_ready_enable_valid), }, { @@ -473,7 +511,8 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x10, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct + wlfw_ind_register_req_msg_v01, fw_ready_enable), }, { @@ -482,7 +521,8 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x11, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct + wlfw_ind_register_req_msg_v01, initiate_cal_download_enable_valid), }, { @@ -491,7 +531,8 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x11, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct + wlfw_ind_register_req_msg_v01, initiate_cal_download_enable), }, { @@ -500,7 +541,8 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x12, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct + wlfw_ind_register_req_msg_v01, initiate_cal_update_enable_valid), }, { @@ -509,7 +551,8 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x12, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct + wlfw_ind_register_req_msg_v01, initiate_cal_update_enable), }, { @@ -518,7 +561,8 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x13, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct + wlfw_ind_register_req_msg_v01, msa_ready_enable_valid), }, { @@ -527,7 +571,8 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x13, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct + wlfw_ind_register_req_msg_v01, msa_ready_enable), }, { @@ -536,7 +581,8 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x14, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct + wlfw_ind_register_req_msg_v01, pin_connect_result_enable_valid), }, { @@ -545,7 +591,8 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x14, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct + wlfw_ind_register_req_msg_v01, pin_connect_result_enable), }, { @@ -554,7 +601,8 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x15, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct + wlfw_ind_register_req_msg_v01, client_id_valid), }, { @@ -563,7 +611,8 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0x15, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct + wlfw_ind_register_req_msg_v01, client_id), }, { @@ -572,7 +621,8 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x16, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct + wlfw_ind_register_req_msg_v01, request_mem_enable_valid), }, { @@ -581,7 +631,8 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x16, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct + wlfw_ind_register_req_msg_v01, request_mem_enable), }, { @@ -590,7 +641,8 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x17, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct + wlfw_ind_register_req_msg_v01, fw_mem_ready_enable_valid), }, { @@ -599,7 +651,8 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x17, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct + wlfw_ind_register_req_msg_v01, fw_mem_ready_enable), }, { @@ -608,7 +661,8 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x18, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct + wlfw_ind_register_req_msg_v01, fw_init_done_enable_valid), }, { @@ -617,7 +671,8 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x18, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct + wlfw_ind_register_req_msg_v01, fw_init_done_enable), }, { @@ -626,7 +681,8 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x19, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct + wlfw_ind_register_req_msg_v01, rejuvenate_enable_valid), }, { @@ -635,7 +691,8 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0x19, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct + wlfw_ind_register_req_msg_v01, rejuvenate_enable), }, { @@ -644,7 +701,8 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x1A, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct + wlfw_ind_register_req_msg_v01, xo_cal_enable_valid), }, { @@ -653,7 +711,8 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x1A, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct + wlfw_ind_register_req_msg_v01, xo_cal_enable), }, { @@ -662,7 +721,8 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x1B, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct + wlfw_ind_register_req_msg_v01, cal_done_enable_valid), }, { @@ -671,7 +731,8 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x1B, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct + wlfw_ind_register_req_msg_v01, cal_done_enable), }, { @@ -680,7 +741,8 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x1C, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct + wlfw_ind_register_req_msg_v01, qdss_trace_req_mem_enable_valid), }, { @@ -689,7 +751,8 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x1C, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct + wlfw_ind_register_req_msg_v01, qdss_trace_req_mem_enable), }, { @@ -698,7 +761,8 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x1D, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct + wlfw_ind_register_req_msg_v01, qdss_trace_save_enable_valid), }, { @@ -707,7 +771,8 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x1D, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct + wlfw_ind_register_req_msg_v01, qdss_trace_save_enable), }, { @@ -716,7 +781,8 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x1E, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct + wlfw_ind_register_req_msg_v01, qdss_trace_free_enable_valid), }, { @@ -725,7 +791,8 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x1E, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct + wlfw_ind_register_req_msg_v01, qdss_trace_free_enable), }, { @@ -734,7 +801,8 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x1F, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct + wlfw_ind_register_req_msg_v01, respond_get_info_enable_valid), }, { @@ -743,7 +811,8 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x1F, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct + wlfw_ind_register_req_msg_v01, respond_get_info_enable), }, { @@ -752,7 +821,8 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x20, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct + wlfw_ind_register_req_msg_v01, m3_dump_upload_req_enable_valid), }, { @@ -761,7 +831,8 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x20, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct + wlfw_ind_register_req_msg_v01, m3_dump_upload_req_enable), }, { @@ -770,7 +841,8 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x21, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct + wlfw_ind_register_req_msg_v01, wfc_call_twt_config_enable_valid), }, { @@ -779,7 +851,8 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x21, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct + wlfw_ind_register_req_msg_v01, wfc_call_twt_config_enable), }, { @@ -788,7 +861,8 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x22, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct + wlfw_ind_register_req_msg_v01, qdss_mem_ready_enable_valid), }, { @@ -797,7 +871,8 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x22, - .offset = offsetof(struct wlfw_ind_register_req_msg_v01, + .offset = offsetof(struct + wlfw_ind_register_req_msg_v01, qdss_mem_ready_enable), }, { @@ -806,6 +881,7 @@ struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_ind_register_req_msg_v01_ei); struct qmi_elem_info wlfw_ind_register_resp_msg_v01_ei[] = { { @@ -845,6 +921,7 @@ struct qmi_elem_info wlfw_ind_register_resp_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_ind_register_resp_msg_v01_ei); struct qmi_elem_info wlfw_fw_ready_ind_msg_v01_ei[] = { { @@ -853,6 +930,7 @@ struct qmi_elem_info wlfw_fw_ready_ind_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_fw_ready_ind_msg_v01_ei); struct qmi_elem_info wlfw_msa_ready_ind_msg_v01_ei[] = { { @@ -861,7 +939,8 @@ struct qmi_elem_info wlfw_msa_ready_ind_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x10, - .offset = offsetof(struct wlfw_msa_ready_ind_msg_v01, + .offset = offsetof(struct + wlfw_msa_ready_ind_msg_v01, hang_data_addr_offset_valid), }, { @@ -870,7 +949,8 @@ struct qmi_elem_info wlfw_msa_ready_ind_msg_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0x10, - .offset = offsetof(struct wlfw_msa_ready_ind_msg_v01, + .offset = offsetof(struct + wlfw_msa_ready_ind_msg_v01, hang_data_addr_offset), }, { @@ -879,7 +959,8 @@ struct qmi_elem_info wlfw_msa_ready_ind_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x11, - .offset = offsetof(struct wlfw_msa_ready_ind_msg_v01, + .offset = offsetof(struct + wlfw_msa_ready_ind_msg_v01, hang_data_length_valid), }, { @@ -888,7 +969,8 @@ struct qmi_elem_info wlfw_msa_ready_ind_msg_v01_ei[] = { .elem_size = sizeof(u16), .array_type = NO_ARRAY, .tlv_type = 0x11, - .offset = offsetof(struct wlfw_msa_ready_ind_msg_v01, + .offset = offsetof(struct + wlfw_msa_ready_ind_msg_v01, hang_data_length), }, { @@ -897,6 +979,7 @@ struct qmi_elem_info wlfw_msa_ready_ind_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_msa_ready_ind_msg_v01_ei); struct qmi_elem_info wlfw_pin_connect_result_ind_msg_v01_ei[] = { { @@ -965,6 +1048,7 @@ struct qmi_elem_info wlfw_pin_connect_result_ind_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_pin_connect_result_ind_msg_v01_ei); struct qmi_elem_info wlfw_wlan_mode_req_msg_v01_ei[] = { { @@ -973,7 +1057,8 @@ struct qmi_elem_info wlfw_wlan_mode_req_msg_v01_ei[] = { .elem_size = sizeof(enum wlfw_driver_mode_enum_v01), .array_type = NO_ARRAY, .tlv_type = 0x01, - .offset = offsetof(struct wlfw_wlan_mode_req_msg_v01, + .offset = offsetof(struct + wlfw_wlan_mode_req_msg_v01, mode), }, { @@ -982,7 +1067,8 @@ struct qmi_elem_info wlfw_wlan_mode_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x10, - .offset = offsetof(struct wlfw_wlan_mode_req_msg_v01, + .offset = offsetof(struct + wlfw_wlan_mode_req_msg_v01, hw_debug_valid), }, { @@ -991,7 +1077,8 @@ struct qmi_elem_info wlfw_wlan_mode_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x10, - .offset = offsetof(struct wlfw_wlan_mode_req_msg_v01, + .offset = offsetof(struct + wlfw_wlan_mode_req_msg_v01, hw_debug), }, { @@ -1000,6 +1087,7 @@ struct qmi_elem_info wlfw_wlan_mode_req_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_wlan_mode_req_msg_v01_ei); struct qmi_elem_info wlfw_wlan_mode_resp_msg_v01_ei[] = { { @@ -1008,7 +1096,8 @@ struct qmi_elem_info wlfw_wlan_mode_resp_msg_v01_ei[] = { .elem_size = sizeof(struct qmi_response_type_v01), .array_type = NO_ARRAY, .tlv_type = 0x02, - .offset = offsetof(struct wlfw_wlan_mode_resp_msg_v01, + .offset = offsetof(struct + wlfw_wlan_mode_resp_msg_v01, resp), .ei_array = qmi_response_type_v01_ei, }, @@ -1018,6 +1107,7 @@ struct qmi_elem_info wlfw_wlan_mode_resp_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_wlan_mode_resp_msg_v01_ei); struct qmi_elem_info wlfw_wlan_cfg_req_msg_v01_ei[] = { { @@ -1026,7 +1116,8 @@ struct qmi_elem_info wlfw_wlan_cfg_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x10, - .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, + .offset = offsetof(struct + wlfw_wlan_cfg_req_msg_v01, host_version_valid), }, { @@ -1035,7 +1126,8 @@ struct qmi_elem_info wlfw_wlan_cfg_req_msg_v01_ei[] = { .elem_size = sizeof(char), .array_type = NO_ARRAY, .tlv_type = 0x10, - .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, + .offset = offsetof(struct + wlfw_wlan_cfg_req_msg_v01, host_version), }, { @@ -1044,7 +1136,8 @@ struct qmi_elem_info wlfw_wlan_cfg_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x11, - .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, + .offset = offsetof(struct + wlfw_wlan_cfg_req_msg_v01, tgt_cfg_valid), }, { @@ -1053,7 +1146,8 @@ struct qmi_elem_info wlfw_wlan_cfg_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x11, - .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, + .offset = offsetof(struct + wlfw_wlan_cfg_req_msg_v01, tgt_cfg_len), }, { @@ -1062,7 +1156,8 @@ struct qmi_elem_info wlfw_wlan_cfg_req_msg_v01_ei[] = { .elem_size = sizeof(struct wlfw_ce_tgt_pipe_cfg_s_v01), .array_type = VAR_LEN_ARRAY, .tlv_type = 0x11, - .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, + .offset = offsetof(struct + wlfw_wlan_cfg_req_msg_v01, tgt_cfg), .ei_array = wlfw_ce_tgt_pipe_cfg_s_v01_ei, }, @@ -1072,7 +1167,8 @@ struct qmi_elem_info wlfw_wlan_cfg_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x12, - .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, + .offset = offsetof(struct + wlfw_wlan_cfg_req_msg_v01, svc_cfg_valid), }, { @@ -1081,7 +1177,8 @@ struct qmi_elem_info wlfw_wlan_cfg_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x12, - .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, + .offset = offsetof(struct + wlfw_wlan_cfg_req_msg_v01, svc_cfg_len), }, { @@ -1090,7 +1187,8 @@ struct qmi_elem_info wlfw_wlan_cfg_req_msg_v01_ei[] = { .elem_size = sizeof(struct wlfw_ce_svc_pipe_cfg_s_v01), .array_type = VAR_LEN_ARRAY, .tlv_type = 0x12, - .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, + .offset = offsetof(struct + wlfw_wlan_cfg_req_msg_v01, svc_cfg), .ei_array = wlfw_ce_svc_pipe_cfg_s_v01_ei, }, @@ -1100,7 +1198,8 @@ struct qmi_elem_info wlfw_wlan_cfg_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x13, - .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, + .offset = offsetof(struct + wlfw_wlan_cfg_req_msg_v01, shadow_reg_valid), }, { @@ -1109,7 +1208,8 @@ struct qmi_elem_info wlfw_wlan_cfg_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x13, - .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, + .offset = offsetof(struct + wlfw_wlan_cfg_req_msg_v01, shadow_reg_len), }, { @@ -1118,7 +1218,8 @@ struct qmi_elem_info wlfw_wlan_cfg_req_msg_v01_ei[] = { .elem_size = sizeof(struct wlfw_shadow_reg_cfg_s_v01), .array_type = VAR_LEN_ARRAY, .tlv_type = 0x13, - .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, + .offset = offsetof(struct + wlfw_wlan_cfg_req_msg_v01, shadow_reg), .ei_array = wlfw_shadow_reg_cfg_s_v01_ei, }, @@ -1128,7 +1229,8 @@ struct qmi_elem_info wlfw_wlan_cfg_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x14, - .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, + .offset = offsetof(struct + wlfw_wlan_cfg_req_msg_v01, shadow_reg_v2_valid), }, { @@ -1137,7 +1239,8 @@ struct qmi_elem_info wlfw_wlan_cfg_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x14, - .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, + .offset = offsetof(struct + wlfw_wlan_cfg_req_msg_v01, shadow_reg_v2_len), }, { @@ -1146,7 +1249,8 @@ struct qmi_elem_info wlfw_wlan_cfg_req_msg_v01_ei[] = { .elem_size = sizeof(struct wlfw_shadow_reg_v2_cfg_s_v01), .array_type = VAR_LEN_ARRAY, .tlv_type = 0x14, - .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, + .offset = offsetof(struct + wlfw_wlan_cfg_req_msg_v01, shadow_reg_v2), .ei_array = wlfw_shadow_reg_v2_cfg_s_v01_ei, }, @@ -1156,7 +1260,8 @@ struct qmi_elem_info wlfw_wlan_cfg_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x15, - .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, + .offset = offsetof(struct + wlfw_wlan_cfg_req_msg_v01, rri_over_ddr_cfg_valid), }, { @@ -1165,7 +1270,8 @@ struct qmi_elem_info wlfw_wlan_cfg_req_msg_v01_ei[] = { .elem_size = sizeof(struct wlfw_rri_over_ddr_cfg_s_v01), .array_type = NO_ARRAY, .tlv_type = 0x15, - .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, + .offset = offsetof(struct + wlfw_wlan_cfg_req_msg_v01, rri_over_ddr_cfg), .ei_array = wlfw_rri_over_ddr_cfg_s_v01_ei, }, @@ -1175,7 +1281,8 @@ struct qmi_elem_info wlfw_wlan_cfg_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x16, - .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, + .offset = offsetof(struct + wlfw_wlan_cfg_req_msg_v01, msi_cfg_valid), }, { @@ -1184,7 +1291,8 @@ struct qmi_elem_info wlfw_wlan_cfg_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x16, - .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, + .offset = offsetof(struct + wlfw_wlan_cfg_req_msg_v01, msi_cfg_len), }, { @@ -1193,7 +1301,8 @@ struct qmi_elem_info wlfw_wlan_cfg_req_msg_v01_ei[] = { .elem_size = sizeof(struct wlfw_msi_cfg_s_v01), .array_type = VAR_LEN_ARRAY, .tlv_type = 0x16, - .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01, + .offset = offsetof(struct + wlfw_wlan_cfg_req_msg_v01, msi_cfg), .ei_array = wlfw_msi_cfg_s_v01_ei, }, @@ -1203,6 +1312,7 @@ struct qmi_elem_info wlfw_wlan_cfg_req_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_wlan_cfg_req_msg_v01_ei); struct qmi_elem_info wlfw_wlan_cfg_resp_msg_v01_ei[] = { { @@ -1211,7 +1321,8 @@ struct qmi_elem_info wlfw_wlan_cfg_resp_msg_v01_ei[] = { .elem_size = sizeof(struct qmi_response_type_v01), .array_type = NO_ARRAY, .tlv_type = 0x02, - .offset = offsetof(struct wlfw_wlan_cfg_resp_msg_v01, + .offset = offsetof(struct + wlfw_wlan_cfg_resp_msg_v01, resp), .ei_array = qmi_response_type_v01_ei, }, @@ -1221,6 +1332,7 @@ struct qmi_elem_info wlfw_wlan_cfg_resp_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_wlan_cfg_resp_msg_v01_ei); struct qmi_elem_info wlfw_cap_req_msg_v01_ei[] = { { @@ -1229,6 +1341,7 @@ struct qmi_elem_info wlfw_cap_req_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_cap_req_msg_v01_ei); struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[] = { { @@ -1237,7 +1350,8 @@ struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[] = { .elem_size = sizeof(struct qmi_response_type_v01), .array_type = NO_ARRAY, .tlv_type = 0x02, - .offset = offsetof(struct wlfw_cap_resp_msg_v01, + .offset = offsetof(struct + wlfw_cap_resp_msg_v01, resp), .ei_array = qmi_response_type_v01_ei, }, @@ -1247,7 +1361,8 @@ struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x10, - .offset = offsetof(struct wlfw_cap_resp_msg_v01, + .offset = offsetof(struct + wlfw_cap_resp_msg_v01, chip_info_valid), }, { @@ -1256,7 +1371,8 @@ struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[] = { .elem_size = sizeof(struct wlfw_rf_chip_info_s_v01), .array_type = NO_ARRAY, .tlv_type = 0x10, - .offset = offsetof(struct wlfw_cap_resp_msg_v01, + .offset = offsetof(struct + wlfw_cap_resp_msg_v01, chip_info), .ei_array = wlfw_rf_chip_info_s_v01_ei, }, @@ -1266,7 +1382,8 @@ struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x11, - .offset = offsetof(struct wlfw_cap_resp_msg_v01, + .offset = offsetof(struct + wlfw_cap_resp_msg_v01, board_info_valid), }, { @@ -1275,7 +1392,8 @@ struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[] = { .elem_size = sizeof(struct wlfw_rf_board_info_s_v01), .array_type = NO_ARRAY, .tlv_type = 0x11, - .offset = offsetof(struct wlfw_cap_resp_msg_v01, + .offset = offsetof(struct + wlfw_cap_resp_msg_v01, board_info), .ei_array = wlfw_rf_board_info_s_v01_ei, }, @@ -1285,7 +1403,8 @@ struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x12, - .offset = offsetof(struct wlfw_cap_resp_msg_v01, + .offset = offsetof(struct + wlfw_cap_resp_msg_v01, soc_info_valid), }, { @@ -1294,7 +1413,8 @@ struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[] = { .elem_size = sizeof(struct wlfw_soc_info_s_v01), .array_type = NO_ARRAY, .tlv_type = 0x12, - .offset = offsetof(struct wlfw_cap_resp_msg_v01, + .offset = offsetof(struct + wlfw_cap_resp_msg_v01, soc_info), .ei_array = wlfw_soc_info_s_v01_ei, }, @@ -1304,7 +1424,8 @@ struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x13, - .offset = offsetof(struct wlfw_cap_resp_msg_v01, + .offset = offsetof(struct + wlfw_cap_resp_msg_v01, fw_version_info_valid), }, { @@ -1313,7 +1434,8 @@ struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[] = { .elem_size = sizeof(struct wlfw_fw_version_info_s_v01), .array_type = NO_ARRAY, .tlv_type = 0x13, - .offset = offsetof(struct wlfw_cap_resp_msg_v01, + .offset = offsetof(struct + wlfw_cap_resp_msg_v01, fw_version_info), .ei_array = wlfw_fw_version_info_s_v01_ei, }, @@ -1323,7 +1445,8 @@ struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x14, - .offset = offsetof(struct wlfw_cap_resp_msg_v01, + .offset = offsetof(struct + wlfw_cap_resp_msg_v01, fw_build_id_valid), }, { @@ -1332,7 +1455,8 @@ struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[] = { .elem_size = sizeof(char), .array_type = NO_ARRAY, .tlv_type = 0x14, - .offset = offsetof(struct wlfw_cap_resp_msg_v01, + .offset = offsetof(struct + wlfw_cap_resp_msg_v01, fw_build_id), }, { @@ -1341,7 +1465,8 @@ struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x15, - .offset = offsetof(struct wlfw_cap_resp_msg_v01, + .offset = offsetof(struct + wlfw_cap_resp_msg_v01, num_macs_valid), }, { @@ -1350,7 +1475,8 @@ struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x15, - .offset = offsetof(struct wlfw_cap_resp_msg_v01, + .offset = offsetof(struct + wlfw_cap_resp_msg_v01, num_macs), }, { @@ -1359,7 +1485,8 @@ struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x16, - .offset = offsetof(struct wlfw_cap_resp_msg_v01, + .offset = offsetof(struct + wlfw_cap_resp_msg_v01, voltage_mv_valid), }, { @@ -1368,7 +1495,8 @@ struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0x16, - .offset = offsetof(struct wlfw_cap_resp_msg_v01, + .offset = offsetof(struct + wlfw_cap_resp_msg_v01, voltage_mv), }, { @@ -1377,7 +1505,8 @@ struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x17, - .offset = offsetof(struct wlfw_cap_resp_msg_v01, + .offset = offsetof(struct + wlfw_cap_resp_msg_v01, time_freq_hz_valid), }, { @@ -1386,7 +1515,8 @@ struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0x17, - .offset = offsetof(struct wlfw_cap_resp_msg_v01, + .offset = offsetof(struct + wlfw_cap_resp_msg_v01, time_freq_hz), }, { @@ -1395,7 +1525,8 @@ struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x18, - .offset = offsetof(struct wlfw_cap_resp_msg_v01, + .offset = offsetof(struct + wlfw_cap_resp_msg_v01, otp_version_valid), }, { @@ -1404,7 +1535,8 @@ struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0x18, - .offset = offsetof(struct wlfw_cap_resp_msg_v01, + .offset = offsetof(struct + wlfw_cap_resp_msg_v01, otp_version), }, { @@ -1413,7 +1545,8 @@ struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x19, - .offset = offsetof(struct wlfw_cap_resp_msg_v01, + .offset = offsetof(struct + wlfw_cap_resp_msg_v01, eeprom_caldata_read_timeout_valid), }, { @@ -1422,7 +1555,8 @@ struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0x19, - .offset = offsetof(struct wlfw_cap_resp_msg_v01, + .offset = offsetof(struct + wlfw_cap_resp_msg_v01, eeprom_caldata_read_timeout), }, { @@ -1431,7 +1565,8 @@ struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x1A, - .offset = offsetof(struct wlfw_cap_resp_msg_v01, + .offset = offsetof(struct + wlfw_cap_resp_msg_v01, fw_caps_valid), }, { @@ -1440,7 +1575,8 @@ struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[] = { .elem_size = sizeof(u64), .array_type = NO_ARRAY, .tlv_type = 0x1A, - .offset = offsetof(struct wlfw_cap_resp_msg_v01, + .offset = offsetof(struct + wlfw_cap_resp_msg_v01, fw_caps), }, { @@ -1449,7 +1585,8 @@ struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x1B, - .offset = offsetof(struct wlfw_cap_resp_msg_v01, + .offset = offsetof(struct + wlfw_cap_resp_msg_v01, rd_card_chain_cap_valid), }, { @@ -1458,7 +1595,8 @@ struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[] = { .elem_size = sizeof(enum wlfw_rd_card_chain_cap_v01), .array_type = NO_ARRAY, .tlv_type = 0x1B, - .offset = offsetof(struct wlfw_cap_resp_msg_v01, + .offset = offsetof(struct + wlfw_cap_resp_msg_v01, rd_card_chain_cap), }, { @@ -1467,6 +1605,7 @@ struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_cap_resp_msg_v01_ei); struct qmi_elem_info wlfw_bdf_download_req_msg_v01_ei[] = { { @@ -1475,7 +1614,8 @@ struct qmi_elem_info wlfw_bdf_download_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x01, - .offset = offsetof(struct wlfw_bdf_download_req_msg_v01, + .offset = offsetof(struct + wlfw_bdf_download_req_msg_v01, valid), }, { @@ -1484,7 +1624,8 @@ struct qmi_elem_info wlfw_bdf_download_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x10, - .offset = offsetof(struct wlfw_bdf_download_req_msg_v01, + .offset = offsetof(struct + wlfw_bdf_download_req_msg_v01, file_id_valid), }, { @@ -1493,7 +1634,8 @@ struct qmi_elem_info wlfw_bdf_download_req_msg_v01_ei[] = { .elem_size = sizeof(enum wlfw_cal_temp_id_enum_v01), .array_type = NO_ARRAY, .tlv_type = 0x10, - .offset = offsetof(struct wlfw_bdf_download_req_msg_v01, + .offset = offsetof(struct + wlfw_bdf_download_req_msg_v01, file_id), }, { @@ -1502,7 +1644,8 @@ struct qmi_elem_info wlfw_bdf_download_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x11, - .offset = offsetof(struct wlfw_bdf_download_req_msg_v01, + .offset = offsetof(struct + wlfw_bdf_download_req_msg_v01, total_size_valid), }, { @@ -1511,7 +1654,8 @@ struct qmi_elem_info wlfw_bdf_download_req_msg_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0x11, - .offset = offsetof(struct wlfw_bdf_download_req_msg_v01, + .offset = offsetof(struct + wlfw_bdf_download_req_msg_v01, total_size), }, { @@ -1520,7 +1664,8 @@ struct qmi_elem_info wlfw_bdf_download_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x12, - .offset = offsetof(struct wlfw_bdf_download_req_msg_v01, + .offset = offsetof(struct + wlfw_bdf_download_req_msg_v01, seg_id_valid), }, { @@ -1529,7 +1674,8 @@ struct qmi_elem_info wlfw_bdf_download_req_msg_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0x12, - .offset = offsetof(struct wlfw_bdf_download_req_msg_v01, + .offset = offsetof(struct + wlfw_bdf_download_req_msg_v01, seg_id), }, { @@ -1538,7 +1684,8 @@ struct qmi_elem_info wlfw_bdf_download_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x13, - .offset = offsetof(struct wlfw_bdf_download_req_msg_v01, + .offset = offsetof(struct + wlfw_bdf_download_req_msg_v01, data_valid), }, { @@ -1547,7 +1694,8 @@ struct qmi_elem_info wlfw_bdf_download_req_msg_v01_ei[] = { .elem_size = sizeof(u16), .array_type = NO_ARRAY, .tlv_type = 0x13, - .offset = offsetof(struct wlfw_bdf_download_req_msg_v01, + .offset = offsetof(struct + wlfw_bdf_download_req_msg_v01, data_len), }, { @@ -1556,7 +1704,8 @@ struct qmi_elem_info wlfw_bdf_download_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = VAR_LEN_ARRAY, .tlv_type = 0x13, - .offset = offsetof(struct wlfw_bdf_download_req_msg_v01, + .offset = offsetof(struct + wlfw_bdf_download_req_msg_v01, data), }, { @@ -1565,7 +1714,8 @@ struct qmi_elem_info wlfw_bdf_download_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x14, - .offset = offsetof(struct wlfw_bdf_download_req_msg_v01, + .offset = offsetof(struct + wlfw_bdf_download_req_msg_v01, end_valid), }, { @@ -1574,7 +1724,8 @@ struct qmi_elem_info wlfw_bdf_download_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x14, - .offset = offsetof(struct wlfw_bdf_download_req_msg_v01, + .offset = offsetof(struct + wlfw_bdf_download_req_msg_v01, end), }, { @@ -1583,7 +1734,8 @@ struct qmi_elem_info wlfw_bdf_download_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x15, - .offset = offsetof(struct wlfw_bdf_download_req_msg_v01, + .offset = offsetof(struct + wlfw_bdf_download_req_msg_v01, bdf_type_valid), }, { @@ -1592,7 +1744,8 @@ struct qmi_elem_info wlfw_bdf_download_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x15, - .offset = offsetof(struct wlfw_bdf_download_req_msg_v01, + .offset = offsetof(struct + wlfw_bdf_download_req_msg_v01, bdf_type), }, { @@ -1601,6 +1754,7 @@ struct qmi_elem_info wlfw_bdf_download_req_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_bdf_download_req_msg_v01_ei); struct qmi_elem_info wlfw_bdf_download_resp_msg_v01_ei[] = { { @@ -1640,6 +1794,7 @@ struct qmi_elem_info wlfw_bdf_download_resp_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_bdf_download_resp_msg_v01_ei); struct qmi_elem_info wlfw_cal_report_req_msg_v01_ei[] = { { @@ -1648,7 +1803,8 @@ struct qmi_elem_info wlfw_cal_report_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x01, - .offset = offsetof(struct wlfw_cal_report_req_msg_v01, + .offset = offsetof(struct + wlfw_cal_report_req_msg_v01, meta_data_len), }, { @@ -1657,7 +1813,8 @@ struct qmi_elem_info wlfw_cal_report_req_msg_v01_ei[] = { .elem_size = sizeof(enum wlfw_cal_temp_id_enum_v01), .array_type = VAR_LEN_ARRAY, .tlv_type = 0x01, - .offset = offsetof(struct wlfw_cal_report_req_msg_v01, + .offset = offsetof(struct + wlfw_cal_report_req_msg_v01, meta_data), }, { @@ -1666,7 +1823,8 @@ struct qmi_elem_info wlfw_cal_report_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x10, - .offset = offsetof(struct wlfw_cal_report_req_msg_v01, + .offset = offsetof(struct + wlfw_cal_report_req_msg_v01, xo_cal_data_valid), }, { @@ -1675,7 +1833,8 @@ struct qmi_elem_info wlfw_cal_report_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x10, - .offset = offsetof(struct wlfw_cal_report_req_msg_v01, + .offset = offsetof(struct + wlfw_cal_report_req_msg_v01, xo_cal_data), }, { @@ -1684,7 +1843,8 @@ struct qmi_elem_info wlfw_cal_report_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x11, - .offset = offsetof(struct wlfw_cal_report_req_msg_v01, + .offset = offsetof(struct + wlfw_cal_report_req_msg_v01, cal_remove_supported_valid), }, { @@ -1693,7 +1853,8 @@ struct qmi_elem_info wlfw_cal_report_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x11, - .offset = offsetof(struct wlfw_cal_report_req_msg_v01, + .offset = offsetof(struct + wlfw_cal_report_req_msg_v01, cal_remove_supported), }, { @@ -1702,6 +1863,7 @@ struct qmi_elem_info wlfw_cal_report_req_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_cal_report_req_msg_v01_ei); struct qmi_elem_info wlfw_cal_report_resp_msg_v01_ei[] = { { @@ -1710,7 +1872,8 @@ struct qmi_elem_info wlfw_cal_report_resp_msg_v01_ei[] = { .elem_size = sizeof(struct qmi_response_type_v01), .array_type = NO_ARRAY, .tlv_type = 0x02, - .offset = offsetof(struct wlfw_cal_report_resp_msg_v01, + .offset = offsetof(struct + wlfw_cal_report_resp_msg_v01, resp), .ei_array = qmi_response_type_v01_ei, }, @@ -1720,6 +1883,7 @@ struct qmi_elem_info wlfw_cal_report_resp_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_cal_report_resp_msg_v01_ei); struct qmi_elem_info wlfw_initiate_cal_download_ind_msg_v01_ei[] = { { @@ -1729,8 +1893,8 @@ struct qmi_elem_info wlfw_initiate_cal_download_ind_msg_v01_ei[] = { .array_type = NO_ARRAY, .tlv_type = 0x01, .offset = offsetof(struct - wlfw_initiate_cal_download_ind_msg_v01, - cal_id), + wlfw_initiate_cal_download_ind_msg_v01, + cal_id), }, { .data_type = QMI_OPT_FLAG, @@ -1739,81 +1903,7 @@ struct qmi_elem_info wlfw_initiate_cal_download_ind_msg_v01_ei[] = { .array_type = NO_ARRAY, .tlv_type = 0x10, .offset = offsetof(struct - wlfw_initiate_cal_download_ind_msg_v01, - total_size_valid), - }, - { - .data_type = QMI_UNSIGNED_4_BYTE, - .elem_len = 1, - .elem_size = sizeof(u32), - .array_type = NO_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct - wlfw_initiate_cal_download_ind_msg_v01, - total_size), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x11, - .offset = offsetof(struct - wlfw_initiate_cal_download_ind_msg_v01, - cal_data_location_valid), - }, - { - .data_type = QMI_UNSIGNED_4_BYTE, - .elem_len = 1, - .elem_size = sizeof(u32), - .array_type = NO_ARRAY, - .tlv_type = 0x11, - .offset = offsetof(struct - wlfw_initiate_cal_download_ind_msg_v01, - cal_data_location), - }, - { - .data_type = QMI_EOTI, - .array_type = NO_ARRAY, - .tlv_type = QMI_COMMON_TLV_TYPE, - }, -}; - -struct qmi_elem_info wlfw_cal_download_req_msg_v01_ei[] = { - { - .data_type = QMI_UNSIGNED_1_BYTE, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x01, - .offset = offsetof(struct wlfw_cal_download_req_msg_v01, - valid), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct wlfw_cal_download_req_msg_v01, - file_id_valid), - }, - { - .data_type = QMI_SIGNED_4_BYTE_ENUM, - .elem_len = 1, - .elem_size = sizeof(enum wlfw_cal_temp_id_enum_v01), - .array_type = NO_ARRAY, - .tlv_type = 0x10, - .offset = offsetof(struct wlfw_cal_download_req_msg_v01, - file_id), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x11, - .offset = offsetof(struct wlfw_cal_download_req_msg_v01, + wlfw_initiate_cal_download_ind_msg_v01, total_size_valid), }, { @@ -1821,8 +1911,9 @@ struct qmi_elem_info wlfw_cal_download_req_msg_v01_ei[] = { .elem_len = 1, .elem_size = sizeof(u32), .array_type = NO_ARRAY, - .tlv_type = 0x11, - .offset = offsetof(struct wlfw_cal_download_req_msg_v01, + .tlv_type = 0x10, + .offset = offsetof(struct + wlfw_initiate_cal_download_ind_msg_v01, total_size), }, { @@ -1830,71 +1921,9 @@ struct qmi_elem_info wlfw_cal_download_req_msg_v01_ei[] = { .elem_len = 1, .elem_size = sizeof(u8), .array_type = NO_ARRAY, - .tlv_type = 0x12, - .offset = offsetof(struct wlfw_cal_download_req_msg_v01, - seg_id_valid), - }, - { - .data_type = QMI_UNSIGNED_4_BYTE, - .elem_len = 1, - .elem_size = sizeof(u32), - .array_type = NO_ARRAY, - .tlv_type = 0x12, - .offset = offsetof(struct wlfw_cal_download_req_msg_v01, - seg_id), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x13, - .offset = offsetof(struct wlfw_cal_download_req_msg_v01, - data_valid), - }, - { - .data_type = QMI_DATA_LEN, - .elem_len = 1, - .elem_size = sizeof(u16), - .array_type = NO_ARRAY, - .tlv_type = 0x13, - .offset = offsetof(struct wlfw_cal_download_req_msg_v01, - data_len), - }, - { - .data_type = QMI_UNSIGNED_1_BYTE, - .elem_len = QMI_WLFW_MAX_DATA_SIZE_V01, - .elem_size = sizeof(u8), - .array_type = VAR_LEN_ARRAY, - .tlv_type = 0x13, - .offset = offsetof(struct wlfw_cal_download_req_msg_v01, - data), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x14, - .offset = offsetof(struct wlfw_cal_download_req_msg_v01, - end_valid), - }, - { - .data_type = QMI_UNSIGNED_1_BYTE, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x14, - .offset = offsetof(struct wlfw_cal_download_req_msg_v01, - end), - }, - { - .data_type = QMI_OPT_FLAG, - .elem_len = 1, - .elem_size = sizeof(u8), - .array_type = NO_ARRAY, - .tlv_type = 0x15, - .offset = offsetof(struct wlfw_cal_download_req_msg_v01, + .tlv_type = 0x11, + .offset = offsetof(struct + wlfw_initiate_cal_download_ind_msg_v01, cal_data_location_valid), }, { @@ -1902,8 +1931,9 @@ struct qmi_elem_info wlfw_cal_download_req_msg_v01_ei[] = { .elem_len = 1, .elem_size = sizeof(u32), .array_type = NO_ARRAY, - .tlv_type = 0x15, - .offset = offsetof(struct wlfw_cal_download_req_msg_v01, + .tlv_type = 0x11, + .offset = offsetof(struct + wlfw_initiate_cal_download_ind_msg_v01, cal_data_location), }, { @@ -1912,6 +1942,156 @@ struct qmi_elem_info wlfw_cal_download_req_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_initiate_cal_download_ind_msg_v01_ei); + +struct qmi_elem_info wlfw_cal_download_req_msg_v01_ei[] = { + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x01, + .offset = offsetof(struct + wlfw_cal_download_req_msg_v01, + valid), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct + wlfw_cal_download_req_msg_v01, + file_id_valid), + }, + { + .data_type = QMI_SIGNED_4_BYTE_ENUM, + .elem_len = 1, + .elem_size = sizeof(enum wlfw_cal_temp_id_enum_v01), + .array_type = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct + wlfw_cal_download_req_msg_v01, + file_id), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x11, + .offset = offsetof(struct + wlfw_cal_download_req_msg_v01, + total_size_valid), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0x11, + .offset = offsetof(struct + wlfw_cal_download_req_msg_v01, + total_size), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x12, + .offset = offsetof(struct + wlfw_cal_download_req_msg_v01, + seg_id_valid), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0x12, + .offset = offsetof(struct + wlfw_cal_download_req_msg_v01, + seg_id), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x13, + .offset = offsetof(struct + wlfw_cal_download_req_msg_v01, + data_valid), + }, + { + .data_type = QMI_DATA_LEN, + .elem_len = 1, + .elem_size = sizeof(u16), + .array_type = NO_ARRAY, + .tlv_type = 0x13, + .offset = offsetof(struct + wlfw_cal_download_req_msg_v01, + data_len), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = QMI_WLFW_MAX_DATA_SIZE_V01, + .elem_size = sizeof(u8), + .array_type = VAR_LEN_ARRAY, + .tlv_type = 0x13, + .offset = offsetof(struct + wlfw_cal_download_req_msg_v01, + data), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x14, + .offset = offsetof(struct + wlfw_cal_download_req_msg_v01, + end_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x14, + .offset = offsetof(struct + wlfw_cal_download_req_msg_v01, + end), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x15, + .offset = offsetof(struct + wlfw_cal_download_req_msg_v01, + cal_data_location_valid), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0x15, + .offset = offsetof(struct + wlfw_cal_download_req_msg_v01, + cal_data_location), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; +EXPORT_SYMBOL(wlfw_cal_download_req_msg_v01_ei); struct qmi_elem_info wlfw_cal_download_resp_msg_v01_ei[] = { { @@ -1931,6 +2111,7 @@ struct qmi_elem_info wlfw_cal_download_resp_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_cal_download_resp_msg_v01_ei); struct qmi_elem_info wlfw_initiate_cal_update_ind_msg_v01_ei[] = { { @@ -1979,6 +2160,7 @@ struct qmi_elem_info wlfw_initiate_cal_update_ind_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_initiate_cal_update_ind_msg_v01_ei); struct qmi_elem_info wlfw_cal_update_req_msg_v01_ei[] = { { @@ -1987,7 +2169,8 @@ struct qmi_elem_info wlfw_cal_update_req_msg_v01_ei[] = { .elem_size = sizeof(enum wlfw_cal_temp_id_enum_v01), .array_type = NO_ARRAY, .tlv_type = 0x01, - .offset = offsetof(struct wlfw_cal_update_req_msg_v01, + .offset = offsetof(struct + wlfw_cal_update_req_msg_v01, cal_id), }, { @@ -1996,7 +2179,8 @@ struct qmi_elem_info wlfw_cal_update_req_msg_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0x02, - .offset = offsetof(struct wlfw_cal_update_req_msg_v01, + .offset = offsetof(struct + wlfw_cal_update_req_msg_v01, seg_id), }, { @@ -2005,6 +2189,7 @@ struct qmi_elem_info wlfw_cal_update_req_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_cal_update_req_msg_v01_ei); struct qmi_elem_info wlfw_cal_update_resp_msg_v01_ei[] = { { @@ -2013,7 +2198,8 @@ struct qmi_elem_info wlfw_cal_update_resp_msg_v01_ei[] = { .elem_size = sizeof(struct qmi_response_type_v01), .array_type = NO_ARRAY, .tlv_type = 0x02, - .offset = offsetof(struct wlfw_cal_update_resp_msg_v01, + .offset = offsetof(struct + wlfw_cal_update_resp_msg_v01, resp), .ei_array = qmi_response_type_v01_ei, }, @@ -2023,7 +2209,8 @@ struct qmi_elem_info wlfw_cal_update_resp_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x10, - .offset = offsetof(struct wlfw_cal_update_resp_msg_v01, + .offset = offsetof(struct + wlfw_cal_update_resp_msg_v01, file_id_valid), }, { @@ -2032,7 +2219,8 @@ struct qmi_elem_info wlfw_cal_update_resp_msg_v01_ei[] = { .elem_size = sizeof(enum wlfw_cal_temp_id_enum_v01), .array_type = NO_ARRAY, .tlv_type = 0x10, - .offset = offsetof(struct wlfw_cal_update_resp_msg_v01, + .offset = offsetof(struct + wlfw_cal_update_resp_msg_v01, file_id), }, { @@ -2041,7 +2229,8 @@ struct qmi_elem_info wlfw_cal_update_resp_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x11, - .offset = offsetof(struct wlfw_cal_update_resp_msg_v01, + .offset = offsetof(struct + wlfw_cal_update_resp_msg_v01, total_size_valid), }, { @@ -2050,7 +2239,8 @@ struct qmi_elem_info wlfw_cal_update_resp_msg_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0x11, - .offset = offsetof(struct wlfw_cal_update_resp_msg_v01, + .offset = offsetof(struct + wlfw_cal_update_resp_msg_v01, total_size), }, { @@ -2059,7 +2249,8 @@ struct qmi_elem_info wlfw_cal_update_resp_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x12, - .offset = offsetof(struct wlfw_cal_update_resp_msg_v01, + .offset = offsetof(struct + wlfw_cal_update_resp_msg_v01, seg_id_valid), }, { @@ -2068,7 +2259,8 @@ struct qmi_elem_info wlfw_cal_update_resp_msg_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0x12, - .offset = offsetof(struct wlfw_cal_update_resp_msg_v01, + .offset = offsetof(struct + wlfw_cal_update_resp_msg_v01, seg_id), }, { @@ -2077,7 +2269,8 @@ struct qmi_elem_info wlfw_cal_update_resp_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x13, - .offset = offsetof(struct wlfw_cal_update_resp_msg_v01, + .offset = offsetof(struct + wlfw_cal_update_resp_msg_v01, data_valid), }, { @@ -2086,7 +2279,8 @@ struct qmi_elem_info wlfw_cal_update_resp_msg_v01_ei[] = { .elem_size = sizeof(u16), .array_type = NO_ARRAY, .tlv_type = 0x13, - .offset = offsetof(struct wlfw_cal_update_resp_msg_v01, + .offset = offsetof(struct + wlfw_cal_update_resp_msg_v01, data_len), }, { @@ -2095,7 +2289,8 @@ struct qmi_elem_info wlfw_cal_update_resp_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = VAR_LEN_ARRAY, .tlv_type = 0x13, - .offset = offsetof(struct wlfw_cal_update_resp_msg_v01, + .offset = offsetof(struct + wlfw_cal_update_resp_msg_v01, data), }, { @@ -2104,7 +2299,8 @@ struct qmi_elem_info wlfw_cal_update_resp_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x14, - .offset = offsetof(struct wlfw_cal_update_resp_msg_v01, + .offset = offsetof(struct + wlfw_cal_update_resp_msg_v01, end_valid), }, { @@ -2113,7 +2309,8 @@ struct qmi_elem_info wlfw_cal_update_resp_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x14, - .offset = offsetof(struct wlfw_cal_update_resp_msg_v01, + .offset = offsetof(struct + wlfw_cal_update_resp_msg_v01, end), }, { @@ -2122,7 +2319,8 @@ struct qmi_elem_info wlfw_cal_update_resp_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x15, - .offset = offsetof(struct wlfw_cal_update_resp_msg_v01, + .offset = offsetof(struct + wlfw_cal_update_resp_msg_v01, cal_data_location_valid), }, { @@ -2131,7 +2329,8 @@ struct qmi_elem_info wlfw_cal_update_resp_msg_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0x15, - .offset = offsetof(struct wlfw_cal_update_resp_msg_v01, + .offset = offsetof(struct + wlfw_cal_update_resp_msg_v01, cal_data_location), }, { @@ -2140,6 +2339,7 @@ struct qmi_elem_info wlfw_cal_update_resp_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_cal_update_resp_msg_v01_ei); struct qmi_elem_info wlfw_msa_info_req_msg_v01_ei[] = { { @@ -2148,7 +2348,8 @@ struct qmi_elem_info wlfw_msa_info_req_msg_v01_ei[] = { .elem_size = sizeof(u64), .array_type = NO_ARRAY, .tlv_type = 0x01, - .offset = offsetof(struct wlfw_msa_info_req_msg_v01, + .offset = offsetof(struct + wlfw_msa_info_req_msg_v01, msa_addr), }, { @@ -2157,7 +2358,8 @@ struct qmi_elem_info wlfw_msa_info_req_msg_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0x02, - .offset = offsetof(struct wlfw_msa_info_req_msg_v01, + .offset = offsetof(struct + wlfw_msa_info_req_msg_v01, size), }, { @@ -2166,6 +2368,7 @@ struct qmi_elem_info wlfw_msa_info_req_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_msa_info_req_msg_v01_ei); struct qmi_elem_info wlfw_msa_info_resp_msg_v01_ei[] = { { @@ -2174,7 +2377,8 @@ struct qmi_elem_info wlfw_msa_info_resp_msg_v01_ei[] = { .elem_size = sizeof(struct qmi_response_type_v01), .array_type = NO_ARRAY, .tlv_type = 0x02, - .offset = offsetof(struct wlfw_msa_info_resp_msg_v01, + .offset = offsetof(struct + wlfw_msa_info_resp_msg_v01, resp), .ei_array = qmi_response_type_v01_ei, }, @@ -2184,7 +2388,8 @@ struct qmi_elem_info wlfw_msa_info_resp_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x03, - .offset = offsetof(struct wlfw_msa_info_resp_msg_v01, + .offset = offsetof(struct + wlfw_msa_info_resp_msg_v01, mem_region_info_len), }, { @@ -2193,7 +2398,8 @@ struct qmi_elem_info wlfw_msa_info_resp_msg_v01_ei[] = { .elem_size = sizeof(struct wlfw_memory_region_info_s_v01), .array_type = VAR_LEN_ARRAY, .tlv_type = 0x03, - .offset = offsetof(struct wlfw_msa_info_resp_msg_v01, + .offset = offsetof(struct + wlfw_msa_info_resp_msg_v01, mem_region_info), .ei_array = wlfw_memory_region_info_s_v01_ei, }, @@ -2203,6 +2409,7 @@ struct qmi_elem_info wlfw_msa_info_resp_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_msa_info_resp_msg_v01_ei); struct qmi_elem_info wlfw_msa_ready_req_msg_v01_ei[] = { { @@ -2211,6 +2418,7 @@ struct qmi_elem_info wlfw_msa_ready_req_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_msa_ready_req_msg_v01_ei); struct qmi_elem_info wlfw_msa_ready_resp_msg_v01_ei[] = { { @@ -2219,7 +2427,8 @@ struct qmi_elem_info wlfw_msa_ready_resp_msg_v01_ei[] = { .elem_size = sizeof(struct qmi_response_type_v01), .array_type = NO_ARRAY, .tlv_type = 0x02, - .offset = offsetof(struct wlfw_msa_ready_resp_msg_v01, + .offset = offsetof(struct + wlfw_msa_ready_resp_msg_v01, resp), .ei_array = qmi_response_type_v01_ei, }, @@ -2229,6 +2438,7 @@ struct qmi_elem_info wlfw_msa_ready_resp_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_msa_ready_resp_msg_v01_ei); struct qmi_elem_info wlfw_ini_req_msg_v01_ei[] = { { @@ -2237,7 +2447,8 @@ struct qmi_elem_info wlfw_ini_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x10, - .offset = offsetof(struct wlfw_ini_req_msg_v01, + .offset = offsetof(struct + wlfw_ini_req_msg_v01, enablefwlog_valid), }, { @@ -2246,7 +2457,8 @@ struct qmi_elem_info wlfw_ini_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x10, - .offset = offsetof(struct wlfw_ini_req_msg_v01, + .offset = offsetof(struct + wlfw_ini_req_msg_v01, enablefwlog), }, { @@ -2255,6 +2467,7 @@ struct qmi_elem_info wlfw_ini_req_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_ini_req_msg_v01_ei); struct qmi_elem_info wlfw_ini_resp_msg_v01_ei[] = { { @@ -2263,7 +2476,8 @@ struct qmi_elem_info wlfw_ini_resp_msg_v01_ei[] = { .elem_size = sizeof(struct qmi_response_type_v01), .array_type = NO_ARRAY, .tlv_type = 0x02, - .offset = offsetof(struct wlfw_ini_resp_msg_v01, + .offset = offsetof(struct + wlfw_ini_resp_msg_v01, resp), .ei_array = qmi_response_type_v01_ei, }, @@ -2273,6 +2487,7 @@ struct qmi_elem_info wlfw_ini_resp_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_ini_resp_msg_v01_ei); struct qmi_elem_info wlfw_athdiag_read_req_msg_v01_ei[] = { { @@ -2281,7 +2496,8 @@ struct qmi_elem_info wlfw_athdiag_read_req_msg_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0x01, - .offset = offsetof(struct wlfw_athdiag_read_req_msg_v01, + .offset = offsetof(struct + wlfw_athdiag_read_req_msg_v01, offset), }, { @@ -2290,7 +2506,8 @@ struct qmi_elem_info wlfw_athdiag_read_req_msg_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0x02, - .offset = offsetof(struct wlfw_athdiag_read_req_msg_v01, + .offset = offsetof(struct + wlfw_athdiag_read_req_msg_v01, mem_type), }, { @@ -2299,7 +2516,8 @@ struct qmi_elem_info wlfw_athdiag_read_req_msg_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0x03, - .offset = offsetof(struct wlfw_athdiag_read_req_msg_v01, + .offset = offsetof(struct + wlfw_athdiag_read_req_msg_v01, data_len), }, { @@ -2308,6 +2526,7 @@ struct qmi_elem_info wlfw_athdiag_read_req_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_athdiag_read_req_msg_v01_ei); struct qmi_elem_info wlfw_athdiag_read_resp_msg_v01_ei[] = { { @@ -2357,6 +2576,7 @@ struct qmi_elem_info wlfw_athdiag_read_resp_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_athdiag_read_resp_msg_v01_ei); struct qmi_elem_info wlfw_athdiag_write_req_msg_v01_ei[] = { { @@ -2405,6 +2625,7 @@ struct qmi_elem_info wlfw_athdiag_write_req_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_athdiag_write_req_msg_v01_ei); struct qmi_elem_info wlfw_athdiag_write_resp_msg_v01_ei[] = { { @@ -2424,6 +2645,7 @@ struct qmi_elem_info wlfw_athdiag_write_resp_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_athdiag_write_resp_msg_v01_ei); struct qmi_elem_info wlfw_vbatt_req_msg_v01_ei[] = { { @@ -2432,7 +2654,8 @@ struct qmi_elem_info wlfw_vbatt_req_msg_v01_ei[] = { .elem_size = sizeof(u64), .array_type = NO_ARRAY, .tlv_type = 0x01, - .offset = offsetof(struct wlfw_vbatt_req_msg_v01, + .offset = offsetof(struct + wlfw_vbatt_req_msg_v01, voltage_uv), }, { @@ -2441,6 +2664,7 @@ struct qmi_elem_info wlfw_vbatt_req_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_vbatt_req_msg_v01_ei); struct qmi_elem_info wlfw_vbatt_resp_msg_v01_ei[] = { { @@ -2449,7 +2673,8 @@ struct qmi_elem_info wlfw_vbatt_resp_msg_v01_ei[] = { .elem_size = sizeof(struct qmi_response_type_v01), .array_type = NO_ARRAY, .tlv_type = 0x02, - .offset = offsetof(struct wlfw_vbatt_resp_msg_v01, + .offset = offsetof(struct + wlfw_vbatt_resp_msg_v01, resp), .ei_array = qmi_response_type_v01_ei, }, @@ -2459,6 +2684,7 @@ struct qmi_elem_info wlfw_vbatt_resp_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_vbatt_resp_msg_v01_ei); struct qmi_elem_info wlfw_mac_addr_req_msg_v01_ei[] = { { @@ -2467,7 +2693,8 @@ struct qmi_elem_info wlfw_mac_addr_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x10, - .offset = offsetof(struct wlfw_mac_addr_req_msg_v01, + .offset = offsetof(struct + wlfw_mac_addr_req_msg_v01, mac_addr_valid), }, { @@ -2476,7 +2703,8 @@ struct qmi_elem_info wlfw_mac_addr_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = STATIC_ARRAY, .tlv_type = 0x10, - .offset = offsetof(struct wlfw_mac_addr_req_msg_v01, + .offset = offsetof(struct + wlfw_mac_addr_req_msg_v01, mac_addr), }, { @@ -2485,6 +2713,7 @@ struct qmi_elem_info wlfw_mac_addr_req_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_mac_addr_req_msg_v01_ei); struct qmi_elem_info wlfw_mac_addr_resp_msg_v01_ei[] = { { @@ -2493,7 +2722,8 @@ struct qmi_elem_info wlfw_mac_addr_resp_msg_v01_ei[] = { .elem_size = sizeof(struct qmi_response_type_v01), .array_type = NO_ARRAY, .tlv_type = 0x02, - .offset = offsetof(struct wlfw_mac_addr_resp_msg_v01, + .offset = offsetof(struct + wlfw_mac_addr_resp_msg_v01, resp), .ei_array = qmi_response_type_v01_ei, }, @@ -2503,6 +2733,7 @@ struct qmi_elem_info wlfw_mac_addr_resp_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_mac_addr_resp_msg_v01_ei); struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { { @@ -2511,7 +2742,8 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x10, - .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + .offset = offsetof(struct + wlfw_host_cap_req_msg_v01, num_clients_valid), }, { @@ -2520,7 +2752,8 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0x10, - .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + .offset = offsetof(struct + wlfw_host_cap_req_msg_v01, num_clients), }, { @@ -2529,7 +2762,8 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x11, - .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + .offset = offsetof(struct + wlfw_host_cap_req_msg_v01, wake_msi_valid), }, { @@ -2538,7 +2772,8 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0x11, - .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + .offset = offsetof(struct + wlfw_host_cap_req_msg_v01, wake_msi), }, { @@ -2547,7 +2782,8 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x12, - .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + .offset = offsetof(struct + wlfw_host_cap_req_msg_v01, gpios_valid), }, { @@ -2556,7 +2792,8 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x12, - .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + .offset = offsetof(struct + wlfw_host_cap_req_msg_v01, gpios_len), }, { @@ -2565,7 +2802,8 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { .elem_size = sizeof(u32), .array_type = VAR_LEN_ARRAY, .tlv_type = 0x12, - .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + .offset = offsetof(struct + wlfw_host_cap_req_msg_v01, gpios), }, { @@ -2574,7 +2812,8 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x13, - .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + .offset = offsetof(struct + wlfw_host_cap_req_msg_v01, nm_modem_valid), }, { @@ -2583,7 +2822,8 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x13, - .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + .offset = offsetof(struct + wlfw_host_cap_req_msg_v01, nm_modem), }, { @@ -2592,7 +2832,8 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x14, - .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + .offset = offsetof(struct + wlfw_host_cap_req_msg_v01, bdf_support_valid), }, { @@ -2601,7 +2842,8 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x14, - .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + .offset = offsetof(struct + wlfw_host_cap_req_msg_v01, bdf_support), }, { @@ -2610,7 +2852,8 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x15, - .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + .offset = offsetof(struct + wlfw_host_cap_req_msg_v01, bdf_cache_support_valid), }, { @@ -2619,7 +2862,8 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x15, - .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + .offset = offsetof(struct + wlfw_host_cap_req_msg_v01, bdf_cache_support), }, { @@ -2628,7 +2872,8 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x16, - .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + .offset = offsetof(struct + wlfw_host_cap_req_msg_v01, m3_support_valid), }, { @@ -2637,7 +2882,8 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x16, - .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + .offset = offsetof(struct + wlfw_host_cap_req_msg_v01, m3_support), }, { @@ -2646,7 +2892,8 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x17, - .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + .offset = offsetof(struct + wlfw_host_cap_req_msg_v01, m3_cache_support_valid), }, { @@ -2655,7 +2902,8 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x17, - .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + .offset = offsetof(struct + wlfw_host_cap_req_msg_v01, m3_cache_support), }, { @@ -2664,7 +2912,8 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x18, - .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + .offset = offsetof(struct + wlfw_host_cap_req_msg_v01, cal_filesys_support_valid), }, { @@ -2673,7 +2922,8 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x18, - .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + .offset = offsetof(struct + wlfw_host_cap_req_msg_v01, cal_filesys_support), }, { @@ -2682,7 +2932,8 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x19, - .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + .offset = offsetof(struct + wlfw_host_cap_req_msg_v01, cal_cache_support_valid), }, { @@ -2691,7 +2942,8 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x19, - .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + .offset = offsetof(struct + wlfw_host_cap_req_msg_v01, cal_cache_support), }, { @@ -2700,7 +2952,8 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x1A, - .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + .offset = offsetof(struct + wlfw_host_cap_req_msg_v01, cal_done_valid), }, { @@ -2709,7 +2962,8 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x1A, - .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + .offset = offsetof(struct + wlfw_host_cap_req_msg_v01, cal_done), }, { @@ -2718,7 +2972,8 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x1B, - .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + .offset = offsetof(struct + wlfw_host_cap_req_msg_v01, mem_bucket_valid), }, { @@ -2727,7 +2982,8 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0x1B, - .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + .offset = offsetof(struct + wlfw_host_cap_req_msg_v01, mem_bucket), }, { @@ -2736,7 +2992,8 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x1C, - .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + .offset = offsetof(struct + wlfw_host_cap_req_msg_v01, mem_cfg_mode_valid), }, { @@ -2745,7 +3002,8 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x1C, - .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + .offset = offsetof(struct + wlfw_host_cap_req_msg_v01, mem_cfg_mode), }, { @@ -2754,7 +3012,8 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x1D, - .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + .offset = offsetof(struct + wlfw_host_cap_req_msg_v01, cal_duration_valid), }, { @@ -2763,7 +3022,8 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { .elem_size = sizeof(u16), .array_type = NO_ARRAY, .tlv_type = 0x1D, - .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + .offset = offsetof(struct + wlfw_host_cap_req_msg_v01, cal_duration), }, { @@ -2772,7 +3032,8 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x1E, - .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + .offset = offsetof(struct + wlfw_host_cap_req_msg_v01, platform_name_valid), }, { @@ -2781,7 +3042,8 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { .elem_size = sizeof(char), .array_type = NO_ARRAY, .tlv_type = 0x1E, - .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + .offset = offsetof(struct + wlfw_host_cap_req_msg_v01, platform_name), }, { @@ -2790,7 +3052,8 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x1F, - .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + .offset = offsetof(struct + wlfw_host_cap_req_msg_v01, ddr_range_valid), }, { @@ -2799,7 +3062,8 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { .elem_size = sizeof(struct wlfw_host_ddr_range_s_v01), .array_type = STATIC_ARRAY, .tlv_type = 0x1F, - .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + .offset = offsetof(struct + wlfw_host_cap_req_msg_v01, ddr_range), .ei_array = wlfw_host_ddr_range_s_v01_ei, }, @@ -2809,7 +3073,8 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x20, - .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + .offset = offsetof(struct + wlfw_host_cap_req_msg_v01, host_build_type_valid), }, { @@ -2818,7 +3083,8 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { .elem_size = sizeof(enum wlfw_host_build_type_v01), .array_type = NO_ARRAY, .tlv_type = 0x20, - .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + .offset = offsetof(struct + wlfw_host_cap_req_msg_v01, host_build_type), }, { @@ -2827,6 +3093,7 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_host_cap_req_msg_v01_ei); struct qmi_elem_info wlfw_host_cap_resp_msg_v01_ei[] = { { @@ -2835,7 +3102,8 @@ struct qmi_elem_info wlfw_host_cap_resp_msg_v01_ei[] = { .elem_size = sizeof(struct qmi_response_type_v01), .array_type = NO_ARRAY, .tlv_type = 0x02, - .offset = offsetof(struct wlfw_host_cap_resp_msg_v01, + .offset = offsetof(struct + wlfw_host_cap_resp_msg_v01, resp), .ei_array = qmi_response_type_v01_ei, }, @@ -2845,6 +3113,7 @@ struct qmi_elem_info wlfw_host_cap_resp_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_host_cap_resp_msg_v01_ei); struct qmi_elem_info wlfw_request_mem_ind_msg_v01_ei[] = { { @@ -2853,7 +3122,8 @@ struct qmi_elem_info wlfw_request_mem_ind_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x01, - .offset = offsetof(struct wlfw_request_mem_ind_msg_v01, + .offset = offsetof(struct + wlfw_request_mem_ind_msg_v01, mem_seg_len), }, { @@ -2862,7 +3132,8 @@ struct qmi_elem_info wlfw_request_mem_ind_msg_v01_ei[] = { .elem_size = sizeof(struct wlfw_mem_seg_s_v01), .array_type = VAR_LEN_ARRAY, .tlv_type = 0x01, - .offset = offsetof(struct wlfw_request_mem_ind_msg_v01, + .offset = offsetof(struct + wlfw_request_mem_ind_msg_v01, mem_seg), .ei_array = wlfw_mem_seg_s_v01_ei, }, @@ -2872,6 +3143,7 @@ struct qmi_elem_info wlfw_request_mem_ind_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_request_mem_ind_msg_v01_ei); struct qmi_elem_info wlfw_respond_mem_req_msg_v01_ei[] = { { @@ -2880,7 +3152,8 @@ struct qmi_elem_info wlfw_respond_mem_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x01, - .offset = offsetof(struct wlfw_respond_mem_req_msg_v01, + .offset = offsetof(struct + wlfw_respond_mem_req_msg_v01, mem_seg_len), }, { @@ -2889,7 +3162,8 @@ struct qmi_elem_info wlfw_respond_mem_req_msg_v01_ei[] = { .elem_size = sizeof(struct wlfw_mem_seg_resp_s_v01), .array_type = VAR_LEN_ARRAY, .tlv_type = 0x01, - .offset = offsetof(struct wlfw_respond_mem_req_msg_v01, + .offset = offsetof(struct + wlfw_respond_mem_req_msg_v01, mem_seg), .ei_array = wlfw_mem_seg_resp_s_v01_ei, }, @@ -2899,6 +3173,7 @@ struct qmi_elem_info wlfw_respond_mem_req_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_respond_mem_req_msg_v01_ei); struct qmi_elem_info wlfw_respond_mem_resp_msg_v01_ei[] = { { @@ -2907,7 +3182,8 @@ struct qmi_elem_info wlfw_respond_mem_resp_msg_v01_ei[] = { .elem_size = sizeof(struct qmi_response_type_v01), .array_type = NO_ARRAY, .tlv_type = 0x02, - .offset = offsetof(struct wlfw_respond_mem_resp_msg_v01, + .offset = offsetof(struct + wlfw_respond_mem_resp_msg_v01, resp), .ei_array = qmi_response_type_v01_ei, }, @@ -2917,6 +3193,7 @@ struct qmi_elem_info wlfw_respond_mem_resp_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_respond_mem_resp_msg_v01_ei); struct qmi_elem_info wlfw_fw_mem_ready_ind_msg_v01_ei[] = { { @@ -2925,6 +3202,7 @@ struct qmi_elem_info wlfw_fw_mem_ready_ind_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_fw_mem_ready_ind_msg_v01_ei); struct qmi_elem_info wlfw_fw_init_done_ind_msg_v01_ei[] = { { @@ -2933,6 +3211,7 @@ struct qmi_elem_info wlfw_fw_init_done_ind_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_fw_init_done_ind_msg_v01_ei); struct qmi_elem_info wlfw_rejuvenate_ind_msg_v01_ei[] = { { @@ -2941,7 +3220,8 @@ struct qmi_elem_info wlfw_rejuvenate_ind_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x10, - .offset = offsetof(struct wlfw_rejuvenate_ind_msg_v01, + .offset = offsetof(struct + wlfw_rejuvenate_ind_msg_v01, cause_for_rejuvenation_valid), }, { @@ -2950,7 +3230,8 @@ struct qmi_elem_info wlfw_rejuvenate_ind_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x10, - .offset = offsetof(struct wlfw_rejuvenate_ind_msg_v01, + .offset = offsetof(struct + wlfw_rejuvenate_ind_msg_v01, cause_for_rejuvenation), }, { @@ -2959,7 +3240,8 @@ struct qmi_elem_info wlfw_rejuvenate_ind_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x11, - .offset = offsetof(struct wlfw_rejuvenate_ind_msg_v01, + .offset = offsetof(struct + wlfw_rejuvenate_ind_msg_v01, requesting_sub_system_valid), }, { @@ -2968,7 +3250,8 @@ struct qmi_elem_info wlfw_rejuvenate_ind_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x11, - .offset = offsetof(struct wlfw_rejuvenate_ind_msg_v01, + .offset = offsetof(struct + wlfw_rejuvenate_ind_msg_v01, requesting_sub_system), }, { @@ -2977,7 +3260,8 @@ struct qmi_elem_info wlfw_rejuvenate_ind_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x12, - .offset = offsetof(struct wlfw_rejuvenate_ind_msg_v01, + .offset = offsetof(struct + wlfw_rejuvenate_ind_msg_v01, line_number_valid), }, { @@ -2986,7 +3270,8 @@ struct qmi_elem_info wlfw_rejuvenate_ind_msg_v01_ei[] = { .elem_size = sizeof(u16), .array_type = NO_ARRAY, .tlv_type = 0x12, - .offset = offsetof(struct wlfw_rejuvenate_ind_msg_v01, + .offset = offsetof(struct + wlfw_rejuvenate_ind_msg_v01, line_number), }, { @@ -2995,7 +3280,8 @@ struct qmi_elem_info wlfw_rejuvenate_ind_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x13, - .offset = offsetof(struct wlfw_rejuvenate_ind_msg_v01, + .offset = offsetof(struct + wlfw_rejuvenate_ind_msg_v01, function_name_valid), }, { @@ -3004,7 +3290,8 @@ struct qmi_elem_info wlfw_rejuvenate_ind_msg_v01_ei[] = { .elem_size = sizeof(char), .array_type = NO_ARRAY, .tlv_type = 0x13, - .offset = offsetof(struct wlfw_rejuvenate_ind_msg_v01, + .offset = offsetof(struct + wlfw_rejuvenate_ind_msg_v01, function_name), }, { @@ -3013,6 +3300,7 @@ struct qmi_elem_info wlfw_rejuvenate_ind_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_rejuvenate_ind_msg_v01_ei); struct qmi_elem_info wlfw_rejuvenate_ack_req_msg_v01_ei[] = { { @@ -3021,6 +3309,7 @@ struct qmi_elem_info wlfw_rejuvenate_ack_req_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_rejuvenate_ack_req_msg_v01_ei); struct qmi_elem_info wlfw_rejuvenate_ack_resp_msg_v01_ei[] = { { @@ -3040,6 +3329,7 @@ struct qmi_elem_info wlfw_rejuvenate_ack_resp_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_rejuvenate_ack_resp_msg_v01_ei); struct qmi_elem_info wlfw_dynamic_feature_mask_req_msg_v01_ei[] = { { @@ -3049,8 +3339,8 @@ struct qmi_elem_info wlfw_dynamic_feature_mask_req_msg_v01_ei[] = { .array_type = NO_ARRAY, .tlv_type = 0x10, .offset = offsetof(struct - wlfw_dynamic_feature_mask_req_msg_v01, - mask_valid), + wlfw_dynamic_feature_mask_req_msg_v01, + mask_valid), }, { .data_type = QMI_UNSIGNED_8_BYTE, @@ -3059,8 +3349,8 @@ struct qmi_elem_info wlfw_dynamic_feature_mask_req_msg_v01_ei[] = { .array_type = NO_ARRAY, .tlv_type = 0x10, .offset = offsetof(struct - wlfw_dynamic_feature_mask_req_msg_v01, - mask), + wlfw_dynamic_feature_mask_req_msg_v01, + mask), }, { .data_type = QMI_EOTI, @@ -3068,6 +3358,7 @@ struct qmi_elem_info wlfw_dynamic_feature_mask_req_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_dynamic_feature_mask_req_msg_v01_ei); struct qmi_elem_info wlfw_dynamic_feature_mask_resp_msg_v01_ei[] = { { @@ -3077,8 +3368,8 @@ struct qmi_elem_info wlfw_dynamic_feature_mask_resp_msg_v01_ei[] = { .array_type = NO_ARRAY, .tlv_type = 0x02, .offset = offsetof(struct - wlfw_dynamic_feature_mask_resp_msg_v01, - resp), + wlfw_dynamic_feature_mask_resp_msg_v01, + resp), .ei_array = qmi_response_type_v01_ei, }, { @@ -3088,8 +3379,8 @@ struct qmi_elem_info wlfw_dynamic_feature_mask_resp_msg_v01_ei[] = { .array_type = NO_ARRAY, .tlv_type = 0x10, .offset = offsetof(struct - wlfw_dynamic_feature_mask_resp_msg_v01, - prev_mask_valid), + wlfw_dynamic_feature_mask_resp_msg_v01, + prev_mask_valid), }, { .data_type = QMI_UNSIGNED_8_BYTE, @@ -3098,8 +3389,8 @@ struct qmi_elem_info wlfw_dynamic_feature_mask_resp_msg_v01_ei[] = { .array_type = NO_ARRAY, .tlv_type = 0x10, .offset = offsetof(struct - wlfw_dynamic_feature_mask_resp_msg_v01, - prev_mask), + wlfw_dynamic_feature_mask_resp_msg_v01, + prev_mask), }, { .data_type = QMI_OPT_FLAG, @@ -3108,8 +3399,8 @@ struct qmi_elem_info wlfw_dynamic_feature_mask_resp_msg_v01_ei[] = { .array_type = NO_ARRAY, .tlv_type = 0x11, .offset = offsetof(struct - wlfw_dynamic_feature_mask_resp_msg_v01, - curr_mask_valid), + wlfw_dynamic_feature_mask_resp_msg_v01, + curr_mask_valid), }, { .data_type = QMI_UNSIGNED_8_BYTE, @@ -3118,8 +3409,8 @@ struct qmi_elem_info wlfw_dynamic_feature_mask_resp_msg_v01_ei[] = { .array_type = NO_ARRAY, .tlv_type = 0x11, .offset = offsetof(struct - wlfw_dynamic_feature_mask_resp_msg_v01, - curr_mask), + wlfw_dynamic_feature_mask_resp_msg_v01, + curr_mask), }, { .data_type = QMI_EOTI, @@ -3127,6 +3418,7 @@ struct qmi_elem_info wlfw_dynamic_feature_mask_resp_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_dynamic_feature_mask_resp_msg_v01_ei); struct qmi_elem_info wlfw_m3_info_req_msg_v01_ei[] = { { @@ -3135,7 +3427,8 @@ struct qmi_elem_info wlfw_m3_info_req_msg_v01_ei[] = { .elem_size = sizeof(u64), .array_type = NO_ARRAY, .tlv_type = 0x01, - .offset = offsetof(struct wlfw_m3_info_req_msg_v01, + .offset = offsetof(struct + wlfw_m3_info_req_msg_v01, addr), }, { @@ -3144,7 +3437,8 @@ struct qmi_elem_info wlfw_m3_info_req_msg_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0x02, - .offset = offsetof(struct wlfw_m3_info_req_msg_v01, + .offset = offsetof(struct + wlfw_m3_info_req_msg_v01, size), }, { @@ -3153,6 +3447,7 @@ struct qmi_elem_info wlfw_m3_info_req_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_m3_info_req_msg_v01_ei); struct qmi_elem_info wlfw_m3_info_resp_msg_v01_ei[] = { { @@ -3161,7 +3456,8 @@ struct qmi_elem_info wlfw_m3_info_resp_msg_v01_ei[] = { .elem_size = sizeof(struct qmi_response_type_v01), .array_type = NO_ARRAY, .tlv_type = 0x02, - .offset = offsetof(struct wlfw_m3_info_resp_msg_v01, + .offset = offsetof(struct + wlfw_m3_info_resp_msg_v01, resp), .ei_array = qmi_response_type_v01_ei, }, @@ -3171,6 +3467,7 @@ struct qmi_elem_info wlfw_m3_info_resp_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_m3_info_resp_msg_v01_ei); struct qmi_elem_info wlfw_xo_cal_ind_msg_v01_ei[] = { { @@ -3179,7 +3476,8 @@ struct qmi_elem_info wlfw_xo_cal_ind_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x01, - .offset = offsetof(struct wlfw_xo_cal_ind_msg_v01, + .offset = offsetof(struct + wlfw_xo_cal_ind_msg_v01, xo_cal_data), }, { @@ -3188,6 +3486,7 @@ struct qmi_elem_info wlfw_xo_cal_ind_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_xo_cal_ind_msg_v01_ei); struct qmi_elem_info wlfw_cal_done_ind_msg_v01_ei[] = { { @@ -3196,6 +3495,7 @@ struct qmi_elem_info wlfw_cal_done_ind_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_cal_done_ind_msg_v01_ei); struct qmi_elem_info wlfw_qdss_trace_req_mem_ind_msg_v01_ei[] = { { @@ -3225,6 +3525,7 @@ struct qmi_elem_info wlfw_qdss_trace_req_mem_ind_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_qdss_trace_req_mem_ind_msg_v01_ei); struct qmi_elem_info wlfw_qdss_trace_mem_info_req_msg_v01_ei[] = { { @@ -3254,6 +3555,7 @@ struct qmi_elem_info wlfw_qdss_trace_mem_info_req_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_qdss_trace_mem_info_req_msg_v01_ei); struct qmi_elem_info wlfw_qdss_trace_mem_info_resp_msg_v01_ei[] = { { @@ -3263,8 +3565,8 @@ struct qmi_elem_info wlfw_qdss_trace_mem_info_resp_msg_v01_ei[] = { .array_type = NO_ARRAY, .tlv_type = 0x02, .offset = offsetof(struct - wlfw_qdss_trace_mem_info_resp_msg_v01, - resp), + wlfw_qdss_trace_mem_info_resp_msg_v01, + resp), .ei_array = qmi_response_type_v01_ei, }, { @@ -3273,6 +3575,7 @@ struct qmi_elem_info wlfw_qdss_trace_mem_info_resp_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_qdss_trace_mem_info_resp_msg_v01_ei); struct qmi_elem_info wlfw_qdss_trace_save_ind_msg_v01_ei[] = { { @@ -3352,6 +3655,7 @@ struct qmi_elem_info wlfw_qdss_trace_save_ind_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_qdss_trace_save_ind_msg_v01_ei); struct qmi_elem_info wlfw_qdss_trace_data_req_msg_v01_ei[] = { { @@ -3370,6 +3674,7 @@ struct qmi_elem_info wlfw_qdss_trace_data_req_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_qdss_trace_data_req_msg_v01_ei); struct qmi_elem_info wlfw_qdss_trace_data_resp_msg_v01_ei[] = { { @@ -3479,6 +3784,7 @@ struct qmi_elem_info wlfw_qdss_trace_data_resp_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_qdss_trace_data_resp_msg_v01_ei); struct qmi_elem_info wlfw_qdss_trace_config_download_req_msg_v01_ei[] = { { @@ -3488,8 +3794,8 @@ struct qmi_elem_info wlfw_qdss_trace_config_download_req_msg_v01_ei[] = { .array_type = NO_ARRAY, .tlv_type = 0x10, .offset = offsetof(struct - wlfw_qdss_trace_config_download_req_msg_v01, - total_size_valid), + wlfw_qdss_trace_config_download_req_msg_v01, + total_size_valid), }, { .data_type = QMI_UNSIGNED_4_BYTE, @@ -3498,8 +3804,8 @@ struct qmi_elem_info wlfw_qdss_trace_config_download_req_msg_v01_ei[] = { .array_type = NO_ARRAY, .tlv_type = 0x10, .offset = offsetof(struct - wlfw_qdss_trace_config_download_req_msg_v01, - total_size), + wlfw_qdss_trace_config_download_req_msg_v01, + total_size), }, { .data_type = QMI_OPT_FLAG, @@ -3508,8 +3814,8 @@ struct qmi_elem_info wlfw_qdss_trace_config_download_req_msg_v01_ei[] = { .array_type = NO_ARRAY, .tlv_type = 0x11, .offset = offsetof(struct - wlfw_qdss_trace_config_download_req_msg_v01, - seg_id_valid), + wlfw_qdss_trace_config_download_req_msg_v01, + seg_id_valid), }, { .data_type = QMI_UNSIGNED_4_BYTE, @@ -3518,8 +3824,8 @@ struct qmi_elem_info wlfw_qdss_trace_config_download_req_msg_v01_ei[] = { .array_type = NO_ARRAY, .tlv_type = 0x11, .offset = offsetof(struct - wlfw_qdss_trace_config_download_req_msg_v01, - seg_id), + wlfw_qdss_trace_config_download_req_msg_v01, + seg_id), }, { .data_type = QMI_OPT_FLAG, @@ -3528,8 +3834,8 @@ struct qmi_elem_info wlfw_qdss_trace_config_download_req_msg_v01_ei[] = { .array_type = NO_ARRAY, .tlv_type = 0x12, .offset = offsetof(struct - wlfw_qdss_trace_config_download_req_msg_v01, - data_valid), + wlfw_qdss_trace_config_download_req_msg_v01, + data_valid), }, { .data_type = QMI_DATA_LEN, @@ -3538,8 +3844,8 @@ struct qmi_elem_info wlfw_qdss_trace_config_download_req_msg_v01_ei[] = { .array_type = NO_ARRAY, .tlv_type = 0x12, .offset = offsetof(struct - wlfw_qdss_trace_config_download_req_msg_v01, - data_len), + wlfw_qdss_trace_config_download_req_msg_v01, + data_len), }, { .data_type = QMI_UNSIGNED_1_BYTE, @@ -3548,8 +3854,8 @@ struct qmi_elem_info wlfw_qdss_trace_config_download_req_msg_v01_ei[] = { .array_type = VAR_LEN_ARRAY, .tlv_type = 0x12, .offset = offsetof(struct - wlfw_qdss_trace_config_download_req_msg_v01, - data), + wlfw_qdss_trace_config_download_req_msg_v01, + data), }, { .data_type = QMI_OPT_FLAG, @@ -3558,8 +3864,8 @@ struct qmi_elem_info wlfw_qdss_trace_config_download_req_msg_v01_ei[] = { .array_type = NO_ARRAY, .tlv_type = 0x13, .offset = offsetof(struct - wlfw_qdss_trace_config_download_req_msg_v01, - end_valid), + wlfw_qdss_trace_config_download_req_msg_v01, + end_valid), }, { .data_type = QMI_UNSIGNED_1_BYTE, @@ -3568,8 +3874,8 @@ struct qmi_elem_info wlfw_qdss_trace_config_download_req_msg_v01_ei[] = { .array_type = NO_ARRAY, .tlv_type = 0x13, .offset = offsetof(struct - wlfw_qdss_trace_config_download_req_msg_v01, - end), + wlfw_qdss_trace_config_download_req_msg_v01, + end), }, { .data_type = QMI_EOTI, @@ -3577,6 +3883,7 @@ struct qmi_elem_info wlfw_qdss_trace_config_download_req_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_qdss_trace_config_download_req_msg_v01_ei); struct qmi_elem_info wlfw_qdss_trace_config_download_resp_msg_v01_ei[] = { { @@ -3586,8 +3893,8 @@ struct qmi_elem_info wlfw_qdss_trace_config_download_resp_msg_v01_ei[] = { .array_type = NO_ARRAY, .tlv_type = 0x02, .offset = offsetof(struct - wlfw_qdss_trace_config_download_resp_msg_v01, - resp), + wlfw_qdss_trace_config_download_resp_msg_v01, + resp), .ei_array = qmi_response_type_v01_ei, }, { @@ -3596,6 +3903,7 @@ struct qmi_elem_info wlfw_qdss_trace_config_download_resp_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_qdss_trace_config_download_resp_msg_v01_ei); struct qmi_elem_info wlfw_qdss_trace_mode_req_msg_v01_ei[] = { { @@ -3605,8 +3913,8 @@ struct qmi_elem_info wlfw_qdss_trace_mode_req_msg_v01_ei[] = { .array_type = NO_ARRAY, .tlv_type = 0x10, .offset = offsetof(struct - wlfw_qdss_trace_mode_req_msg_v01, - mode_valid), + wlfw_qdss_trace_mode_req_msg_v01, + mode_valid), }, { .data_type = QMI_SIGNED_4_BYTE_ENUM, @@ -3664,6 +3972,7 @@ struct qmi_elem_info wlfw_qdss_trace_mode_req_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_qdss_trace_mode_req_msg_v01_ei); struct qmi_elem_info wlfw_qdss_trace_mode_resp_msg_v01_ei[] = { { @@ -3683,6 +3992,7 @@ struct qmi_elem_info wlfw_qdss_trace_mode_resp_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_qdss_trace_mode_resp_msg_v01_ei); struct qmi_elem_info wlfw_qdss_trace_free_ind_msg_v01_ei[] = { { @@ -3722,6 +4032,7 @@ struct qmi_elem_info wlfw_qdss_trace_free_ind_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_qdss_trace_free_ind_msg_v01_ei); struct qmi_elem_info wlfw_shutdown_req_msg_v01_ei[] = { { @@ -3730,7 +4041,8 @@ struct qmi_elem_info wlfw_shutdown_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x10, - .offset = offsetof(struct wlfw_shutdown_req_msg_v01, + .offset = offsetof(struct + wlfw_shutdown_req_msg_v01, shutdown_valid), }, { @@ -3739,7 +4051,8 @@ struct qmi_elem_info wlfw_shutdown_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x10, - .offset = offsetof(struct wlfw_shutdown_req_msg_v01, + .offset = offsetof(struct + wlfw_shutdown_req_msg_v01, shutdown), }, { @@ -3748,6 +4061,7 @@ struct qmi_elem_info wlfw_shutdown_req_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_shutdown_req_msg_v01_ei); struct qmi_elem_info wlfw_shutdown_resp_msg_v01_ei[] = { { @@ -3756,7 +4070,8 @@ struct qmi_elem_info wlfw_shutdown_resp_msg_v01_ei[] = { .elem_size = sizeof(struct qmi_response_type_v01), .array_type = NO_ARRAY, .tlv_type = 0x02, - .offset = offsetof(struct wlfw_shutdown_resp_msg_v01, + .offset = offsetof(struct + wlfw_shutdown_resp_msg_v01, resp), .ei_array = qmi_response_type_v01_ei, }, @@ -3766,6 +4081,7 @@ struct qmi_elem_info wlfw_shutdown_resp_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_shutdown_resp_msg_v01_ei); struct qmi_elem_info wlfw_antenna_switch_req_msg_v01_ei[] = { { @@ -3774,6 +4090,7 @@ struct qmi_elem_info wlfw_antenna_switch_req_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_antenna_switch_req_msg_v01_ei); struct qmi_elem_info wlfw_antenna_switch_resp_msg_v01_ei[] = { { @@ -3813,6 +4130,7 @@ struct qmi_elem_info wlfw_antenna_switch_resp_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_antenna_switch_resp_msg_v01_ei); struct qmi_elem_info wlfw_antenna_grant_req_msg_v01_ei[] = { { @@ -3841,6 +4159,7 @@ struct qmi_elem_info wlfw_antenna_grant_req_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_antenna_grant_req_msg_v01_ei); struct qmi_elem_info wlfw_antenna_grant_resp_msg_v01_ei[] = { { @@ -3860,6 +4179,7 @@ struct qmi_elem_info wlfw_antenna_grant_resp_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_antenna_grant_resp_msg_v01_ei); struct qmi_elem_info wlfw_wfc_call_status_req_msg_v01_ei[] = { { @@ -4008,6 +4328,7 @@ struct qmi_elem_info wlfw_wfc_call_status_req_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_wfc_call_status_req_msg_v01_ei); struct qmi_elem_info wlfw_wfc_call_status_resp_msg_v01_ei[] = { { @@ -4027,6 +4348,7 @@ struct qmi_elem_info wlfw_wfc_call_status_resp_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_wfc_call_status_resp_msg_v01_ei); struct qmi_elem_info wlfw_get_info_req_msg_v01_ei[] = { { @@ -4035,7 +4357,8 @@ struct qmi_elem_info wlfw_get_info_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x01, - .offset = offsetof(struct wlfw_get_info_req_msg_v01, + .offset = offsetof(struct + wlfw_get_info_req_msg_v01, type), }, { @@ -4044,7 +4367,8 @@ struct qmi_elem_info wlfw_get_info_req_msg_v01_ei[] = { .elem_size = sizeof(u16), .array_type = NO_ARRAY, .tlv_type = 0x02, - .offset = offsetof(struct wlfw_get_info_req_msg_v01, + .offset = offsetof(struct + wlfw_get_info_req_msg_v01, data_len), }, { @@ -4053,7 +4377,8 @@ struct qmi_elem_info wlfw_get_info_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = VAR_LEN_ARRAY, .tlv_type = 0x02, - .offset = offsetof(struct wlfw_get_info_req_msg_v01, + .offset = offsetof(struct + wlfw_get_info_req_msg_v01, data), }, { @@ -4062,6 +4387,7 @@ struct qmi_elem_info wlfw_get_info_req_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_get_info_req_msg_v01_ei); struct qmi_elem_info wlfw_get_info_resp_msg_v01_ei[] = { { @@ -4070,7 +4396,8 @@ struct qmi_elem_info wlfw_get_info_resp_msg_v01_ei[] = { .elem_size = sizeof(struct qmi_response_type_v01), .array_type = NO_ARRAY, .tlv_type = 0x02, - .offset = offsetof(struct wlfw_get_info_resp_msg_v01, + .offset = offsetof(struct + wlfw_get_info_resp_msg_v01, resp), .ei_array = qmi_response_type_v01_ei, }, @@ -4080,6 +4407,7 @@ struct qmi_elem_info wlfw_get_info_resp_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_get_info_resp_msg_v01_ei); struct qmi_elem_info wlfw_respond_get_info_ind_msg_v01_ei[] = { { @@ -4168,6 +4496,7 @@ struct qmi_elem_info wlfw_respond_get_info_ind_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_respond_get_info_ind_msg_v01_ei); struct qmi_elem_info wlfw_device_info_req_msg_v01_ei[] = { { @@ -4176,6 +4505,7 @@ struct qmi_elem_info wlfw_device_info_req_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_device_info_req_msg_v01_ei); struct qmi_elem_info wlfw_device_info_resp_msg_v01_ei[] = { { @@ -4184,7 +4514,8 @@ struct qmi_elem_info wlfw_device_info_resp_msg_v01_ei[] = { .elem_size = sizeof(struct qmi_response_type_v01), .array_type = NO_ARRAY, .tlv_type = 0x02, - .offset = offsetof(struct wlfw_device_info_resp_msg_v01, + .offset = offsetof(struct + wlfw_device_info_resp_msg_v01, resp), .ei_array = qmi_response_type_v01_ei, }, @@ -4194,7 +4525,8 @@ struct qmi_elem_info wlfw_device_info_resp_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x10, - .offset = offsetof(struct wlfw_device_info_resp_msg_v01, + .offset = offsetof(struct + wlfw_device_info_resp_msg_v01, bar_addr_valid), }, { @@ -4203,7 +4535,8 @@ struct qmi_elem_info wlfw_device_info_resp_msg_v01_ei[] = { .elem_size = sizeof(u64), .array_type = NO_ARRAY, .tlv_type = 0x10, - .offset = offsetof(struct wlfw_device_info_resp_msg_v01, + .offset = offsetof(struct + wlfw_device_info_resp_msg_v01, bar_addr), }, { @@ -4212,7 +4545,8 @@ struct qmi_elem_info wlfw_device_info_resp_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x11, - .offset = offsetof(struct wlfw_device_info_resp_msg_v01, + .offset = offsetof(struct + wlfw_device_info_resp_msg_v01, bar_size_valid), }, { @@ -4221,7 +4555,8 @@ struct qmi_elem_info wlfw_device_info_resp_msg_v01_ei[] = { .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0x11, - .offset = offsetof(struct wlfw_device_info_resp_msg_v01, + .offset = offsetof(struct + wlfw_device_info_resp_msg_v01, bar_size), }, { @@ -4230,6 +4565,7 @@ struct qmi_elem_info wlfw_device_info_resp_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_device_info_resp_msg_v01_ei); struct qmi_elem_info wlfw_m3_dump_upload_req_ind_msg_v01_ei[] = { { @@ -4268,6 +4604,7 @@ struct qmi_elem_info wlfw_m3_dump_upload_req_ind_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_m3_dump_upload_req_ind_msg_v01_ei); struct qmi_elem_info wlfw_m3_dump_upload_done_req_msg_v01_ei[] = { { @@ -4296,6 +4633,7 @@ struct qmi_elem_info wlfw_m3_dump_upload_done_req_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_m3_dump_upload_done_req_msg_v01_ei); struct qmi_elem_info wlfw_m3_dump_upload_done_resp_msg_v01_ei[] = { { @@ -4305,8 +4643,8 @@ struct qmi_elem_info wlfw_m3_dump_upload_done_resp_msg_v01_ei[] = { .array_type = NO_ARRAY, .tlv_type = 0x02, .offset = offsetof(struct - wlfw_m3_dump_upload_done_resp_msg_v01, - resp), + wlfw_m3_dump_upload_done_resp_msg_v01, + resp), .ei_array = qmi_response_type_v01_ei, }, { @@ -4315,6 +4653,7 @@ struct qmi_elem_info wlfw_m3_dump_upload_done_resp_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_m3_dump_upload_done_resp_msg_v01_ei); struct qmi_elem_info wlfw_soc_wake_req_msg_v01_ei[] = { { @@ -4333,7 +4672,8 @@ struct qmi_elem_info wlfw_soc_wake_req_msg_v01_ei[] = { .elem_size = sizeof(enum wlfw_soc_wake_enum_v01), .array_type = NO_ARRAY, .tlv_type = 0x10, - .offset = offsetof(struct wlfw_soc_wake_req_msg_v01, + .offset = offsetof(struct + wlfw_soc_wake_req_msg_v01, wake), }, { @@ -4342,6 +4682,7 @@ struct qmi_elem_info wlfw_soc_wake_req_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_soc_wake_req_msg_v01_ei); struct qmi_elem_info wlfw_soc_wake_resp_msg_v01_ei[] = { { @@ -4350,7 +4691,8 @@ struct qmi_elem_info wlfw_soc_wake_resp_msg_v01_ei[] = { .elem_size = sizeof(struct qmi_response_type_v01), .array_type = NO_ARRAY, .tlv_type = 0x02, - .offset = offsetof(struct wlfw_soc_wake_resp_msg_v01, + .offset = offsetof(struct + wlfw_soc_wake_resp_msg_v01, resp), .ei_array = qmi_response_type_v01_ei, }, @@ -4360,6 +4702,7 @@ struct qmi_elem_info wlfw_soc_wake_resp_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_soc_wake_resp_msg_v01_ei); struct qmi_elem_info wlfw_power_save_req_msg_v01_ei[] = { { @@ -4368,7 +4711,8 @@ struct qmi_elem_info wlfw_power_save_req_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x10, - .offset = offsetof(struct wlfw_power_save_req_msg_v01, + .offset = offsetof(struct + wlfw_power_save_req_msg_v01, power_save_mode_valid), }, { @@ -4377,7 +4721,8 @@ struct qmi_elem_info wlfw_power_save_req_msg_v01_ei[] = { .elem_size = sizeof(enum wlfw_power_save_mode_v01), .array_type = NO_ARRAY, .tlv_type = 0x10, - .offset = offsetof(struct wlfw_power_save_req_msg_v01, + .offset = offsetof(struct + wlfw_power_save_req_msg_v01, power_save_mode), }, { @@ -4386,6 +4731,7 @@ struct qmi_elem_info wlfw_power_save_req_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_power_save_req_msg_v01_ei); struct qmi_elem_info wlfw_power_save_resp_msg_v01_ei[] = { { @@ -4394,7 +4740,8 @@ struct qmi_elem_info wlfw_power_save_resp_msg_v01_ei[] = { .elem_size = sizeof(struct qmi_response_type_v01), .array_type = NO_ARRAY, .tlv_type = 0x02, - .offset = offsetof(struct wlfw_power_save_resp_msg_v01, + .offset = offsetof(struct + wlfw_power_save_resp_msg_v01, resp), .ei_array = qmi_response_type_v01_ei, }, @@ -4404,6 +4751,7 @@ struct qmi_elem_info wlfw_power_save_resp_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_power_save_resp_msg_v01_ei); struct qmi_elem_info wlfw_wfc_call_twt_config_ind_msg_v01_ei[] = { { @@ -4412,9 +4760,9 @@ struct qmi_elem_info wlfw_wfc_call_twt_config_ind_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x10, - .offset = - offsetof(struct wlfw_wfc_call_twt_config_ind_msg_v01, - twt_sta_start_valid), + .offset = offsetof(struct + wlfw_wfc_call_twt_config_ind_msg_v01, + twt_sta_start_valid), }, { .data_type = QMI_UNSIGNED_8_BYTE, @@ -4422,9 +4770,9 @@ struct qmi_elem_info wlfw_wfc_call_twt_config_ind_msg_v01_ei[] = { .elem_size = sizeof(u64), .array_type = NO_ARRAY, .tlv_type = 0x10, - .offset = - offsetof(struct wlfw_wfc_call_twt_config_ind_msg_v01, - twt_sta_start), + .offset = offsetof(struct + wlfw_wfc_call_twt_config_ind_msg_v01, + twt_sta_start), }, { .data_type = QMI_OPT_FLAG, @@ -4432,9 +4780,9 @@ struct qmi_elem_info wlfw_wfc_call_twt_config_ind_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x11, - .offset = - offsetof(struct wlfw_wfc_call_twt_config_ind_msg_v01, - twt_sta_int_valid), + .offset = offsetof(struct + wlfw_wfc_call_twt_config_ind_msg_v01, + twt_sta_int_valid), }, { .data_type = QMI_UNSIGNED_2_BYTE, @@ -4442,9 +4790,9 @@ struct qmi_elem_info wlfw_wfc_call_twt_config_ind_msg_v01_ei[] = { .elem_size = sizeof(u16), .array_type = NO_ARRAY, .tlv_type = 0x11, - .offset = - offsetof(struct wlfw_wfc_call_twt_config_ind_msg_v01, - twt_sta_int), + .offset = offsetof(struct + wlfw_wfc_call_twt_config_ind_msg_v01, + twt_sta_int), }, { .data_type = QMI_OPT_FLAG, @@ -4452,9 +4800,9 @@ struct qmi_elem_info wlfw_wfc_call_twt_config_ind_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x12, - .offset = - offsetof(struct wlfw_wfc_call_twt_config_ind_msg_v01, - twt_sta_upo_valid), + .offset = offsetof(struct + wlfw_wfc_call_twt_config_ind_msg_v01, + twt_sta_upo_valid), }, { .data_type = QMI_UNSIGNED_2_BYTE, @@ -4462,9 +4810,9 @@ struct qmi_elem_info wlfw_wfc_call_twt_config_ind_msg_v01_ei[] = { .elem_size = sizeof(u16), .array_type = NO_ARRAY, .tlv_type = 0x12, - .offset = - offsetof(struct wlfw_wfc_call_twt_config_ind_msg_v01, - twt_sta_upo), + .offset = offsetof(struct + wlfw_wfc_call_twt_config_ind_msg_v01, + twt_sta_upo), }, { .data_type = QMI_OPT_FLAG, @@ -4472,9 +4820,9 @@ struct qmi_elem_info wlfw_wfc_call_twt_config_ind_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x13, - .offset = - offsetof(struct wlfw_wfc_call_twt_config_ind_msg_v01, - twt_sta_sp_valid), + .offset = offsetof(struct + wlfw_wfc_call_twt_config_ind_msg_v01, + twt_sta_sp_valid), }, { .data_type = QMI_UNSIGNED_2_BYTE, @@ -4482,9 +4830,9 @@ struct qmi_elem_info wlfw_wfc_call_twt_config_ind_msg_v01_ei[] = { .elem_size = sizeof(u16), .array_type = NO_ARRAY, .tlv_type = 0x13, - .offset = - offsetof(struct wlfw_wfc_call_twt_config_ind_msg_v01, - twt_sta_sp), + .offset = offsetof(struct + wlfw_wfc_call_twt_config_ind_msg_v01, + twt_sta_sp), }, { .data_type = QMI_OPT_FLAG, @@ -4492,9 +4840,9 @@ struct qmi_elem_info wlfw_wfc_call_twt_config_ind_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x14, - .offset = - offsetof(struct wlfw_wfc_call_twt_config_ind_msg_v01, - twt_sta_dl_valid), + .offset = offsetof(struct + wlfw_wfc_call_twt_config_ind_msg_v01, + twt_sta_dl_valid), }, { .data_type = QMI_UNSIGNED_2_BYTE, @@ -4502,9 +4850,9 @@ struct qmi_elem_info wlfw_wfc_call_twt_config_ind_msg_v01_ei[] = { .elem_size = sizeof(u16), .array_type = NO_ARRAY, .tlv_type = 0x14, - .offset = - offsetof(struct wlfw_wfc_call_twt_config_ind_msg_v01, - twt_sta_dl), + .offset = offsetof(struct + wlfw_wfc_call_twt_config_ind_msg_v01, + twt_sta_dl), }, { .data_type = QMI_OPT_FLAG, @@ -4512,9 +4860,9 @@ struct qmi_elem_info wlfw_wfc_call_twt_config_ind_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x15, - .offset = - offsetof(struct wlfw_wfc_call_twt_config_ind_msg_v01, - twt_sta_config_changed_valid), + .offset = offsetof(struct + wlfw_wfc_call_twt_config_ind_msg_v01, + twt_sta_config_changed_valid), }, { .data_type = QMI_UNSIGNED_1_BYTE, @@ -4522,9 +4870,9 @@ struct qmi_elem_info wlfw_wfc_call_twt_config_ind_msg_v01_ei[] = { .elem_size = sizeof(u8), .array_type = NO_ARRAY, .tlv_type = 0x15, - .offset = - offsetof(struct wlfw_wfc_call_twt_config_ind_msg_v01, - twt_sta_config_changed), + .offset = offsetof(struct + wlfw_wfc_call_twt_config_ind_msg_v01, + twt_sta_config_changed), }, { .data_type = QMI_EOTI, @@ -4532,6 +4880,7 @@ struct qmi_elem_info wlfw_wfc_call_twt_config_ind_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_wfc_call_twt_config_ind_msg_v01_ei); struct qmi_elem_info wlfw_qdss_mem_ready_ind_msg_v01_ei[] = { { @@ -4540,6 +4889,7 @@ struct qmi_elem_info wlfw_qdss_mem_ready_ind_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_qdss_mem_ready_ind_msg_v01_ei); struct qmi_elem_info wlfw_pcie_gen_switch_req_msg_v01_ei[] = { { @@ -4558,6 +4908,7 @@ struct qmi_elem_info wlfw_pcie_gen_switch_req_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_pcie_gen_switch_req_msg_v01_ei); struct qmi_elem_info wlfw_pcie_gen_switch_resp_msg_v01_ei[] = { { @@ -4577,4 +4928,5 @@ struct qmi_elem_info wlfw_pcie_gen_switch_resp_msg_v01_ei[] = { .tlv_type = QMI_COMMON_TLV_TYPE, }, }; +EXPORT_SYMBOL(wlfw_pcie_gen_switch_resp_msg_v01_ei); diff --git a/drivers/soc/qcom/icnss2/wlan_firmware_service_v01.h b/drivers/net/wireless/cnss_utils/wlan_firmware_service_v01.h similarity index 98% rename from drivers/soc/qcom/icnss2/wlan_firmware_service_v01.h rename to drivers/net/wireless/cnss_utils/wlan_firmware_service_v01.h index aac8403d11c3..cdd81b429a97 100644 --- a/drivers/soc/qcom/icnss2/wlan_firmware_service_v01.h +++ b/drivers/net/wireless/cnss_utils/wlan_firmware_service_v01.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0-only */ -/* Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. */ +/* Copyright (c) 2020, The Linux Foundation. All rights reserved. */ #ifndef WLAN_FIRMWARE_SERVICE_V01_H #define WLAN_FIRMWARE_SERVICE_V01_H @@ -88,10 +88,6 @@ #define QMI_WLFW_XO_CAL_IND_V01 0x003D #define QMI_WLFW_SHUTDOWN_RESP_V01 0x0043 #define QMI_WLFW_ATHDIAG_READ_REQ_V01 0x0030 -#define QMI_WLFW_WLAN_CFG_REQ_V01 0x0023 -#define QMI_WLFW_IND_REGISTER_RESP_V01 0x0020 -#define QMI_WLFW_PCIE_GEN_SWITCH_REQ_V01 0x0053 -#define QMI_WLFW_PCIE_GEN_SWITCH_RESP_V01 0x0053 #define QMI_WLFW_WFC_CALL_TWT_CONFIG_IND_V01 0x0051 #define QMI_WLFW_WLAN_MODE_RESP_V01 0x0022 #define QMI_WLFW_WFC_CALL_STATUS_REQ_V01 0x0049 @@ -371,7 +367,6 @@ struct wlfw_ind_register_req_msg_v01 { u8 qdss_mem_ready_enable_valid; u8 qdss_mem_ready_enable; }; - #define WLFW_IND_REGISTER_REQ_MSG_V01_MAX_MSG_LEN 82 extern struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[]; @@ -434,12 +429,10 @@ struct wlfw_wlan_cfg_req_msg_v01 { struct wlfw_ce_svc_pipe_cfg_s_v01 svc_cfg[QMI_WLFW_MAX_NUM_SVC_V01]; u8 shadow_reg_valid; u32 shadow_reg_len; - struct wlfw_shadow_reg_cfg_s_v01 - shadow_reg[QMI_WLFW_MAX_NUM_SHADOW_REG_V01]; + struct wlfw_shadow_reg_cfg_s_v01 shadow_reg[QMI_WLFW_MAX_NUM_SHADOW_REG_V01]; u8 shadow_reg_v2_valid; u32 shadow_reg_v2_len; - struct wlfw_shadow_reg_v2_cfg_s_v01 - shadow_reg_v2[QMI_WLFW_MAX_NUM_SHADOW_REG_V2_V01]; + struct wlfw_shadow_reg_v2_cfg_s_v01 shadow_reg_v2[QMI_WLFW_MAX_NUM_SHADOW_REG_V2_V01]; u8 rri_over_ddr_cfg_valid; struct wlfw_rri_over_ddr_cfg_s_v01 rri_over_ddr_cfg; u8 msi_cfg_valid; @@ -488,7 +481,6 @@ struct wlfw_cap_resp_msg_v01 { u8 rd_card_chain_cap_valid; enum wlfw_rd_card_chain_cap_v01 rd_card_chain_cap; }; - #define WLFW_CAP_RESP_MSG_V01_MAX_MSG_LEN 253 extern struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[]; @@ -516,7 +508,6 @@ struct wlfw_bdf_download_resp_msg_v01 { u8 host_bdf_data_valid; u64 host_bdf_data; }; - #define WLFW_BDF_DOWNLOAD_RESP_MSG_V01_MAX_MSG_LEN 18 extern struct qmi_elem_info wlfw_bdf_download_resp_msg_v01_ei[]; @@ -617,8 +608,7 @@ extern struct qmi_elem_info wlfw_msa_info_req_msg_v01_ei[]; struct wlfw_msa_info_resp_msg_v01 { struct qmi_response_type_v01 resp; u32 mem_region_info_len; - struct wlfw_memory_region_info_s_v01 - mem_region_info[QMI_WLFW_MAX_NUM_MEMORY_REGIONS_V01]; + struct wlfw_memory_region_info_s_v01 mem_region_info[QMI_WLFW_MAX_NUM_MEMORY_REGIONS_V01]; }; #define WLFW_MSA_INFO_RESP_MSG_V01_MAX_MSG_LEN 37 extern struct qmi_elem_info wlfw_msa_info_resp_msg_v01_ei[]; @@ -738,8 +728,7 @@ struct wlfw_host_cap_req_msg_v01 { u8 platform_name_valid; char platform_name[QMI_WLFW_MAX_PLATFORM_NAME_LEN_V01 + 1]; u8 ddr_range_valid; - struct wlfw_host_ddr_range_s_v01 - ddr_range[QMI_WLFW_MAX_HOST_DDR_RANGE_SIZE_V01]; + struct wlfw_host_ddr_range_s_v01 ddr_range[QMI_WLFW_MAX_HOST_DDR_RANGE_SIZE_V01]; u8 host_build_type_valid; enum wlfw_host_build_type_v01 host_build_type; }; @@ -1095,14 +1084,12 @@ struct wlfw_power_save_req_msg_v01 { u8 power_save_mode_valid; enum wlfw_power_save_mode_v01 power_save_mode; }; - #define WLFW_POWER_SAVE_REQ_MSG_V01_MAX_MSG_LEN 7 extern struct qmi_elem_info wlfw_power_save_req_msg_v01_ei[]; struct wlfw_power_save_resp_msg_v01 { struct qmi_response_type_v01 resp; }; - #define WLFW_POWER_SAVE_RESP_MSG_V01_MAX_MSG_LEN 7 extern struct qmi_elem_info wlfw_power_save_resp_msg_v01_ei[]; @@ -1120,28 +1107,24 @@ struct wlfw_wfc_call_twt_config_ind_msg_v01 { u8 twt_sta_config_changed_valid; u8 twt_sta_config_changed; }; - #define WLFW_WFC_CALL_TWT_CONFIG_IND_MSG_V01_MAX_MSG_LEN 35 extern struct qmi_elem_info wlfw_wfc_call_twt_config_ind_msg_v01_ei[]; struct wlfw_qdss_mem_ready_ind_msg_v01 { char placeholder; }; - #define WLFW_QDSS_MEM_READY_IND_MSG_V01_MAX_MSG_LEN 0 extern struct qmi_elem_info wlfw_qdss_mem_ready_ind_msg_v01_ei[]; struct wlfw_pcie_gen_switch_req_msg_v01 { enum wlfw_pcie_gen_speed_v01 pcie_speed; }; - #define WLFW_PCIE_GEN_SWITCH_REQ_MSG_V01_MAX_MSG_LEN 7 extern struct qmi_elem_info wlfw_pcie_gen_switch_req_msg_v01_ei[]; struct wlfw_pcie_gen_switch_resp_msg_v01 { struct qmi_response_type_v01 resp; }; - #define WLFW_PCIE_GEN_SWITCH_RESP_MSG_V01_MAX_MSG_LEN 7 extern struct qmi_elem_info wlfw_pcie_gen_switch_resp_msg_v01_ei[]; diff --git a/drivers/soc/qcom/icnss2/Kconfig b/drivers/soc/qcom/icnss2/Kconfig index 7e1e469dd133..829db44f2cd8 100644 --- a/drivers/soc/qcom/icnss2/Kconfig +++ b/drivers/soc/qcom/icnss2/Kconfig @@ -20,6 +20,7 @@ config ICNSS2_DEBUG config ICNSS2_QMI bool "ICNSS2 Platform Driver QMI support" depends on ICNSS2 + select CNSS_QMI_SVC help Say 'Y' here to enable ICNSS QMI support. ICNSS driver will use QMI framework to communicate with WLAN FW. It will send coldboot diff --git a/drivers/soc/qcom/icnss2/Makefile b/drivers/soc/qcom/icnss2/Makefile index f0ac96742b03..735d85556b44 100644 --- a/drivers/soc/qcom/icnss2/Makefile +++ b/drivers/soc/qcom/icnss2/Makefile @@ -2,8 +2,9 @@ obj-$(CONFIG_ICNSS2) += icnss2.o +ccflags-y += -I$(srctree)/drivers/net/wireless/cnss_utils/ icnss2-y := main.o icnss2-y += debug.o icnss2-y += power.o icnss2-y += genl.o -icnss2-$(CONFIG_ICNSS2_QMI) += qmi.o wlan_firmware_service_v01.o +icnss2-$(CONFIG_ICNSS2_QMI) += qmi.o From 1ffce0deede9c60f8d5da671f264a9b8810d97df Mon Sep 17 00:00:00 2001 From: Niranjan Reddy Dumbala Date: Tue, 22 Dec 2020 12:03:55 +0530 Subject: [PATCH 100/698] Revert "Revert "serial: msm_geni_serial: Don't queue the rx dma buffer in stop rx"" This reverts commit cde50e6cdf2f06ccc621bc405484203f683ffce0. Change-Id: I9219975d1b697e8e86bcd8972f449780988ba292 Signed-off-by: Niranjan Reddy Dumbala --- drivers/tty/serial/msm_geni_serial.c | 45 +++++++++++++++++++++------- 1 file changed, 34 insertions(+), 11 deletions(-) diff --git a/drivers/tty/serial/msm_geni_serial.c b/drivers/tty/serial/msm_geni_serial.c index bce893cdf919..e2d94c714226 100644 --- a/drivers/tty/serial/msm_geni_serial.c +++ b/drivers/tty/serial/msm_geni_serial.c @@ -1402,12 +1402,13 @@ static void msm_geni_serial_set_manual_flow(bool enable, } } -static void stop_rx_sequencer(struct uart_port *uport) +static int stop_rx_sequencer(struct uart_port *uport) { unsigned int geni_status; bool timeout, is_irq_masked; struct msm_geni_serial_port *port = GET_DEV_PORT(uport); unsigned long flags = 0; + bool is_rx_active; IPC_LOG_MSG(port->ipc_log_misc, "%s\n", __func__); @@ -1417,7 +1418,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); - return; + return 0; } port->s_cmd_done = false; @@ -1440,8 +1441,6 @@ static void stop_rx_sequencer(struct uart_port *uport) mb(); timeout = geni_wait_for_cmd_done(uport, is_irq_masked); if (timeout) { - bool is_rx_active; - geni_status = geni_read_reg_nolog(uport->membase, SE_GENI_STATUS); /* @@ -1498,18 +1497,28 @@ exit_rx_seq: 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); + + is_rx_active = geni_status & S_GENI_CMD_ACTIVE; + if (is_rx_active) + return -EBUSY; + else + return 0; } static void msm_geni_serial_stop_rx(struct uart_port *uport) { struct msm_geni_serial_port *port = GET_DEV_PORT(uport); + int ret; if (!uart_console(uport) && device_pending_suspend(uport)) { IPC_LOG_MSG(port->ipc_log_misc, "%s.Device is suspended.\n", __func__); return; } - stop_rx_sequencer(uport); + ret = stop_rx_sequencer(uport); + if (ret) + IPC_LOG_MSG(port->ipc_log_misc, "%s: stop rx failed %d\n", + __func__, ret); } static int handle_rx_hs(struct uart_port *uport, @@ -1880,6 +1889,7 @@ static bool handle_tx_dma_xfer(u32 m_irq_status, struct uart_port *uport) static bool handle_rx_dma_xfer(u32 s_irq_status, struct uart_port *uport) { + u32 rx_dma_len; bool ret = false; bool drop_rx = false; struct msm_geni_serial_port *msm_port = GET_DEV_PORT(uport); @@ -1912,14 +1922,22 @@ static bool handle_rx_dma_xfer(u32 s_irq_status, struct uart_port *uport) uport->icount.brk); } - if (dma_rx_status & RX_EOT || dma_rx_status & RX_DMA_DONE) { - msm_geni_serial_handle_dma_rx(uport, drop_rx); - if (!(dma_rx_status & RX_GENI_CANCEL_IRQ)) { + if (dma_rx_status & RX_EOT || + dma_rx_status & RX_DMA_DONE) { + msm_geni_serial_handle_dma_rx(uport, + drop_rx); + rx_dma_len = + geni_read_reg_nolog(uport->membase, + SE_DMA_RX_LEN_IN); + if (rx_dma_len != 0) { geni_se_rx_dma_start(uport->membase, - DMA_RX_BUF_SIZE, &msm_port->rx_dma); + DMA_RX_BUF_SIZE, &msm_port->rx_dma); + } else { + IPC_LOG_MSG(msm_port->ipc_log_misc, + "%s.stop dma Rx 0x%x\n", + __func__, dma_rx_status); } } - if (dma_rx_status & RX_SBE) { IPC_LOG_MSG(msm_port->ipc_log_misc, "%s.Rx Errors. 0x%x\n", @@ -3196,7 +3214,12 @@ static int msm_geni_serial_runtime_suspend(struct device *dev) * Disable Interrupt * Resources off */ - stop_rx_sequencer(&port->uport); + ret = stop_rx_sequencer(&port->uport); + if (ret) { + IPC_LOG_MSG(port->ipc_log_pwr, "%s: stop rx failed %d\n", + __func__, ret); + return -EBUSY; + } geni_status = geni_read_reg_nolog(port->uport.membase, SE_GENI_STATUS); if ((geni_status & M_GENI_CMD_ACTIVE)) From c57c2cfb3c193d402aef07cabf217c7c399a7ba7 Mon Sep 17 00:00:00 2001 From: Niranjan Reddy Dumbala Date: Tue, 22 Dec 2020 12:05:16 +0530 Subject: [PATCH 101/698] Revert "Revert "serial: msm_geni_serial: Pull RFR before stop_rx for uart"" This reverts commit 3adaf5d918a21af89f24a08fb7054d938238f440. Change-Id: If6336a69fd9c4fc34a6aa7ee1ffec4e93e6a7fc2 Signed-off-by: Niranjan Reddy Dumbala --- drivers/tty/serial/msm_geni_serial.c | 71 +++++++++++++++++++++------- 1 file changed, 55 insertions(+), 16 deletions(-) diff --git a/drivers/tty/serial/msm_geni_serial.c b/drivers/tty/serial/msm_geni_serial.c index e2d94c714226..00f34c0cd901 100644 --- a/drivers/tty/serial/msm_geni_serial.c +++ b/drivers/tty/serial/msm_geni_serial.c @@ -101,6 +101,8 @@ #define UART_OVERSAMPLING (32) #define STALE_TIMEOUT (16) +#define STALE_COUNT (DEFAULT_BITS_PER_CHAR * STALE_TIMEOUT) +#define SEC_TO_USEC (1000000) #define DEFAULT_BITS_PER_CHAR (10) #define GENI_UART_NR_PORTS (6) #define GENI_UART_CONS_PORTS (1) @@ -1397,8 +1399,11 @@ static void msm_geni_serial_set_manual_flow(bool enable, SE_UART_MANUAL_RFR); /* Ensure that the manual flow off writes go through */ mb(); + uart_manual_rfr = geni_read_reg_nolog(port->uport.membase, + SE_UART_MANUAL_RFR); IPC_LOG_MSG(port->ipc_log_misc, - "%s: Manual Flow Disabled, HW Flow ON\n", __func__); + "%s: Manual Flow Disabled, HW Flow ON rfr = 0x%x\n", + __func__, uart_manual_rfr); } } @@ -1409,6 +1414,7 @@ static int stop_rx_sequencer(struct uart_port *uport) struct msm_geni_serial_port *port = GET_DEV_PORT(uport); unsigned long flags = 0; bool is_rx_active; + unsigned int stale_delay; IPC_LOG_MSG(port->ipc_log_misc, "%s\n", __func__); @@ -1421,9 +1427,18 @@ static int stop_rx_sequencer(struct uart_port *uport) return 0; } - port->s_cmd_done = false; - port->s_cmd = true; - reinit_completion(&port->s_cmd_timeout); + if (!uart_console(uport)) { + msm_geni_serial_set_manual_flow(false, port); + /* + * Wait for the stale timeout to happen if there + * is any data pending in the rx fifo. + * Have a safety factor of 2 to include the interrupt + * and system latencies. + */ + stale_delay = (STALE_COUNT * SEC_TO_USEC) / port->cur_baud; + stale_delay = (2 * stale_delay); + udelay(stale_delay); + } IPC_LOG_MSG(port->ipc_log_misc, "%s: Start 0x%x\n", __func__, geni_status); @@ -1432,6 +1447,11 @@ static int stop_rx_sequencer(struct uart_port *uport) * cancel command as this might be in an atomic context. */ is_irq_masked = msm_serial_try_disable_interrupts(uport); + + port->s_cmd_done = false; + port->s_cmd = true; + reinit_completion(&port->s_cmd_timeout); + geni_cancel_s_cmd(uport->membase); /* @@ -1494,6 +1514,9 @@ static int stop_rx_sequencer(struct uart_port *uport) port->s_cmd = false; exit_rx_seq: + if (!uart_console(uport)) + msm_geni_serial_set_manual_flow(true, port); + 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); @@ -1889,7 +1912,6 @@ static bool handle_tx_dma_xfer(u32 m_irq_status, struct uart_port *uport) static bool handle_rx_dma_xfer(u32 s_irq_status, struct uart_port *uport) { - u32 rx_dma_len; bool ret = false; bool drop_rx = false; struct msm_geni_serial_port *msm_port = GET_DEV_PORT(uport); @@ -1926,16 +1948,13 @@ static bool handle_rx_dma_xfer(u32 s_irq_status, struct uart_port *uport) dma_rx_status & RX_DMA_DONE) { msm_geni_serial_handle_dma_rx(uport, drop_rx); - rx_dma_len = - geni_read_reg_nolog(uport->membase, - SE_DMA_RX_LEN_IN); - if (rx_dma_len != 0) { + if (!(dma_rx_status & RX_GENI_CANCEL_IRQ)) { geni_se_rx_dma_start(uport->membase, DMA_RX_BUF_SIZE, &msm_port->rx_dma); } else { IPC_LOG_MSG(msm_port->ipc_log_misc, - "%s.stop dma Rx 0x%x\n", - __func__, dma_rx_status); + "%s. not mapping rx dma\n", + __func__); } } if (dma_rx_status & RX_SBE) { @@ -2174,7 +2193,7 @@ static int msm_geni_serial_port_setup(struct uart_port *uport) struct msm_geni_serial_port *msm_port = GET_DEV_PORT(uport); unsigned long cfg0, cfg1; dma_addr_t dma_address; - unsigned int rxstale = DEFAULT_BITS_PER_CHAR * STALE_TIMEOUT; + unsigned int rxstale = STALE_COUNT; set_rfr_wm(msm_port); geni_write_reg_nolog(rxstale, uport->membase, SE_UART_RX_STALE_CNT); @@ -2465,7 +2484,6 @@ static void msm_geni_serial_set_termios(struct uart_port *uport, __func__, ret); return; } - msm_geni_serial_set_manual_flow(false, port); } msm_geni_serial_stop_rx(uport); /* baud rate */ @@ -2512,9 +2530,6 @@ static void msm_geni_serial_set_termios(struct uart_port *uport, msm_geni_serial_termios_cfg(uport, termios); IPC_LOG_MSG(port->ipc_log_misc, "%s: baud %d\n", __func__, baud); exit_set_termios: - if (!uart_console(uport)) - msm_geni_serial_set_manual_flow(true, port); - msm_geni_serial_start_rx(uport); if (!uart_console(uport)) msm_geni_serial_power_off(uport); @@ -3197,6 +3212,23 @@ static int msm_geni_serial_remove(struct platform_device *pdev) return 0; } +static void msm_geni_serial_allow_rx(struct msm_geni_serial_port *port) +{ + u32 uart_manual_rfr; + + uart_manual_rfr = (UART_MANUAL_RFR_EN | UART_RFR_READY); + geni_write_reg_nolog(uart_manual_rfr, port->uport.membase, + SE_UART_MANUAL_RFR); + /* Ensure that the manual flow off writes go through */ + mb(); + uart_manual_rfr = geni_read_reg_nolog(port->uport.membase, + SE_UART_MANUAL_RFR); + IPC_LOG_MSG(port->ipc_log_misc, "%s(): rfr = 0x%x\n", + __func__, uart_manual_rfr); + + /* To give control of RFR back to HW */ + msm_geni_serial_set_manual_flow(true, port); +} #ifdef CONFIG_PM static int msm_geni_serial_runtime_suspend(struct device *dev) @@ -3226,6 +3258,13 @@ static int msm_geni_serial_runtime_suspend(struct device *dev) stop_tx_sequencer(&port->uport); disable_irq(port->uport.irq); + + /* + * Above stop_rx disabled the flow so we need to enable it here + * Make sure wake up interrupt is enabled before RFR is made low + */ + msm_geni_serial_allow_rx(port); + ret = se_geni_resources_off(&port->serial_rsc); if (ret) { dev_err(dev, "%s: Error ret %d\n", __func__, ret); From 6e65a4b41a1e38dd05a9e37effa8b9574003c3fb Mon Sep 17 00:00:00 2001 From: Santosh Mardi Date: Thu, 10 Dec 2020 00:15:30 +0530 Subject: [PATCH 102/698] arm_scmi: cleanup the mailbox channels upon errors During probe failure current implementation returns with error without cleaning the mailbox channels. Update the probe function to cleanup the mail box channels for scmi tx and rx paths. Change-Id: Iafd370638cad586c47ff8191ed12a0933bf4dbf3 Signed-off-by: Santosh Mardi --- drivers/firmware/arm_scmi/driver.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c index 7cdd507a80ec..a5ce9b44d202 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -174,6 +174,8 @@ static const int scmi_linux_errmap[] = { -EPROTO, /* SCMI_ERR_PROTOCOL */ }; +static int scmi_mbox_free_channel(int id, void *p, void *data); + static inline int scmi_to_linux_errno(int errno) { if (errno < SCMI_SUCCESS && errno > SCMI_ERR_MAX) @@ -824,6 +826,21 @@ scmi_create_protocol_device(struct device_node *np, struct scmi_info *info, scmi_set_handle(sdev); } +static void scmi_cleanup_mbox_channels(struct scmi_info *info) +{ + struct idr *idr; + + /* free tx channels */ + idr = &info->tx_idr; + idr_for_each(idr, scmi_mbox_free_channel, idr); + idr_destroy(&info->tx_idr); + + /* free rx channels */ + idr = &info->rx_idr; + idr_for_each(idr, scmi_mbox_free_channel, idr); + idr_destroy(&info->rx_idr); +} + static int scmi_probe(struct platform_device *pdev) { int ret; @@ -870,6 +887,7 @@ static int scmi_probe(struct platform_device *pdev) ret = scmi_base_protocol_init(handle); if (ret) { dev_err(dev, "unable to communicate with SCMI(%d)\n", ret); + scmi_cleanup_mbox_channels(info); return ret; } From cfa1f61c7e322dfdfb8d521bc716e02384da7caa Mon Sep 17 00:00:00 2001 From: Mayank Grover Date: Wed, 9 Dec 2020 16:05:25 +0530 Subject: [PATCH 103/698] soc: qcom: Avoid race shutdown and receive data for mbox channel In scenario where channel shutdown is in progress interrupt handler can call callback for mbox channel which might be free. Change to avoid race between mbox channel free and receive data. Change-Id: I07ef5f08aa1946be775de6b3e2f89d9069fa6ee3 Signed-off-by: Mayank Grover --- drivers/soc/qcom/qcom_rimps.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/soc/qcom/qcom_rimps.c b/drivers/soc/qcom/qcom_rimps.c index fd10a810a968..7e01b38a43c5 100644 --- a/drivers/soc/qcom/qcom_rimps.c +++ b/drivers/soc/qcom/qcom_rimps.c @@ -20,6 +20,7 @@ #define RIMPS_STATUS_IRQ_VAL BIT(3) #define RIMPS_CLOCK_DOMAIN_OFFSET 0x1000 +static DEFINE_SPINLOCK(mbox_chan_lock); /** * struct rimps_ipc ipc per channel @@ -41,6 +42,7 @@ struct qcom_rimps_ipc { static irqreturn_t qcom_rimps_rx_interrupt(int irq, void *p) { struct qcom_rimps_ipc *rimps_ipc; + unsigned long flags; u32 val; int i; @@ -59,9 +61,11 @@ static irqreturn_t qcom_rimps_rx_interrupt(int irq, void *p) /* Make sure register write is complete before proceeding */ mb(); + spin_lock_irqsave(&mbox_chan_lock, flags); if (rimps_ipc->chans[i].con_priv) mbox_chan_received_data(&rimps_ipc->chans[i] , NULL); + spin_unlock_irqrestore(&mbox_chan_lock, flags); } } @@ -70,7 +74,11 @@ static irqreturn_t qcom_rimps_rx_interrupt(int irq, void *p) static void qcom_rimps_mbox_shutdown(struct mbox_chan *chan) { + unsigned long flags; + + spin_lock_irqsave(&mbox_chan_lock, flags); chan->con_priv = NULL; + spin_unlock_irqrestore(&mbox_chan_lock, flags); } static int qcom_rimps_mbox_send_data(struct mbox_chan *chan, void *data) From 74c7419a54822ab23ed6cf3345c340853b6a7379 Mon Sep 17 00:00:00 2001 From: Phanindra Babu Pabba Date: Tue, 1 Dec 2020 22:21:22 +0530 Subject: [PATCH 104/698] mmc: host: Fix bootup issue with file encryption with GKI Export and call crypto APIs from command queue driver to service file encryption request and program inline crypto engine to encrypt/decrypt the data. Change-Id: I8c9c8413e59454605c711a6a5c14308122a751e2 Signed-off-by: Phanindra Babu Pabba --- drivers/mmc/host/Kconfig | 2 +- drivers/mmc/host/cqhci-crypto-qti.c | 13 ++-- drivers/mmc/host/cqhci-crypto-qti.h | 5 ++ drivers/mmc/host/cqhci-crypto.c | 10 ++++ drivers/mmc/host/cqhci-crypto.h | 92 +++++++++++++++++++++++------ drivers/mmc/host/cqhci.c | 26 +------- drivers/mmc/host/sdhci-msm.c | 2 - 7 files changed, 99 insertions(+), 51 deletions(-) diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index e6eb14b9795c..a95781d7a4fd 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -1044,7 +1044,7 @@ config SDC_QTI config MMC_CQHCI_CRYPTO tristate "CQHCI Crypto Engine Support" - depends on MMC_CQHCI && BLK_INLINE_ENCRYPTION + depends on BLK_INLINE_ENCRYPTION help Enable Crypto Engine Support in CQHCI. Enabling this makes it possible for the kernel to use the crypto diff --git a/drivers/mmc/host/cqhci-crypto-qti.c b/drivers/mmc/host/cqhci-crypto-qti.c index de7fc5c5c63b..27dcebe1e1b4 100644 --- a/drivers/mmc/host/cqhci-crypto-qti.c +++ b/drivers/mmc/host/cqhci-crypto-qti.c @@ -210,19 +210,21 @@ int cqhci_host_init_crypto_qti_spec(struct cqhci_host *host, host->crypto_cap_array[cap_idx].sdus_mask * 512; } - host->ksm = keyslot_manager_create(host->mmc->parent, + host->mmc->ksm = keyslot_manager_create(host->mmc->parent, cqhci_num_keyslots(host), ksm_ops, BLK_CRYPTO_FEATURE_STANDARD_KEYS | BLK_CRYPTO_FEATURE_WRAPPED_KEYS, crypto_modes_supported, host); - keyslot_manager_set_max_dun_bytes(host->ksm, sizeof(u32)); - - if (!host->ksm) { + if (!host->mmc->ksm) { err = -ENOMEM; goto out; } + + host->mmc->caps2 |= MMC_CAP2_CRYPTO; + keyslot_manager_set_max_dun_bytes(host->mmc->ksm, sizeof(u32)); + /* * In case host controller supports cryptographic operations * then, it uses 128bit task descriptor. Upper 64 bits of task @@ -305,10 +307,9 @@ int cqhci_crypto_qti_debug(struct cqhci_host *host) void cqhci_crypto_qti_set_vops(struct cqhci_host *host) { -#if defined(CONFIG_MMC_CQHCI_CRYPTO) return cqhci_crypto_set_vops(host, &cqhci_crypto_qti_variant_ops); -#endif } +EXPORT_SYMBOL(cqhci_crypto_qti_set_vops); int cqhci_crypto_qti_resume(struct cqhci_host *host) { diff --git a/drivers/mmc/host/cqhci-crypto-qti.h b/drivers/mmc/host/cqhci-crypto-qti.h index 2788e96b8c16..07300624b6a1 100644 --- a/drivers/mmc/host/cqhci-crypto-qti.h +++ b/drivers/mmc/host/cqhci-crypto-qti.h @@ -19,7 +19,12 @@ int cqhci_crypto_qti_init_crypto(struct cqhci_host *host, int cqhci_crypto_qti_debug(struct cqhci_host *host); +#if IS_ENABLED(CONFIG_MMC_CQHCI_CRYPTO_QTI) void cqhci_crypto_qti_set_vops(struct cqhci_host *host); +#else +void cqhci_crypto_qti_set_vops(struct cqhci_host *host) +{} +#endif /* CONFIG_MMC_CQHCI_CRYPTO_QTI) */ int cqhci_crypto_qti_resume(struct cqhci_host *host); diff --git a/drivers/mmc/host/cqhci-crypto.c b/drivers/mmc/host/cqhci-crypto.c index 2241ba7f7e92..adb61f6c48a7 100644 --- a/drivers/mmc/host/cqhci-crypto.c +++ b/drivers/mmc/host/cqhci-crypto.c @@ -426,6 +426,7 @@ void cqhci_crypto_enable(struct cqhci_host *host) return cqhci_crypto_enable_spec(host); } +EXPORT_SYMBOL(cqhci_crypto_enable); void cqhci_crypto_disable(struct cqhci_host *host) { @@ -434,6 +435,7 @@ void cqhci_crypto_disable(struct cqhci_host *host) return cqhci_crypto_disable_spec(host); } +EXPORT_SYMBOL(cqhci_crypto_disable); int cqhci_host_init_crypto(struct cqhci_host *host) { @@ -443,6 +445,7 @@ int cqhci_host_init_crypto(struct cqhci_host *host) return cqhci_host_init_crypto_spec(host, &cqhci_ksm_ops); } +EXPORT_SYMBOL(cqhci_host_init_crypto); void cqhci_crypto_setup_rq_keyslot_manager(struct cqhci_host *host, struct request_queue *q) @@ -472,6 +475,7 @@ int cqhci_crypto_get_ctx(struct cqhci_host *host, return cqhci_prepare_crypto_desc_spec(host, mrq, ice_ctx); } +EXPORT_SYMBOL(cqhci_crypto_get_ctx); int cqhci_complete_crypto_desc(struct cqhci_host *host, struct mmc_request *mrq, @@ -483,18 +487,21 @@ int cqhci_complete_crypto_desc(struct cqhci_host *host, return 0; } +EXPORT_SYMBOL(cqhci_complete_crypto_desc); void cqhci_crypto_debug(struct cqhci_host *host) { if (host->crypto_vops && host->crypto_vops->debug) host->crypto_vops->debug(host); } +EXPORT_SYMBOL(cqhci_crypto_debug); void cqhci_crypto_set_vops(struct cqhci_host *host, struct cqhci_host_crypto_variant_ops *crypto_vops) { host->crypto_vops = crypto_vops; } +EXPORT_SYMBOL(cqhci_crypto_set_vops); int cqhci_crypto_suspend(struct cqhci_host *host) { @@ -503,6 +510,7 @@ int cqhci_crypto_suspend(struct cqhci_host *host) return 0; } +EXPORT_SYMBOL(cqhci_crypto_suspend); int cqhci_crypto_resume(struct cqhci_host *host) { @@ -519,6 +527,7 @@ int cqhci_crypto_reset(struct cqhci_host *host) return 0; } +EXPORT_SYMBOL(cqhci_crypto_reset); int cqhci_crypto_recovery_finish(struct cqhci_host *host) { @@ -530,6 +539,7 @@ int cqhci_crypto_recovery_finish(struct cqhci_host *host) return 0; } +EXPORT_SYMBOL(cqhci_crypto_recovery_finish); MODULE_DESCRIPTION("CQHCI Crypto Engine Support"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/mmc/host/cqhci-crypto.h b/drivers/mmc/host/cqhci-crypto.h index a6dbeb25f198..94f6cc174ebf 100644 --- a/drivers/mmc/host/cqhci-crypto.h +++ b/drivers/mmc/host/cqhci-crypto.h @@ -40,8 +40,8 @@ static inline bool cqhci_is_crypto_enabled(struct cqhci_host *host) /* Functions implementing eMMC v5.2 specification behaviour */ int cqhci_prepare_crypto_desc_spec(struct cqhci_host *host, - struct mmc_request *mrq, - u64 *ice_ctx); + struct mmc_request *mrq, + u64 *ice_ctx); void cqhci_crypto_enable_spec(struct cqhci_host *host); @@ -51,46 +51,102 @@ int cqhci_host_init_crypto_spec(struct cqhci_host *host, const struct keyslot_mgmt_ll_ops *ksm_ops); void cqhci_crypto_setup_rq_keyslot_manager_spec(struct cqhci_host *host, - struct request_queue *q); + struct request_queue *q); void cqhci_crypto_destroy_rq_keyslot_manager_spec(struct cqhci_host *host, - struct request_queue *q); + struct request_queue *q); +#if IS_ENABLED(CONFIG_MMC_CQHCI_CRYPTO) void cqhci_crypto_set_vops(struct cqhci_host *host, - struct cqhci_host_crypto_variant_ops *crypto_vops); + struct cqhci_host_crypto_variant_ops *crypto_vops); +#else +void cqhci_crypto_set_vops(struct cqhci_host *host, + struct cqhci_host_crypto_variant_ops *crypto_vops) +{} +#endif /* CONFIG_MMC_CQHCI_CRYPTO */ /* Crypto Variant Ops Support */ - +#if IS_ENABLED(CONFIG_MMC_CQHCI_CRYPTO) void cqhci_crypto_enable(struct cqhci_host *host); void cqhci_crypto_disable(struct cqhci_host *host); int cqhci_host_init_crypto(struct cqhci_host *host); -void cqhci_crypto_setup_rq_keyslot_manager(struct cqhci_host *host, - struct request_queue *q); - -void cqhci_crypto_destroy_rq_keyslot_manager(struct cqhci_host *host, - struct request_queue *q); - int cqhci_crypto_get_ctx(struct cqhci_host *host, - struct mmc_request *mrq, - u64 *ice_ctx); + struct mmc_request *mrq, + u64 *ice_ctx); int cqhci_complete_crypto_desc(struct cqhci_host *host, - struct mmc_request *mrq, - u64 *ice_ctx); + struct mmc_request *mrq, + u64 *ice_ctx); void cqhci_crypto_debug(struct cqhci_host *host); int cqhci_crypto_suspend(struct cqhci_host *host); -int cqhci_crypto_resume(struct cqhci_host *host); - int cqhci_crypto_reset(struct cqhci_host *host); int cqhci_crypto_recovery_finish(struct cqhci_host *host); + +void cqhci_crypto_setup_rq_keyslot_manager(struct cqhci_host *host, + struct request_queue *q); +#else +void cqhci_crypto_enable(struct cqhci_host *host) +{} + +void cqhci_crypto_disable(struct cqhci_host *host) +{} + +int cqhci_host_init_crypto(struct cqhci_host *host) +{ + return 0; +} + +int cqhci_crypto_get_ctx(struct cqhci_host *host, + struct mmc_request *mrq, + u64 *ice_ctx) +{ + return 0; +} + +int cqhci_complete_crypto_desc(struct cqhci_host *host, + struct mmc_request *mrq, + u64 *ice_ctx) +{ + return 0; +} + +void cqhci_crypto_debug(struct cqhci_host *host) +{} + +int cqhci_crypto_suspend(struct cqhci_host *host) +{ + return 0; +} + +int cqhci_crypto_reset(struct cqhci_host *host) +{ + return 0; +} + +int cqhci_crypto_recovery_finish(struct cqhci_host *host) +{ + return 0; +} + +void cqhci_crypto_setup_rq_keyslot_manager(struct cqhci_host *host, + struct request_queue *q) +{} +#endif /* CONFIG_MMC_CQHCI_CRYPTO */ + +void cqhci_crypto_destroy_rq_keyslot_manager(struct cqhci_host *host, + struct request_queue *q); + + +int cqhci_crypto_resume(struct cqhci_host *host); + int cqhci_crypto_cap_find(void *host_p, enum blk_crypto_mode_num crypto_mode, unsigned int data_unit_size); diff --git a/drivers/mmc/host/cqhci.c b/drivers/mmc/host/cqhci.c index 8c41477bcb88..c239ffa7629d 100644 --- a/drivers/mmc/host/cqhci.c +++ b/drivers/mmc/host/cqhci.c @@ -154,9 +154,7 @@ static void cqhci_dumpregs(struct cqhci_host *cq_host) CQHCI_DUMP("Vendor cfg 0x%08x\n", cqhci_readl(cq_host, CQHCI_VENDOR_CFG + offset)); -#if defined(CONFIG_MMC_CQHCI_CRYPTO) cqhci_crypto_debug(cq_host); -#endif if (cq_host->ops->dumpregs) cq_host->ops->dumpregs(mmc); @@ -278,10 +276,8 @@ static void __cqhci_enable(struct cqhci_host *cq_host) if (cq_host->caps & CQHCI_TASK_DESC_SZ_128) cqcfg |= CQHCI_TASK_DESC_SZ; -#if defined(CONFIG_MMC_CQHCI_CRYPTO) if (cqhci_host_is_crypto_supported(cq_host)) cqcfg |= CQHCI_ICE_ENABLE; -#endif cqhci_writel(cq_host, cqcfg, CQHCI_CFG); @@ -330,9 +326,7 @@ int cqhci_deactivate(struct mmc_host *mmc) { struct cqhci_host *cq_host = mmc->cqe_private; -#if defined(CONFIG_MMC_CQHCI_CRYPTO) cqhci_crypto_suspend(cq_host); -#endif if (cq_host->enabled && cq_host->activated) __cqhci_disable(cq_host); @@ -367,10 +361,8 @@ static int cqhci_enable(struct mmc_host *mmc, struct mmc_card *card) return err; } -#if defined(CONFIG_MMC_CQHCI_CRYPTO) if (cqhci_host_is_crypto_supported(cq_host)) cqhci_crypto_enable(cq_host); -#endif __cqhci_enable(cq_host); @@ -425,10 +417,8 @@ static void cqhci_disable(struct mmc_host *mmc) cqhci_off(mmc); -#if defined(CONFIG_MMC_CQHCI_CRYPTO) if (cqhci_host_is_crypto_supported(cq_host)) cqhci_crypto_disable(cq_host); -#endif __cqhci_disable(cq_host); @@ -660,14 +650,12 @@ static int cqhci_request(struct mmc_host *mmc, struct mmc_request *mrq) } if (mrq->data) { -#if defined(CONFIG_MMC_CQHCI_CRYPTO) err = cqhci_crypto_get_ctx(cq_host, mrq, &ice_ctx); if (err) { pr_err("%s: failed to retrieve crypto ctx for tag %d\n", mmc_hostname(mmc), tag); return err; } -#endif task_desc = (__le64 __force *)get_desc(cq_host, tag); cqhci_prep_task_desc(mrq, &data, 1); *task_desc = cpu_to_le64(data); @@ -707,14 +695,12 @@ out_unlock: if (err) cqhci_post_req(mmc, mrq); -#if defined(CONFIG_MMC_CQHCI_CRYPTO) if (mrq->data) cqhci_complete_crypto_desc(cq_host, mrq, NULL); -#endif return err; } -#if defined(CONFIG_SDC_QTI) && defined(CONFIG_MMC_CQHCI_CRYPTO) +#if defined(CONFIG_SDC_QTI) static void cqhci_crypto_update_queue(struct mmc_host *mmc, struct request_queue *queue) { @@ -852,9 +838,7 @@ static void cqhci_finish_mrq(struct mmc_host *mmc, unsigned int tag) data = mrq->data; if (data) { -#if defined(CONFIG_MMC_CQHCI_CRYPTO) cqhci_complete_crypto_desc(cq_host, mrq, NULL); -#endif if (data->error) data->bytes_xfered = 0; else @@ -1062,9 +1046,7 @@ static void cqhci_recovery_start(struct mmc_host *mmc) pr_debug("%s: cqhci: %s\n", mmc_hostname(mmc), __func__); -#if defined(CONFIG_MMC_CQHCI_CRYPTO) cqhci_crypto_reset(cq_host); -#endif WARN_ON(!cq_host->recovery_halt); @@ -1186,9 +1168,7 @@ static void cqhci_recovery_finish(struct mmc_host *mmc) cqhci_set_irqs(cq_host, CQHCI_IS_MASK); -#if defined(CONFIG_MMC_CQHCI_CRYPTO) cqhci_crypto_recovery_finish(cq_host); -#endif pr_debug("%s: cqhci: recovery done\n", mmc_hostname(mmc)); mmc_log_string(mmc, "recovery done\n"); } @@ -1203,7 +1183,7 @@ static const struct mmc_cqe_ops cqhci_cqe_ops = { .cqe_timeout = cqhci_timeout, .cqe_recovery_start = cqhci_recovery_start, .cqe_recovery_finish = cqhci_recovery_finish, -#if defined(CONFIG_SDC_QTI) && defined(CONFIG_MMC_CQHCI_CRYPTO) +#if defined(CONFIG_SDC_QTI) .cqe_crypto_update_queue = cqhci_crypto_update_queue, #endif }; @@ -1279,14 +1259,12 @@ int cqhci_init(struct cqhci_host *cq_host, struct mmc_host *mmc, spin_lock_init(&cq_host->lock); -#if defined(CONFIG_MMC_CQHCI_CRYPTO) err = cqhci_host_init_crypto(cq_host); if (err) { pr_err("%s: CQHCI version %u.%02u Crypto init failed err %d\n", mmc_hostname(mmc), cqhci_ver_major(cq_host), cqhci_ver_minor(cq_host), err); } -#endif init_completion(&cq_host->halt_comp); init_waitqueue_head(&cq_host->wait_queue); diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c index 3659601a46d3..d4352faa295c 100644 --- a/drivers/mmc/host/sdhci-msm.c +++ b/drivers/mmc/host/sdhci-msm.c @@ -3161,9 +3161,7 @@ static int sdhci_msm_cqe_add_host(struct sdhci_host *host, * Set the vendor specific ops needed for ICE. * Default implementation if the ops are not set. */ -#ifdef CONFIG_MMC_CQHCI_CRYPTO_QTI cqhci_crypto_qti_set_vops(cq_host); -#endif ret = cqhci_init(cq_host, host->mmc, dma64); if (ret) { From d11b031c72c1814b981586315b40314e13f253fd Mon Sep 17 00:00:00 2001 From: Pavankumar Kondeti Date: Fri, 9 Oct 2020 12:02:18 +0530 Subject: [PATCH 105/698] sched: Improve the scheduler This change is for general scheduler improvemnts. Change-Id: I8e6d7afe12387d86f3721c6fd880812ba86d885e Signed-off-by: Pavankumar Kondeti Signed-off-by: Lingutla Chandrasekhar --- kernel/sched/rt.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c index 0cfca9b00e97..eae47c6a54d9 100644 --- a/kernel/sched/rt.c +++ b/kernel/sched/rt.c @@ -1830,6 +1830,7 @@ static int rt_energy_aware_wake_cpu(struct task_struct *task) int best_cpu_idle_idx = INT_MAX; int cpu_idle_idx = -1; bool boost_on_big = rt_boost_on_big(); + bool best_cpu_lt = true; rcu_read_lock(); @@ -1856,6 +1857,7 @@ retry: } for_each_cpu_and(cpu, lowest_mask, sched_group_span(sg)) { + bool lt; trace_sched_cpu_util(cpu); @@ -1870,8 +1872,20 @@ retry: util = cpu_util(cpu); - /* Find the least loaded CPU */ - if (util > best_cpu_util) + lt = (walt_low_latency_task(cpu_rq(cpu)->curr) || + walt_nr_rtg_high_prio(cpu)); + + /* + * When the best is suitable and the current is not, + * skip it + */ + if (lt && !best_cpu_lt) + continue; + /* + * Either both are sutilable or unsuitable, load takes + * precedence. + */ + if (!(best_cpu_lt ^ lt) && (util > best_cpu_util)) continue; /* @@ -1905,6 +1919,7 @@ retry: best_cpu_util = util; best_cpu = cpu; best_capacity = capacity_orig; + best_cpu_lt = lt; } } while (sg = sg->next, sg != sd->groups); From e4db82dbaccf7625a16737082e963720bf046bb3 Mon Sep 17 00:00:00 2001 From: Andrii Nakryiko Date: Wed, 14 Oct 2020 13:45:28 -0700 Subject: [PATCH 106/698] fs: fix NULL dereference due to data race in prepend_path() Fix data race in prepend_path() with re-reading mnt->mnt_ns twice without holding the lock. is_mounted() does check for NULL, but is_anon_ns(mnt->mnt_ns) might re-read the pointer again which could be NULL already, if in between reads one of kern_unmount()/kern_unmount_array()/umount_tree() sets mnt->mnt_ns to NULL. This is seen in production with the following stack trace: BUG: kernel NULL pointer dereference, address: 0000000000000048 ... RIP: 0010:prepend_path.isra.4+0x1ce/0x2e0 Call Trace: d_path+0xe6/0x150 proc_pid_readlink+0x8f/0x100 vfs_readlink+0xf8/0x110 do_readlinkat+0xfd/0x120 __x64_sys_readlinkat+0x1a/0x20 do_syscall_64+0x42/0x110 entry_SYSCALL_64_after_hwframe+0x44/0xa9 Fixes: f2683bd8d5bd ("[PATCH] fix d_absolute_path() interplay with fsmount()") Change-Id: If634d570fb7f37f4a77ae4f10970013dbc0762cb Signed-off-by: Andrii Nakryiko Reviewed-by: Josef Bacik Cc: Alexander Viro Signed-off-by: Linus Torvalds Git-commit: 09cad07547445bf3a41683e4d3abcd154c123ef5 Git-repo: https://android.googlesource.com/kernel/common/ Signed-off-by: Sayali Lokhande --- fs/d_path.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/fs/d_path.c b/fs/d_path.c index 0f1fc1743302..a69e2cd36e6e 100644 --- a/fs/d_path.c +++ b/fs/d_path.c @@ -102,6 +102,8 @@ restart: if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) { struct mount *parent = READ_ONCE(mnt->mnt_parent); + struct mnt_namespace *mnt_ns; + /* Escaped? */ if (dentry != vfsmnt->mnt_root) { bptr = *buffer; @@ -116,7 +118,9 @@ restart: vfsmnt = &mnt->mnt; continue; } - if (is_mounted(vfsmnt) && !is_anon_ns(mnt->mnt_ns)) + mnt_ns = READ_ONCE(mnt->mnt_ns); + /* open-coded is_mounted() to use local mnt_ns */ + if (!IS_ERR_OR_NULL(mnt_ns) && !is_anon_ns(mnt_ns)) error = 1; // absolute root else error = 2; // detached or not attached yet From 299c2babb8d9bc1da5829bfa19d66c31d1304b08 Mon Sep 17 00:00:00 2001 From: Deepak Kumar Singh Date: Tue, 15 Dec 2020 23:03:15 +0530 Subject: [PATCH 107/698] rpmsg: glink: remove IRQF_NO_SUSPEND flag while requesting irq Using IRQF_NO_SUSPEND flag may not mark irq wakeup capable. Use enable_irq_wake to mark glink irq wake up capable. Change-Id: I0fb5010ff1450a3bd15894a3d4706d7bd73e8cac Signed-off-by: Deepak Kumar Singh --- drivers/rpmsg/qcom_glink_native.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/rpmsg/qcom_glink_native.c b/drivers/rpmsg/qcom_glink_native.c index 3a1099c94830..8051c7ad2d13 100644 --- a/drivers/rpmsg/qcom_glink_native.c +++ b/drivers/rpmsg/qcom_glink_native.c @@ -2114,13 +2114,14 @@ struct qcom_glink *qcom_glink_native_probe(struct device *dev, irq = of_irq_get(dev->of_node, 0); ret = devm_request_irq(dev, irq, qcom_glink_native_intr, - IRQF_NO_SUSPEND | IRQF_SHARED, + IRQF_SHARED, glink->irqname, glink); if (ret) { dev_err(dev, "failed to request IRQ\n"); goto unregister; } + enable_irq_wake(irq); glink->irq = irq; size = of_property_count_u32_elems(dev->of_node, "cpu-affinity"); From 41d13dcff7eea17058f134bc5e1574c8c72e618f Mon Sep 17 00:00:00 2001 From: Deepak Kumar Singh Date: Mon, 14 Dec 2020 12:06:22 +0530 Subject: [PATCH 108/698] mailbox: msm_qmp: remove IRQF_NO_SUSPEND while requesting irq Using IRQF_NO_SUSPEND and enable_irq_wake together can sometime cause issue in wakeup from suspend and local host may not come out of suspend on receiving qmp interrupt. It is sufficient to use enable_irq_wake to mark irq as wakeup capable. Change-Id: I714724b31b92d23df0ac6a648f70416a130c9896 Signed-off-by: Deepak Kumar Singh --- drivers/mailbox/msm_qmp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mailbox/msm_qmp.c b/drivers/mailbox/msm_qmp.c index 6084e34ac439..299876a301a2 100644 --- a/drivers/mailbox/msm_qmp.c +++ b/drivers/mailbox/msm_qmp.c @@ -991,7 +991,7 @@ static int qmp_mbox_probe(struct platform_device *pdev) mdev->name); ret = devm_request_irq(&pdev->dev, mdev->rx_irq_line, qmp_irq_handler, - IRQF_TRIGGER_RISING | IRQF_NO_SUSPEND | IRQF_SHARED, + IRQF_TRIGGER_RISING | IRQF_SHARED, edge_node->name, mdev); if (ret < 0) { qmp_mbox_remove(pdev); From a287fc4e613a72ea494aaa08d4d6480994010dba Mon Sep 17 00:00:00 2001 From: Peter Xu Date: Fri, 21 Aug 2020 19:49:57 -0400 Subject: [PATCH 109/698] mm/gup: Remove enfornced COW mechanism With the more strict (but greatly simplified) page reuse logic in do_wp_page(), we can safely go back to the world where cow is not enforced with writes. This essentially reverts commit 17839856fd58 ("gup: document and work around 'COW can break either way' issue"). There are some context differences due to some changes later on around it: 2170ecfa7688 ("drm/i915: convert get_user_pages() --> pin_user_pages()", 2020-06-03) 376a34efa4ee ("mm/gup: refactor and de-duplicate gup_fast() code", 2020-06-03) Some lines moved back and forth with those, but this revert patch should have striped out and covered all the enforced cow bits anyways. Suggested-by: Linus Torvalds Signed-off-by: Peter Xu Signed-off-by: Linus Torvalds Git-commit: a308c71bf1e6e19cc2e4ced31853ee0fc7cb439a Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git [zhenhuah@codeaurora.org: resolve trivial merge conflict] Change-Id: I1e72c780c74b324efe6dbeed17ab131657254f16 Signed-off-by: Zhenhua Huang --- drivers/gpu/drm/i915/gem/i915_gem_userptr.c | 8 ------- mm/gup.c | 24 ++++++--------------- mm/huge_memory.c | 7 +++--- 3 files changed, 10 insertions(+), 29 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_userptr.c b/drivers/gpu/drm/i915/gem/i915_gem_userptr.c index 6d0cc90401c0..968d9b2705d0 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_userptr.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_userptr.c @@ -619,14 +619,6 @@ static int i915_gem_userptr_get_pages(struct drm_i915_gem_object *obj) GFP_KERNEL | __GFP_NORETRY | __GFP_NOWARN); - /* - * Using __get_user_pages_fast() with a read-only - * access is questionable. A read-only page may be - * COW-broken, and then this might end up giving - * the wrong side of the COW.. - * - * We may or may not care. - */ if (pvec) /* defer to worker if malloc fails */ pinned = __get_user_pages_fast(obj->userptr.ptr, num_pages, diff --git a/mm/gup.c b/mm/gup.c index 4a8e969a6e59..0f7a806904ae 100644 --- a/mm/gup.c +++ b/mm/gup.c @@ -161,12 +161,13 @@ static int follow_pfn_pte(struct vm_area_struct *vma, unsigned long address, } /* - * FOLL_FORCE or a forced COW break can write even to unwritable pte's, - * but only after we've gone through a COW cycle and they are dirty. + * FOLL_FORCE can write to even unwritable pte's, but only + * after we've gone through a COW cycle and they are dirty. */ static inline bool can_follow_write_pte(pte_t pte, unsigned int flags) { - return pte_write(pte) || ((flags & FOLL_COW) && pte_dirty(pte)); + return pte_write(pte) || + ((flags & FOLL_FORCE) && (flags & FOLL_COW) && pte_dirty(pte)); } /* @@ -832,18 +833,12 @@ static long __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, goto out; } if (is_vm_hugetlb_page(vma)) { - if (should_force_cow_break(vma, foll_flags)) - foll_flags |= FOLL_WRITE; i = follow_hugetlb_page(mm, vma, pages, vmas, &start, &nr_pages, i, - foll_flags, nonblocking); + gup_flags, nonblocking); continue; } } - - if (should_force_cow_break(vma, foll_flags)) - foll_flags |= FOLL_WRITE; - retry: /* * If we have a pending SIGKILL, don't keep faulting pages and @@ -2440,17 +2435,10 @@ int get_user_pages_fast(unsigned long start, int nr_pages, if (unlikely(!access_ok((void __user *)start, len))) return -EFAULT; - /* - * The FAST_GUP case requires FOLL_WRITE even for pure reads, - * because get_user_pages() may need to cause an early COW in - * order to avoid confusing the normal COW routines. So only - * targets that are already writable are safe to do by just - * looking at the page tables. - */ if (IS_ENABLED(CONFIG_HAVE_FAST_GUP) && gup_fast_permitted(start, end)) { local_irq_disable(); - gup_pgd_range(addr, end, gup_flags | FOLL_WRITE, pages, &nr); + gup_pgd_range(addr, end, gup_flags, pages, &nr); local_irq_enable(); ret = nr; } diff --git a/mm/huge_memory.c b/mm/huge_memory.c index e7b6c3d0447a..d29fc49aca1d 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -1454,12 +1454,13 @@ out_unlock: } /* - * FOLL_FORCE or a forced COW break can write even to unwritable pmd's, - * but only after we've gone through a COW cycle and they are dirty. + * FOLL_FORCE can write to even unwritable pmd's, but only + * after we've gone through a COW cycle and they are dirty. */ static inline bool can_follow_write_pmd(pmd_t pmd, unsigned int flags) { - return pmd_write(pmd) || ((flags & FOLL_COW) && pmd_dirty(pmd)); + return pmd_write(pmd) || + ((flags & FOLL_FORCE) && (flags & FOLL_COW) && pmd_dirty(pmd)); } struct page *follow_trans_huge_pmd(struct vm_area_struct *vma, From 786e35631fa70b15b7c7cd675ed95cec0af03474 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Thu, 24 Sep 2020 08:41:32 -0700 Subject: [PATCH 110/698] mm: fix misplaced unlock_page in do_wp_page() Commit 09854ba94c6a ("mm: do_wp_page() simplification") reorganized all the code around the page re-use vs copy, but in the process also moved the final unlock_page() around to after the wp_page_reuse() call. That normally doesn't matter - but it means that the unlock_page() is now done after releasing the page table lock. Again, not a big deal, you'd think. But it turns out that it's very wrong indeed, because once we've released the page table lock, we've basically lost our only reference to the page - the page tables - and it could now be free'd at any time. We do hold the mmap_sem, so no actual unmap() can happen, but madvise can come in and a MADV_DONTNEED will zap the page range - and free the page. So now the page may be free'd just as we're unlocking it, which in turn will usually trigger a "Bad page state" error in the freeing path. To make matters more confusing, by the time the debug code prints out the page state, the unlock has typically completed and everything looks fine again. This all doesn't happen in any normal situations, but it does trigger with the dirtyc0w_child LTP test. And it seems to trigger much more easily (but not expclusively) on s390 than elsewhere, probably because s390 doesn't do the "batch pages up for freeing after the TLB flush" that gives the unlock_page() more time to complete and makes the race harder to hit. Fixes: 09854ba94c6a ("mm: do_wp_page() simplification") Link: https://lore.kernel.org/lkml/a46e9bbef2ed4e17778f5615e818526ef848d791.camel@redhat.com/ Link: https://lore.kernel.org/linux-mm/c41149a8-211e-390b-af1d-d5eee690fecb@linux.alibaba.com/ Reported-by: Qian Cai Reported-by: Alex Shi Bisected-and-analyzed-by: Gerald Schaefer Tested-by: Gerald Schaefer Signed-off-by: Linus Torvalds Git-commit: be068f29034fb00530a053d18b8cf140c32b12b3 Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git [zhenhuah@codeaurora.org: resolved conflict] Change-Id: I775e3706aa5d6be6b8352e8f59cb10e8d9326c5c Signed-off-by: Zhenhua Huang --- mm/memory.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/memory.c b/mm/memory.c index 5b974bbe9c24..2396e1608770 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -2771,8 +2771,8 @@ static vm_fault_t do_wp_page(struct vm_fault *vmf) * page count reference, and the page is locked, * it's dark out, and we're wearing sunglasses. Hit it. */ - wp_page_reuse(vmf); unlock_page(page); + wp_page_reuse(vmf); return VM_FAULT_WRITE; } else if (unlikely((vmf->vma_flags & (VM_WRITE|VM_SHARED)) == (VM_WRITE|VM_SHARED))) { From fddaa876a7c73d2d11fa61fd9438249b0975371a Mon Sep 17 00:00:00 2001 From: Chandana Kishori Chiluveru Date: Wed, 16 Dec 2020 13:29:21 +0530 Subject: [PATCH 111/698] serial: msm_geni_serial: Perform Abort sequence for cancel failure Currently driver performing Abort sequence only when we seeing timeout for Cancel interrupt. When there is a race condition between rx data coming into rx fifo and a cancel_s_cmd is given. The rx data will end up consuming the rx dma buffer mapped for cancel command and due to this geni secondary sequencer will be in active state even after cancel command. This changes is to check for geni status after cancel operation. If geni is active perform abort sequence. Change-Id: I1b463284b48eb940de342da6df9233157d48f469 Signed-off-by: Chandana Kishori Chiluveru --- drivers/tty/serial/msm_geni_serial.c | 46 ++++++++++++++++++---------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/drivers/tty/serial/msm_geni_serial.c b/drivers/tty/serial/msm_geni_serial.c index 8c9b19fd102a..d8d9855f9d07 100644 --- a/drivers/tty/serial/msm_geni_serial.c +++ b/drivers/tty/serial/msm_geni_serial.c @@ -104,6 +104,7 @@ #define STALE_TIMEOUT (16) #define STALE_COUNT (DEFAULT_BITS_PER_CHAR * STALE_TIMEOUT) #define SEC_TO_USEC (1000000) +#define SYSTEM_DELAY (500) #define DEFAULT_BITS_PER_CHAR (10) #define GENI_UART_NR_PORTS (6) #define GENI_UART_CONS_PORTS (1) @@ -1437,10 +1438,11 @@ static int stop_rx_sequencer(struct uart_port *uport) * Wait for the stale timeout to happen if there * is any data pending in the rx fifo. * Have a safety factor of 2 to include the interrupt - * and system latencies. + * and system latencies, add 500usec delay for interrupt + * latency or system delay. */ stale_delay = (STALE_COUNT * SEC_TO_USEC) / port->cur_baud; - stale_delay = (2 * stale_delay); + stale_delay = (2 * stale_delay) + SYSTEM_DELAY; udelay(stale_delay); } @@ -1464,22 +1466,26 @@ static int stop_rx_sequencer(struct uart_port *uport) */ mb(); timeout = geni_wait_for_cmd_done(uport, is_irq_masked); - if (timeout) { - geni_status = geni_read_reg_nolog(uport->membase, + geni_status = geni_read_reg_nolog(uport->membase, SE_GENI_STATUS); + is_rx_active = geni_status & S_GENI_CMD_ACTIVE; + IPC_LOG_MSG(port->ipc_log_misc, "%s: 0x%x, dma_dbg:0x%x\n", __func__, + geni_status, geni_read_reg(uport->membase, SE_DMA_DEBUG_REG0)); + if (timeout || is_rx_active) { + IPC_LOG_MSG(port->ipc_log_misc, + "%s cancel failed timeout:%d is_rx_active:%d 0x%x\n", + __func__, timeout, is_rx_active, geni_status); + IPC_LOG_MSG(port->console_log, + "%s cancel failed timeout:%d is_rx_active:%d 0x%x\n", + __func__, timeout, is_rx_active, geni_status); + geni_se_dump_dbg_regs(&port->serial_rsc, + uport->membase, port->ipc_log_misc); /* * Possible that stop_rx is called from system resume context * for console usecase. In early resume, irq remains disabled * in the system. call msm_geni_serial_handle_isr to clear * the interrupts. */ - is_rx_active = geni_status & S_GENI_CMD_ACTIVE; - IPC_LOG_MSG(port->ipc_log_misc, - "%s cancel failed is_rx_active:%d 0x%x\n", - __func__, is_rx_active, geni_status); - IPC_LOG_MSG(port->console_log, - "%s cancel failed is_rx_active:%d 0x%x\n", - __func__, is_rx_active, geni_status); if (uart_console(uport) && !is_rx_active) { msm_geni_serial_handle_isr(uport, &flags, true); goto exit_rx_seq; @@ -1491,13 +1497,20 @@ static int stop_rx_sequencer(struct uart_port *uport) mb(); timeout = geni_wait_for_cmd_done(uport, is_irq_masked); - if (timeout) { + geni_status = geni_read_reg_nolog(uport->membase, + SE_GENI_STATUS); + is_rx_active = geni_status & S_GENI_CMD_ACTIVE; + if (timeout || is_rx_active) { geni_status = geni_read_reg_nolog(uport->membase, SE_GENI_STATUS); IPC_LOG_MSG(port->ipc_log_misc, - "%s abort fail 0x%x\n", __func__, geni_status); + "%s abort fail timeout:%d is_rx_active:%d 0x%x\n", + __func__, timeout, is_rx_active, geni_status); IPC_LOG_MSG(port->console_log, - "%s abort fail 0x%x\n", __func__, geni_status); + "%s abort fail timeout:%d is_rx_active:%d 0x%x\n", + __func__, timeout, is_rx_active, geni_status); + geni_se_dump_dbg_regs(&port->serial_rsc, + uport->membase, port->ipc_log_misc); } if (port->xfer_mode == SE_DMA) { @@ -1522,8 +1535,9 @@ exit_rx_seq: msm_geni_serial_set_manual_flow(true, port); 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); + IPC_LOG_MSG(port->ipc_log_misc, "%s: End 0x%x dma_dbg:0x%x\n", + __func__, geni_status, + geni_read_reg(uport->membase, SE_DMA_DEBUG_REG0)); is_rx_active = geni_status & S_GENI_CMD_ACTIVE; if (is_rx_active) From c8b7684b80cc2299aa6c85e1a88ef9685a096500 Mon Sep 17 00:00:00 2001 From: Raghavendra Kakarla Date: Mon, 7 Dec 2020 09:22:02 +0530 Subject: [PATCH 112/698] driver: lpm-levels: Add check for IPI pendning in core lpm path Add check whether IPI is in pending state for the core while its entering to LPM. Change-Id: I6927fd445a1e2e46a4b5329003994a5bd710dc66 Signed-off-by: Raghavendra Kakarla --- drivers/cpuidle/lpm-levels.c | 3 ++- include/trace/events/trace_msm_low_power.h | 17 +++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/drivers/cpuidle/lpm-levels.c b/drivers/cpuidle/lpm-levels.c index 4c4e8ed6bc88..f4028b2b62d8 100644 --- a/drivers/cpuidle/lpm-levels.c +++ b/drivers/cpuidle/lpm-levels.c @@ -1418,6 +1418,7 @@ void update_ipi_history(int cpu) if (history->current_ptr >= MAXSAMPLES) history->current_ptr = 0; history->cpu_idle_resched_ts = now; + trace_ipi_wakeup_time(ktime_to_us(now)); } #endif @@ -1474,7 +1475,7 @@ static int lpm_cpuidle_enter(struct cpuidle_device *dev, trace_cpu_idle_enter(idx); lpm_stats_cpu_enter(idx, start_time); - if (need_resched()) + if (need_resched() || is_IPI_pending(cpumask_of(dev->cpu))) goto exit; if (idx == cpu->nlevels - 1) diff --git a/include/trace/events/trace_msm_low_power.h b/include/trace/events/trace_msm_low_power.h index 3a4aceadafed..9210583e8f87 100644 --- a/include/trace/events/trace_msm_low_power.h +++ b/include/trace/events/trace_msm_low_power.h @@ -244,6 +244,23 @@ TRACE_EVENT(cluster_pred_hist, __entry->sample, __entry->tmr) ); +TRACE_EVENT(ipi_wakeup_time, + + TP_PROTO(u64 wakeup), + + TP_ARGS(wakeup), + + TP_STRUCT__entry( + __field(u64, wakeup) + ), + + TP_fast_assign( + __entry->wakeup = wakeup; + ), + + TP_printk("wakeup:%llu", __entry->wakeup) +); + #endif #define TRACE_INCLUDE_FILE trace_msm_low_power #include From e000a079ff5216169609daf4292f31fbc3a0b15e Mon Sep 17 00:00:00 2001 From: Niranjan Reddy Dumbala Date: Thu, 7 Jan 2021 19:52:42 +0530 Subject: [PATCH 113/698] Revert "rpmsg: glink: remove IRQF_NO_SUSPEND flag while requesting irq" This reverts commit 676140efc508cef1d9ae5a6ce147b1e5fe191a59. Change-Id: I76b61b016da93ac4cc8da14390c9992ffb67aa1f Signed-off-by: Niranjan Reddy Dumbala --- drivers/rpmsg/qcom_glink_native.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/rpmsg/qcom_glink_native.c b/drivers/rpmsg/qcom_glink_native.c index 8051c7ad2d13..3a1099c94830 100644 --- a/drivers/rpmsg/qcom_glink_native.c +++ b/drivers/rpmsg/qcom_glink_native.c @@ -2114,14 +2114,13 @@ struct qcom_glink *qcom_glink_native_probe(struct device *dev, irq = of_irq_get(dev->of_node, 0); ret = devm_request_irq(dev, irq, qcom_glink_native_intr, - IRQF_SHARED, + IRQF_NO_SUSPEND | IRQF_SHARED, glink->irqname, glink); if (ret) { dev_err(dev, "failed to request IRQ\n"); goto unregister; } - enable_irq_wake(irq); glink->irq = irq; size = of_property_count_u32_elems(dev->of_node, "cpu-affinity"); From f08502f00d0d1e57dfc0b61e6a9f0207d064ea32 Mon Sep 17 00:00:00 2001 From: Prakash Gupta Date: Wed, 20 Jan 2021 14:10:21 +0530 Subject: [PATCH 114/698] iommu: arm-smmu: optimize arch write sync delay With ARM_SMMU_POWER_ALWAYS_ON enabled, clocks are always on. There arch write sync is not required. Move arch write sync post checking for clock refcount. Arch write sync takes longer due to virtualized global register read. Use non virtuazlied global register to reduce read latency. Change-Id: Ic497c7ba75cc8ba2ed804f2c987e0c595487ce40 Signed-off-by: Prakash Gupta --- drivers/iommu/arm-smmu.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 0466a3a3eed5..9e445242f8ec 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -365,7 +365,8 @@ static void arm_smmu_arch_write_sync(struct arm_smmu_device *smmu) return; /* Read to complete prior write transcations */ - id = arm_smmu_gr0_read(smmu, ARM_SMMU_GR0_ID0); + id = arm_smmu_readl(smmu, ARM_SMMU_IMPL_DEF0, 0); + /* Wait for read to complete before off */ rmb(); @@ -656,8 +657,6 @@ static void arm_smmu_power_off_atomic(struct arm_smmu_device *smmu, { unsigned long flags; - arm_smmu_arch_write_sync(smmu); - spin_lock_irqsave(&pwr->clock_refs_lock, flags); if (pwr->clock_refs_count == 0) { WARN(1, "%s: bad clock_ref_count\n", dev_name(pwr->dev)); @@ -670,6 +669,7 @@ static void arm_smmu_power_off_atomic(struct arm_smmu_device *smmu, return; } + arm_smmu_arch_write_sync(smmu); arm_smmu_disable_clocks(pwr); pwr->clock_refs_count = 0; From 705f90f24d137532aef9f414913dfae5fe9bc249 Mon Sep 17 00:00:00 2001 From: Sriharsha Allenki Date: Tue, 23 Jun 2020 15:27:10 +0530 Subject: [PATCH 115/698] usb: dwc3: Handle race between composition switch and cable disconnect The current implementation of handling run/~stop of DCTL based on state of VBUS or the pullup call from the udc core can result in a below race condition where the run/~stop is cleared twice leading to an invalid state of controller. Thread -1 Thread-2 vbus_session (1) spin_lock no run_stop(1) call pullup(1) spin_unlock softconnect = 1 vbus_active checked vbus_session (0) spin_lock run_stop(0) called spin_unlock Prevent this by ensuring a proper state transitions and clear run/~stop only when when there is a transition from ACTIVE and there is an pullup(0) event or vbus_session(0) call. Change-Id: I03c4acfc2c6697e02c510d079c7d48d9a82bb322 Signed-off-by: Sriharsha Allenki Signed-off-by: Pratham Pratap --- drivers/usb/dwc3/core.h | 8 ++++ drivers/usb/dwc3/gadget.c | 86 +++++++++++++++++++++++++++++++-------- 2 files changed, 78 insertions(+), 16 deletions(-) diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 361b86c90a75..f7a437ed2ac7 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -850,6 +850,13 @@ enum dwc3_link_state { DWC3_LINK_STATE_MASK = 0x0f, }; +enum gadget_state { + DWC3_GADGET_INACTIVE, + DWC3_GADGET_SOFT_CONN, + DWC3_GADGET_CABLE_CONN, + DWC3_GADGET_ACTIVE, +}; + /* TRB Length, PCM and Status */ #define DWC3_TRB_SIZE_MASK (0x00ffffff) #define DWC3_TRB_SIZE_LENGTH(n) ((n) & DWC3_TRB_SIZE_MASK) @@ -1382,6 +1389,7 @@ struct dwc3 { unsigned int irq_event_count[MAX_INTR_STATS]; unsigned int irq_dbg_index; + enum gadget_state gadget_state; /* Indicate if the gadget was powered by the otg driver */ unsigned int vbus_active:1; /* Indicate if software connect was issued by the usb_gadget_driver */ diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 834f286cf79d..37a261218e8c 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -2309,6 +2309,71 @@ static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on, int suspend) return 0; } +static int dwc3_gadget_run_stop_util(struct dwc3 *dwc) +{ + int ret = 0; + + dev_dbg(dwc->dev, "%s: enter: %d\n", __func__, dwc->gadget_state); + switch (dwc->gadget_state) { + case DWC3_GADGET_INACTIVE: + if (dwc->vbus_active && dwc->softconnect) { + ret = dwc3_gadget_run_stop(dwc, true, false); + dwc->gadget_state = DWC3_GADGET_ACTIVE; + break; + } + + if (dwc->vbus_active) { + dwc->gadget_state = DWC3_GADGET_CABLE_CONN; + break; + } + + if (dwc->softconnect) { + dwc->gadget_state = DWC3_GADGET_SOFT_CONN; + break; + } + case DWC3_GADGET_SOFT_CONN: + if (!dwc->softconnect) { + dwc->gadget_state = DWC3_GADGET_INACTIVE; + break; + } + + if (dwc->vbus_active) { + ret = dwc3_gadget_run_stop(dwc, true, false); + dwc->gadget_state = DWC3_GADGET_ACTIVE; + } + break; + case DWC3_GADGET_CABLE_CONN: + if (!dwc->vbus_active) { + dwc->gadget_state = DWC3_GADGET_INACTIVE; + break; + } + + if (dwc->softconnect) { + ret = dwc3_gadget_run_stop(dwc, true, false); + dwc->gadget_state = DWC3_GADGET_ACTIVE; + } + break; + case DWC3_GADGET_ACTIVE: + if (!dwc->vbus_active) { + dwc->gadget_state = DWC3_GADGET_SOFT_CONN; + ret = dwc3_gadget_run_stop(dwc, false, false); + break; + } + + if (!dwc->softconnect) { + dwc->gadget_state = DWC3_GADGET_CABLE_CONN; + ret = dwc3_gadget_run_stop(dwc, false, false); + break; + } + break; + default: + dev_err(dwc->dev, "Invalid state\n"); + } + + dev_dbg(dwc->dev, "%s: exit: %d\n", __func__, dwc->gadget_state); + return ret; +} + static int dwc3_gadget_vbus_draw(struct usb_gadget *g, unsigned int mA) { struct dwc3 *dwc = gadget_to_dwc(g); @@ -2328,6 +2393,7 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on) ktime_t diff; is_on = !!is_on; + spin_lock_irqsave(&dwc->lock, flags); dwc->softconnect = is_on; if (((dwc->dr_mode > USB_DR_MODE_HOST) && !dwc->vbus_active) @@ -2337,9 +2403,11 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on) * Need to wait for vbus_session(on) from otg driver or to * the udc_start. */ + spin_unlock_irqrestore(&dwc->lock, flags); dbg_event(0xFF, "WaitPullup", 0); return 0; } + spin_unlock_irqrestore(&dwc->lock, flags); pm_runtime_get_sync(dwc->dev); dbg_event(0xFF, "Pullup gsync", @@ -2393,7 +2461,7 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on) dwc->b_suspend = false; dwc3_notify_event(dwc, DWC3_CONTROLLER_NOTIFY_OTG_EVENT, 0); - ret = dwc3_gadget_run_stop(dwc, is_on, false); + ret = dwc3_gadget_run_stop_util(dwc); spin_unlock_irqrestore(&dwc->lock, flags); if (!is_on && ret == -ETIMEDOUT) { /* @@ -2514,21 +2582,7 @@ static int dwc3_gadget_vbus_session(struct usb_gadget *_gadget, int is_active) /* Mark that the vbus was powered */ dwc->vbus_active = is_active; - /* - * Check if upper level usb_gadget_driver was already registered with - * this udc controller driver (if dwc3_gadget_start was called) - */ - if (dwc->gadget_driver && dwc->softconnect) { - if (dwc->vbus_active) { - /* - * Both vbus was activated by otg and pullup was - * signaled by the gadget driver. - */ - ret = dwc3_gadget_run_stop(dwc, 1, false); - } else { - ret = dwc3_gadget_run_stop(dwc, 0, false); - } - } + ret = dwc3_gadget_run_stop_util(dwc); /* * Clearing run/stop bit might occur before disconnect event is seen. From 27bc5774a807a2d0a66f67a04f993997ae914efb Mon Sep 17 00:00:00 2001 From: Niranjan Reddy Dumbala Date: Mon, 8 Mar 2021 17:03:36 +0530 Subject: [PATCH 116/698] Revert "Revert "rpmsg: glink: remove IRQF_NO_SUSPEND flag while requesting irq"" This reverts commit e000a079ff5216169609daf4292f31fbc3a0b15e. Change-Id: If54f074b5a5bde11610b1de93bb3ac2d587fa4b3 Signed-off-by: Niranjan Reddy Dumbala --- drivers/rpmsg/qcom_glink_native.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/rpmsg/qcom_glink_native.c b/drivers/rpmsg/qcom_glink_native.c index 3a1099c94830..8051c7ad2d13 100644 --- a/drivers/rpmsg/qcom_glink_native.c +++ b/drivers/rpmsg/qcom_glink_native.c @@ -2114,13 +2114,14 @@ struct qcom_glink *qcom_glink_native_probe(struct device *dev, irq = of_irq_get(dev->of_node, 0); ret = devm_request_irq(dev, irq, qcom_glink_native_intr, - IRQF_NO_SUSPEND | IRQF_SHARED, + IRQF_SHARED, glink->irqname, glink); if (ret) { dev_err(dev, "failed to request IRQ\n"); goto unregister; } + enable_irq_wake(irq); glink->irq = irq; size = of_property_count_u32_elems(dev->of_node, "cpu-affinity"); From cc81111ecab68dc535c7e1b44b61bca792d36efa Mon Sep 17 00:00:00 2001 From: Deepak Kumar Singh Date: Fri, 5 Feb 2021 10:54:19 +0530 Subject: [PATCH 117/698] rpmsg: glink: Use IRQF_NO_SUSPEND and pm_system_wakeup() for glink irq Glink irq should be wakeup capable, to achieve this irq is marked with enable_irq_wake(). There are some use cases where glink communication is required in system suspend path and glink interrupt handler needs to be run immediately. But wakeup cpabale interrupts even if received during suspend will not run immediately, this will be marked pending and run when system resumes from suspend. In such scenario there can be a potential deadock in suspend path due to any irq thread which is waiting for glink interrupt completion while glink interrupt cannot be handled immediately. One such use case is usb plugin interrupt received during suspend, which calls regulator api to communicate with rpm over glink and waits for rpm ack. RPM ack cannot be processed because glink interrupt received from rpm goes in pending state. Suspend path is blocked because regulator irq thread is still waiting. So there is requirement to run glink interrupt handler in suspend path at the same time making it wakeup capable. IRQ frameworks forbids usage of both IRQF_NO_SUSPEND and enable_irq_wake() together. This patch adds IRQF_NO_SUSPEND and pm_system_wakeup() for glink irq to implement this requirement. Change-Id: I1da199c9e10c640bb84d00e569c4fafc5c104d24 Signed-off-by: Deepak Kumar Singh --- drivers/rpmsg/qcom_glink_native.c | 30 +++++++++++++++++++++++++++--- drivers/rpmsg/qcom_glink_native.h | 3 ++- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/drivers/rpmsg/qcom_glink_native.c b/drivers/rpmsg/qcom_glink_native.c index 8051c7ad2d13..13121f08b5fe 100644 --- a/drivers/rpmsg/qcom_glink_native.c +++ b/drivers/rpmsg/qcom_glink_native.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 /* * Copyright (c) 2016-2017, Linaro Ltd - * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved. */ #include @@ -23,6 +23,7 @@ #include #include #include +#include #include #include "rpmsg_internal.h" @@ -54,6 +55,8 @@ do { \ #define RPM_GLINK_CID_MIN 1 #define RPM_GLINK_CID_MAX 65536 +static int wakeup_enabled; + struct glink_msg { __le16 cmd; __le16 param1; @@ -1240,6 +1243,8 @@ static irqreturn_t qcom_glink_native_intr(int irq, void *data) unsigned int cmd; int ret = 0; + if (wakeup_enabled) + pm_system_wakeup(); /* To wakeup any blocking writers */ wake_up_all(&glink->tx_avail_notify); @@ -2114,14 +2119,13 @@ struct qcom_glink *qcom_glink_native_probe(struct device *dev, irq = of_irq_get(dev->of_node, 0); ret = devm_request_irq(dev, irq, qcom_glink_native_intr, - IRQF_SHARED, + IRQF_NO_SUSPEND | IRQF_SHARED, glink->irqname, glink); if (ret) { dev_err(dev, "failed to request IRQ\n"); goto unregister; } - enable_irq_wake(irq); glink->irq = irq; size = of_property_count_u32_elems(dev->of_node, "cpu-affinity"); @@ -2212,5 +2216,25 @@ void qcom_glink_native_unregister(struct qcom_glink *glink) } EXPORT_SYMBOL_GPL(qcom_glink_native_unregister); +static int qcom_glink_suspend_no_irq(struct device *dev) +{ + wakeup_enabled = true; + + return 0; +} + +static int qcom_glink_resume_no_irq(struct device *dev) +{ + wakeup_enabled = false; + + return 0; +} + +const struct dev_pm_ops glink_native_pm_ops = { + .suspend_noirq = qcom_glink_suspend_no_irq, + .resume_noirq = qcom_glink_resume_no_irq, +}; +EXPORT_SYMBOL(glink_native_pm_ops); + MODULE_DESCRIPTION("Qualcomm GLINK driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/rpmsg/qcom_glink_native.h b/drivers/rpmsg/qcom_glink_native.h index 51c8e0d2c3f6..f87632121ce3 100644 --- a/drivers/rpmsg/qcom_glink_native.h +++ b/drivers/rpmsg/qcom_glink_native.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* - * Copyright (c) 2016-2017, Linaro Ltd + * Copyright (c) 2016-2017, 2021, Linaro Ltd */ #ifndef __QCOM_GLINK_NATIVE_H__ @@ -27,6 +27,7 @@ struct qcom_glink_pipe { }; struct qcom_glink; +extern const struct dev_pm_ops glink_native_pm_ops; struct qcom_glink *qcom_glink_native_probe(struct device *dev, unsigned long features, From 84d52e5c543c01fd70ea3c98a79d47be23521619 Mon Sep 17 00:00:00 2001 From: Deepak Kumar Singh Date: Fri, 19 Feb 2021 16:25:16 +0530 Subject: [PATCH 118/698] rpmsg: glink: add dev_pm_ops for tracking no irq phase Glink native interrupt handler need to wakeup local host only in post noirq phase of suspend. Adding dev_pm_ops to track suspend/resume noirq phase. Change-Id: I46ff9108e28cd2355562ff95e54b955d3d90c07c Signed-off-by: Deepak Kumar Singh --- drivers/rpmsg/qcom_glink_rpm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/rpmsg/qcom_glink_rpm.c b/drivers/rpmsg/qcom_glink_rpm.c index f64f45d1a735..04e33f608b2c 100644 --- a/drivers/rpmsg/qcom_glink_rpm.c +++ b/drivers/rpmsg/qcom_glink_rpm.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Copyright (c) 2016-2017, Linaro Ltd + * Copyright (c) 2016-2017, 2021 Linaro Ltd */ #include @@ -331,6 +331,7 @@ static struct platform_driver glink_rpm_driver = { .driver = { .name = "qcom_glink_rpm", .of_match_table = glink_rpm_of_match, + .pm = &glink_native_pm_ops, }, }; From c4baf5d4db2936c6fc57b90fa384fa5e130967f1 Mon Sep 17 00:00:00 2001 From: Deepak Kumar Singh Date: Fri, 19 Feb 2021 16:38:56 +0530 Subject: [PATCH 119/698] soc: qcom: add dev_pm_ops for tracking no irq phase Glink native interrupt handler need to wakeup local host only in post noirq phase of suspend. Adding dev_pm_ops to track suspend/resume noirq phase. Change-Id: I338f6ca8da8956592d3c95b2676163651ea86361 Signed-off-by: Deepak Kumar Singh --- drivers/soc/qcom/glink_probe.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/soc/qcom/glink_probe.c b/drivers/soc/qcom/glink_probe.c index a7a8da98ec00..ed18cf86c897 100644 --- a/drivers/soc/qcom/glink_probe.c +++ b/drivers/soc/qcom/glink_probe.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-2019, 2021, The Linux Foundation. All rights reserved. */ #include @@ -25,6 +25,8 @@ do { \ ipc_log_string(glink_ilc, "[%s]: "x, __func__, ##__VA_ARGS__); \ } while (0) +extern const struct dev_pm_ops glink_native_pm_ops; + struct edge_info { struct list_head list; struct device *dev; @@ -202,6 +204,7 @@ static struct platform_driver glink_probe_driver = { .driver = { .name = "msm_glink", .of_match_table = glink_match_table, + .pm = &glink_native_pm_ops, }, }; From 21ffad78ea8592dba6fa0a109e660165ba3dd8e3 Mon Sep 17 00:00:00 2001 From: Niranjan Reddy Dumbala Date: Wed, 10 Mar 2021 11:05:16 +0530 Subject: [PATCH 120/698] rpmsg: glink: revert the copyrights to original Change-Id: Ic77d17299e6bc572535c4bbec452b04f45fad1fd Signed-off-by: Niranjan Reddy Dumbala --- drivers/rpmsg/qcom_glink_native.h | 2 +- drivers/rpmsg/qcom_glink_rpm.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/rpmsg/qcom_glink_native.h b/drivers/rpmsg/qcom_glink_native.h index f87632121ce3..7a83d7bfe153 100644 --- a/drivers/rpmsg/qcom_glink_native.h +++ b/drivers/rpmsg/qcom_glink_native.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* - * Copyright (c) 2016-2017, 2021, Linaro Ltd + * Copyright (c) 2016-2017, Linaro Ltd */ #ifndef __QCOM_GLINK_NATIVE_H__ diff --git a/drivers/rpmsg/qcom_glink_rpm.c b/drivers/rpmsg/qcom_glink_rpm.c index 04e33f608b2c..7a7600f34342 100644 --- a/drivers/rpmsg/qcom_glink_rpm.c +++ b/drivers/rpmsg/qcom_glink_rpm.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Copyright (c) 2016-2017, 2021 Linaro Ltd + * Copyright (c) 2016-2017, Linaro Ltd */ #include From 5610f6a6958462c44c34e6ef1fb48d21efb49ea7 Mon Sep 17 00:00:00 2001 From: Saurabh Sahu Date: Wed, 14 Apr 2021 14:39:21 +0530 Subject: [PATCH 121/698] dt-bindings: clock: Revert rpmcc id copyright year for MONACO Revert the copyright year from 2021 to 2020 for rpmcc ids for MONACO. Change-Id: I8a3dc5248945c42cb8cda2e9c97d133b982fa5ed Signed-off-by: Saurabh Sahu --- include/dt-bindings/clock/qcom,rpmcc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/dt-bindings/clock/qcom,rpmcc.h b/include/dt-bindings/clock/qcom,rpmcc.h index 1fdc5674c667..a3c17f28773a 100644 --- a/include/dt-bindings/clock/qcom,rpmcc.h +++ b/include/dt-bindings/clock/qcom,rpmcc.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright 2015-2021, Linaro Limited + * Copyright 2015-2020, Linaro Limited */ #ifndef _DT_BINDINGS_CLK_MSM_RPMCC_H From a78115d38a8a9e9f307d80c2ed43edd42dab1dc6 Mon Sep 17 00:00:00 2001 From: Maria Yu Date: Thu, 6 May 2021 11:22:59 +0800 Subject: [PATCH 122/698] Revert "clocksource: arch_timer: make virtual counter access configurable" This reverts commit dc9b4c45b25988bdd2e0bcd89eb7bbf4940f58e0. Disable userspace virtual counter access intended to makes it difficult to obtain precise timing measurements of the cache side channel. But it has been deprecated since it was found to be ineffective. Change-Id: I5cf59632ff1beb6ea51a53bea4eb3ad9467d4cd0 Signed-off-by: Maria Yu --- drivers/clocksource/Kconfig | 8 -------- drivers/clocksource/arm_arch_timer.c | 3 +-- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index e37cd76b6163..080f05b740b8 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -385,14 +385,6 @@ config SUN50I_ERRATUM_UNKNOWN1 the Allwinner A64 SoC. The workaround will only be active if the allwinner,erratum-unknown1 property is found in the timer node. -config ARM_ARCH_TIMER_VCT_ACCESS - bool "Support for ARM architected timer virtual counter access in userspace" - default n - depends on ARM_ARCH_TIMER - help - This option enables support for reading the ARM architected timer's - virtual counter in userspace. - config ARM_GLOBAL_TIMER bool "Support for the ARM global timer" if COMPILE_TEST select TIMER_OF if OF diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index e23f995e390d..ed29722e0258 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -863,8 +863,7 @@ static void arch_counter_set_user_access(void) * need to be workaround. The vdso may have been already * disabled though. */ - if (arch_timer_this_cpu_has_cntvct_wa() || - !IS_ENABLED(CONFIG_ARM_ARCH_TIMER_VCT_ACCESS)) + if (arch_timer_this_cpu_has_cntvct_wa()) pr_info("CPU%d: Trapping CNTVCT access\n", smp_processor_id()); else cntkctl |= ARCH_TIMER_USR_VCT_ACCESS_EN; From 2cd34954a48cc1f470393837300aa019f2218819 Mon Sep 17 00:00:00 2001 From: Deepak Kumar Singh Date: Tue, 24 Nov 2020 23:44:24 +0530 Subject: [PATCH 123/698] net: qrtr: Use cyclic idr allocator for port assignment Use cyclic id allocator to avoid immediate reassignment of same port id. Assigning incremental port id gives more clarity over ports assignment and makes it easy to debug problem in certain scenario. Change-Id: Ib432ff641f4c81ba33ff0176cb67f1cdf4b3b1f9 Signed-off-by: Deepak Kumar Singh --- net/qrtr/qrtr.c | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/net/qrtr/qrtr.c b/net/qrtr/qrtr.c index eca3c5ec84bf..d5f77efbd149 100644 --- a/net/qrtr/qrtr.c +++ b/net/qrtr/qrtr.c @@ -1381,27 +1381,25 @@ static void qrtr_port_remove(struct qrtr_sock *ipc) */ static int qrtr_port_assign(struct qrtr_sock *ipc, int *port) { - u32 min_port; int rc; if (!*port) { - min_port = QRTR_MIN_EPH_SOCKET; - rc = idr_alloc_u32(&qrtr_ports, ipc, &min_port, QRTR_MAX_EPH_SOCKET, GFP_ATOMIC); - if (!rc) - *port = min_port; + rc = idr_alloc_cyclic(&qrtr_ports, ipc, QRTR_MIN_EPH_SOCKET, + QRTR_MAX_EPH_SOCKET + 1, GFP_ATOMIC); + if (rc >= 0) + *port = rc; } else if (*port < QRTR_MIN_EPH_SOCKET && - !(capable(CAP_NET_ADMIN) || - in_egroup_p(AID_VENDOR_QRTR) || - in_egroup_p(GLOBAL_ROOT_GID))) { + !(capable(CAP_NET_ADMIN) || + in_egroup_p(AID_VENDOR_QRTR) || + in_egroup_p(GLOBAL_ROOT_GID))) { rc = -EACCES; } else if (*port == QRTR_PORT_CTRL) { - min_port = 0; - rc = idr_alloc_u32(&qrtr_ports, ipc, &min_port, 0, GFP_ATOMIC); + rc = idr_alloc(&qrtr_ports, ipc, 0, 1, GFP_ATOMIC); } else { - min_port = *port; - rc = idr_alloc_u32(&qrtr_ports, ipc, &min_port, *port, GFP_ATOMIC); - if (!rc) - *port = min_port; + rc = idr_alloc_cyclic(&qrtr_ports, ipc, *port, *port + 1, + GFP_ATOMIC); + if (rc >= 0) + *port = rc; } if (rc == -ENOSPC) From b52f4051b7c57cdf548dfabe62ed323a243364ee Mon Sep 17 00:00:00 2001 From: Udipto Goswami Date: Mon, 10 May 2021 14:05:18 +0530 Subject: [PATCH 124/698] usb: dwc3: Handle race between remove_request and ep_dequeue Commit 3ef97296e7b5 ("usb: dwc3: gadget: Handle race between remove_request & ep_dequeue") was introduced to fix the race between remove_requests & dequeue process,but it exposes a new issue where we see crash on ep_set_halt where the started list gets corrupted since composite cleanup already did a free_req. Fix this by reverting the older patch and handling the race of remove_requests & dequeue in cleanup_cancelled_request by iterating over the list using while loop which will insure to access the first node from list_head. Change-Id: I727ca54e5ac839ceb55efb644a7cd8d514db63b6 Signed-off-by: Udipto Goswami --- drivers/usb/dwc3/gadget.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index c6dab7fa8351..f2b8665324f1 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1778,11 +1778,11 @@ static void dwc3_gadget_ep_skip_trbs(struct dwc3_ep *dep, struct dwc3_request *r static void dwc3_gadget_ep_cleanup_cancelled_requests(struct dwc3_ep *dep) { struct dwc3_request *req; - struct dwc3_request *tmp; struct dwc3 *dwc = dep->dwc; int request_count = 0; - list_for_each_entry_safe(req, tmp, &dep->cancelled_list, list) { + while (!list_empty(&dep->cancelled_list)) { + req = next_request(&dep->cancelled_list); dwc3_gadget_ep_skip_trbs(dep, req); dwc3_gadget_giveback(dep, req, -ECONNRESET); request_count++; @@ -1851,8 +1851,7 @@ static int dwc3_gadget_ep_dequeue(struct usb_ep *ep, /* If ep isn't started, then there's no end transfer * pending */ - if ((dep->flags & DWC3_EP_TRANSFER_STARTED) && - !(dep->flags & DWC3_EP_END_TRANSFER_PENDING)) + if (!(dep->flags & DWC3_EP_END_TRANSFER_PENDING)) dwc3_gadget_ep_cleanup_cancelled_requests(dep); goto out; @@ -3583,11 +3582,8 @@ int dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force, bool interrupt) ret = dwc3_send_gadget_ep_cmd(dep, cmd, ¶ms); WARN_ON_ONCE(ret); dep->resource_index = 0; - if (ret == -ETIMEDOUT) { - dbg_log_string("%s(%d): endxfer ret:%d", - dep->name, dep->number, ret); - return ret; - } + + dbg_log_string("%s(%d): endxfer ret:%d", dep->name, dep->number, ret); if (!interrupt) dep->flags &= ~DWC3_EP_TRANSFER_STARTED; From 082b162248b8ad1530ec43f7267b955b01532a7d Mon Sep 17 00:00:00 2001 From: shiwgupt Date: Tue, 1 Jun 2021 14:45:34 +0530 Subject: [PATCH 125/698] dt-bindings: msm: Add bindings for flash type Add binding support for flash type. CRs-Fixed: 2938804 Change-Id: Ie4c7978d9baf34456300f39cd1d607c693420862 Signed-off-by: shiwgupt --- include/dt-bindings/msm/msm-camera.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/dt-bindings/msm/msm-camera.h b/include/dt-bindings/msm/msm-camera.h index a1eca27a755c..0a5aadce4eb7 100644 --- a/include/dt-bindings/msm/msm-camera.h +++ b/include/dt-bindings/msm/msm-camera.h @@ -94,4 +94,9 @@ #define CAM_CPAS_RT_OT_FUSE 9 #define CAM_CPAS_FUSE_FEATURE_MAX 10 +/* Flash type*/ +#define CAM_FLASH_TYPE_GPIO 0 +#define CAM_FLASH_TYPE_I2C 1 +#define CAM_FLASH_TYPE_PMIC 2 + #endif From f5abc45022c7c34b658ac3fa8959fe1070a27244 Mon Sep 17 00:00:00 2001 From: Madhuri Medasani Date: Sun, 6 Jun 2021 12:40:09 +0530 Subject: [PATCH 126/698] clk: qcom: debugcc: Update the CPU mux offset for BLAIR Correct the mux offset for CPU debug mux to be able to measure the CPU frequencies. Change-Id: I042d36cc94c08b80142c86f545102c24b00ea7e5 Signed-off-by: Madhuri Medasani --- drivers/clk/qcom/debugcc-blair.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/qcom/debugcc-blair.c b/drivers/clk/qcom/debugcc-blair.c index 998f0d4ffebf..b8b55554678b 100644 --- a/drivers/clk/qcom/debugcc-blair.c +++ b/drivers/clk/qcom/debugcc-blair.c @@ -240,7 +240,7 @@ static const char *const gcc_debug_mux_parent_names[] = { }; static int gcc_debug_mux_sels[] = { - 0xBA, /* cpu_cc_debug_mux */ + 0xBF, /* cpu_cc_debug_mux */ 0x43, /* disp_cc_debug_mux */ 0x67, /* gcc_ahb2phy_csi_clk */ 0x68, /* gcc_ahb2phy_usb_clk */ From 3778ba91c5e83cfa60a3d12113fac5761f8fab4d Mon Sep 17 00:00:00 2001 From: Odelu Kukatla Date: Tue, 15 Jun 2021 22:21:23 +0530 Subject: [PATCH 127/698] interconnect: qcom: holi: Configure QoS during probe Configure QoS settings during probe for all nodes instead of each node individually upon first client request. Change-Id: I66e8776c8c27ca55382bca78e963ca8db1055637 Signed-off-by: Odelu Kukatla --- drivers/interconnect/qcom/holi.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/drivers/interconnect/qcom/holi.c b/drivers/interconnect/qcom/holi.c index d0edbfd1e1e9..a6a92e8719c8 100644 --- a/drivers/interconnect/qcom/holi.c +++ b/drivers/interconnect/qcom/holi.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. * */ @@ -1718,6 +1718,13 @@ static int qnoc_probe(struct platform_device *pdev) return ret; } + ret = clk_bulk_prepare_enable(qp->num_qos_clks, qp->qos_clks); + if (ret) { + clk_bulk_disable_unprepare(qp->num_clks, qp->bus_clks); + dev_err(&pdev->dev, "failed to enable QoS clocks\n"); + return ret; + } + for (i = 0; i < num_nodes; i++) { size_t j; @@ -1732,6 +1739,11 @@ static int qnoc_probe(struct platform_device *pdev) goto err; } + if (qnodes[i]->qosbox) { + qnodes[i]->noc_ops->set_qos(qnodes[i]); + qnodes[i]->qosbox->initialized = true; + } + node->name = qnodes[i]->name; node->data = qnodes[i]; icc_node_add(node, provider); @@ -1743,6 +1755,8 @@ static int qnoc_probe(struct platform_device *pdev) } data->num_nodes = num_nodes; + clk_bulk_disable_unprepare(qp->num_qos_clks, qp->qos_clks); + platform_set_drvdata(pdev, qp); dev_info(dev, "Registered HOLI ICC\n"); @@ -1758,6 +1772,7 @@ err: icc_node_destroy(node->id); } + clk_bulk_disable_unprepare(qp->num_qos_clks, qp->qos_clks); clk_bulk_disable_unprepare(qp->num_clks, qp->bus_clks); icc_provider_del(provider); return ret; From 2596008a31edaab3af1056a59eafa3a767aa735f Mon Sep 17 00:00:00 2001 From: Mohit Sharma Date: Thu, 24 Jun 2021 15:20:37 +0530 Subject: [PATCH 128/698] Revert "block: Enable BFQ io scheduler as default" This reverts commit 71edb4e7994d5f0db6486a6ae20a2bc99fbb772c. Change-Id: I64d26a44dd164d98d32b5f23c41074f595658eee Signed-off-by: Mohit Sharma --- block/elevator.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/block/elevator.c b/block/elevator.c index 9340e2388c62..076ba7308e65 100644 --- a/block/elevator.c +++ b/block/elevator.c @@ -630,10 +630,7 @@ static struct elevator_type *elevator_get_default(struct request_queue *q) { if (q->nr_hw_queues != 1) return NULL; -#if defined(CONFIG_SDC_QTI) || defined(CONFIG_SCSI_UFSHCD_QTI) - if (IS_ENABLED(CONFIG_IOSCHED_BFQ)) - return elevator_get(q, "bfq", false); -#endif + return elevator_get(q, "mq-deadline", false); } From 29734cd296119399b8022738b0baee8edf52360d Mon Sep 17 00:00:00 2001 From: Pavankumar Kondeti Date: Tue, 15 Jun 2021 18:18:48 +0530 Subject: [PATCH 129/698] irqchip: mpm: Add mpm mapping for Blair Currently both Blair and Holi use the same MPM pins mapping configuration as they use the same compatible string. USB PHY has a different GIC IRQ on Blair, so different MPM configuration is required. Change-Id: I1d72a70c0139abeac2d2ee32d103b7119a192ec9 Signed-off-by: Pavankumar Kondeti --- drivers/irqchip/Makefile | 2 +- drivers/irqchip/qcom-mpm-blair.c | 17 +++++++++++++++++ drivers/irqchip/qcom-mpm.c | 4 ++++ include/soc/qcom/mpm.h | 1 + 4 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 drivers/irqchip/qcom-mpm-blair.c diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index 4e4ac6b2dfff..ef73e2c2cf85 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile @@ -99,7 +99,7 @@ obj-$(CONFIG_QCOM_PDC) += qcom-pdc.o obj-$(CONFIG_CSKY_MPINTC) += irq-csky-mpintc.o obj-$(CONFIG_CSKY_APB_INTC) += irq-csky-apb-intc.o obj-$(CONFIG_QCOM_MPM) += mpm.o -mpm-objs += qcom-mpm.o qcom-mpm-holi.o qcom-mpm-sdxnightjar.o qcom-mpm-monaco.o qcom-mpm-qcs405.o +mpm-objs += qcom-mpm.o qcom-mpm-holi.o qcom-mpm-sdxnightjar.o qcom-mpm-monaco.o qcom-mpm-qcs405.o qcom-mpm-blair.o obj-$(CONFIG_SIFIVE_PLIC) += irq-sifive-plic.o obj-$(CONFIG_IMX_IRQSTEER) += irq-imx-irqsteer.o obj-$(CONFIG_MADERA_IRQ) += irq-madera.o diff --git a/drivers/irqchip/qcom-mpm-blair.c b/drivers/irqchip/qcom-mpm-blair.c new file mode 100644 index 000000000000..b4da13878435 --- /dev/null +++ b/drivers/irqchip/qcom-mpm-blair.c @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: GPL-2.0-only + +/* + * Copyright (c) 2021, The Linux Foundation. All rights reserved. + */ + +#include +const struct mpm_pin mpm_blair_gic_chip_data[] = { + {5, 296}, /* lpass_irq_out_sdc */ + {12, 422}, /* qmp_usb3_lfps_rxterm_irq_cx */ + {86, 183}, /* mpm_wake,spmi_m */ + {89, 314}, /* tsens0_tsens_0C_int */ + {90, 315}, /* tsens1_tsens_0C_int */ + {93, 164}, /* eud_p0_dmse_int_mx */ + {94, 165}, /* eud_p0_dpse_int_mx */ + {-1}, +}; diff --git a/drivers/irqchip/qcom-mpm.c b/drivers/irqchip/qcom-mpm.c index acdddcbfac11..bebd0a8898fe 100644 --- a/drivers/irqchip/qcom-mpm.c +++ b/drivers/irqchip/qcom-mpm.c @@ -572,6 +572,10 @@ static const struct of_device_id mpm_gic_chip_data_table[] = { .compatible = "qcom,mpm-gic-qcs405", .data = mpm_qcs405_gic_chip_data, }, + { + .compatible = "qcom,mpm-gic-blair", + .data = mpm_blair_gic_chip_data, + }, {} }; MODULE_DEVICE_TABLE(of, mpm_gic_chip_data_table); diff --git a/include/soc/qcom/mpm.h b/include/soc/qcom/mpm.h index 49a82f6246a1..6c9cb12cddc8 100644 --- a/include/soc/qcom/mpm.h +++ b/include/soc/qcom/mpm.h @@ -20,4 +20,5 @@ extern const struct mpm_pin mpm_holi_gic_chip_data[]; extern const struct mpm_pin mpm_sdxnightjar_gic_chip_data[]; extern const struct mpm_pin mpm_monaco_gic_chip_data[]; extern const struct mpm_pin mpm_qcs405_gic_chip_data[]; +extern const struct mpm_pin mpm_blair_gic_chip_data[]; #endif /* __QCOM_MPM_H__ */ From 460632cac4864a788553f62b9d4b05e6cd17604e Mon Sep 17 00:00:00 2001 From: Rohith Kollalsi Date: Sun, 20 Jun 2021 23:46:57 +0530 Subject: [PATCH 130/698] usb: dwc3: Use pwr_evt_irq to wakeup if dp/dm directly connected to GIC Currently support to enable/disable dplus hsphy irq and dminus hsphy irq in case of resume/suspend is present only for pdc interrupts. This support should be present even for non pdc interrupts if the platform uses snps usb hs phy. Absence of this support leads to dp/dm hsphy irq not being fired and usb stuck in lpm in host mode eventhough there is a disconnect or remote wakeup issued from hs/fs device connected to it. Hence add support to enable/disable dp hsphy irq and dm hsphy irq for platforms that use snps hs phy. On platforms which use snps phy and mpm interrupts, dp/dm lines are directly connected to gic when cpu is active, mpm is involved only when cpu is not active. Now in cpu active case, in host mode if usb goes to lpm with hs/fs/ls device connected and unplug/remote wakeup is issued, dp falling edge is monitored in software to detect that. But GIC is not capable of detecting a falling edge. Hence this change adds support to program power event irq to wakeup the system in this case. Note that gic takes care of dp rising edge wakeup events like usb connect over otg when usb is in lpm and in host mode. Only in case where dp falling edge is monitored i.e in case of hs/fs/ls device connect and usb enteres lpm, then power event irq is used to detect wakeup event as GIC cannot detect falling edge Change-Id: I085b86c7df52daeedfb35cb71657c5163c2d5aaa Signed-off-by: Rohith Kollalsi --- drivers/usb/dwc3/dwc3-msm.c | 92 ++++++++++++++++++++++++++++--------- 1 file changed, 70 insertions(+), 22 deletions(-) diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c index 77afbed72763..0bd64b96638a 100644 --- a/drivers/usb/dwc3/dwc3-msm.c +++ b/drivers/usb/dwc3/dwc3-msm.c @@ -490,11 +490,15 @@ struct dwc3_msm { bool suspend; bool use_pdc_interrupts; enum dwc3_id_state id_state; - bool use_pwr_event_for_wakeup; + unsigned long use_pwr_event_for_wakeup; unsigned long lpm_flags; #define MDWC3_SS_PHY_SUSPEND BIT(0) #define MDWC3_ASYNC_IRQ_WAKE_CAPABILITY BIT(1) #define MDWC3_POWER_COLLAPSE BIT(2) +#define MDWC3_USE_PWR_EVENT_IRQ_FOR_WAKEUP BIT(3) + +#define PWR_EVENT_SS_WAKEUP BIT(0) +#define PWR_EVENT_HS_WAKEUP BIT(1) struct extcon_nb *extcon; int ext_idx; @@ -3047,7 +3051,7 @@ static void configure_usb_wakeup_interrupt(struct dwc3_msm *mdwc, } } -static void enable_usb_pdc_interrupt(struct dwc3_msm *mdwc, bool enable) +static void configure_usb_wakeup_interrupts(struct dwc3_msm *mdwc, bool enable) { if (!enable) goto disable_usb_irq; @@ -3131,7 +3135,7 @@ static void configure_nonpdc_usb_interrupt(struct dwc3_msm *mdwc, } } -static void dwc3_msm_set_ss_pwr_events(struct dwc3_msm *mdwc, bool on) +static void dwc3_msm_set_pwr_events(struct dwc3_msm *mdwc, bool on) { u32 irq_mask, irq_stat; @@ -3142,12 +3146,26 @@ static void dwc3_msm_set_ss_pwr_events(struct dwc3_msm *mdwc, bool on) irq_mask = dwc3_msm_read_reg(mdwc->base, PWR_EVNT_IRQ_MASK_REG); - if (on) - irq_mask |= (PWR_EVNT_POWERDOWN_OUT_P3_MASK | - PWR_EVNT_LPM_OUT_RX_ELECIDLE_IRQ_MASK); - else - irq_mask &= ~(PWR_EVNT_POWERDOWN_OUT_P3_MASK | - PWR_EVNT_LPM_OUT_RX_ELECIDLE_IRQ_MASK); + if (on) { + /* + * In case of platforms which use mpm interrupts, in case where + * suspend happens with a hs/fs/ls device connected in host mode. + * DP/DM falling edge will be monitored, but gic doesn't have + * capability to detect falling edge. So program power event irq + * to notify exit from lpm in such case. + */ + if (mdwc->use_pwr_event_for_wakeup & PWR_EVENT_HS_WAKEUP) + irq_mask |= PWR_EVNT_LPM_OUT_L2_MASK; + if (mdwc->use_pwr_event_for_wakeup & PWR_EVENT_SS_WAKEUP) + irq_mask |= (PWR_EVNT_POWERDOWN_OUT_P3_MASK | + PWR_EVNT_LPM_OUT_RX_ELECIDLE_IRQ_MASK); + } else { + if (mdwc->use_pwr_event_for_wakeup & PWR_EVENT_HS_WAKEUP) + irq_mask &= ~PWR_EVNT_LPM_OUT_L2_MASK; + if (mdwc->use_pwr_event_for_wakeup & PWR_EVENT_SS_WAKEUP) + irq_mask &= ~(PWR_EVNT_POWERDOWN_OUT_P3_MASK | + PWR_EVNT_LPM_OUT_RX_ELECIDLE_IRQ_MASK); + } dwc3_msm_write_reg(mdwc->base, PWR_EVNT_IRQ_MASK_REG, irq_mask); } @@ -3280,7 +3298,7 @@ static int dwc3_msm_suspend(struct dwc3_msm *mdwc, bool force_power_collapse, ((mdwc->hs_phy->flags & (PHY_HSFS_MODE | PHY_LS_MODE)) && !dwc3_msm_is_superspeed(mdwc))); can_suspend_ssphy = dwc->maximum_speed >= USB_SPEED_SUPER && - (!mdwc->use_pwr_event_for_wakeup || no_active_ss || + (!(mdwc->use_pwr_event_for_wakeup & PWR_EVENT_SS_WAKEUP) || no_active_ss || !enable_wakeup); /* Suspend SS PHY */ if (can_suspend_ssphy) { @@ -3306,8 +3324,20 @@ static int dwc3_msm_suspend(struct dwc3_msm *mdwc, bool force_power_collapse, usb_phy_set_suspend(mdwc->ss_phy, 1); usb_phy_set_suspend(mdwc->ss_phy1, 1); mdwc->lpm_flags |= MDWC3_SS_PHY_SUSPEND; - } else if (mdwc->use_pwr_event_for_wakeup) { - dwc3_msm_set_ss_pwr_events(mdwc, true); + } else if (mdwc->use_pwr_event_for_wakeup & PWR_EVENT_SS_WAKEUP) { + mdwc->lpm_flags |= MDWC3_USE_PWR_EVENT_IRQ_FOR_WAKEUP; + } + + /* + * When operating in HS host mode, check if pwr event IRQ is + * required for wakep. + */ + if (mdwc->in_host_mode && no_active_ss && + (mdwc->use_pwr_event_for_wakeup & PWR_EVENT_HS_WAKEUP)) + mdwc->lpm_flags |= MDWC3_USE_PWR_EVENT_IRQ_FOR_WAKEUP; + + if (mdwc->lpm_flags & MDWC3_USE_PWR_EVENT_IRQ_FOR_WAKEUP) { + dwc3_msm_set_pwr_events(mdwc, true); enable_irq(mdwc->wakeup_irq[PWR_EVNT_IRQ].irq); } @@ -3362,11 +3392,13 @@ static int dwc3_msm_suspend(struct dwc3_msm *mdwc, bool force_power_collapse, /* * with the core in power collapse, we dont require wakeup * using HS_PHY_IRQ or SS_PHY_IRQ. Hence enable wakeup only in - * case of host bus suspend and device bus suspend. + * case of host bus suspend and device bus suspend. Also in + * case of platforms with mpm interrupts and snps phy, enable + * dpse hsphy irq and dmse hsphy irq as done for pdc interrupts. */ if (!(mdwc->lpm_flags & MDWC3_POWER_COLLAPSE) && enable_wakeup) { - if (mdwc->use_pdc_interrupts) { - enable_usb_pdc_interrupt(mdwc, true); + if (mdwc->use_pdc_interrupts || !mdwc->wakeup_irq[HS_PHY_IRQ].irq) { + configure_usb_wakeup_interrupts(mdwc, true); } else { uirq = &mdwc->wakeup_irq[HS_PHY_IRQ]; configure_nonpdc_usb_interrupt(mdwc, uirq, true); @@ -3468,10 +3500,10 @@ static int dwc3_msm_resume(struct dwc3_msm *mdwc) * Disable any wakeup events that were enabled if pwr_event_irq * is used as wakeup interrupt. */ - if (mdwc->use_pwr_event_for_wakeup && - !(mdwc->lpm_flags & MDWC3_SS_PHY_SUSPEND)) { + if (mdwc->lpm_flags & MDWC3_USE_PWR_EVENT_IRQ_FOR_WAKEUP) { disable_irq_nosync(mdwc->wakeup_irq[PWR_EVNT_IRQ].irq); - dwc3_msm_set_ss_pwr_events(mdwc, false); + dwc3_msm_set_pwr_events(mdwc, false); + mdwc->lpm_flags &= ~MDWC3_USE_PWR_EVENT_IRQ_FOR_WAKEUP; } /* Resume SS PHY */ @@ -3542,8 +3574,8 @@ static int dwc3_msm_resume(struct dwc3_msm *mdwc) /* Disable wakeup capable for HS_PHY IRQ & SS_PHY_IRQ if enabled */ if (mdwc->lpm_flags & MDWC3_ASYNC_IRQ_WAKE_CAPABILITY) { - if (mdwc->use_pdc_interrupts) { - enable_usb_pdc_interrupt(mdwc, false); + if (mdwc->use_pdc_interrupts || !mdwc->wakeup_irq[HS_PHY_IRQ].irq) { + configure_usb_wakeup_interrupts(mdwc, false); } else { uirq = &mdwc->wakeup_irq[HS_PHY_IRQ]; configure_nonpdc_usb_interrupt(mdwc, uirq, false); @@ -3791,6 +3823,13 @@ static void dwc3_pwr_event_handler(struct dwc3_msm *mdwc) irq_clear |= PWR_EVNT_LPM_OUT_L1_MASK; } + /* Handle exit from L2 events */ + if (irq_stat & PWR_EVNT_LPM_OUT_L2_MASK) { + dev_dbg(mdwc->dev, "%s: handling PWR_EVNT_LPM_OUT_L2_MASK\n", + __func__); + irq_stat &= ~PWR_EVNT_LPM_OUT_L2_MASK; + irq_clear |= PWR_EVNT_LPM_OUT_L2_MASK; + } /* Unhandled events */ if (irq_stat) dev_dbg(mdwc->dev, "%s: unexpected PWR_EVNT, irq_stat=%X\n", @@ -4895,8 +4934,17 @@ static int dwc3_msm_probe(struct platform_device *pdev) * On platforms with SS PHY that do not support ss_phy_irq for wakeup * events, use pwr_event_irq for wakeup events in superspeed mode. */ - mdwc->use_pwr_event_for_wakeup = dwc->maximum_speed >= USB_SPEED_SUPER - && !mdwc->wakeup_irq[SS_PHY_IRQ].irq; + if (dwc->maximum_speed >= USB_SPEED_SUPER + && !mdwc->wakeup_irq[SS_PHY_IRQ].irq) + mdwc->use_pwr_event_for_wakeup |= PWR_EVENT_SS_WAKEUP; + + /* + * On platforms with mpm interrupts and snps phy, when operating in + * HS host mode use power event irq for wakeup events as GIC is not + * capable to detect falling edge of dp/dm hsphy irq. + */ + if (!mdwc->use_pdc_interrupts && !mdwc->wakeup_irq[HS_PHY_IRQ].irq) + mdwc->use_pwr_event_for_wakeup |= PWR_EVENT_HS_WAKEUP; /* * Clocks and regulators will not be turned on until the first time From 29374956181e9ff8ddebd7d0c5c63da9fc4e1464 Mon Sep 17 00:00:00 2001 From: shiwgupt Date: Tue, 22 Jun 2021 15:34:08 +0530 Subject: [PATCH 131/698] dt-bindings: msm: Add bindings for flash type Add binding support for flash type for khaje camera. CRs-Fixed: 2938804 Change-Id: I844b59125bb08034b1937422ac29485d5a7a2746 Signed-off-by: shiwgupt --- include/dt-bindings/msm/msm-camera.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/dt-bindings/msm/msm-camera.h b/include/dt-bindings/msm/msm-camera.h index 0a5aadce4eb7..9735e75f7900 100644 --- a/include/dt-bindings/msm/msm-camera.h +++ b/include/dt-bindings/msm/msm-camera.h @@ -95,8 +95,8 @@ #define CAM_CPAS_FUSE_FEATURE_MAX 10 /* Flash type*/ -#define CAM_FLASH_TYPE_GPIO 0 +#define CAM_FLASH_TYPE_PMIC 0 #define CAM_FLASH_TYPE_I2C 1 -#define CAM_FLASH_TYPE_PMIC 2 +#define CAM_FLASH_TYPE_GPIO 2 #endif From be381e1436d7d3060a75a6ea371326ab09f2994b Mon Sep 17 00:00:00 2001 From: Udipto Goswami Date: Wed, 23 Jun 2021 14:00:29 +0530 Subject: [PATCH 132/698] usb: dwc3: Add support of disable L1 in HS mode On some platforms, L1 in HS mode is not supported. Add support to disable L1 in HS mode on those platforms by default through dt. Change-Id: I624bde1e091e6e864bf7f7af93804c3728374d0d Signed-off-by: Udipto Goswami --- drivers/usb/dwc3/core.c | 2 ++ drivers/usb/dwc3/core.h | 1 + drivers/usb/dwc3/gadget.c | 2 +- drivers/usb/gadget/composite.c | 3 ++- 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 6791b4ca95dd..5395c52edf3d 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -1485,6 +1485,8 @@ static void dwc3_get_properties(struct dwc3 *dwc) "snps,dis-tx-ipgap-linecheck-quirk"); dwc->parkmode_disable_ss_quirk = device_property_read_bool(dev, "snps,parkmode-disable-ss-quirk"); + dwc->usb2_l1_disable = device_property_read_bool(dev, + "snps,usb2-l1-disable"); dwc->tx_de_emphasis_quirk = device_property_read_bool(dev, "snps,tx_de_emphasis_quirk"); diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index fee3cf068915..a019b0e6180e 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -1363,6 +1363,7 @@ struct dwc3 { unsigned tx_de_emphasis:2; unsigned err_evt_seen:1; unsigned enable_bus_suspend:1; + unsigned usb2_l1_disable:1; atomic_t in_lpm; bool b_suspend; diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index fdc52c8d940e..aa03c5b6da10 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -4369,7 +4369,7 @@ int dwc3_gadget_init(struct dwc3 *dwc) dwc->gadget.speed = USB_SPEED_UNKNOWN; dwc->gadget.sg_supported = true; dwc->gadget.name = "dwc3-gadget"; - dwc->gadget.lpm_capable = true; + dwc->gadget.lpm_capable = !dwc->usb2_l1_disable; /* * FIXME We might be setting max_speed to desc.bMaxPacketSize0 = cdev->gadget->ep0->maxpacket; + cdev->desc.bcdUSB = cpu_to_le16(0x0200); if (gadget_is_superspeed(gadget)) { if (gadget->speed >= USB_SPEED_SUPER) { cdev->desc.bcdUSB = cpu_to_le16(0x0320); cdev->desc.bMaxPacketSize0 = 9; - } else { + } else if (gadget->lpm_capable) { cdev->desc.bcdUSB = cpu_to_le16(0x0210); } } else { From cd096172e5001fb584803843e4fd0b13bd9baa5a Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Thu, 8 Jul 2021 09:12:22 +0530 Subject: [PATCH 133/698] clk: qcom: clk-alpha-pll: Update the steps to slew the Lucid PLL When PLL HW_UPDATE_LOGIC_BYPASS bit is not set then PLL can be updated dynamically by setting the PLL_UPDATE bit in mode register and hardware would clear the PLL_UPDATE automatically when PLL_ACK_LATCH is asserted. Change-Id: I1c568c9fdd37a554d71fc5c3d840a71e983baf60 Signed-off-by: Taniya Das --- drivers/clk/qcom/clk-alpha-pll.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c index e40f344609f8..391761765f3b 100644 --- a/drivers/clk/qcom/clk-alpha-pll.c +++ b/drivers/clk/qcom/clk-alpha-pll.c @@ -2895,7 +2895,12 @@ static int alpha_pll_lucid_set_rate(struct clk_hw *hw, unsigned long rate, /* Wait for 2 reference cycles before checking the ACK bit. */ udelay(1); regmap_read(pll->clkr.regmap, PLL_MODE(pll), ®val); - if (!(regval & ALPHA_PLL_ACK_LATCH)) { + if (!(regval & PLL_UPDATE_BYPASS)) { + ret = wait_for_pll_update(pll); + if (ret) + WARN_CLK(&pll->clkr.hw, 1, "PLL Update clear failed\n"); + return ret; + } else if (!(regval & ALPHA_PLL_ACK_LATCH)) { WARN_CLK(&pll->clkr.hw, 1, "PLL latch failed. Output may be unstable!\n"); return -EINVAL; From 0871d48d8a72ae3a60a0457dcf9ec722b3f45537 Mon Sep 17 00:00:00 2001 From: Fei Mao Date: Thu, 24 Jun 2021 19:04:52 +0800 Subject: [PATCH 134/698] input: touchscreen: focaltech: add a new property Add a new property to indicate power's state when sleep. Change-Id: Ic54fbbd0adee8716ad0b2d892814f8ac38b683c5 Signed-off-by: Fei Mao --- .../touchscreen/focaltech_touch/focaltech_core.c | 11 +++++++++-- .../touchscreen/focaltech_touch/focaltech_core.h | 1 + 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/input/touchscreen/focaltech_touch/focaltech_core.c b/drivers/input/touchscreen/focaltech_touch/focaltech_core.c index 9eefb3e783f4..823caa4fdc8e 100644 --- a/drivers/input/touchscreen/focaltech_touch/focaltech_core.c +++ b/drivers/input/touchscreen/focaltech_touch/focaltech_core.c @@ -2476,6 +2476,9 @@ static int fts_parse_dt(struct device *dev, struct fts_ts_platform_data *pdata) FTS_INFO("max touch number:%d, irq gpio:%d, reset gpio:%d", pdata->max_touch_number, pdata->irq_gpio, pdata->reset_gpio); + pdata->power_always_on = + of_property_read_bool(np, "focaltech,power-always-on"); + ret = of_property_read_u32(np, "focaltech,ic-type", &temp_val); if (ret < 0) pdata->type = _FT3518; @@ -2903,6 +2906,7 @@ static int fts_ts_suspend(struct device *dev) { int ret = 0; struct fts_ts_data *ts_data = fts_data; + struct fts_ts_platform_data *pdata = ts_data->pdata; FTS_FUNC_ENTER(); if (ts_data->suspended) { @@ -2934,7 +2938,8 @@ static int fts_ts_suspend(struct device *dev) if (ret < 0) FTS_ERROR("set TP to sleep mode fail, ret=%d", ret); - if (!ts_data->ic_info.is_incell) { + if (!ts_data->ic_info.is_incell && !pdata->power_always_on) { + #if FTS_POWER_SOURCE_CUST_EN ret = fts_power_source_suspend(ts_data); if (ret < 0) { @@ -2953,6 +2958,7 @@ static int fts_ts_suspend(struct device *dev) static int fts_ts_resume(struct device *dev) { struct fts_ts_data *ts_data = fts_data; + struct fts_ts_platform_data *pdata = ts_data->pdata; FTS_FUNC_ENTER(); if (!ts_data->suspended) { @@ -2971,7 +2977,8 @@ static int fts_ts_resume(struct device *dev) if (!ts_data->ic_info.is_incell) { #if FTS_POWER_SOURCE_CUST_EN - fts_power_source_resume(ts_data); + if (!pdata->power_always_on) + fts_power_source_resume(ts_data); #endif fts_reset_proc(200); } diff --git a/drivers/input/touchscreen/focaltech_touch/focaltech_core.h b/drivers/input/touchscreen/focaltech_touch/focaltech_core.h index c87cc52e5e47..3c8701f98c62 100644 --- a/drivers/input/touchscreen/focaltech_touch/focaltech_core.h +++ b/drivers/input/touchscreen/focaltech_touch/focaltech_core.h @@ -139,6 +139,7 @@ struct fts_ts_platform_data { u32 x_min; u32 y_min; u32 max_touch_number; + bool power_always_on; }; struct ts_event { From 2c3d0599fd54dfaeea12fc9733a9080ab311430b Mon Sep 17 00:00:00 2001 From: Mike Tipton Date: Fri, 25 Jun 2021 05:55:36 -0700 Subject: [PATCH 135/698] clk: qcom: Round parent rate in clk_rcg2_determine_rate We currently set best_parent_rate to the ideal frequency wanted by the RCG. This doesn't always align to the exact frequency the parent can provide. If they differ, then clk_calc_new_rates() will return the parent as top, even if the rounded parent frequency isn't changing. This causes clk_propagate_rate_change() to return before being called for its children, which means children aren't notified of the PRE_RATE_CHANGE events. Set best_parent_rate to the rounded rate so that we don't unnecessarily try to change the parent. Change-Id: Ic976db7a13dfbc63cb66b032a45060565ca90b43 Signed-off-by: Mike Tipton --- drivers/clk/qcom/clk-rcg2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c index d1148af5eeb2..88a19aa5115f 100644 --- a/drivers/clk/qcom/clk-rcg2.c +++ b/drivers/clk/qcom/clk-rcg2.c @@ -359,7 +359,7 @@ static int _freq_tbl_determine_rate(struct clk_hw *hw, const struct freq_tbl *f, rate = clk_hw_get_rate(p); } req->best_parent_hw = p; - req->best_parent_rate = rate; + req->best_parent_rate = clk_hw_round_rate(p, rate); req->rate = f->freq; if (f->src_freq != FIXED_FREQ_SRC) { From 52470557a9012148bd680d87c3c523d7a38eca7f Mon Sep 17 00:00:00 2001 From: Pankaj Gupta Date: Mon, 30 Aug 2021 12:51:32 +0530 Subject: [PATCH 136/698] msm: kgsl: Fix list corruption in worker initialization of mem_entry While deferring mem_entry_put, we are doing INIT_WORK for entry. When mem_entry_put get called again for the same entry before execution of previous work finishes, there is a chance of corruption in the list and cause a crash. Update kgsl_mem_entry_put_deferred to put refcount on mem entry and trigger deferred mem entry destroy only when refcount on entry is the last refcount. Change-Id: I2a8533fd26e776d49ab128bdb484053ce3bc82dc Signed-off-by: Pankaj Gupta --- drivers/gpu/msm/kgsl.c | 20 ++++++++++++++------ drivers/gpu/msm/kgsl.h | 9 ++++++--- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c index f1e978020213..4b0e1d13fa78 100644 --- a/drivers/gpu/msm/kgsl.c +++ b/drivers/gpu/msm/kgsl.c @@ -239,20 +239,28 @@ const char *kgsl_context_type(int type) return "ANY"; } -/* Scheduled by kgsl_mem_entry_put_deferred() */ -static void _deferred_put(struct work_struct *work) +/* Scheduled by kgsl_mem_entry_destroy_deferred() */ +static void _deferred_destroy(struct work_struct *work) { struct kgsl_mem_entry *entry = container_of(work, struct kgsl_mem_entry, work); - kgsl_mem_entry_put(entry); + kgsl_mem_entry_destroy(&entry->refcount); +} + +static void kgsl_mem_entry_destroy_deferred(struct kref *kref) +{ + struct kgsl_mem_entry *entry = + container_of(kref, struct kgsl_mem_entry, refcount); + + INIT_WORK(&entry->work, _deferred_destroy); + queue_work(kgsl_driver.mem_workqueue, &entry->work); } -/* Use a worker to put the refcount on mem entry */ void kgsl_mem_entry_put_deferred(struct kgsl_mem_entry *entry) { - INIT_WORK(&entry->work, _deferred_put); - queue_work(kgsl_driver.mem_workqueue, &entry->work); + if (entry) + kref_put(&entry->refcount, kgsl_mem_entry_destroy_deferred); } static struct kgsl_mem_entry *kgsl_mem_entry_create(void) diff --git a/drivers/gpu/msm/kgsl.h b/drivers/gpu/msm/kgsl.h index 85d67d0dc2bb..69fdf288fa68 100644 --- a/drivers/gpu/msm/kgsl.h +++ b/drivers/gpu/msm/kgsl.h @@ -562,9 +562,12 @@ kgsl_mem_entry_put(struct kgsl_mem_entry *entry) } /** - * kgsl_mem_entry_put_deferred() - use a worker to put the refcount - * on mem entry from a sysfs handler or debugfs handler. - * @entry - The memory entry + * kgsl_mem_entry_put_deferred() - Puts refcount and triggers deferred + * mem_entry destroy when refcount is the last refcount. + * @entry: memory entry to be put. + * + * Use this to put a memory entry when we don't want to block + * the caller while destroying memory entry. */ void kgsl_mem_entry_put_deferred(struct kgsl_mem_entry *entry); From 01e0eb2458417bbab5ebe7324914a814ac40f1a5 Mon Sep 17 00:00:00 2001 From: Chandana Kishori Chiluveru Date: Mon, 30 Aug 2021 20:12:31 +0530 Subject: [PATCH 137/698] serial: msm_geni_serial: Fix deadlock scenario with rx_lock In one core msm_geni_serial driver acquiring port->rx_lock in stop_rx_sequencer function in process context by calling handle_rx_dma_xfer and this process is preempted becz of core interrupt is fired on same core and then same lock is trying to acquire from interrupt context. This is resulting in deadlock issue. Below are the core call stack of deadlock. Core 0 LR: _raw_spin_lock[jt]+40 [] handle_rx_dma_xfer+0x44 [] msm_geni_serial_handle_isr+0x6fc [] msm_geni_serial_isr+0x40 [] __handle_irq_event_percpu+0x158 [] handle_irq_event+0x60 [] handle_fasteoi_irq+0x128 [] __handle_domain_irq+0xa0 [] gic_handle_irq$7f58c51dd0f0d487d89dbb027abc57c5+0xb8 [] el1_irq+0x104 [] handle_rx_dma_xfer+0x50 [] stop_rx_sequencer+0x118 [] msm_geni_serial_set_termios+0x114 [] uart_change_speed+0x58 [] uart_set_termios$ecf561cdccc9a487f79dc2d4825d91c7+0xd4 [] tty_set_termios[jt]+0x1c0 [] set_termios+0x124 [] tty_mode_ioctl+0x468 [] n_tty_ioctl_helper+0xac [] n_tty_ioctl$31461d4e731178606d28313f43c714a4[jt]+0x318 [] tty_ioctl+0x37c [] do_vfs_ioctl+0x384 [] __arm64_sys_ioctl+0x78 [] el0_svc_common[jt]+0xd8 [] el0_svc_handler+0x68 [] ret_to_user[jt]+0x0. Change-Id: I7e1392cd82a93b1da6b19f05dbe67b66d46193f1 Signed-off-by: Chandana Kishori Chiluveru --- drivers/tty/serial/msm_geni_serial.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/tty/serial/msm_geni_serial.c b/drivers/tty/serial/msm_geni_serial.c index f81be32b396b..ed0b027b2047 100644 --- a/drivers/tty/serial/msm_geni_serial.c +++ b/drivers/tty/serial/msm_geni_serial.c @@ -2100,8 +2100,9 @@ static bool handle_rx_dma_xfer(u32 s_irq_status, struct uart_port *uport) bool drop_rx = false; struct msm_geni_serial_port *msm_port = GET_DEV_PORT(uport); u32 dma_rx_status; + unsigned long lock_flags; - spin_lock(&msm_port->rx_lock); + spin_lock_irqsave(&msm_port->rx_lock, lock_flags); dma_rx_status = geni_read_reg_nolog(uport->membase, SE_DMA_RX_IRQ_STAT); @@ -2166,7 +2167,7 @@ static bool handle_rx_dma_xfer(u32 s_irq_status, struct uart_port *uport) ret = true; exit: - spin_unlock(&msm_port->rx_lock); + spin_unlock_irqrestore(&msm_port->rx_lock, lock_flags); return ret; } From 53a7ee0a66bee729360285cde3e93585fd5a1463 Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Fri, 20 Aug 2021 17:37:25 +0530 Subject: [PATCH 138/698] clk: smd: rpm: Add a qup active only vote for HOLI The pm8008 regulator is connected over I2C and the I2C device configures its BW vote in runtime_resume and runtime_suspend. These callbacks are triggered from the pm8008 driver's regmap calls. This means regulator framework requests for pm8008 call into the ICC framework which in turn calls into clock framework. The qcom rpm smd clock providers calls into RPM message with the the regulator framework, ICC framework and clock framework locks held. To prevent these deadlocks, enable the I2C qup clocks required for pm8008 by default during probe and stop requesting for clock enable/rate from the framework. Change-Id: Ifd486bec85a46139ccb15f4b5dbd2d43c33f3fda Signed-off-by: Taniya Das --- drivers/clk/qcom/clk-smd-rpm.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/clk/qcom/clk-smd-rpm.c b/drivers/clk/qcom/clk-smd-rpm.c index 49429c5fadda..3e96ceb0826a 100644 --- a/drivers/clk/qcom/clk-smd-rpm.c +++ b/drivers/clk/qcom/clk-smd-rpm.c @@ -1134,6 +1134,10 @@ static int rpm_smd_clk_probe(struct platform_device *pdev) /* Hold an active set vote for the snoc_keepalive_a_clk */ clk_prepare_enable(holi_snoc_a_clk.hw.clk); clk_set_rate(holi_snoc_a_clk.hw.clk, 19200000); + + /* Hold an active set vote for qup clock */ + clk_prepare_enable(holi_qup_a_clk.hw.clk); + clk_set_rate(holi_qup_a_clk.hw.clk, 19200000); } if (is_sdxnightjar) { From 87a304be0295cb5551a56d20bf3073fa66da5ae6 Mon Sep 17 00:00:00 2001 From: Mukesh Kumar Savaliya Date: Thu, 12 Aug 2021 02:19:12 +0530 Subject: [PATCH 139/698] i2c: i2c-msm-geni: Skip BW vote for PMIC used I2C SE node This change is a workaround change to fix the PMIC race condition with the clock enablement. In case of PMIC txfer over i2c, I2C driver resumes and votes for BW and clocks. The BW vote goes to RPM and that in turn waiting for the global PMIC mutex causing race condition in rare cases. Hence as a workaroun, do not vote for the BW vote only for PMIC used I2C SE instance. Change-Id: I94c57427200a71dd2792533b1af249940b0bf03f Signed-off-by: Mukesh Kumar Savaliya --- drivers/i2c/busses/i2c-msm-geni.c | 3 +++ drivers/platform/msm/msm-geni-se.c | 6 ++++++ include/linux/msm-geni-se.h | 2 ++ 3 files changed, 11 insertions(+) diff --git a/drivers/i2c/busses/i2c-msm-geni.c b/drivers/i2c/busses/i2c-msm-geni.c index 33fdc8a4f3f7..c850bdce9f70 100644 --- a/drivers/i2c/busses/i2c-msm-geni.c +++ b/drivers/i2c/busses/i2c-msm-geni.c @@ -1237,6 +1237,9 @@ static int geni_i2c_probe(struct platform_device *pdev) dev_info(&pdev->dev, "LE-VM usecase\n"); } + if (of_property_read_bool(pdev->dev.of_node, "qcom,leica-used-i2c")) + gi2c->i2c_rsc.skip_bw_vote = true; + gi2c->i2c_rsc.wrapper_dev = &wrapper_pdev->dev; gi2c->i2c_rsc.ctrl_dev = gi2c->dev; diff --git a/drivers/platform/msm/msm-geni-se.c b/drivers/platform/msm/msm-geni-se.c index 66a34dd7816d..80e5a719c97d 100644 --- a/drivers/platform/msm/msm-geni-se.c +++ b/drivers/platform/msm/msm-geni-se.c @@ -715,6 +715,9 @@ static int geni_se_rmv_ab_ib(struct geni_se_device *geni_se_dev, if (geni_se_dev->vectors == NULL) return 0; + if (rsc->skip_bw_vote) + return 0; + if (unlikely(list_empty(&rsc->ab_list) || list_empty(&rsc->ib_list))) return -EINVAL; @@ -862,6 +865,9 @@ static int geni_se_add_ab_ib(struct geni_se_device *geni_se_dev, if (geni_se_dev->vectors == NULL) return 0; + if (rsc->skip_bw_vote) + return 0; + mutex_lock(&geni_se_dev->geni_dev_lock); list_add(&rsc->ab_list, &geni_se_dev->ab_list_head); diff --git a/include/linux/msm-geni-se.h b/include/linux/msm-geni-se.h index 92f587b7deaa..47872cda8a90 100644 --- a/include/linux/msm-geni-se.h +++ b/include/linux/msm-geni-se.h @@ -51,6 +51,7 @@ enum se_protocol_types { * @geni_gpi_sleep: Handle to the sleep pinctrl state. * @num_clk_levels: Number of valid clock levels in clk_perf_tbl. * @clk_perf_tbl: Table of clock frequency input to Serial Engine clock. + * @skip_bw_vote: Used for PMIC over i2c use case to skip the BW vote. */ struct se_geni_rsc { struct device *ctrl_dev; @@ -73,6 +74,7 @@ struct se_geni_rsc { int clk_freq_out; unsigned int num_clk_levels; unsigned long *clk_perf_tbl; + bool skip_bw_vote; }; #define PINCTRL_DEFAULT "default" From 011bd664d773a4ae4fc9296fd1fab36e8600296e Mon Sep 17 00:00:00 2001 From: Prakruthi Deepak Heragu Date: Tue, 24 Aug 2021 19:34:43 -0700 Subject: [PATCH 140/698] haven: hh_rm_iface: Avoid integer overflow for req_payload_size calculation There is a possibility for the calculation to overflow when size is large enough to overflow when added to the size of payload. Ensure that this overflow is caught early. Change-Id: I876fbaa704ba51dc4a9e4eb4d3f7f0eaa749e06d Signed-off-by: Prakruthi Deepak Heragu Signed-off-by: Swetha Chikkaboraiah --- drivers/virt/haven/hh_rm_iface.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/virt/haven/hh_rm_iface.c b/drivers/virt/haven/hh_rm_iface.c index 1c4923c0288c..ea8ab935d736 100644 --- a/drivers/virt/haven/hh_rm_iface.c +++ b/drivers/virt/haven/hh_rm_iface.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. * */ @@ -121,6 +121,8 @@ hh_rm_vm_get_hyp_res(hh_vmid_t vmid, u32 *n_entries) /* The response payload should contain all the resource entries */ if (resp_payload_size < sizeof(*n_entries) || + (sizeof(*n_entries) > (U32_MAX - + (resp_payload->n_resource_entries * sizeof(*resp_entries)))) || resp_payload_size != sizeof(*n_entries) + (resp_payload->n_resource_entries * sizeof(*resp_entries))) { pr_err("%s: Invalid size received for GET_HYP_RESOURCES: %u\n", @@ -614,7 +616,7 @@ int hh_rm_console_write(hh_vmid_t vmid, const char *buf, size_t size) int reply_err_code = 0; size_t req_payload_size = sizeof(*req_payload) + size; - if (size < 1 || size > U32_MAX) + if (size < 1 || size > (U32_MAX - sizeof(*req_payload))) return -EINVAL; req_payload = kzalloc(req_payload_size, GFP_KERNEL); From da3af80859728733dc9d1ec8d25386bde508358b Mon Sep 17 00:00:00 2001 From: Guru Das Srinagesh Date: Tue, 24 Aug 2021 13:03:51 -0700 Subject: [PATCH 141/698] haven: hh_rm_core: Change datatype of num_fragments Integer overflow can occur for a large value of req_buff_size because num_fragments is declared as u8. Declare it as int in order to prevent this from occurring. Change-Id: I9e3655af13134ec57d123317ebb7b287a7470a19 Signed-off-by: Guru Das Srinagesh Signed-off-by: Swetha Chikkaboraiah --- drivers/virt/haven/hh_rm_core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/virt/haven/hh_rm_core.c b/drivers/virt/haven/hh_rm_core.c index eb5c9c56b83c..1e5a924c5c1b 100644 --- a/drivers/virt/haven/hh_rm_core.c +++ b/drivers/virt/haven/hh_rm_core.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2021, The Linux Foundation. All rights reserved. * */ @@ -485,7 +485,7 @@ static int hh_rm_send_request(u32 message_id, const void *req_buff_curr = req_buff; struct hh_rm_rpc_hdr *hdr; unsigned long tx_flags; - u8 num_fragments = 0; + u32 num_fragments = 0; size_t payload_size; void *send_buff; int i, ret; From d489add5c381a09648e1fc7556e4b248cf19947c Mon Sep 17 00:00:00 2001 From: Ram Prakash Gupta Date: Tue, 2 Nov 2021 19:47:09 +0530 Subject: [PATCH 142/698] Revert "scsi: ufs-qcom: Abort phy power on sequence if clks are off" This reverts commit 767358cd96f9854977e9b8d60210b011c7845762. Revert as this change causing cx pc failure. Change-Id: Ic2ee49b4420132dd7b118cd06689a875ff578928 Signed-off-by: Ram Prakash Gupta --- drivers/scsi/ufs/ufs-qcom.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c index 750ceed0abe8..eed1afec5275 100644 --- a/drivers/scsi/ufs/ufs-qcom.c +++ b/drivers/scsi/ufs/ufs-qcom.c @@ -494,16 +494,6 @@ static int ufs_qcom_phy_power_on(struct ufs_hba *hba) int ret = 0; mutex_lock(&host->phy_mutex); - if (hba->curr_dev_pwr_mode == UFS_POWERDOWN_PWR_MODE && - hba->clk_gating.state != CLKS_ON) { - ret = -1; - dev_err(hba->dev, "%s: abort phy power on, clks are off %d\n", - __func__, ret); - - mutex_unlock(&host->phy_mutex); - - return ret; - } if (!host->is_phy_pwr_on) { ret = phy_power_on(phy); if (ret) { From 3a8dd8c9aad7a92171fd47615097ed99b61f73e7 Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Fri, 3 Dec 2021 15:00:45 +0530 Subject: [PATCH 143/698] clk: qcom: gpucc-blair: Scale both cx and gx rails for gfx3d clock There is a requirement to scale both CX and GX rails during the gpu core clock scaling, thus add the corresponding vdd data. Change-Id: Ib27f4697a84ece1d0d1ce2b5297c03bf8ed955c6 Signed-off-by: Taniya Das --- drivers/clk/qcom/gpucc-blair.c | 20 +++++++++++++++++--- drivers/clk/qcom/vdd-level-holi.h | 13 +++++++++++++ 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/drivers/clk/qcom/gpucc-blair.c b/drivers/clk/qcom/gpucc-blair.c index c92a8c7bc6f2..51ce96715ca7 100644 --- a/drivers/clk/qcom/gpucc-blair.c +++ b/drivers/clk/qcom/gpucc-blair.c @@ -23,12 +23,10 @@ static DEFINE_VDD_REGULATORS(vdd_cx, VDD_HIGH_L1 + 1, 1, vdd_corner); static DEFINE_VDD_REGULATORS(vdd_mx, VDD_HIGH_L1 + 1, 1, vdd_corner); -static DEFINE_VDD_REGULATORS(vdd_gx, VDD_HIGH_L1 + 1, 1, vdd_corner); +static DEFINE_VDD_REGULATORS(vdd_gx, VDD_NUM, 2, vdd_gx_corner); static struct clk_vdd_class *gpu_cc_blair_regulators[] = { - &vdd_cx, &vdd_mx, - &vdd_gx, }; enum { @@ -468,6 +466,22 @@ static int gpu_cc_blair_probe(struct platform_device *pdev) struct regmap *regmap; int ret; + vdd_gx.regulator[0] = devm_regulator_get(&pdev->dev, "vdd_gx"); + if (IS_ERR(vdd_gx.regulator[0])) { + if (!(PTR_ERR(vdd_gx.regulator[0]) == -EPROBE_DEFER)) + dev_err(&pdev->dev, "Unable to get vdd_gx regulator\n"); + return PTR_ERR(vdd_gx.regulator[0]); + } + + vdd_gx.regulator[1] = devm_regulator_get(&pdev->dev, "vdd_cx"); + if (IS_ERR(vdd_gx.regulator[1])) { + if (!(PTR_ERR(vdd_gx.regulator[1]) == -EPROBE_DEFER)) + dev_err(&pdev->dev, "Unable to get vdd_cx regulator\n"); + return PTR_ERR(vdd_gx.regulator[1]); + } + + vdd_cx.regulator[0] = vdd_gx.regulator[1]; + regmap = qcom_cc_map(pdev, &gpu_cc_blair_desc); if (IS_ERR(regmap)) return PTR_ERR(regmap); diff --git a/drivers/clk/qcom/vdd-level-holi.h b/drivers/clk/qcom/vdd-level-holi.h index d37d307e45a1..356c6eaee427 100644 --- a/drivers/clk/qcom/vdd-level-holi.h +++ b/drivers/clk/qcom/vdd-level-holi.h @@ -32,4 +32,17 @@ static int vdd_corner[] = { [VDD_HIGH_L1] = RPM_SMD_REGULATOR_LEVEL_TURBO_NO_CPR, }; + +static int vdd_gx_corner[] = { + 0, 0, + RPM_SMD_REGULATOR_LEVEL_MIN_SVS, RPM_SMD_REGULATOR_LEVEL_MIN_SVS, + RPM_SMD_REGULATOR_LEVEL_LOW_SVS, RPM_SMD_REGULATOR_LEVEL_LOW_SVS, + RPM_SMD_REGULATOR_LEVEL_SVS, RPM_SMD_REGULATOR_LEVEL_SVS, + RPM_SMD_REGULATOR_LEVEL_SVS_PLUS, RPM_SMD_REGULATOR_LEVEL_SVS_PLUS, + RPM_SMD_REGULATOR_LEVEL_NOM, RPM_SMD_REGULATOR_LEVEL_NOM, + RPM_SMD_REGULATOR_LEVEL_NOM_PLUS, RPM_SMD_REGULATOR_LEVEL_NOM_PLUS, + RPM_SMD_REGULATOR_LEVEL_TURBO, RPM_SMD_REGULATOR_LEVEL_TURBO, + RPM_SMD_REGULATOR_LEVEL_TURBO_NO_CPR, RPM_SMD_REGULATOR_LEVEL_TURBO_NO_CPR, +}; + #endif From e3a4f428e005edb968bb9ee3793352f9a321f5e4 Mon Sep 17 00:00:00 2001 From: prabha Date: Thu, 25 Nov 2021 13:09:50 +0530 Subject: [PATCH 144/698] msm: adsprpc: Handle UAF in process shell memory Added flag to indicate memory used in process initialization. And, this memory would not removed in internal unmap to avoid UAF or double free. Change-Id: Ie470fe58ac334421d186feb41fa67bd24bb5efea Signed-off-by: prabha --- drivers/char/adsprpc.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c index 8c3103eb30a2..05cfe33e6987 100644 --- a/drivers/char/adsprpc.c +++ b/drivers/char/adsprpc.c @@ -573,6 +573,7 @@ struct fastrpc_mmap { bool in_use; /* Indicates if persistent map is in use*/ struct timespec64 map_start_time; struct timespec64 map_end_time; + bool is_filemap; /*flag to indicate map used in process init*/ }; enum fastrpc_perfkeys { @@ -1199,9 +1200,10 @@ static int fastrpc_mmap_remove(struct fastrpc_file *fl, int fd, uintptr_t va, spin_lock(&me->hlock); hlist_for_each_entry_safe(map, n, &me->maps, hn) { - if ((fd < 0 || map->fd == fd) && map->raddr == va && + if (map->refs == 1 && map->raddr == va && map->raddr + map->len == va + len && - map->refs == 1 && !map->is_persistent) { + /*Remove map if not used in process initialization*/ + !map->is_filemap) { match = map; hlist_del_init(&map->hn); break; @@ -1213,9 +1215,10 @@ static int fastrpc_mmap_remove(struct fastrpc_file *fl, int fd, uintptr_t va, return 0; } hlist_for_each_entry_safe(map, n, &fl->maps, hn) { - if ((fd < 0 || map->fd == fd) && map->raddr == va && + if (map->refs == 1 && map->raddr == va && map->raddr + map->len == va + len && - map->refs == 1) { + /*Remove map if not used in process initialization*/ + !map->is_filemap) { match = map; hlist_del_init(&map->hn); break; @@ -1399,6 +1402,7 @@ static int fastrpc_mmap_create(struct fastrpc_file *fl, int fd, map->fd = fd; map->attr = attr; map->frpc_md_index = -1; + map->is_filemap = false; ktime_get_real_ts64(&map->map_start_time); if (mflags == ADSP_MMAP_HEAP_ADDR || mflags == ADSP_MMAP_REMOTE_HEAP_ADDR) { @@ -3683,6 +3687,8 @@ static int fastrpc_init_create_dynamic_process(struct fastrpc_file *fl, mutex_lock(&fl->map_mutex); err = fastrpc_mmap_create(fl, init->filefd, 0, init->file, init->filelen, mflags, &file); + if (file) + file->is_filemap = true; mutex_unlock(&fl->map_mutex); if (err) goto bail; @@ -3904,6 +3910,8 @@ static int fastrpc_init_create_static_process(struct fastrpc_file *fl, mutex_lock(&fl->map_mutex); err = fastrpc_mmap_create(fl, -1, 0, init->mem, init->memlen, ADSP_MMAP_REMOTE_HEAP_ADDR, &mem); + if (mem) + mem->is_filemap = true; mutex_unlock(&fl->map_mutex); if (err) goto bail; From 869a11a9942c9b28e9e83bc8af819a9e40b30477 Mon Sep 17 00:00:00 2001 From: Sumukh Hallymysore Ravindra Date: Wed, 8 Sep 2021 13:43:05 +0530 Subject: [PATCH 145/698] msm: synx: Prevent accessing valid but released handles Release function removes the reference taken during create, but same release function can be invoked again to take away the valid reference held by other threads, which got these references before release was invoked the first time. This could lead to successive release call/s taking away reference held by other threads leading to UAF. Change adds another member variable to fail release function even though it is still valid, if the rel_count member has reached zero. rel_count variable is set to 1 during synx creation and decremented on release. All functions after release will fail, as per design and avoid taking away the reference of pending functions on same handle. Change-Id: Ie7ab279bc1e08e82c394b704e181716b726bcf4e Signed-off-by: Sumukh Hallymysore Ravindra --- drivers/media/platform/msm/synx/synx.c | 44 ++++++++++++------- .../media/platform/msm/synx/synx_private.h | 4 +- drivers/media/platform/msm/synx/synx_util.c | 4 ++ 3 files changed, 35 insertions(+), 17 deletions(-) diff --git a/drivers/media/platform/msm/synx/synx.c b/drivers/media/platform/msm/synx/synx.c index 4ab19050a39f..8043cc1489ed 100644 --- a/drivers/media/platform/msm/synx/synx.c +++ b/drivers/media/platform/msm/synx/synx.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. */ #define pr_fmt(fmt) "synx: " fmt @@ -681,9 +681,9 @@ EXPORT_SYMBOL(synx_merge); int synx_release(struct synx_session session_id, s32 h_synx) { int rc = 0; + u32 idx; struct synx_client *client; struct synx_handle_coredata *synx_data; - struct synx_coredata *synx_obj; pr_debug("[sess: %u] Enter release from pid %d\n", session_id.client_id, current->pid); @@ -692,21 +692,31 @@ int synx_release(struct synx_session session_id, s32 h_synx) if (!client) return -EINVAL; - synx_data = synx_util_acquire_handle(client, h_synx); - synx_obj = synx_util_obtain_object(synx_data); - /* no need to check for fence here */ - if (!synx_obj) { - pr_err("%s: [sess: %u] invalid handle access %d\n", - __func__, client->id, h_synx); - rc = -EINVAL; - goto fail; + synx_data = NULL; + idx = synx_util_handle_index(h_synx); + + mutex_lock(&client->synx_table_lock[idx]); + synx_data = &client->synx_table[idx]; + if (!synx_data->synx_obj) { + pr_err("[sess: %u] invalid object handle %d\n", + client->id, h_synx); + } else if (synx_data->handle != h_synx) { + pr_err("[sess: %u] stale object handle %d\n", + client->id, h_synx); + } else if (synx_data->rel_count == 0) { + pr_err("[sess: %u] released object handle %d\n", + client->id, h_synx); + } else if (!kref_read(&synx_data->internal_refcount)) { + pr_err("[sess: %u] destroyed object handle %d\n", + client->id, h_synx); + } else { + synx_data->rel_count--; + /* release the reference obtained at synx creation */ + kref_put(&synx_data->internal_refcount, + synx_util_destroy_internal_handle); } + mutex_unlock(&client->synx_table_lock[idx]); - /* release the reference obtained at synx creation */ - synx_util_release_handle(synx_data); - -fail: - synx_util_release_handle(synx_data); synx_put_client(client); pr_debug("[sess: %u] exit release with status %d\n", session_id.client_id, rc); @@ -953,8 +963,10 @@ int synx_addrefcount(struct synx_session session_id, s32 h_synx, s32 count) idx = synx_util_handle_index(h_synx); mutex_lock(&client->synx_table_lock[idx]); /* acquire additional references to handle */ - while (count--) + while (count--) { + synx_data->rel_count++; kref_get(&synx_data->internal_refcount); + } mutex_unlock(&client->synx_table_lock[idx]); fail: diff --git a/drivers/media/platform/msm/synx/synx_private.h b/drivers/media/platform/msm/synx/synx_private.h index e8f5d8e3ba41..9ebc162ee88c 100644 --- a/drivers/media/platform/msm/synx/synx_private.h +++ b/drivers/media/platform/msm/synx/synx_private.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. */ #ifndef __SYNX_PRIVATE_H__ @@ -181,6 +181,7 @@ struct synx_device; * @import_refcount : References for external clients for import * @id : Synx object handle for the client * @key : Key for import authentication + * @rel_count : No of allowed release counts */ struct synx_handle_coredata { struct synx_client *client; @@ -189,6 +190,7 @@ struct synx_handle_coredata { struct kref import_refcount; u32 handle; u16 key; + u32 rel_count; }; /** diff --git a/drivers/media/platform/msm/synx/synx_util.c b/drivers/media/platform/msm/synx/synx_util.c index 3739f81a13d3..737351fadf60 100644 --- a/drivers/media/platform/msm/synx/synx_util.c +++ b/drivers/media/platform/msm/synx/synx_util.c @@ -231,6 +231,7 @@ int synx_util_init_handle(struct synx_client *client, synx_data->handle = h_synx; synx_data->synx_obj = synx_obj; kref_init(&synx_data->internal_refcount); + synx_data->rel_count = 1; mutex_unlock(&client->synx_table_lock[idx]); *new_synx = h_synx; @@ -570,6 +571,9 @@ struct synx_handle_coredata *synx_util_acquire_handle( } else if (synx_data->handle != h_synx) { pr_err("[sess: %u] stale object handle %d\n", client->id, h_synx); + } else if (synx_data->rel_count == 0) { + pr_err("[sess: %u] released object handle %d\n", + client->id, h_synx); } else if (!kref_read(&synx_data->internal_refcount)) { pr_err("[sess: %u] destroyed object handle %d\n", client->id, h_synx); From 6f4b3f625349d224aabbdbbb6ce2b6a80e76a74e Mon Sep 17 00:00:00 2001 From: Pratham Pratap Date: Tue, 14 Dec 2021 16:10:13 +0530 Subject: [PATCH 146/698] usb: dwc: Release wakeup source if vbus_active is cleared Commit 980a25b5c2b7 ("usb: dwc3: Dont release wakeup source during usb restart") introduced a check in dwc3_msm_suspend for in_restart before releasing the wakeup source to ensure that driver doesn't release the wakeup source if suspend is kicked while restart session was executing. Now consider a case where, due to some reason, erratic event is seen on the controller and restart session is kicked. While restart work was running, physical cable disconnect happened which will call suspend routine eventually but due to in_restart flag being set driver will not release the wakeup source and will end up consuming power even though cable got disconnected. Fix this by adding one more level of judgement of vbus_active to ensure that wakeup source is released when cable gets disconnected during restart usb work. Change-Id: Ie54618640d08c4f2e3f0dc1d38260e0aa2d309c2 Signed-off-by: Pratham Pratap Signed-off-by: Shreyas Narayan --- drivers/usb/dwc3/dwc3-msm.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c index 959700da4498..6ffec5079401 100644 --- a/drivers/usb/dwc3/dwc3-msm.c +++ b/drivers/usb/dwc3/dwc3-msm.c @@ -2324,6 +2324,10 @@ static void dwc3_restart_usb_work(struct work_struct *w) dwc->err_evt_seen = false; flush_delayed_work(&mdwc->sm_work); + + /* see comments in dwc3_msm_suspend */ + if(!mdwc->vbus_active) + pm_relax(mdwc->dev); } /* @@ -3375,6 +3379,12 @@ static int dwc3_msm_suspend(struct dwc3_msm *mdwc, bool force_power_collapse, dwc3_msm_update_bus_bw(mdwc, BUS_VOTE_NONE); + /* + * if in_restart is marked as true from restart work do not release the wakeup + * active source as it can lead the device to enter system suspend (if usb is + * the last holding the wakeup active source) ; if actual cable disconnect happens + * while in_restart is true wakeup active source will be released from restart work. + */ if (!mdwc->in_restart) { /* * release wakeup source with timeout to defer system suspend to From 8c7c517853f88c7f3b2c7a566512c9eb08a692fb Mon Sep 17 00:00:00 2001 From: Ashok Gummadidala Date: Wed, 8 Dec 2021 19:43:21 +0530 Subject: [PATCH 147/698] haven: hh_msgq: Use GFP_ATOMIC allocations in hh_msgq_alloc_entry() Commit 81d6b86bd96e ("haven: hh_msgq: Disallow multiple registrations with same label") makes the entire gh_msgq_alloc_entry() function a critical section by calling it with the gh_msgq_cap_list_lock spinlock held. It also changed the allocation flags of one of the three memory allocation operations from GFP_KERNEL to GFP_ATOMIC for this reason, leaving the other two intact. This sometimes leads to the following: [ 0.052850][ T1] BUG: sleeping function called from invalid context at mm/slab.h:557 [ 0.052852][ T1] in_atomic(): 1, irqs_disabled(): 0, non_block: 0, pid: 1, name: swapper/0 [ 0.052854][ T1] Preemption disabled at: [ 0.052861][ T1] [] gh_msgq_populate_cap_info+0x3c/0x26c [ 0.052864][ T1] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 5.10.43-debug-04611-g00783572e88c-dirty #1 [ 0.052866][ T1] Hardware name: Qualcomm Technologies, Inc. Waipio SVM MTP (DT) [ 0.052868][ T1] Call trace: [ 0.052873][ T1] dump_backtrace+0x0/0x20c [ 0.052875][ T1] show_stack+0x18/0x24 [ 0.052880][ T1] dump_stack_lvl+0xbc/0x134 [ 0.052883][ T1] ___might_sleep+0x16c/0x1c0 [ 0.052884][ T1] __might_sleep+0x50/0x88 [ 0.052887][ T1] __kmalloc_track_caller+0x6c/0x388 [ 0.052891][ T1] kvasprintf+0xa8/0x134 [ 0.052892][ T1] kasprintf+0x54/0x7c [ 0.052894][ T1] hh_msgq_alloc_entry+0x98/0x128 [ 0.052896][ T1] hh_msgq_populate_cap_info+0x74/0x26c [ 0.052897][ T1] hh_msgq_probe_direction+0x78/0xf0 [ 0.052899][ T1] hh_msgq_probe+0x4c/0xdc [ 0.052901][ T1] hh_rm_drv_probe+0x34/0x310 [ 0.052904][ T1] platform_drv_probe+0x3c/0x9c [ 0.052906][ T1] really_probe+0x11c/0x4c8 [ 0.052909][ T1] driver_probe_device+0x84/0xec [ 0.052911][ T1] device_driver_attach+0x4c/0x70 [ 0.052913][ T1] __driver_attach.llvm.3781602661191075997+0x40/0x154 [ 0.052915][ T1] bus_for_each_dev+0x7c/0xc8 [ 0.052917][ T1] bus_add_driver+0x110/0x20c [ 0.052919][ T1] driver_register+0x64/0x104 [ 0.052921][ T1] __platform_driver_register+0x44/0x50 [ 0.052926][ T1] __initstub__kmod_gh_rm_drv__334_1315_gh_rm_driver_init6+0x1c/0x28 [ 0.052928][ T1] do_one_initcall+0x50/0x29c [ 0.052931][ T1] do_initcall_level+0xa4/0x16c [ 0.052933][ T1] do_initcalls+0x60/0xa0 [ 0.052934][ T1] do_basic_setup+0x20/0x2c [ 0.052936][ T1] kernel_init_freeable+0x8c/0xdc [ 0.052939][ T1] kernel_init+0x14/0x110 [ 0.052941][ T1] ret_from_fork+0x10/0x30 Even though the error signature says "BUG:" it isn't really a kernel panic. It only dumps the stack and then carries on, courtesy CONFIG_DEBUG_ATOMIC_SLEEP. Change the remaining two memory allocation operations to use GFP_ATOMIC as well and thereby fix the appearance of this error message. Change-Id: If7f91e67541b1e925313eeb96f58cc4e2280dba2 Signed-off-by: Ashok Gummadidala --- drivers/virt/haven/hh_msgq.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/virt/haven/hh_msgq.c b/drivers/virt/haven/hh_msgq.c index 0f19aa8468af..fc945f681d16 100644 --- a/drivers/virt/haven/hh_msgq.c +++ b/drivers/virt/haven/hh_msgq.c @@ -561,14 +561,14 @@ static int __init hh_msgq_init(void) spin_lock_init(&cap_table_entry->rx_lock); spin_lock_init(&cap_table_entry->cap_entry_lock); - cap_table_entry->tx_irq_name = kasprintf(GFP_KERNEL, + cap_table_entry->tx_irq_name = kasprintf(GFP_ATOMIC, "hh_msgq_tx_%d", i); if (!cap_table_entry->tx_irq_name) { ret = -ENOMEM; goto err; } - cap_table_entry->rx_irq_name = kasprintf(GFP_KERNEL, + cap_table_entry->rx_irq_name = kasprintf(GFP_ATOMIC, "hh_msgq_rx_%d", i); if (!cap_table_entry->rx_irq_name) { ret = -ENOMEM; From 4ea176780518ce8392cb977a1980da82be0fa21c Mon Sep 17 00:00:00 2001 From: Mohammed Mirza Mandayappurath Manzoor Date: Tue, 18 Jan 2022 16:06:24 -0800 Subject: [PATCH 148/698] msm: kgsl: Zap performance counters across context switches Performance counter values need not be retained across contexts unless specifically requested for debug. Zap the counters by initialising perfcounter SRAM with 0's using GPU_RBBM_PERFCTR_SRAM_INIT_CMD. Add pm4 packets during context switches and add a KMD postamble packet to clear the counters during preemption. Do not enable perfcounter save and restore unless requested. Change-Id: I371779ce659c07a1cc664327f5ecdcf0374201d8 Signed-off-by: Mohammed Mirza Mandayappurath Manzoor Signed-off-by: Harshitha Sai Neelati --- drivers/gpu/msm/a6xx_reg.h | 3 ++ drivers/gpu/msm/adreno.h | 8 +++++ drivers/gpu/msm/adreno_a6xx_preempt.c | 44 ++++++++++++++++++++++++--- drivers/gpu/msm/adreno_iommu.c | 18 +++++++++++ drivers/gpu/msm/adreno_perfcounter.c | 7 +++-- drivers/gpu/msm/adreno_pm4types.h | 7 +++++ drivers/gpu/msm/adreno_ringbuffer.c | 3 +- 7 files changed, 83 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/msm/a6xx_reg.h b/drivers/gpu/msm/a6xx_reg.h index 9d16d09cb3d2..df52db8ac6d1 100644 --- a/drivers/gpu/msm/a6xx_reg.h +++ b/drivers/gpu/msm/a6xx_reg.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. */ #ifndef _A6XX_REG_H @@ -406,6 +407,8 @@ #define A6XX_RBBM_PERFCTR_RBBM_SEL_2 0x509 #define A6XX_RBBM_PERFCTR_RBBM_SEL_3 0x50A #define A6XX_RBBM_PERFCTR_GPU_BUSY_MASKED 0x50B +#define A6XX_RBBM_PERFCTR_SRAM_INIT_CMD 0x50e +#define A6XX_RBBM_PERFCTR_SRAM_INIT_STATUS 0x50f #define A6XX_RBBM_ISDB_CNT 0x533 #define A6XX_RBBM_NC_MODE_CNTL 0X534 diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h index e7dd6c18a6ad..ac685b24144b 100644 --- a/drivers/gpu/msm/adreno.h +++ b/drivers/gpu/msm/adreno.h @@ -16,6 +16,9 @@ #include "adreno_ringbuffer.h" #include "kgsl_sharedmem.h" +/* Index to preemption scratch buffer to store KMD postamble */ +#define KMD_POSTAMBLE_IDX 100 + /* ADRENO_DEVICE - Given a kgsl_device return the adreno device struct */ #define ADRENO_DEVICE(device) \ container_of(device, struct adreno_device, dev) @@ -232,6 +235,9 @@ struct adreno_gpudev; /* Time to allow preemption to complete (in ms) */ #define ADRENO_PREEMPT_TIMEOUT 10000 +#define PREEMPT_SCRATCH_ADDR(dev, id) \ + ((dev)->preempt.scratch->gpuaddr + (id * sizeof(u64))) + /** * enum adreno_preempt_states * ADRENO_PREEMPT_NONE: No preemption is scheduled @@ -261,6 +267,7 @@ enum adreno_preempt_states { * skipsaverestore: To skip saverestore during L1 preemption (for 6XX) * usesgmem: enable GMEM save/restore across preemption (for 6XX) * count: Track the number of preemptions triggered + * @postamble_len: Number of dwords in KMD postamble pm4 packet */ struct adreno_preemption { atomic_t state; @@ -271,6 +278,7 @@ struct adreno_preemption { bool skipsaverestore; bool usesgmem; unsigned int count; + u32 postamble_len; }; struct adreno_busy_data { diff --git a/drivers/gpu/msm/adreno_a6xx_preempt.c b/drivers/gpu/msm/adreno_a6xx_preempt.c index 49b082dd0e7c..f0c5cf5a4869 100644 --- a/drivers/gpu/msm/adreno_a6xx_preempt.c +++ b/drivers/gpu/msm/adreno_a6xx_preempt.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. */ #include "adreno.h" @@ -543,13 +544,24 @@ unsigned int a6xx_preemption_pre_ibsubmit( if (context) { struct adreno_context *drawctxt = ADRENO_CONTEXT(context); struct adreno_ringbuffer *rb = drawctxt->rb; - uint64_t dest = adreno_dev->preempt.scratch->gpuaddr - + (rb->id * sizeof(u64)); + uint64_t dest = PREEMPT_SCRATCH_ADDR(adreno_dev, rb->id); *cmds++ = cp_mem_packet(adreno_dev, CP_MEM_WRITE, 2, 2); cmds += cp_gpuaddr(adreno_dev, cmds, dest); *cmds++ = lower_32_bits(gpuaddr); *cmds++ = upper_32_bits(gpuaddr); + + /* Add a KMD post amble to clear the perf counters during preemption */ + if (!adreno_dev->perfcounter) { + u64 kmd_postamble_addr = + PREEMPT_SCRATCH_ADDR(adreno_dev, KMD_POSTAMBLE_IDX); + + *cmds++ = cp_type7_packet(CP_SET_AMBLE, 3); + *cmds++ = lower_32_bits(kmd_postamble_addr); + *cmds++ = upper_32_bits(kmd_postamble_addr); + *cmds++ = FIELD_PREP(GENMASK(22, 20), CP_KMD_AMBLE_TYPE) + | (FIELD_PREP(GENMASK(19, 0), adreno_dev->preempt.postamble_len)); + } } return (unsigned int) (cmds - cmds_orig); @@ -562,8 +574,7 @@ unsigned int a6xx_preemption_post_ibsubmit(struct adreno_device *adreno_dev, struct adreno_ringbuffer *rb = adreno_dev->cur_rb; if (rb) { - uint64_t dest = adreno_dev->preempt.scratch->gpuaddr - + (rb->id * sizeof(u64)); + uint64_t dest = PREEMPT_SCRATCH_ADDR(adreno_dev, adreno_dev->cur_rb->id); *cmds++ = cp_mem_packet(adreno_dev, CP_MEM_WRITE, 2, 2); cmds += cp_gpuaddr(adreno_dev, cmds, dest); @@ -721,6 +732,31 @@ int a6xx_preemption_init(struct adreno_device *adreno_dev) if (ret) return ret; + /* + * First 8 dwords of the preemption scratch buffer is used to store the address for CP + * to save/restore VPC data. Reserve 11 dwords in the preemption scratch buffer from + * index KMD_POSTAMBLE_IDX for KMD postamble pm4 packets + */ + if (!adreno_dev->perfcounter) { + u32 *postamble = preempt->scratch->hostptr + (KMD_POSTAMBLE_IDX * sizeof(u64)); + u32 count = 0; + + postamble[count++] = cp_type7_packet(CP_REG_RMW, 3); + postamble[count++] = A6XX_RBBM_PERFCTR_SRAM_INIT_CMD; + postamble[count++] = 0x0; + postamble[count++] = 0x1; + + postamble[count++] = cp_type7_packet(CP_WAIT_REG_MEM, 6); + postamble[count++] = 0x3; + postamble[count++] = A6XX_RBBM_PERFCTR_SRAM_INIT_STATUS; + postamble[count++] = 0x0; + postamble[count++] = 0x1; + postamble[count++] = 0x1; + postamble[count++] = 0x0; + + preempt->postamble_len = count; + } + set_bit(ADRENO_DEVICE_PREEMPTION, &adreno_dev->priv); return 0; } diff --git a/drivers/gpu/msm/adreno_iommu.c b/drivers/gpu/msm/adreno_iommu.c index 73e6016bf1d9..be88bafb12da 100644 --- a/drivers/gpu/msm/adreno_iommu.c +++ b/drivers/gpu/msm/adreno_iommu.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2002,2007-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -217,6 +218,12 @@ static unsigned int _adreno_iommu_set_pt_v2_a6xx(struct kgsl_device *device, struct adreno_device *adreno_dev = ADRENO_DEVICE(device); unsigned int *cmds = cmds_orig; + /* Clear performance counters during contect switches */ + if (!adreno_dev->perfcounter) { + *cmds++ = cp_type4_packet(A6XX_RBBM_PERFCTR_SRAM_INIT_CMD, 1); + *cmds++ = 0x1; + } + /* CP switches the pagetable and flushes the Caches */ *cmds++ = cp_packet(adreno_dev, CP_SMMU_TABLE_UPDATE, 4); *cmds++ = lower_32_bits(ttbr0); @@ -245,6 +252,17 @@ static unsigned int _adreno_iommu_set_pt_v2_a6xx(struct kgsl_device *device, *cmds++ = 0; } + /* Wait for performance counter clear to finish */ + if (!adreno_dev->perfcounter) { + *cmds++ = cp_type7_packet(CP_WAIT_REG_MEM, 6); + *cmds++ = 0x3; + *cmds++ = A6XX_RBBM_PERFCTR_SRAM_INIT_STATUS; + *cmds++ = 0x0; + *cmds++ = 0x1; + *cmds++ = 0x1; + *cmds++ = 0x0; + } + return cmds - cmds_orig; } diff --git a/drivers/gpu/msm/adreno_perfcounter.c b/drivers/gpu/msm/adreno_perfcounter.c index d0b0bd3a2846..49ff0356a065 100644 --- a/drivers/gpu/msm/adreno_perfcounter.c +++ b/drivers/gpu/msm/adreno_perfcounter.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2002,2007-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -72,7 +73,8 @@ void adreno_perfcounter_restore(struct adreno_device *adreno_dev) const struct adreno_perfcount_group *group; unsigned int counter, groupid; - if (counters == NULL) + /* Do not save/restore if not requested */ + if (counters == NULL || !adreno_dev->perfcounter) return; for (groupid = 0; groupid < counters->group_count; groupid++) { @@ -106,7 +108,8 @@ inline void adreno_perfcounter_save(struct adreno_device *adreno_dev) const struct adreno_perfcount_group *group; unsigned int counter, groupid; - if (counters == NULL) + /* Do not save/restore if not requested */ + if (counters == NULL || !adreno_dev->perfcounter) return; for (groupid = 0; groupid < counters->group_count; groupid++) { diff --git a/drivers/gpu/msm/adreno_pm4types.h b/drivers/gpu/msm/adreno_pm4types.h index b64492044400..deb54dcc6ccc 100644 --- a/drivers/gpu/msm/adreno_pm4types.h +++ b/drivers/gpu/msm/adreno_pm4types.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2002,2007-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. */ #ifndef __ADRENO_PM4TYPES_H #define __ADRENO_PM4TYPES_H @@ -47,6 +48,9 @@ /* switches SMMU pagetable, used on a5xx only */ #define CP_SMMU_TABLE_UPDATE 0x53 +/* Designate command streams to be executed before/after CP does state restore during preemption */ +#define CP_SET_AMBLE 0x55 + /* Set internal CP registers, used to indicate context save data addresses */ #define CP_SET_PSEUDO_REGISTER 0x56 @@ -157,6 +161,9 @@ #define CP_LOADSTATE_STATETYPE_SHIFT 0x00000000 #define CP_LOADSTATE_EXTSRCADDR_SHIFT 0x00000002 +/* Used to define amble type in SET_AMBLE packet to execute during preemption */ +#define CP_KMD_AMBLE_TYPE 3 + static inline uint pm4_calc_odd_parity_bit(uint val) { return (0x9669 >> (0xf & ((val) ^ diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c index 33e67cd0390a..0e25e7bfcf81 100644 --- a/drivers/gpu/msm/adreno_ringbuffer.c +++ b/drivers/gpu/msm/adreno_ringbuffer.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2002,2007-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -482,7 +483,7 @@ adreno_ringbuffer_addcmds(struct adreno_ringbuffer *rb, if (gpudev->preemption_pre_ibsubmit && adreno_is_preemption_enabled(adreno_dev)) - total_sizedwords += 27; + total_sizedwords += 31; if (gpudev->preemption_post_ibsubmit && adreno_is_preemption_enabled(adreno_dev)) From 46e7925ba7b337701926f335191abdc74d266c61 Mon Sep 17 00:00:00 2001 From: Sandeep Singh Date: Tue, 1 Mar 2022 14:23:52 +0530 Subject: [PATCH 149/698] icnss2: Add code to pass device configs to wlan driver Add code to pass device configs to wlan driver. Change-Id: I977fc564914f9fbdabc0004eff4c5c2f14a1fc7c Signed-off-by: Sandeep Singh --- drivers/soc/qcom/icnss2/main.c | 21 +++++++++++++++++++++ drivers/soc/qcom/icnss2/main.h | 1 + include/soc/qcom/icnss2.h | 5 +++++ 3 files changed, 27 insertions(+) diff --git a/drivers/soc/qcom/icnss2/main.c b/drivers/soc/qcom/icnss2/main.c index dc873a24e54f..462d4bb807d7 100644 --- a/drivers/soc/qcom/icnss2/main.c +++ b/drivers/soc/qcom/icnss2/main.c @@ -400,6 +400,17 @@ bool icnss_is_fw_down(void) } EXPORT_SYMBOL(icnss_is_fw_down); +unsigned long icnss_get_device_config(void) +{ + struct icnss_priv *priv = icnss_get_plat_priv(); + + if (!priv) + return 0; + + return priv->device_config; +} +EXPORT_SYMBOL(icnss_get_device_config); + bool icnss_is_rejuvenate(void) { if (!penv) @@ -3905,6 +3916,14 @@ static void icnss_init_control_params(struct icnss_priv *priv) } } +static void icnss_read_device_configs(struct icnss_priv *priv) +{ + if (of_property_read_bool(priv->pdev->dev.of_node, + "wlan-ipa-disabled")) { + set_bit(ICNSS_IPA_DISABLED, &priv->device_config); + } +} + static inline void icnss_get_smp2p_info(struct icnss_priv *priv) { @@ -4007,6 +4026,8 @@ static int icnss_probe(struct platform_device *pdev) icnss_init_control_params(priv); + icnss_read_device_configs(priv); + ret = icnss_resource_parse(priv); if (ret) goto out_reset_drvdata; diff --git a/drivers/soc/qcom/icnss2/main.h b/drivers/soc/qcom/icnss2/main.h index b75767a07af0..8ff61897b8a9 100644 --- a/drivers/soc/qcom/icnss2/main.h +++ b/drivers/soc/qcom/icnss2/main.h @@ -465,6 +465,7 @@ struct icnss_priv { struct icnss_dms_data dms; u8 use_nv_mac; u32 wlan_en_delay_ms; + unsigned long device_config; }; struct icnss_reg_info { diff --git a/include/soc/qcom/icnss2.h b/include/soc/qcom/icnss2.h index cca3a95be74a..19510f022e12 100644 --- a/include/soc/qcom/icnss2.h +++ b/include/soc/qcom/icnss2.h @@ -23,6 +23,10 @@ enum icnss_uevent { ICNSS_UEVENT_SMMU_FAULT, }; +enum icnss_device_config { + ICNSS_IPA_DISABLED, +}; + struct icnss_uevent_hang_data { void *hang_event_data; uint16_t hang_event_data_len; @@ -196,4 +200,5 @@ extern int icnss_prevent_l1(struct device *dev); extern void icnss_allow_l1(struct device *dev); extern int icnss_get_mhi_state(struct device *dev); extern int icnss_is_pci_ep_awake(struct device *dev); +extern unsigned long icnss_get_device_config(void); #endif /* _ICNSS_WLAN_H_ */ From caff0ca6ee00815360c27f9942655cdf1ba3f91d Mon Sep 17 00:00:00 2001 From: Ashish Chavan Date: Mon, 11 Apr 2022 15:56:24 +0530 Subject: [PATCH 150/698] power: smblite: Copyright update for smb5-lib.c copyright fix Change-Id: I831dfabcdbedf1fa2c45d5be4b1e22ebd28688d1 Signed-off-by: Ashish Chavan Signed-off-by: Shreyas Narayan --- drivers/power/supply/qcom/smb5-lib.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/power/supply/qcom/smb5-lib.c b/drivers/power/supply/qcom/smb5-lib.c index 4bfead753772..538bd7116830 100644 --- a/drivers/power/supply/qcom/smb5-lib.c +++ b/drivers/power/supply/qcom/smb5-lib.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2018-2022 The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. */ #include From 1b4be978220f60be0e5c809199904649300b711a Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (VMware)" Date: Tue, 13 Oct 2020 15:48:52 -0400 Subject: [PATCH 151/698] tracing: Check return value of __create_val_fields() before using its result After having a typo for writing a histogram trigger. Wrote: echo 'hist:key=pid:ts=common_timestamp.usec' > events/sched/sched_waking/trigger Instead of: echo 'hist:key=pid:ts=common_timestamp.usecs' > events/sched/sched_waking/trigger and the following crash happened: BUG: kernel NULL pointer dereference, address: 0000000000000008 #PF: supervisor read access in kernel mode #PF: error_code(0x0000) - not-present page PGD 0 P4D 0 Oops: 0000 [#1] PREEMPT SMP PTI CPU: 4 PID: 1641 Comm: sh Not tainted 5.9.0-rc5-test+ #549 Hardware name: Hewlett-Packard HP Compaq Pro 6300 SFF/339A, BIOS K01 v03.03 07/14/2016 RIP: 0010:event_hist_trigger_func+0x70b/0x1ee0 Code: 24 08 89 d5 49 89 cc e9 8c 00 00 00 4c 89 f2 41 b9 00 10 00 00 4c 89 e1 44 89 ee 4c 89 ff e8 dc d3 ff ff 45 89 ea 4b 8b 14 d7 42 08 04 74 17 41 8b 8f c0 00 00 00 8d 71 01 41 89 b7 c0 00 00 RSP: 0018:ffff959213d53db0 EFLAGS: 00010202 RAX: ffffffffffffffea RBX: 0000000000000000 RCX: 0000000000084c04 RDX: 0000000000000000 RSI: df7326aefebd174c RDI: 0000000000031080 RBP: 0000000000000002 R08: 0000000000000001 R09: 0000000000000001 R10: 0000000000000001 R11: 0000000000000046 R12: ffff959211dcf690 R13: 0000000000000001 R14: ffff95925a36e370 R15: ffff959251c89800 FS: 00007fb9ea934740(0000) GS:ffff95925ab00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000000000000008 CR3: 00000000c976c005 CR4: 00000000001706e0 Call Trace: ? trigger_process_regex+0x78/0x110 trigger_process_regex+0xc5/0x110 event_trigger_write+0x71/0xd0 vfs_write+0xca/0x210 ksys_write+0x70/0xf0 do_syscall_64+0x33/0x40 entry_SYSCALL_64_after_hwframe+0x44/0xa9 RIP: 0033:0x7fb9eaa29487 Code: 64 89 02 48 c7 c0 ff ff ff ff eb bb 0f 1f 80 00 00 00 00 f3 0f 1e fa 64 8b 04 25 18 00 00 00 85 c0 75 10 b8 01 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 51 c3 48 83 ec 28 48 89 54 24 18 48 89 74 24 This was caused by accessing the hlist_data fields after the call to __create_val_fields() without checking if the creation succeed. Link: https://lkml.kernel.org/r/20201013154852.3abd8702@gandalf.local.home Change-Id: I5c9f3561f724aceea24a7ef43dcc50c7e79bf8ff Fixes: 63a1e5de3006 ("tracing: Save normal string variables") Reviewed-by: Masami Hiramatsu Reviewed-by: Tom Zanussi Signed-off-by: Steven Rostedt (VMware) Git-commit: 6d9bd139455d9d40fec8c242985996468b34180c Git-repo: https://android.googlesource.com/kernel/common/ Signed-off-by: Srinivasarao Pathipati --- kernel/trace/trace_events_hist.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c index 2b95fed0b543..9433c7faf877 100644 --- a/kernel/trace/trace_events_hist.c +++ b/kernel/trace/trace_events_hist.c @@ -4638,7 +4638,7 @@ static int create_var_field(struct hist_trigger_data *hist_data, ret = __create_val_field(hist_data, val_idx, file, var_name, expr_str, flags); - if (hist_data->fields[val_idx]->flags & HIST_FIELD_FL_STRING) + if (!ret && hist_data->fields[val_idx]->flags & HIST_FIELD_FL_STRING) hist_data->fields[val_idx]->var_str_idx = hist_data->n_var_str++; return ret; From c2bcd255b85fc115709363afee360ea8ad3cac1c Mon Sep 17 00:00:00 2001 From: ravnar Date: Wed, 20 Apr 2022 19:51:19 +0530 Subject: [PATCH 152/698] msm: kgsl: Remove 'fd' dependency to get dma_buf handle Get the dma_buf handle directly from 'vm_file' after doing necessary checks on the file. Change-Id: Id5eec16588d64e4e28483b32bb52d4d3d9b86b99 Signed-off-by: ravnar Signed-off-by: Sanjay Yadav --- drivers/gpu/msm/kgsl.c | 24 ++++-------------------- 1 file changed, 4 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c index f7cafa94a50e..7044d7f1520a 100644 --- a/drivers/gpu/msm/kgsl.c +++ b/drivers/gpu/msm/kgsl.c @@ -2583,15 +2583,6 @@ static int kgsl_setup_anon_useraddr(struct kgsl_pagetable *pagetable, } #ifdef CONFIG_DMA_SHARED_BUFFER -static int match_file(const void *p, struct file *file, unsigned int fd) -{ - /* - * We must return fd + 1 because iterate_fd stops searching on - * non-zero return, but 0 is a valid fd. - */ - return (p == file) ? (fd + 1) : 0; -} - static void _setup_cache_mode(struct kgsl_mem_entry *entry, struct vm_area_struct *vma) { @@ -2628,8 +2619,6 @@ static int kgsl_setup_dmabuf_useraddr(struct kgsl_device *device, vma = find_vma(current->mm, hostptr); if (vma && vma->vm_file) { - int fd; - ret = check_vma_flags(vma, entry->memdesc.flags); if (ret) { up_read(¤t->mm->mmap_sem); @@ -2645,15 +2634,10 @@ static int kgsl_setup_dmabuf_useraddr(struct kgsl_device *device, return -EFAULT; } - /* Look for the fd that matches this the vma file */ - fd = iterate_fd(current->files, 0, match_file, vma->vm_file); - if (fd != 0) { - dmabuf = dma_buf_get(fd - 1); - if (IS_ERR(dmabuf)) { - up_read(¤t->mm->mmap_sem); - return PTR_ERR(dmabuf); - } - } + /* Take a refcount because dma_buf_put() decrements the refcount */ + get_file(vma->vm_file); + + dmabuf = vma->vm_file->private_data; } if (!dmabuf) { From a82dff5bf711b6e620325b63edec92afbfecb778 Mon Sep 17 00:00:00 2001 From: Rohan Sethi Date: Mon, 22 Nov 2021 14:23:30 +0530 Subject: [PATCH 153/698] msm: kgsl: Fix gpuaddr_in_range() to check upper bound Currently gpuaddr_in_range() accepts only the gpuaddr & returns true if it lies in valid range. But this does not mean that the entire buffer is within range. Modify the function to accept size as a parameter and check that both starting & ending points of buffer lie within mmu range. Change-Id: I1d722295b9a27e746bfdb6d3bf409ffe722193cb Signed-off-by: Rohan Sethi --- drivers/gpu/msm/adreno_dispatch.c | 4 ++-- drivers/gpu/msm/adreno_hwsched.c | 3 ++- drivers/gpu/msm/kgsl.c | 4 ++-- drivers/gpu/msm/kgsl_iommu.c | 8 ++++---- drivers/gpu/msm/kgsl_mmu.c | 6 +++--- drivers/gpu/msm/kgsl_mmu.h | 7 ++++--- 6 files changed, 17 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/msm/adreno_dispatch.c b/drivers/gpu/msm/adreno_dispatch.c index 5177e74acc10..823a382b56b4 100644 --- a/drivers/gpu/msm/adreno_dispatch.c +++ b/drivers/gpu/msm/adreno_dispatch.c @@ -1125,8 +1125,8 @@ static inline bool _verify_ib(struct kgsl_device_private *dev_priv, } /* Make sure that the address is in range and dword aligned */ - if (!kgsl_mmu_gpuaddr_in_range(private->pagetable, ib->gpuaddr) || - !IS_ALIGNED(ib->gpuaddr, 4)) { + if (!kgsl_mmu_gpuaddr_in_range(private->pagetable, ib->gpuaddr, + ib->size) || !IS_ALIGNED(ib->gpuaddr, 4)) { pr_context(device, context, "ctxt %d invalid ib gpuaddr %llX\n", context->id, ib->gpuaddr); return false; diff --git a/drivers/gpu/msm/adreno_hwsched.c b/drivers/gpu/msm/adreno_hwsched.c index 6eb466919833..085c003e0bcd 100644 --- a/drivers/gpu/msm/adreno_hwsched.c +++ b/drivers/gpu/msm/adreno_hwsched.c @@ -657,7 +657,8 @@ static inline bool _verify_ib(struct kgsl_device_private *dev_priv, } /* Make sure that the address is mapped */ - if (!kgsl_mmu_gpuaddr_in_range(private->pagetable, ib->gpuaddr)) { + if (!kgsl_mmu_gpuaddr_in_range(private->pagetable, ib->gpuaddr, + ib->size)) { pr_context(device, context, "ctxt %d invalid ib gpuaddr %llX\n", context->id, ib->gpuaddr); return false; diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c index 7044d7f1520a..196b6ed7fd92 100644 --- a/drivers/gpu/msm/kgsl.c +++ b/drivers/gpu/msm/kgsl.c @@ -1302,9 +1302,9 @@ kgsl_sharedmem_find(struct kgsl_process_private *private, uint64_t gpuaddr) if (!private) return NULL; - if (!kgsl_mmu_gpuaddr_in_range(private->pagetable, gpuaddr) && + if (!kgsl_mmu_gpuaddr_in_range(private->pagetable, gpuaddr, 0) && !kgsl_mmu_gpuaddr_in_range( - private->pagetable->mmu->securepagetable, gpuaddr)) + private->pagetable->mmu->securepagetable, gpuaddr, 0)) return NULL; spin_lock(&private->mem_lock); diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c index 0a16898be6e2..fc75683dd210 100644 --- a/drivers/gpu/msm/kgsl_iommu.c +++ b/drivers/gpu/msm/kgsl_iommu.c @@ -2287,20 +2287,20 @@ static int kgsl_iommu_svm_range(struct kgsl_pagetable *pagetable, } static bool kgsl_iommu_addr_in_range(struct kgsl_pagetable *pagetable, - uint64_t gpuaddr) + uint64_t gpuaddr, uint64_t size) { struct kgsl_iommu_pt *pt = pagetable->priv; if (gpuaddr == 0) return false; - if (gpuaddr >= pt->va_start && gpuaddr < pt->va_end) + if (gpuaddr >= pt->va_start && (gpuaddr + size) < pt->va_end) return true; - if (gpuaddr >= pt->compat_va_start && gpuaddr < pt->compat_va_end) + if (gpuaddr >= pt->compat_va_start && (gpuaddr + size) < pt->compat_va_end) return true; - if (gpuaddr >= pt->svm_start && gpuaddr < pt->svm_end) + if (gpuaddr >= pt->svm_start && (gpuaddr + size) < pt->svm_end) return true; return false; diff --git a/drivers/gpu/msm/kgsl_mmu.c b/drivers/gpu/msm/kgsl_mmu.c index 090a028b3c6f..2633b72f18f7 100644 --- a/drivers/gpu/msm/kgsl_mmu.c +++ b/drivers/gpu/msm/kgsl_mmu.c @@ -529,10 +529,10 @@ enum kgsl_mmutype kgsl_mmu_get_mmutype(struct kgsl_device *device) } bool kgsl_mmu_gpuaddr_in_range(struct kgsl_pagetable *pagetable, - uint64_t gpuaddr) + uint64_t gpuaddr, uint64_t size) { if (PT_OP_VALID(pagetable, addr_in_range)) - return pagetable->pt_ops->addr_in_range(pagetable, gpuaddr); + return pagetable->pt_ops->addr_in_range(pagetable, gpuaddr, size); return false; } @@ -544,7 +544,7 @@ bool kgsl_mmu_gpuaddr_in_range(struct kgsl_pagetable *pagetable, */ static bool nommu_gpuaddr_in_range(struct kgsl_pagetable *pagetable, - uint64_t gpuaddr) + uint64_t gpuaddr, uint64_t size) { return (gpuaddr != 0) ? true : false; } diff --git a/drivers/gpu/msm/kgsl_mmu.h b/drivers/gpu/msm/kgsl_mmu.h index c1bcba4c666f..49d16d7e5491 100644 --- a/drivers/gpu/msm/kgsl_mmu.h +++ b/drivers/gpu/msm/kgsl_mmu.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2002,2007-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2002,2007-2021, The Linux Foundation. All rights reserved. */ #ifndef __KGSL_MMU_H #define __KGSL_MMU_H @@ -92,7 +92,7 @@ struct kgsl_mmu_pt_ops { int (*svm_range)(struct kgsl_pagetable *pt, uint64_t *lo, uint64_t *hi, uint64_t memflags); bool (*addr_in_range)(struct kgsl_pagetable *pagetable, - uint64_t gpuaddr); + uint64_t gpuaddr, uint64_t size); }; enum kgsl_mmu_feature { @@ -174,7 +174,8 @@ void kgsl_mmu_put_gpuaddr(struct kgsl_memdesc *memdesc); unsigned int kgsl_virtaddr_to_physaddr(void *virtaddr); unsigned int kgsl_mmu_log_fault_addr(struct kgsl_mmu *mmu, u64 ttbr0, uint64_t addr); -bool kgsl_mmu_gpuaddr_in_range(struct kgsl_pagetable *pt, uint64_t gpuaddr); +bool kgsl_mmu_gpuaddr_in_range(struct kgsl_pagetable *pt, uint64_t gpuaddr, + uint64_t size); int kgsl_mmu_get_region(struct kgsl_pagetable *pagetable, uint64_t gpuaddr, uint64_t size); From 0dd8b0fb2a6126aa0878bd2055bf07be1fd9c7ce Mon Sep 17 00:00:00 2001 From: Anil Veshala Veshala Date: Sun, 20 Mar 2022 23:35:22 -0700 Subject: [PATCH 154/698] i2c: i2c-msm-geni: add rtl based changes When IO lines not in good state we are not doing cancel and abort for non-rtl SE's, due to this we are seeing unexpected errors from QUP. To solve this added changes like rtl based flag, to proceed further sequence for non-rtl based SE's.. Change-Id: Ib29b48c9e8abaa696c46e3ff67e2eff4126e7016 Signed-off-by: Anil Veshala Veshala --- drivers/i2c/busses/i2c-msm-geni.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/i2c/busses/i2c-msm-geni.c b/drivers/i2c/busses/i2c-msm-geni.c index bc99dae5a635..7c5f298db44f 100644 --- a/drivers/i2c/busses/i2c-msm-geni.c +++ b/drivers/i2c/busses/i2c-msm-geni.c @@ -991,8 +991,11 @@ static int geni_i2c_gsi_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], if ((geni_ios & 0x3) != 0x3) { //SCL:b'1, SDA:b'0 GENI_SE_DBG(gi2c->ipcl, true, gi2c->dev, "%s: IO lines not in good state\n", __func__); - gi2c->prev_cancel_pending = true; - goto geni_i2c_gsi_cancel_pending; + /* doing pending cancel only rtl based SE's */ + if (gi2c->is_i2c_rtl_based) { + gi2c->prev_cancel_pending = true; + goto geni_i2c_gsi_cancel_pending; + } } } geni_i2c_err_prep_sg: @@ -1200,8 +1203,11 @@ static int geni_i2c_xfer(struct i2c_adapter *adap, if ((geni_ios & 0x3) != 0x3) { //SCL:b'1, SDA:b'0 GENI_SE_DBG(gi2c->ipcl, true, gi2c->dev, "%s: IO lines not in good state\n", __func__); - gi2c->prev_cancel_pending = true; - goto geni_i2c_txn_ret; + /* doing pending cancel only rtl based SE's */ + if (gi2c->is_i2c_rtl_based) { + gi2c->prev_cancel_pending = true; + goto geni_i2c_txn_ret; + } } } From 81c311de26cfc795160fa617dd03a3e4170c2299 Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Fri, 20 May 2022 12:21:35 +0530 Subject: [PATCH 155/698] clk: qcom: gpucc: Update the frequency for GPU core clock for blair Add support for 700MHz for GPUCC core clock. Change-Id: Ieb1e5514df0c00f3c6d0eb3cf8d9baccd214ba07 Signed-off-by: Taniya Das --- drivers/clk/qcom/gpucc-blair.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/clk/qcom/gpucc-blair.c b/drivers/clk/qcom/gpucc-blair.c index 51ce96715ca7..8749c0c5fefd 100644 --- a/drivers/clk/qcom/gpucc-blair.c +++ b/drivers/clk/qcom/gpucc-blair.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -200,6 +201,7 @@ static const struct freq_tbl ftbl_gpu_cc_gx_gfx3d_clk_src[] = { F(390000000, P_GPU_CC_PLL0_OUT_EVEN, 2, 0, 0), F(490000000, P_GPU_CC_PLL0_OUT_EVEN, 2, 0, 0), F(650000000, P_GPU_CC_PLL0_OUT_EVEN, 2, 0, 0), + F(700000000, P_GPU_CC_PLL0_OUT_EVEN, 2, 0, 0), F(770000000, P_GPU_CC_PLL0_OUT_EVEN, 2, 0, 0), F(840000000, P_GPU_CC_PLL0_OUT_EVEN, 2, 0, 0), F(900000000, P_GPU_CC_PLL0_OUT_EVEN, 2, 0, 0), From ff05663a6a357ac28d051c5fb0d57f6f585a7899 Mon Sep 17 00:00:00 2001 From: Vamsi Krishna Gattupalli Date: Tue, 7 Jun 2022 11:06:20 +0530 Subject: [PATCH 156/698] msm: ADSPRPC: Restrict untrusted applications from attaching to GuestOS Untrusted application can attach to guestOS and staticPD if it can somehow make INIT IOCTL call with ATTACH flag. This is a potential security issue as the untrusted application can crash guestOS or staticPD. Restrict attach to guestOS or staticPD request if request is being made using non-secure device node. Change-Id: I322c7b242fd0baaf1c1bce2d83b992fecb0ca593 Acked-by: Ekansh Gupta Signed-off-by: Vamsi Krishna Gattupalli From fd5dcef72c29e45f05c09b8fa59d78a62f7d1650 Mon Sep 17 00:00:00 2001 From: Swathi K Date: Wed, 20 Jul 2022 14:52:26 +0530 Subject: [PATCH 157/698] msm: adsprpc: Handle out of bounds access Add check for channel ID in fastrpc_buf_alloc to fix out of bounds access. Change-Id: I92f2717edcc91c19309589ce7c11c91c8129b71a Signed-off-by: Swathi K --- drivers/char/adsprpc.c | 142 ++++++++++++++++++++++++++++++----------- 1 file changed, 106 insertions(+), 36 deletions(-) diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c index 5fdd69044425..2f15605506af 100644 --- a/drivers/char/adsprpc.c +++ b/drivers/char/adsprpc.c @@ -994,7 +994,7 @@ static int fastrpc_minidump_remove_region(struct fastrpc_mmap *map) static void fastrpc_buf_free(struct fastrpc_buf *buf, int cache) { struct fastrpc_file *fl = buf == NULL ? NULL : buf->fl; - int vmid, err = 0; + int vmid, err = 0, cid = -1; if (!fl) return; @@ -1033,7 +1033,16 @@ skip_buf_cache: goto bail; if (fl->sctx->smmu.cb) buf->phys &= ~((uint64_t)fl->sctx->smmu.cb << 32); - vmid = fl->apps->channel[fl->cid].vmid; + cid = fl->cid; + VERIFY(err, VALID_FASTRPC_CID(cid)); + if (err) { + err = -ECHRNG; + ADSPRPC_ERR( + "invalid channel 0x%zx set for session\n", + cid); + goto bail; + } + vmid = fl->apps->channel[cid].vmid; if (vmid) { int srcVM[2] = {VMID_HLOS, vmid}; int hyp_err = 0; @@ -1047,7 +1056,7 @@ skip_buf_cache: hyp_err, buf->phys, buf->size); } } - trace_fastrpc_dma_free(fl->cid, buf->phys, buf->size); + trace_fastrpc_dma_free(cid, buf->phys, buf->size); dma_free_attrs(fl->sctx->smmu.dev, buf->size, buf->virt, buf->phys, buf->dma_attr); } @@ -1301,7 +1310,7 @@ static void fastrpc_mmap_free(struct fastrpc_mmap *map, uint32_t flags) (dma_addr_t)map->phys, (unsigned long)map->attr); } } else if (map->flags == FASTRPC_DMAHANDLE_NOMAP) { - trace_fastrpc_dma_unmap(fl->cid, map->phys, map->size); + trace_fastrpc_dma_unmap(cid, map->phys, map->size); if (!IS_ERR_OR_NULL(map->table)) dma_buf_unmap_attachment(map->attach, map->table, DMA_BIDIRECTIONAL); @@ -1318,7 +1327,7 @@ static void fastrpc_mmap_free(struct fastrpc_mmap *map, uint32_t flags) else sess = fl->sctx; - vmid = fl->apps->channel[fl->cid].vmid; + vmid = fl->apps->channel[cid].vmid; if (vmid && map->phys) { int hyp_err = 0; int srcVM[2] = {VMID_HLOS, vmid}; @@ -1332,7 +1341,7 @@ static void fastrpc_mmap_free(struct fastrpc_mmap *map, uint32_t flags) hyp_err, map->phys, map->size); } } - trace_fastrpc_dma_unmap(fl->cid, map->phys, map->size); + trace_fastrpc_dma_unmap(cid, map->phys, map->size); if (!IS_ERR_OR_NULL(map->table)) dma_buf_unmap_attachment(map->attach, map->table, DMA_BIDIRECTIONAL); @@ -1386,6 +1395,11 @@ static int fastrpc_mmap_create(struct fastrpc_file *fl, int fd, int err = 0, vmid, sgl_index = 0; struct scatterlist *sgl = NULL; + if (!fl) { + err = -EBADF; + goto bail; + } + cid = fl->cid; VERIFY(err, cid >= ADSP_DOMAIN_ID && cid < NUM_CHANNELS); if (err) { err = -ECHRNG; @@ -1482,7 +1496,7 @@ static int fastrpc_mmap_create(struct fastrpc_file *fl, int fd, } map->phys = sg_dma_address(map->table->sgl); map->size = len; - trace_fastrpc_dma_map(fl->cid, fd, map->phys, map->size, + trace_fastrpc_dma_map(cid, fd, map->phys, map->size, len, mflags, map->attach->dma_map_attrs); } else { if (map->attr && (map->attr & FASTRPC_ATTR_KEEP_MAP)) { @@ -1588,7 +1602,7 @@ static int fastrpc_mmap_create(struct fastrpc_file *fl, int fd, } else { map->size = buf_page_size(len); } - trace_fastrpc_dma_map(fl->cid, fd, map->phys, map->size, + trace_fastrpc_dma_map(cid, fd, map->phys, map->size, len, mflags, map->attach->dma_map_attrs); VERIFY(err, map->size >= len && map->size < me->max_size_limit); @@ -1599,7 +1613,7 @@ static int fastrpc_mmap_create(struct fastrpc_file *fl, int fd, goto bail; } - vmid = fl->apps->channel[fl->cid].vmid; + vmid = fl->apps->channel[cid].vmid; if (vmid) { int srcVM[1] = {VMID_HLOS}; int destVM[2] = {VMID_HLOS, vmid}; @@ -1699,7 +1713,7 @@ static int fastrpc_buf_alloc(struct fastrpc_file *fl, size_t size, unsigned long dma_attr, uint32_t rflags, int buf_type, struct fastrpc_buf **obuf) { - int err = 0, vmid; + int err = 0, vmid, cid = -1; struct fastrpc_apps *me = &gfa; struct fastrpc_buf *buf = NULL; @@ -1716,6 +1730,13 @@ static int fastrpc_buf_alloc(struct fastrpc_file *fl, size_t size, err = -EBADR; goto bail; } + cid = fl->cid; + VERIFY(err, VALID_FASTRPC_CID(cid)); + if (err) { + err = -ECHRNG; + goto bail; + } + VERIFY(err, size > 0 && fl->sctx->smmu.dev); if (err) { err = (fl->sctx->smmu.dev == NULL) ? -ENODEV : err; @@ -1763,10 +1784,10 @@ static int fastrpc_buf_alloc(struct fastrpc_file *fl, size_t size, } if (fl->sctx->smmu.cb) buf->phys += ((uint64_t)fl->sctx->smmu.cb << 32); - trace_fastrpc_dma_alloc(fl->cid, buf->phys, size, + trace_fastrpc_dma_alloc(cid, buf->phys, size, dma_attr, (int)rflags); - vmid = fl->apps->channel[fl->cid].vmid; + vmid = fl->apps->channel[cid].vmid; if (vmid) { int srcVM[1] = {VMID_HLOS}; int destVM[2] = {VMID_HLOS, vmid}; @@ -2933,6 +2954,10 @@ static int fastrpc_invoke_send(struct smq_invoke_ctx *ctx, uint32_t sc = ctx->sc; int64_t ns = 0; + if (!fl) { + err = -EBADF; + goto bail; + } cid = fl->cid; VERIFY(err, cid >= ADSP_DOMAIN_ID && cid < NUM_CHANNELS); if (err) { @@ -2940,7 +2965,7 @@ static int fastrpc_invoke_send(struct smq_invoke_ctx *ctx, goto bail; } - channel_ctx = &fl->apps->channel[fl->cid]; + channel_ctx = &fl->apps->channel[cid]; mutex_lock(&channel_ctx->smd_mutex); msg->pid = fl->tgid; msg->tid = current->pid; @@ -2970,7 +2995,7 @@ static int fastrpc_invoke_send(struct smq_invoke_ctx *ctx, } err = rpmsg_send(channel_ctx->rpdev->ept, (void *)msg, sizeof(*msg)); mutex_unlock(&channel_ctx->rpmsg_mutex); - trace_fastrpc_rpmsg_send(fl->cid, (uint64_t)ctx, msg->invoke.header.ctx, + trace_fastrpc_rpmsg_send(cid, (uint64_t)ctx, msg->invoke.header.ctx, handle, sc, msg->invoke.page.addr, msg->invoke.page.size); ns = get_timestamp_in_ns(); fastrpc_update_txmsg_buf(channel_ctx, msg, err, ns); @@ -4109,21 +4134,29 @@ bail: static int fastrpc_send_cpuinfo_to_dsp(struct fastrpc_file *fl) { - int err = 0; + int err = 0, cid = -1; uint64_t cpuinfo = 0; struct fastrpc_apps *me = &gfa; struct fastrpc_ioctl_invoke_async ioctl; remote_arg_t ra[2]; - VERIFY(err, fl && fl->cid >= ADSP_DOMAIN_ID && fl->cid < NUM_CHANNELS); + if (!fl) { + err = -EBADF; + goto bail; + } + cid = fl->cid; + VERIFY(err, VALID_FASTRPC_CID(cid)); if (err) { err = -ECHRNG; + ADSPRPC_ERR( + "invalid channel 0x%zx set for session\n", + cid); goto bail; } - cpuinfo = me->channel[fl->cid].cpuinfo_todsp; + cpuinfo = me->channel[cid].cpuinfo_todsp; /* return success if already updated to remote processor */ - if (me->channel[fl->cid].cpuinfo_status) + if (me->channel[cid].cpuinfo_status) return 0; ra[0].buf.pv = (void *)&cpuinfo; @@ -4141,7 +4174,7 @@ static int fastrpc_send_cpuinfo_to_dsp(struct fastrpc_file *fl) err = fastrpc_internal_invoke(fl, FASTRPC_MODE_PARALLEL, KERNEL_MSG_WITH_ZERO_PID, &ioctl); if (!err) - me->channel[fl->cid].cpuinfo_status = true; + me->channel[cid].cpuinfo_status = true; bail: return err; } @@ -4256,12 +4289,17 @@ bail: static int fastrpc_release_current_dsp_process(struct fastrpc_file *fl) { - int err = 0; + int err = 0, cid = -1; struct fastrpc_ioctl_invoke_async ioctl; remote_arg_t ra[1]; int tgid = 0; - VERIFY(err, fl->cid >= ADSP_DOMAIN_ID && fl->cid < NUM_CHANNELS); + if (!fl) { + err = -EBADF; + goto bail; + } + cid = fl->cid; + VERIFY(err, VALID_FASTRPC_CID(cid)); if (err) { err = -ECHRNG; goto bail; @@ -4271,12 +4309,12 @@ static int fastrpc_release_current_dsp_process(struct fastrpc_file *fl) err = -EBADR; goto bail; } - VERIFY(err, fl->apps->channel[fl->cid].rpdev != NULL); + VERIFY(err, fl->apps->channel[cid].rpdev != NULL); if (err) { err = -ENODEV; goto bail; } - VERIFY(err, fl->apps->channel[fl->cid].issubsystemup == 1); + VERIFY(err, fl->apps->channel[cid].issubsystemup == 1); if (err) { err = -ECONNRESET; goto bail; @@ -4463,7 +4501,7 @@ static int fastrpc_mmap_on_dsp(struct fastrpc_file *fl, uint32_t flags, struct fastrpc_ioctl_invoke_async ioctl; struct fastrpc_apps *me = &gfa; struct smq_phy_page page; - int num = 1; + int num = 1, cid = -1; remote_arg_t ra[3]; int err = 0; struct { @@ -4476,6 +4514,11 @@ static int fastrpc_mmap_on_dsp(struct fastrpc_file *fl, uint32_t flags, uintptr_t vaddrout; } routargs; + if (!fl) { + err = -EBADF; + goto bail; + } + cid = fl->cid; inargs.pid = fl->tgid; inargs.vaddrin = (uintptr_t)va; inargs.flags = flags; @@ -4507,12 +4550,22 @@ static int fastrpc_mmap_on_dsp(struct fastrpc_file *fl, uint32_t flags, *raddr = (uintptr_t)routargs.vaddrout; if (err) goto bail; + if (flags == ADSP_MMAP_REMOTE_HEAP_ADDR) { + VERIFY(err, VALID_FASTRPC_CID(cid)); + if (err) { + err = -ECHRNG; + ADSPRPC_ERR( + "invalid channel 0x%zx set for session\n", + cid); + goto bail; + } + } if (flags == ADSP_MMAP_REMOTE_HEAP_ADDR - && me->channel[fl->cid].rhvm.vmid) { + && me->channel[cid].rhvm.vmid) { err = hyp_assign_phys(phys, (uint64_t)size, - hlosvm, 1, me->channel[fl->cid].rhvm.vmid, - me->channel[fl->cid].rhvm.vmperm, - me->channel[fl->cid].rhvm.vmcount); + hlosvm, 1, me->channel[cid].rhvm.vmid, + me->channel[cid].rhvm.vmperm, + me->channel[cid].rhvm.vmcount); if (err) { ADSPRPC_ERR( "rh hyp assign failed with %d for phys 0x%llx, size %zu\n", @@ -4535,7 +4588,7 @@ bail: static int fastrpc_munmap_on_dsp_rh(struct fastrpc_file *fl, uint64_t phys, size_t size, uint32_t flags) { - int err = 0; + int err = 0, cid = -1; struct fastrpc_apps *me = &gfa; int tgid = 0; int destVM[1] = {VMID_HLOS}; @@ -4549,8 +4602,20 @@ static int fastrpc_munmap_on_dsp_rh(struct fastrpc_file *fl, uint64_t phys, uint8_t skey; } routargs; - if (fl == NULL) + if (!fl) { + err = -EBADF; goto bail; + } + + cid = fl->cid; + VERIFY(err, VALID_FASTRPC_CID(cid)); + if (err) { + err = -ECHRNG; + ADSPRPC_ERR( + "invalid channel 0x%zx set for session\n", + cid); + goto bail; + } tgid = fl->tgid; ra[0].buf.pv = (void *)&tgid; ra[0].buf.len = sizeof(tgid); @@ -4672,6 +4737,10 @@ static int fastrpc_mmap_remove_pdr(struct fastrpc_file *fl) struct fastrpc_apps *me = &gfa; int session = 0, err = 0, cid = -1; + if (!fl) { + err = -EBADF; + goto bail; + } err = fastrpc_get_spd_session(fl->servloc_name, &session, &cid); if (err) @@ -4681,18 +4750,18 @@ static int fastrpc_mmap_remove_pdr(struct fastrpc_file *fl) err = -EBADR; goto bail; } - if (!me->channel[fl->cid].spd[session].ispdup) { + if (!me->channel[cid].spd[session].ispdup) { err = -ENOTCONN; goto bail; } - if (me->channel[fl->cid].spd[session].pdrcount != - me->channel[fl->cid].spd[session].prevpdrcount) { + if (me->channel[cid].spd[session].pdrcount != + me->channel[cid].spd[session].prevpdrcount) { err = fastrpc_mmap_remove_ssr(fl); if (err) ADSPRPC_WARN("failed to unmap remote heap (err %d)\n", err); - me->channel[fl->cid].spd[session].prevpdrcount = - me->channel[fl->cid].spd[session].pdrcount; + me->channel[cid].spd[session].prevpdrcount = + me->channel[cid].spd[session].pdrcount; } bail: return err; @@ -5239,7 +5308,7 @@ static int fastrpc_file_free(struct fastrpc_file *fl) struct hlist_node *n = NULL; struct fastrpc_mmap *map = NULL, *lmap = NULL; unsigned long flags; - int cid; + int cid = -1, err = 0; if (!fl) return 0; @@ -5298,6 +5367,7 @@ skip_dump_wait: } while (lmap); mutex_unlock(&fl->map_mutex); + VERIFY(err, VALID_FASTRPC_CID(cid)); if (fl->sctx) fastrpc_session_free(&fl->apps->channel[cid], fl->sctx); if (fl->secsctx) From f3f832a6595c346c67a38a9ecc2c356528f2448a Mon Sep 17 00:00:00 2001 From: Vijayanand Jitta Date: Tue, 10 May 2022 10:16:42 +0530 Subject: [PATCH 158/698] mem_buf: Validate n_acl_entries Validate n_acl_entries specified by the requesting VM. Limiting n_acl_entries to 1 for now based on the existing check in mem_buf_alloc(). Change-Id: I802219ada9ee9109d18a42b2a80539d1cbd4df64 Signed-off-by: Vijayanand Jitta --- drivers/soc/qcom/mem-buf.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/soc/qcom/mem-buf.c b/drivers/soc/qcom/mem-buf.c index 92bf52b7e7ce..5857e965f590 100644 --- a/drivers/soc/qcom/mem-buf.c +++ b/drivers/soc/qcom/mem-buf.c @@ -529,12 +529,19 @@ struct mem_buf_xfer_mem *mem_buf_prep_xfer_mem(void *req_msg) int ret; struct mem_buf_xfer_mem *xfer_mem; struct mem_buf_alloc_req *req = req_msg; - u32 nr_acl_entries = req->acl_desc.n_acl_entries; - size_t alloc_req_msg_size = offsetof(struct mem_buf_alloc_req, - acl_desc.acl_entries[nr_acl_entries]); - void *arb_payload = req_msg + alloc_req_msg_size; + u32 nr_acl_entries; + size_t alloc_req_msg_size; + void *arb_payload; void *mem_type_data; + nr_acl_entries = req->acl_desc.n_acl_entries; + if (nr_acl_entries != 1) + return ERR_PTR(-EINVAL); + + alloc_req_msg_size = offsetof(struct mem_buf_alloc_req, + acl_desc.acl_entries[nr_acl_entries]); + arb_payload = req_msg + alloc_req_msg_size; + xfer_mem = kzalloc(sizeof(*xfer_mem), GFP_KERNEL); if (!xfer_mem) return ERR_PTR(-ENOMEM); From cdfdc8d41b38af7cce2240c27b0bc6baa2694d5a Mon Sep 17 00:00:00 2001 From: Swathi K Date: Wed, 20 Jul 2022 14:52:26 +0530 Subject: [PATCH 159/698] msm: adsprpc: Handle out of bounds access Add check for channel ID in fastrpc_buf_alloc to fix out of bounds access. Change-Id: I3ef66957cee9b56a18121b1da5d9057aab7067f0 Signed-off-by: Swathi K --- drivers/char/adsprpc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c index 2f15605506af..0d80168a0164 100644 --- a/drivers/char/adsprpc.c +++ b/drivers/char/adsprpc.c @@ -118,6 +118,9 @@ #define GET_TABLE_IDX_FROM_CTXID(ctxid) \ ((ctxid & FASTRPC_CTX_TABLE_IDX_MASK) >> FASTRPC_CTX_TABLE_IDX_POS) +#define VALID_FASTRPC_CID(cid) \ + (cid >= ADSP_DOMAIN_ID && cid < NUM_CHANNELS) + /* Reserve few entries in context table for critical kernel and static RPC * calls to avoid user invocations from exhausting all entries. */ From 7d172e8502ad753336f901070612c1f088b5457f Mon Sep 17 00:00:00 2001 From: Gaurav Kashyap Date: Mon, 12 Sep 2022 11:28:15 +0530 Subject: [PATCH 160/698] qcedev: check num_fds during unmap check the num_fds passed into unmap buf ioctl, or else it can lead to an out of bounds access. Test: Build compilation. qcedev tests. Change-Id: I206ba01dfa989346ade769a0f68b372b21f84043 Signed-off-by: Gaurav Kashyap Signed-off-by: Pranav Lavhate --- drivers/crypto/msm/qcedev.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/crypto/msm/qcedev.c b/drivers/crypto/msm/qcedev.c index 6221510f7997..d81ce43e3fd6 100644 --- a/drivers/crypto/msm/qcedev.c +++ b/drivers/crypto/msm/qcedev.c @@ -1916,7 +1916,9 @@ long qcedev_ioctl(struct file *file, goto exit_free_qcedev_areq; } - if (map_buf.num_fds > QCEDEV_MAX_BUFFERS) { + if (map_buf.num_fds > ARRAY_SIZE(map_buf.fd)) { + pr_err("%s: err: num_fds = %d exceeds max value\n", + __func__, map_buf.num_fds); err = -EINVAL; goto exit_free_qcedev_areq; } @@ -1956,6 +1958,12 @@ long qcedev_ioctl(struct file *file, err = -EFAULT; goto exit_free_qcedev_areq; } + if (unmap_buf.num_fds > ARRAY_SIZE(unmap_buf.fd)) { + pr_err("%s: err: num_fds = %d exceeds max value\n", + __func__, unmap_buf.num_fds); + err = -EINVAL; + goto exit_free_qcedev_areq; + } for (i = 0; i < unmap_buf.num_fds; i++) { err = qcedev_check_and_unmap_buffer(handle, From 152438934cb0eaf7f98bb2605fcfb97e0875ef35 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 10 Jun 2022 16:12:27 +0100 Subject: [PATCH 161/698] arm64: mm: Don't invalidate FROM_DEVICE buffers at start of DMA transfer commit c50f11c6196f45c92ca48b16a5071615d4ae0572 upstream. Invalidating the buffer memory in arch_sync_dma_for_device() for FROM_DEVICE transfers When using the streaming DMA API to map a buffer prior to inbound non-coherent DMA (i.e. DMA_FROM_DEVICE), we invalidate any dirty CPU cachelines so that they will not be written back during the transfer and corrupt the buffer contents written by the DMA. This, however, poses two potential problems: (1) If the DMA transfer does not write to every byte in the buffer, then the unwritten bytes will contain stale data once the transfer has completed. (2) If the buffer has a virtual alias in userspace, then stale data may be visible via this alias during the period between performing the cache invalidation and the DMA writes landing in memory. Address both of these issues by cleaning (aka writing-back) the dirty lines in arch_sync_dma_for_device(DMA_FROM_DEVICE) instead of discarding them using invalidation. Change-Id: Ibfda7d1f68d11d76c7b603f083d8ee773a37cc22 Cc: Ard Biesheuvel Cc: Christoph Hellwig Cc: Robin Murphy Cc: Russell King Cc: Link: https://lore.kernel.org/r/20220606152150.GA31568@willie-the-truck Signed-off-by: Will Deacon Reviewed-by: Ard Biesheuvel Link: https://lore.kernel.org/r/20220610151228.4562-2-will@kernel.org Signed-off-by: Catalin Marinas Signed-off-by: Greg Kroah-Hartman Git-commit: 7b9c3bfbad2510478ac29221d2c40a09184ce6a1 Git-repo: https://android.googlesource.com/kernel/common/ Signed-off-by: Srinivasarao Pathipati --- arch/arm64/mm/cache.S | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/arm64/mm/cache.S b/arch/arm64/mm/cache.S index 0ee30f93b546..a3ac18c2ec24 100644 --- a/arch/arm64/mm/cache.S +++ b/arch/arm64/mm/cache.S @@ -301,8 +301,6 @@ ENDPIPROC(__dma_flush_area) * - dir - DMA direction */ ENTRY(__dma_map_area) - cmp w2, #DMA_FROM_DEVICE - b.eq __dma_inv_area b __dma_clean_area ENDPIPROC(__dma_map_area) From 675a1b7c2d4c6f68178f2cd2120f909ec3fe79f5 Mon Sep 17 00:00:00 2001 From: Charan Teja Kalla Date: Wed, 30 Nov 2022 16:32:58 +0530 Subject: [PATCH 162/698] ANDROID: arm64: mm: perform clean & invalidation in __dma_map_area commit c50f11c6196f ("arm64: mm: Don't invalidate FROM_DEVICE buffers at start of DMA transfer") break assumptions of some device drivers about invalidation that happens as part of __dma_map_area(DMA_FROM_DEVICE). An example include drivers using dmabuf API dma_buf_begin_cpu_access() and dma_buf_end_cpu_access() to achieve buffer invalidation. Fix this breakage by replacing clean with clean and invalidation in __dma_map_area() for DMA inbound case. Bug: 260978220 Change-Id: Id1a2750c2036de693cd52e8f7316f1d820b5a262 Fixes: c50f11c6196f ("arm64: mm: Don't invalidate FROM_DEVICE buffers at start of DMA transfer") Signed-off-by: Charan Teja Kalla Signed-off-by: Shiraz Hashim Signed-off-by: Prakash Gupta Signed-off-by: Pavankumar Kondeti Git-commit: cbbd7242818690f7d67825e96500c398c86f5044 Git-repo: https://android.googlesource.com/kernel/common/ Signed-off-by: Srinivasarao Pathipati --- arch/arm64/mm/cache.S | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/mm/cache.S b/arch/arm64/mm/cache.S index a3ac18c2ec24..26ffb0686a98 100644 --- a/arch/arm64/mm/cache.S +++ b/arch/arm64/mm/cache.S @@ -301,6 +301,8 @@ ENDPIPROC(__dma_flush_area) * - dir - DMA direction */ ENTRY(__dma_map_area) + cmp w2, #DMA_FROM_DEVICE + b.eq __dma_flush_area b __dma_clean_area ENDPIPROC(__dma_map_area) From a82d90ec884be88b33a1dd457564db3c16952639 Mon Sep 17 00:00:00 2001 From: Naman Padhiar Date: Thu, 24 Nov 2022 14:58:44 +0800 Subject: [PATCH 163/698] cnss2: Unregister host driver during PCI remove CNSS2 registers as both platform and PCI driver. PCI device can be removed via sysfs exposed by kernel during PCI device creation. When PCI device gets removed, CNSS PCI remove ops gets called. In cnss_pci_remove, unregister host driver and shutdown WLAN chip to cleanly remove PCI device. Change-Id: Ia60e8b69bda2b3bdd5990cb83f47c082d6667283 Signed-off-by: Naman Padhiar Signed-off-by: Yu Ouyang --- drivers/net/wireless/cnss2/pci.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/cnss2/pci.c b/drivers/net/wireless/cnss2/pci.c index 1428c2493d56..0ef5a462e437 100644 --- a/drivers/net/wireless/cnss2/pci.c +++ b/drivers/net/wireless/cnss2/pci.c @@ -3039,8 +3039,12 @@ int cnss_pci_register_driver_hdlr(struct cnss_pci_data *pci_priv, int cnss_pci_unregister_driver_hdlr(struct cnss_pci_data *pci_priv) { - struct cnss_plat_data *plat_priv = pci_priv->plat_priv; + struct cnss_plat_data *plat_priv; + if (!pci_priv) + return -EINVAL; + + plat_priv = pci_priv->plat_priv; set_bit(CNSS_DRIVER_UNLOADING, &plat_priv->driver_state); cnss_pci_dev_shutdown(pci_priv); pci_priv->driver_ops = NULL; @@ -5739,7 +5743,9 @@ static void cnss_pci_unregister_mhi(struct cnss_pci_data *pci_priv) mhi_unregister_mhi_controller(mhi_ctrl); cnss_pci_mhi_ipc_logging_deinit(pci_priv); kfree(mhi_ctrl->irq); + mhi_ctrl->irq = NULL; mhi_free_controller(mhi_ctrl); + pci_priv->mhi_ctrl = NULL; } static void cnss_pci_config_regs(struct cnss_pci_data *pci_priv) @@ -6118,6 +6124,7 @@ static void cnss_pci_remove(struct pci_dev *pci_dev) struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(&pci_dev->dev); + cnss_pci_unregister_driver_hdlr(pci_priv); cnss_pci_free_m3_mem(pci_priv); cnss_pci_free_fw_mem(pci_priv); cnss_pci_free_qdss_mem(pci_priv); From a88cf26b74ec29ea0e8706f4ee666fcfcf4be8c8 Mon Sep 17 00:00:00 2001 From: Akhil P Oommen Date: Tue, 28 Mar 2023 20:01:44 +0530 Subject: [PATCH 164/698] msm: kgsl: Keep postamble packets in a privileged buffer Postamble packets are executed in privileged mode by gpu. So we should keep them in a privileged scratch buffer to block userspace access. For targets with APRIV feature support, we can mark the preemption scratch buffer as privileged too to avoid similar issues in future. Change-Id: Ifda360dda251083f38dfde80ce1b5dc83daae902 Signed-off-by: Akhil P Oommen Signed-off-by: Kaushal Sanadhya --- drivers/gpu/msm/adreno.h | 5 +---- drivers/gpu/msm/adreno_a6xx_preempt.c | 17 +++++++++-------- drivers/gpu/msm/kgsl.h | 6 ++++++ 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h index ac685b24144b..ec29d1d40c36 100644 --- a/drivers/gpu/msm/adreno.h +++ b/drivers/gpu/msm/adreno.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2008-2021, The Linux Foundation. All rights reserved. - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved. */ #ifndef __ADRENO_H #define __ADRENO_H @@ -16,9 +16,6 @@ #include "adreno_ringbuffer.h" #include "kgsl_sharedmem.h" -/* Index to preemption scratch buffer to store KMD postamble */ -#define KMD_POSTAMBLE_IDX 100 - /* ADRENO_DEVICE - Given a kgsl_device return the adreno device struct */ #define ADRENO_DEVICE(device) \ container_of(device, struct adreno_device, dev) diff --git a/drivers/gpu/msm/adreno_a6xx_preempt.c b/drivers/gpu/msm/adreno_a6xx_preempt.c index f0c5cf5a4869..cc5b11d30c4b 100644 --- a/drivers/gpu/msm/adreno_a6xx_preempt.c +++ b/drivers/gpu/msm/adreno_a6xx_preempt.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved. */ #include "adreno.h" @@ -553,8 +553,7 @@ unsigned int a6xx_preemption_pre_ibsubmit( /* Add a KMD post amble to clear the perf counters during preemption */ if (!adreno_dev->perfcounter) { - u64 kmd_postamble_addr = - PREEMPT_SCRATCH_ADDR(adreno_dev, KMD_POSTAMBLE_IDX); + u64 kmd_postamble_addr = SCRATCH_POSTAMBLE_ADDR(KGSL_DEVICE(adreno_dev)); *cmds++ = cp_type7_packet(CP_SET_AMBLE, 3); *cmds++ = lower_32_bits(kmd_postamble_addr); @@ -695,6 +694,7 @@ static int a6xx_preemption_ringbuffer_init(struct adreno_device *adreno_dev, int a6xx_preemption_init(struct adreno_device *adreno_dev) { + u32 flags = ADRENO_FEATURE(adreno_dev, ADRENO_APRIV) ? KGSL_MEMDESC_PRIVILEGED : 0; struct kgsl_device *device = KGSL_DEVICE(adreno_dev); struct kgsl_iommu *iommu = KGSL_IOMMU_PRIV(device); struct adreno_preemption *preempt = &adreno_dev->preempt; @@ -717,7 +717,7 @@ int a6xx_preemption_init(struct adreno_device *adreno_dev) if (IS_ERR_OR_NULL(preempt->scratch)) { preempt->scratch = kgsl_allocate_global(device, PAGE_SIZE, - 0, 0, 0, "preempt_scratch"); + 0, 0, flags, "preempt_scratch"); if (IS_ERR(preempt->scratch)) return PTR_ERR(preempt->scratch); } @@ -733,12 +733,13 @@ int a6xx_preemption_init(struct adreno_device *adreno_dev) return ret; /* - * First 8 dwords of the preemption scratch buffer is used to store the address for CP - * to save/restore VPC data. Reserve 11 dwords in the preemption scratch buffer from - * index KMD_POSTAMBLE_IDX for KMD postamble pm4 packets + * First 28 dwords of the device scratch buffer are used to store shadow rb data. + * Reserve 11 dwords in the device scratch buffer from SCRATCH_POSTAMBLE_OFFSET for + * KMD postamble pm4 packets. This should be in *device->scratch* so that userspace + * cannot access it. */ if (!adreno_dev->perfcounter) { - u32 *postamble = preempt->scratch->hostptr + (KMD_POSTAMBLE_IDX * sizeof(u64)); + u32 *postamble = device->scratch->hostptr + SCRATCH_POSTAMBLE_OFFSET; u32 count = 0; postamble[count++] = cp_type7_packet(CP_REG_RMW, 3); diff --git a/drivers/gpu/msm/kgsl.h b/drivers/gpu/msm/kgsl.h index 69fdf288fa68..0f0721522574 100644 --- a/drivers/gpu/msm/kgsl.h +++ b/drivers/gpu/msm/kgsl.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2008-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. */ #ifndef __KGSL_H #define __KGSL_H @@ -71,6 +72,11 @@ #define SCRATCH_RPTR_GPU_ADDR(dev, id) \ ((dev)->scratch->gpuaddr + SCRATCH_RPTR_OFFSET(id)) +/* OFFSET to KMD postamble packets in scratch buffer */ +#define SCRATCH_POSTAMBLE_OFFSET (100 * sizeof(u64)) +#define SCRATCH_POSTAMBLE_ADDR(dev) \ + ((dev)->scratch->gpuaddr + SCRATCH_POSTAMBLE_OFFSET) + /* Timestamp window used to detect rollovers (half of integer range) */ #define KGSL_TIMESTAMP_WINDOW 0x80000000 From 93b2f8b573cf71bd79bb9b6a37a550278c9c4c3a Mon Sep 17 00:00:00 2001 From: Kamal Agrawal Date: Fri, 3 Feb 2023 15:05:04 +0530 Subject: [PATCH 165/698] msm: kgsl: Check user generated timestamp before queuing drawobjs In ioctls like kgsl_ioctl_submit_commands(), if both syncobj type and cmd/marker/sparseobj type are submitted, the syncobj is queued first followed by the other obj type. After syncobj is successfully queued, in case of failure in get_timestamp while queuing the other obj, both the command objs are destroyed. As sync obj is already queued, accessing this later would cause a crash. Compare the user generated timestamp with the drawctxt timestamp and return early in case of error. This avoids unnecessary queuing of drawobjs. Change-Id: Iedebd480bc18cd74d2f69d24a9dc1032fab01cdb Signed-off-by: Kamal Agrawal --- drivers/gpu/msm/adreno_hwsched.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/gpu/msm/adreno_hwsched.c b/drivers/gpu/msm/adreno_hwsched.c index 085c003e0bcd..6256b7adf086 100644 --- a/drivers/gpu/msm/adreno_hwsched.c +++ b/drivers/gpu/msm/adreno_hwsched.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. */ #include "adreno.h" @@ -903,6 +904,23 @@ int adreno_hwsched_queue_cmds(struct kgsl_device_private *dev_priv, user_ts = *timestamp; + /* + * If there is only one drawobj in the array and it is of + * type SYNCOBJ_TYPE, skip comparing user_ts as it can be 0 + */ + if (!(count == 1 && drawobj[0]->type == SYNCOBJ_TYPE) && + (drawctxt->base.flags & KGSL_CONTEXT_USER_GENERATED_TS)) { + /* + * User specified timestamps need to be greater than the last + * issued timestamp in the context + */ + if (timestamp_cmp(drawctxt->timestamp, user_ts) >= 0) { + spin_unlock(&drawctxt->lock); + kmem_cache_free(jobs_cache, job); + return -ERANGE; + } + } + for (i = 0; i < count; i++) { switch (drawobj[i]->type) { From ab0c5a1856c7bc48a9c949cfefd8031d03e8ee65 Mon Sep 17 00:00:00 2001 From: Srinivasarao Pathipati Date: Tue, 22 Aug 2023 13:34:47 +0530 Subject: [PATCH 166/698] ANDROID: ABI: Update allowed list for QCOM Leaf changes summary: 1 artifact changed Changed leaf types summary: 0 leaf type changed Removed/Changed/Added functions summary: 0 Removed, 0 Changed, 1 Added function Removed/Changed/Added variables summary: 0 Removed, 0 Changed, 0 Added variable 1 Added function: [A] 'function int sysfs_emit(char*, const char*, ...)'. Change-Id: Ia416ba522f9b7f8b4c163b56125bed0801dbe35e Signed-off-by: Srinivasarao Pathipati --- android/abi_gki_aarch64_e699d543bbc9.xml | 105 ++++++++++++++--------- android/abi_gki_aarch64_qcom | 1 + 2 files changed, 64 insertions(+), 42 deletions(-) diff --git a/android/abi_gki_aarch64_e699d543bbc9.xml b/android/abi_gki_aarch64_e699d543bbc9.xml index 46d059cb5e6a..edf9f12ab325 100644 --- a/android/abi_gki_aarch64_e699d543bbc9.xml +++ b/android/abi_gki_aarch64_e699d543bbc9.xml @@ -2392,6 +2392,7 @@ + @@ -68616,20 +68617,6 @@ - - - - - - - - - - - - - - @@ -68647,8 +68634,8 @@ - - + + @@ -68676,6 +68663,20 @@ + + + + + + + + + + + + + + @@ -68694,7 +68695,6 @@ - @@ -68706,21 +68706,21 @@ - + - + - + - + @@ -68755,99 +68755,99 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -69178,14 +69178,14 @@ - + - + - + @@ -128242,6 +128242,12 @@ + + + + + + @@ -135323,6 +135329,7 @@ + @@ -142280,6 +142287,20 @@ + + + + + + + + + + + + + + diff --git a/android/abi_gki_aarch64_qcom b/android/abi_gki_aarch64_qcom index cf708287f20d..1286f832bea1 100644 --- a/android/abi_gki_aarch64_qcom +++ b/android/abi_gki_aarch64_qcom @@ -2443,6 +2443,7 @@ sysfs_create_group sysfs_create_groups sysfs_create_link + sysfs_emit __sysfs_match_string sysfs_notify sysfs_remove_bin_file From e74921ac4137ba5d4e52300a49cf1c677b541a5a Mon Sep 17 00:00:00 2001 From: Mukesh Ojha Date: Fri, 7 Jan 2022 17:51:04 +0530 Subject: [PATCH 167/698] soc: qcom: socinfo: Add revision 16 support in socinfo structure Below are some new fields are getting updated in socinfo structure from bootloader under revision 16. e.g esku; nproduct_code; npartnamemap_offset; nnum_partname_mapping; Add the change in socinfo driver to accommodate this. Change-Id: I11b5182c15af32da61cddbf4bb45d5aef390135a Signed-off-by: Mukesh Ojha Signed-off-by: Srinivasarao Pathipati --- drivers/soc/qcom/socinfo.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c index 562f35ce68a4..511f08848720 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -167,6 +167,11 @@ static struct socinfo { __le32 ndefective_parts_array_offset; /* Version 15 */ __le32 nmodem_supported; + /* Version 16 */ + __le32 esku; + __le32 nproduct_code; + __le32 npartnamemap_offset; + __le32 nnum_partname_mapping; } *socinfo; /* sysfs attributes */ @@ -959,6 +964,7 @@ static void socinfo_populate_sysfs(struct qcom_socinfo *qcom_socinfo) int i = 0; switch (socinfo_format) { + case SOCINFO_VERSION(0, 16): case SOCINFO_VERSION(0, 15): msm_custom_socinfo_attrs[i++] = &dev_attr_nmodem_supported.attr; case SOCINFO_VERSION(0, 14): @@ -1200,6 +1206,29 @@ static void socinfo_print(void) socinfo->nmodem_supported); break; + case SOCINFO_VERSION(0, 16): + pr_info("v%u.%u, id=%u, ver=%u.%u, raw_id=%u, raw_ver=%u, hw_plat=%u, hw_plat_ver=%u\n accessory_chip=%u, hw_plat_subtype=%u, pmic_model=%u, pmic_die_revision=%u foundry_id=%u serial_number=%u num_pmics=%u chip_family=0x%x raw_device_family=0x%x raw_device_number=0x%x nproduct_id=0x%x num_clusters=0x%x ncluster_array_offset=0x%x num_defective_parts=0x%x ndefective_parts_array_offset=0x%x nmodem_supported=0x%x\n", + f_maj, f_min, socinfo->id, v_maj, v_min, + socinfo->raw_id, socinfo->raw_ver, + socinfo->hw_plat, + socinfo->plat_ver, + socinfo->accessory_chip, + socinfo->hw_plat_subtype, + socinfo->pmic_model, + socinfo->pmic_die_rev, + socinfo->foundry_id, + socinfo->serial_num, + socinfo->num_pmics, + socinfo->chip_family, + socinfo->raw_device_family, + socinfo->raw_device_num, + socinfo->nproduct_id, + socinfo->num_clusters, + socinfo->ncluster_array_offset, + socinfo->num_defective_parts, + socinfo->ndefective_parts_array_offset, + socinfo->nmodem_supported); + default: pr_err("Unknown format found: v%u.%u\n", f_maj, f_min); break; From f81d2d30c4007bb009b2e7d819608396b96b9b26 Mon Sep 17 00:00:00 2001 From: Mukesh Ojha Date: Wed, 19 Jan 2022 21:56:57 +0530 Subject: [PATCH 168/698] soc: qcom: socinfo: Add sku sysfs support Add the support to get the sku information from userspace. Change-Id: I39b60fcc430308cd75e67fa400ad9515b5ad4b65 Signed-off-by: Mukesh Ojha Signed-off-by: Srinivasarao Pathipati --- drivers/soc/qcom/socinfo.c | 112 ++++++++++++++++++++++++++++++++++++- 1 file changed, 110 insertions(+), 2 deletions(-) diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c index 511f08848720..fc369c48f6df 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -34,6 +34,7 @@ #define SMEM_IMAGE_VERSION_TABLE 469 static uint32_t socinfo_format; +static const char *sku; enum { HW_PLATFORM_UNKNOWN = 0, @@ -121,6 +122,51 @@ static const char * const hw_platform_subtype[] = { [PLATFORM_SUBTYPE_INVALID] = "Invalid", }; +enum { + /* External SKU */ + SKU_UNKNOWN = 0x0, + SKU_AA = 0x1, + SKU_AB = 0x2, + SKU_AC = 0x3, + SKU_AD = 0x4, + SKU_AE = 0x5, + SKU_AF = 0x6, + SKU_EXT_RESERVE, + + /* Internal SKU */ + SKU_Y0 = 0xf1, + SKU_Y1 = 0xf2, + SKU_Y2 = 0xf3, + SKU_Y3 = 0xf4, + SKU_Y4 = 0xf5, + SKU_Y5 = 0xf6, + SKU_Y6 = 0xf7, + SKU_Y7 = 0xf8, + SKU_INT_RESERVE, +}; + +static const char * const hw_platform_esku[] = { + [SKU_UNKNOWN] = "Unknown", + [SKU_AA] = "AA", + [SKU_AB] = "AB", + [SKU_AC] = "AC", + [SKU_AD] = "AD", + [SKU_AE] = "AE", + [SKU_AF] = "AF", +}; + +#define SKU_INT_MASK 0x0f +static const char * const hw_platform_isku[] = { + [SKU_Y0 & SKU_INT_MASK] = "Y0", + [SKU_Y1 & SKU_INT_MASK] = "Y1", + [SKU_Y2 & SKU_INT_MASK] = "Y2", + [SKU_Y3 & SKU_INT_MASK] = "Y3", + [SKU_Y4 & SKU_INT_MASK] = "Y4", + [SKU_Y5 & SKU_INT_MASK] = "Y5", + [SKU_Y6 & SKU_INT_MASK] = "Y6", + [SKU_Y7 & SKU_INT_MASK] = "Y7", +}; + /* Socinfo SMEM item structure */ static struct socinfo { __le32 fmt; @@ -367,6 +413,35 @@ static uint32_t socinfo_get_nmodem_supported(void) : 0; } +/* Version 16 */ +static uint32_t socinfo_get_eskuid(void) +{ + return socinfo ? + (socinfo_format >= SOCINFO_VERSION(0, 16) ? + le32_to_cpu(socinfo->esku) : 0) + : 0; +} + +static const char *socinfo_get_esku_mapping(void) +{ + uint32_t id = socinfo_get_eskuid(); + + if (id > SKU_UNKNOWN && id < SKU_EXT_RESERVE) + return hw_platform_esku[id]; + else if (id >= SKU_Y0 && id < SKU_INT_RESERVE) + return hw_platform_isku[id & SKU_INT_MASK]; + + return NULL; +} + +static uint32_t socinfo_get_nproduct_code(void) +{ + return socinfo ? + (socinfo_format >= SOCINFO_VERSION(0, 16) ? + le32_to_cpu(socinfo->nproduct_code) : 0) + : 0; +} + /* Version 2 */ static ssize_t msm_get_raw_id(struct device *dev, @@ -617,6 +692,27 @@ msm_get_nmodem_supported(struct device *dev, } ATTR_DEFINE(nmodem_supported); +/* Version 16 */ +static ssize_t +msm_get_sku(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return sysfs_emit(buf, "%s\n", sku ? sku : "Unknown"); +} +ATTR_DEFINE(sku); + +static ssize_t +msm_get_esku(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + const char *esku = socinfo_get_esku_mapping(); + + return sysfs_emit(buf, "%s\n", esku ? esku : "Unknown"); +} +ATTR_DEFINE(esku); + struct qcom_socinfo { struct soc_device *soc_dev; struct soc_device_attribute attr; @@ -965,6 +1061,8 @@ static void socinfo_populate_sysfs(struct qcom_socinfo *qcom_socinfo) switch (socinfo_format) { case SOCINFO_VERSION(0, 16): + msm_custom_socinfo_attrs[i++] = &dev_attr_sku.attr; + msm_custom_socinfo_attrs[i++] = &dev_attr_esku.attr; case SOCINFO_VERSION(0, 15): msm_custom_socinfo_attrs[i++] = &dev_attr_nmodem_supported.attr; case SOCINFO_VERSION(0, 14): @@ -1207,7 +1305,7 @@ static void socinfo_print(void) break; case SOCINFO_VERSION(0, 16): - pr_info("v%u.%u, id=%u, ver=%u.%u, raw_id=%u, raw_ver=%u, hw_plat=%u, hw_plat_ver=%u\n accessory_chip=%u, hw_plat_subtype=%u, pmic_model=%u, pmic_die_revision=%u foundry_id=%u serial_number=%u num_pmics=%u chip_family=0x%x raw_device_family=0x%x raw_device_number=0x%x nproduct_id=0x%x num_clusters=0x%x ncluster_array_offset=0x%x num_defective_parts=0x%x ndefective_parts_array_offset=0x%x nmodem_supported=0x%x\n", + pr_info("v%u.%u, id=%u, ver=%u.%u, raw_id=%u, raw_ver=%u, hw_plat=%u, hw_plat_ver=%u\n accessory_chip=%u, hw_plat_subtype=%u, pmic_model=%u, pmic_die_revision=%u foundry_id=%u serial_number=%u num_pmics=%u chip_family=0x%x raw_device_family=0x%x raw_device_number=0x%x nproduct_id=0x%x num_clusters=0x%x ncluster_array_offset=0x%x num_defective_parts=0x%x ndefective_parts_array_offset=0x%x nmodem_supported=0x%x sku=%s\n", f_maj, f_min, socinfo->id, v_maj, v_min, socinfo->raw_id, socinfo->raw_ver, socinfo->hw_plat, @@ -1227,7 +1325,8 @@ static void socinfo_print(void) socinfo->ncluster_array_offset, socinfo->num_defective_parts, socinfo->ndefective_parts_array_offset, - socinfo->nmodem_supported); + socinfo->nmodem_supported, + sku ? sku : "Unknown"); default: pr_err("Unknown format found: v%u.%u\n", f_maj, f_min); @@ -1266,6 +1365,7 @@ static int qcom_socinfo_probe(struct platform_device *pdev) struct qcom_socinfo *qs; struct socinfo *info; size_t item_size; + const char *machine, *esku; info = qcom_smem_get(QCOM_SMEM_HOST_ANY, SMEM_HW_SW_BUILD_ID, &item_size); @@ -1290,6 +1390,14 @@ static int qcom_socinfo_probe(struct platform_device *pdev) SOCINFO_MINOR(le32_to_cpu(info->ver))); qs->attr.soc_id = kasprintf(GFP_KERNEL, "%d", socinfo_get_id()); + if (socinfo_format >= SOCINFO_VERSION(0, 16)) { + machine = socinfo_machine(le32_to_cpu(info->id)); + esku = socinfo_get_esku_mapping(); + if (machine && esku) + sku = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%s-%u-%s", + machine, socinfo_get_nproduct_code(), esku); + } + qsocinfo = qs; init_rwsem(&qs->current_image_rwsem); socinfo_populate_sysfs(qs); From abe2d9a800a8eb099cd4d511f34faea91e532b29 Mon Sep 17 00:00:00 2001 From: Soumya Managoli Date: Wed, 27 Sep 2023 15:52:56 +0530 Subject: [PATCH 169/698] ALSA: compress: Allow pause and resume during draining With a stream with low bitrate, user can't pause or resume the stream near the end of the stream because current ALSA doesn't allow it. If the stream has very low bitrate enough to store whole stream into the buffer, user can't do anything except stop the stream and then restart it from the first because most of applications call draining after sending last frame to the kernel. If pause, resume are allowed during draining, user experience can be enhanced. To prevent malfunction in HW drivers which don't support pause during draining, pause during draining will only work if HW driver enable this feature explicitly by calling snd_compr_use_pause_in_draining(). Signed-off-by: Gyeongtaek Lee Acked-by: Vinod Koul Link: https://lore.kernel.org/r/000101d6c3f0$89b312b0$9d193810$@samsung.com Change-Id: I480caca000544c4033cdf2d445598e31754d8e5e Signed-off-by: Takashi Iwai Git-commit: 9be9f2d3d073ef42127475f4fb6a392ab133f629 Git-repo: https://android.googlesource.com/kernel/common/ [quic_c_smanag@quicinc.com: resolve trivial merge conflicts] Signed-off-by: Soumya Managoli --- include/sound/compress_driver.h | 22 ++++++++++++++++ sound/core/compress_offload.c | 45 +++++++++++++++++++++++++++------ 2 files changed, 59 insertions(+), 8 deletions(-) diff --git a/include/sound/compress_driver.h b/include/sound/compress_driver.h index e9a34ca60703..6dc3ca65cc50 100644 --- a/include/sound/compress_driver.h +++ b/include/sound/compress_driver.h @@ -59,6 +59,7 @@ struct snd_compr_runtime { * @direction: stream direction, playback/recording * @metadata_set: metadata set flag, true when set * @next_track: has userspace signal next track transition, true when set + * @pause_in_draining: paused during draining state, true when set * @private_data: pointer to DSP private data */ struct snd_compr_stream { @@ -70,6 +71,9 @@ struct snd_compr_stream { enum snd_compr_direction direction; bool metadata_set; bool next_track; +#ifndef CONFIG_AUDIO_QGKI + bool pause_in_draining; +#endif void *private_data; #ifdef CONFIG_AUDIO_QGKI struct snd_soc_pcm_runtime *be; @@ -140,6 +144,7 @@ struct snd_compr_ops { * @direction: Playback or capture direction * @lock: device lock * @device: device id + * @use_pause_in_draining: allow pause in draining, true when set */ struct snd_compr { const char *name; @@ -150,6 +155,9 @@ struct snd_compr { unsigned int direction; struct mutex lock; int device; +#ifndef CONFIG_AUDIO_QGKI + bool use_pause_in_draining; +#endif #ifdef CONFIG_SND_VERBOSE_PROCFS /* private: */ char id[64]; @@ -164,6 +172,20 @@ int snd_compress_deregister(struct snd_compr *device); int snd_compress_new(struct snd_card *card, int device, int type, const char *id, struct snd_compr *compr); +/** + * snd_compr_use_pause_in_draining - Allow pause and resume in draining state + * @substream: compress substream to set + * + * Allow pause and resume in draining state. + * Only HW driver supports this transition can call this API. + */ +#ifndef CONFIG_AUDIO_QGKI +static inline void snd_compr_use_pause_in_draining(struct snd_compr_stream *substream) +{ + substream->device->use_pause_in_draining = true; +} +#endif + /* dsp driver callback apis * For playback: driver should call snd_compress_fragment_elapsed() to let the * framework know that a fragment has been consumed from the ring buffer diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c index 4f3fb5ce4b31..c1c48207149f 100644 --- a/sound/core/compress_offload.c +++ b/sound/core/compress_offload.c @@ -698,11 +698,24 @@ static int snd_compr_pause(struct snd_compr_stream *stream) { int retval; - if (stream->runtime->state != SNDRV_PCM_STATE_RUNNING) + switch (stream->runtime->state) { + case SNDRV_PCM_STATE_RUNNING: + retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_PAUSE_PUSH); + if (!retval) + stream->runtime->state = SNDRV_PCM_STATE_PAUSED; + break; +#ifndef CONFIG_AUDIO_QGKI + case SNDRV_PCM_STATE_DRAINING: + if (!stream->device->use_pause_in_draining) + return -EPERM; + retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_PAUSE_PUSH); + if (!retval) + stream->pause_in_draining = true; + break; +#endif + default: return -EPERM; - retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_PAUSE_PUSH); - if (!retval) - stream->runtime->state = SNDRV_PCM_STATE_PAUSED; + } return retval; } @@ -710,11 +723,24 @@ static int snd_compr_resume(struct snd_compr_stream *stream) { int retval; - if (stream->runtime->state != SNDRV_PCM_STATE_PAUSED) + switch (stream->runtime->state) { + case SNDRV_PCM_STATE_PAUSED: + retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_PAUSE_RELEASE); + if (!retval) + stream->runtime->state = SNDRV_PCM_STATE_RUNNING; + break; +#ifndef CONFIG_AUDIO_QGKI + case SNDRV_PCM_STATE_DRAINING: + if (!stream->pause_in_draining) + return -EPERM; + retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_PAUSE_RELEASE); + if (!retval) + stream->pause_in_draining = false; + break; +#endif + default: return -EPERM; - retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_PAUSE_RELEASE); - if (!retval) - stream->runtime->state = SNDRV_PCM_STATE_RUNNING; + } return retval; } @@ -754,6 +780,9 @@ static int snd_compr_stop(struct snd_compr_stream *stream) retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_STOP); if (!retval) { +#ifndef CONFIG_AUDIO_QGKI + stream->pause_in_draining = false; +#endif snd_compr_drain_notify(stream); stream->runtime->total_bytes_available = 0; stream->runtime->total_bytes_transferred = 0; From 7f6c5cf98e1f9108d4988acac8f0590b09081a6b Mon Sep 17 00:00:00 2001 From: Marco Zhang Date: Mon, 30 Oct 2023 01:47:32 -0700 Subject: [PATCH 170/698] Revert "ALSA: compress: Allow pause and resume during draining" This reverts commit abe2d9a800a8eb099cd4d511f34faea91e532b29. Reason for revert: Change-Id: I13afb5d8e34c94bb82bb480b227f417d8fc04064 --- include/sound/compress_driver.h | 22 ---------------- sound/core/compress_offload.c | 45 ++++++--------------------------- 2 files changed, 8 insertions(+), 59 deletions(-) diff --git a/include/sound/compress_driver.h b/include/sound/compress_driver.h index 6dc3ca65cc50..e9a34ca60703 100644 --- a/include/sound/compress_driver.h +++ b/include/sound/compress_driver.h @@ -59,7 +59,6 @@ struct snd_compr_runtime { * @direction: stream direction, playback/recording * @metadata_set: metadata set flag, true when set * @next_track: has userspace signal next track transition, true when set - * @pause_in_draining: paused during draining state, true when set * @private_data: pointer to DSP private data */ struct snd_compr_stream { @@ -71,9 +70,6 @@ struct snd_compr_stream { enum snd_compr_direction direction; bool metadata_set; bool next_track; -#ifndef CONFIG_AUDIO_QGKI - bool pause_in_draining; -#endif void *private_data; #ifdef CONFIG_AUDIO_QGKI struct snd_soc_pcm_runtime *be; @@ -144,7 +140,6 @@ struct snd_compr_ops { * @direction: Playback or capture direction * @lock: device lock * @device: device id - * @use_pause_in_draining: allow pause in draining, true when set */ struct snd_compr { const char *name; @@ -155,9 +150,6 @@ struct snd_compr { unsigned int direction; struct mutex lock; int device; -#ifndef CONFIG_AUDIO_QGKI - bool use_pause_in_draining; -#endif #ifdef CONFIG_SND_VERBOSE_PROCFS /* private: */ char id[64]; @@ -172,20 +164,6 @@ int snd_compress_deregister(struct snd_compr *device); int snd_compress_new(struct snd_card *card, int device, int type, const char *id, struct snd_compr *compr); -/** - * snd_compr_use_pause_in_draining - Allow pause and resume in draining state - * @substream: compress substream to set - * - * Allow pause and resume in draining state. - * Only HW driver supports this transition can call this API. - */ -#ifndef CONFIG_AUDIO_QGKI -static inline void snd_compr_use_pause_in_draining(struct snd_compr_stream *substream) -{ - substream->device->use_pause_in_draining = true; -} -#endif - /* dsp driver callback apis * For playback: driver should call snd_compress_fragment_elapsed() to let the * framework know that a fragment has been consumed from the ring buffer diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c index c1c48207149f..4f3fb5ce4b31 100644 --- a/sound/core/compress_offload.c +++ b/sound/core/compress_offload.c @@ -698,24 +698,11 @@ static int snd_compr_pause(struct snd_compr_stream *stream) { int retval; - switch (stream->runtime->state) { - case SNDRV_PCM_STATE_RUNNING: - retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_PAUSE_PUSH); - if (!retval) - stream->runtime->state = SNDRV_PCM_STATE_PAUSED; - break; -#ifndef CONFIG_AUDIO_QGKI - case SNDRV_PCM_STATE_DRAINING: - if (!stream->device->use_pause_in_draining) - return -EPERM; - retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_PAUSE_PUSH); - if (!retval) - stream->pause_in_draining = true; - break; -#endif - default: + if (stream->runtime->state != SNDRV_PCM_STATE_RUNNING) return -EPERM; - } + retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_PAUSE_PUSH); + if (!retval) + stream->runtime->state = SNDRV_PCM_STATE_PAUSED; return retval; } @@ -723,24 +710,11 @@ static int snd_compr_resume(struct snd_compr_stream *stream) { int retval; - switch (stream->runtime->state) { - case SNDRV_PCM_STATE_PAUSED: - retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_PAUSE_RELEASE); - if (!retval) - stream->runtime->state = SNDRV_PCM_STATE_RUNNING; - break; -#ifndef CONFIG_AUDIO_QGKI - case SNDRV_PCM_STATE_DRAINING: - if (!stream->pause_in_draining) - return -EPERM; - retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_PAUSE_RELEASE); - if (!retval) - stream->pause_in_draining = false; - break; -#endif - default: + if (stream->runtime->state != SNDRV_PCM_STATE_PAUSED) return -EPERM; - } + retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_PAUSE_RELEASE); + if (!retval) + stream->runtime->state = SNDRV_PCM_STATE_RUNNING; return retval; } @@ -780,9 +754,6 @@ static int snd_compr_stop(struct snd_compr_stream *stream) retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_STOP); if (!retval) { -#ifndef CONFIG_AUDIO_QGKI - stream->pause_in_draining = false; -#endif snd_compr_drain_notify(stream); stream->runtime->total_bytes_available = 0; stream->runtime->total_bytes_transferred = 0; From cb33e1bdb7c29665134281ad09a7fc647534be0b Mon Sep 17 00:00:00 2001 From: Lynus Vaz Date: Mon, 27 Nov 2023 06:53:01 -0800 Subject: [PATCH 171/698] msm: kgsl: Do not free sharedmem if it cannot be unmapped If sharedmem cannot be unmapped from the mmu, it can still be accessed by the GPU. Therefore it is not safe to free the backing memory. In the case that unmap fails, do not free it or return it to the system. Change-Id: Iad3e86d043f129a4d71cf862865d9033d4a315e3 Signed-off-by: Lynus Vaz (cherry picked from commit 330843f54465ee9b62e1a1e2f6c5d12b14c3b548) --- drivers/gpu/msm/kgsl_mmu.c | 2 ++ drivers/gpu/msm/kgsl_sharedmem.c | 24 ++++++++++++++++++++++-- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/msm/kgsl_mmu.c b/drivers/gpu/msm/kgsl_mmu.c index 2633b72f18f7..33fcaabf838d 100644 --- a/drivers/gpu/msm/kgsl_mmu.c +++ b/drivers/gpu/msm/kgsl_mmu.c @@ -483,6 +483,8 @@ kgsl_mmu_unmap(struct kgsl_pagetable *pagetable, size = kgsl_memdesc_footprint(memdesc); ret = pagetable->pt_ops->mmu_unmap(pagetable, memdesc); + if (ret) + return ret; atomic_dec(&pagetable->stats.entries); atomic_long_sub(size, &pagetable->stats.mapped); diff --git a/drivers/gpu/msm/kgsl_sharedmem.c b/drivers/gpu/msm/kgsl_sharedmem.c index ae66f3acba30..d77ec299ae04 100644 --- a/drivers/gpu/msm/kgsl_sharedmem.c +++ b/drivers/gpu/msm/kgsl_sharedmem.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2002,2007-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -948,6 +949,9 @@ static void kgsl_contiguous_free(struct kgsl_memdesc *memdesc) if (!memdesc->hostptr) return; + if (memdesc->priv & KGSL_MEMDESC_MAPPED) + return; + atomic_long_sub(memdesc->size, &kgsl_driver.stats.coherent); #ifdef CONFIG_MM_STAT_UNRECLAIMABLE_PAGES @@ -963,9 +967,14 @@ static void kgsl_free_secure_system_pages(struct kgsl_memdesc *memdesc) { int i; struct scatterlist *sg; - int ret = unlock_sgt(memdesc->sgt); + int ret; int order = get_order(PAGE_SIZE); + if (memdesc->priv & KGSL_MEMDESC_MAPPED) + return; + + ret = unlock_sgt(memdesc->sgt); + if (ret) { /* * Unlock of the secure buffer failed. This buffer will @@ -998,7 +1007,12 @@ static void kgsl_free_secure_system_pages(struct kgsl_memdesc *memdesc) static void kgsl_free_secure_pool_pages(struct kgsl_memdesc *memdesc) { - int ret = unlock_sgt(memdesc->sgt); + int ret; + + if (memdesc->priv & KGSL_MEMDESC_MAPPED) + return; + + ret = unlock_sgt(memdesc->sgt); if (ret) { /* @@ -1028,6 +1042,9 @@ static void kgsl_free_pool_pages(struct kgsl_memdesc *memdesc) kgsl_paged_unmap_kernel(memdesc); WARN_ON(memdesc->hostptr); + if (memdesc->priv & KGSL_MEMDESC_MAPPED) + return; + atomic_long_sub(memdesc->size, &kgsl_driver.stats.page_alloc); kgsl_pool_free_pages(memdesc->pages, memdesc->page_count); @@ -1045,6 +1062,9 @@ static void kgsl_free_system_pages(struct kgsl_memdesc *memdesc) kgsl_paged_unmap_kernel(memdesc); WARN_ON(memdesc->hostptr); + if (memdesc->priv & KGSL_MEMDESC_MAPPED) + return; + atomic_long_sub(memdesc->size, &kgsl_driver.stats.page_alloc); for (i = 0; i < memdesc->page_count; i++) { From b375ca6675491b4d6d1b8d4a152c949e45e0922b Mon Sep 17 00:00:00 2001 From: Vikash Garodia Date: Wed, 29 Nov 2023 09:32:28 +0530 Subject: [PATCH 172/698] BACKPORT: media: venus: hfi: fix the check in session buffer requirement Buffer requirement, for different buffer type, comes from video firmware. While copying these requirements, there is an OOB possibility when the payload from firmware is more than expected size. Fix the check to avoid the OOB possibility. cherry picked from b18e36dfd6c9 ("media: venus: hfi: fix the check to handle session buffer requirement"). Change-Id: I8169c57b2c244c52bac0b4de460b9820707f6ff7 Cc: stable@vger.kernel.org Fixes: 09c2845e8fe4 ("[media] media: venus: hfi: add Host Firmware Interface (HFI)") Reviewed-by: Nathan Hebert Signed-off-by: Stanimir Varbanov Signed-off-by: Hans Verkuil Signed-off-by: Vikash Garodia (cherry picked from commit 8346a4a3b40d2075635723f537952a8e27dfc949) --- drivers/media/platform/qcom/venus/hfi_msgs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/platform/qcom/venus/hfi_msgs.c b/drivers/media/platform/qcom/venus/hfi_msgs.c index 04ef2286efc6..5694d18b43d5 100644 --- a/drivers/media/platform/qcom/venus/hfi_msgs.c +++ b/drivers/media/platform/qcom/venus/hfi_msgs.c @@ -350,7 +350,7 @@ session_get_prop_buf_req(struct hfi_msg_session_property_info_pkt *pkt, memcpy(&bufreq[idx], buf_req, sizeof(*bufreq)); idx++; - if (idx > HFI_BUFFER_TYPE_MAX) + if (idx >= HFI_BUFFER_TYPE_MAX) return HFI_ERR_SESSION_INVALID_PARAMETER; req_bytes -= sizeof(struct hfi_buffer_requirements); From 9d501ea8822df775478424b196cc9e3f510b35a3 Mon Sep 17 00:00:00 2001 From: Sarannya S Date: Fri, 22 Sep 2023 13:13:58 +0530 Subject: [PATCH 173/698] soc: qcom: smem: Add boundary checks for partitions Add condition check to make sure that the end address of private entry does not go out of partition. Change-Id: I88b3c69d86d90905b214c13a8c632b134b487a49 Signed-off-by: Sarannya S Signed-off-by: Pranav Mahesh Phansalkar (cherry picked from commit 58e401790ae9f1bbaab96eda7d2e21fb4b020247) --- drivers/soc/qcom/smem.c | 107 +++++++++++++++++++++++++++------------- 1 file changed, 72 insertions(+), 35 deletions(-) diff --git a/drivers/soc/qcom/smem.c b/drivers/soc/qcom/smem.c index 0c65d83e8096..04a38617d643 100644 --- a/drivers/soc/qcom/smem.c +++ b/drivers/soc/qcom/smem.c @@ -2,6 +2,7 @@ /* * Copyright (c) 2015, Sony Mobile Communications AB. * Copyright (c) 2012-2013, 2019-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -86,6 +87,17 @@ /* Max number of processors/hosts in a system */ #define SMEM_HOST_COUNT 14 +/* Entry range check + * ptr >= start : Checks if ptr is greater than the start of access region + * ptr + size >= ptr: Check for integer overflow (On 32bit system where ptr + * and size are 32bits, ptr + size can wrap around to be a small integer) + * ptr + size <= end: Checks if ptr+size is less than the end of access region + */ +#define IN_PARTITION_RANGE(ptr, size, start, end) \ + (((void *)(ptr) >= (void *)(start)) && \ + (((void *)(ptr) + (size)) >= (void *)(ptr)) && \ + (((void *)(ptr) + (size)) <= (void *)(end))) + /** * struct smem_proc_comm - proc_comm communication struct (legacy) * @command: current command to be executed @@ -353,6 +365,7 @@ static int qcom_smem_alloc_private(struct qcom_smem *smem, size_t size) { struct smem_private_entry *hdr, *end; + struct smem_private_entry *next_hdr; struct smem_partition_header *phdr; size_t alloc_size; void *cached; @@ -365,18 +378,25 @@ static int qcom_smem_alloc_private(struct qcom_smem *smem, end = phdr_to_last_uncached_entry(phdr); cached = phdr_to_last_cached_entry(phdr); - if (WARN_ON((void *)end > p_end || (void *)cached > p_end)) + if (WARN_ON(!IN_PARTITION_RANGE(end, 0, phdr, cached) || + cached > p_end)) return -EINVAL; - while (hdr < end) { + while ((hdr < end) && ((hdr + 1) < end)) { if (hdr->canary != SMEM_PRIVATE_CANARY) goto bad_canary; if (le16_to_cpu(hdr->item) == item) return -EEXIST; - hdr = uncached_entry_next(hdr); + next_hdr = uncached_entry_next(hdr); + + if (WARN_ON(next_hdr <= hdr)) + return -EINVAL; + + hdr = next_hdr; } - if (WARN_ON((void *)hdr > p_end)) + + if (WARN_ON((void *)hdr > (void *)end)) return -EINVAL; /* Check that we don't grow into the cached region */ @@ -534,9 +554,11 @@ static void *qcom_smem_get_private(struct qcom_smem *smem, unsigned item, size_t *size) { - struct smem_private_entry *e, *end; + struct smem_private_entry *e, *uncached_end, *cached_end; + struct smem_private_entry *next_e; struct smem_partition_header *phdr; void *item_ptr, *p_end; + size_t entry_size = 0; u32 partition_size; size_t cacheline; u32 padding_data; @@ -548,72 +570,87 @@ static void *qcom_smem_get_private(struct qcom_smem *smem, cacheline = le32_to_cpu(entry->cacheline); e = phdr_to_first_uncached_entry(phdr); - end = phdr_to_last_uncached_entry(phdr); + uncached_end = phdr_to_last_uncached_entry(phdr); + cached_end = phdr_to_last_cached_entry(phdr); - if (WARN_ON((void *)end > p_end)) + if (WARN_ON(!IN_PARTITION_RANGE(uncached_end, 0, phdr, cached_end) + || (void *)cached_end > p_end)) return ERR_PTR(-EINVAL); - while (e < end) { + while ((e < uncached_end) && ((e + 1) < uncached_end)) { if (e->canary != SMEM_PRIVATE_CANARY) goto invalid_canary; if (le16_to_cpu(e->item) == item) { - if (size != NULL) { - e_size = le32_to_cpu(e->size); - padding_data = le16_to_cpu(e->padding_data); + e_size = le32_to_cpu(e->size); + padding_data = le16_to_cpu(e->padding_data); - if (e_size < partition_size - && padding_data < e_size) - *size = e_size - padding_data; - else - return ERR_PTR(-EINVAL); - } + if (e_size < partition_size && padding_data < e_size) + entry_size = e_size - padding_data; + else + return ERR_PTR(-EINVAL); item_ptr = uncached_entry_to_item(e); - if (WARN_ON(item_ptr > p_end)) + + if (WARN_ON(!IN_PARTITION_RANGE(item_ptr, entry_size, e, uncached_end))) return ERR_PTR(-EINVAL); + if (size != NULL) + *size = entry_size; + return item_ptr; } - e = uncached_entry_next(e); + next_e = uncached_entry_next(e); + if (WARN_ON(next_e <= e)) + return ERR_PTR(-EINVAL); + + e = next_e; } - if (WARN_ON((void *)e > p_end)) + if (WARN_ON((void *)e > (void *)uncached_end)) return ERR_PTR(-EINVAL); /* Item was not found in the uncached list, search the cached list */ - e = phdr_to_first_cached_entry(phdr, cacheline); - end = phdr_to_last_cached_entry(phdr); + if (cached_end == p_end) + return ERR_PTR(-ENOENT); - if (WARN_ON((void *)e < (void *)phdr || (void *)end > p_end)) + e = phdr_to_first_cached_entry(phdr, cacheline); + + if (WARN_ON(!IN_PARTITION_RANGE(cached_end, 0, uncached_end, p_end) || + !IN_PARTITION_RANGE(e, sizeof(*e), cached_end, p_end))) return ERR_PTR(-EINVAL); - while (e > end) { + while (e > cached_end) { if (e->canary != SMEM_PRIVATE_CANARY) goto invalid_canary; if (le16_to_cpu(e->item) == item) { - if (size != NULL) { - e_size = le32_to_cpu(e->size); - padding_data = le16_to_cpu(e->padding_data); + e_size = le32_to_cpu(e->size); + padding_data = le16_to_cpu(e->padding_data); - if (e_size < partition_size - && padding_data < e_size) - *size = e_size - padding_data; - else - return ERR_PTR(-EINVAL); - } + if (e_size < partition_size && padding_data < e_size) + entry_size = e_size - padding_data; + else + return ERR_PTR(-EINVAL); item_ptr = cached_entry_to_item(e); - if (WARN_ON(item_ptr < (void *)phdr)) + if (WARN_ON(!IN_PARTITION_RANGE(item_ptr, entry_size, cached_end, e))) return ERR_PTR(-EINVAL); + if (size != NULL) + *size = entry_size; + return item_ptr; } - e = cached_entry_next(e, cacheline); + next_e = cached_entry_next(e, cacheline); + if (WARN_ON(next_e >= e)) + return ERR_PTR(-EINVAL); + + e = next_e; } + if (WARN_ON((void *)e < (void *)phdr)) return ERR_PTR(-EINVAL); From 267c47fd45f18eb5498ed917acf3f9e93b296a94 Mon Sep 17 00:00:00 2001 From: Lynus Vaz Date: Wed, 20 Dec 2023 13:52:55 -0800 Subject: [PATCH 174/698] msm: kgsl: Do not release dma and anon buffers if unmap fails If iommu unmap fails and leaves dma or anon buffers still mapped in the iommu, do not free them. Change-Id: Ice0e1a59c1ac0ee7a9d62d8899966b84fa63d5ca Signed-off-by: Lynus Vaz Signed-off-by: Deepak Kumar (cherry picked from commit e7c4bb239ba84e45c05ccd1105d400f0a61a7613) --- drivers/gpu/msm/kgsl.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c index 964b8536666b..ff7e3e5468ea 100644 --- a/drivers/gpu/msm/kgsl.c +++ b/drivers/gpu/msm/kgsl.c @@ -344,6 +344,9 @@ static void kgsl_destroy_ion(struct kgsl_memdesc *memdesc) struct kgsl_mem_entry, memdesc); struct kgsl_dma_buf_meta *meta = entry->priv_data; + if (memdesc->priv & KGSL_MEMDESC_MAPPED) + return; + if (meta != NULL) { remove_dmabuf_list(meta); dma_buf_unmap_attachment(meta->attach, meta->table, @@ -367,6 +370,9 @@ static void kgsl_destroy_anon(struct kgsl_memdesc *memdesc) struct scatterlist *sg; struct page *page; + if (memdesc->priv & KGSL_MEMDESC_MAPPED) + return; + for_each_sg(memdesc->sgt->sgl, sg, memdesc->sgt->nents, i) { page = sg_page(sg); for (j = 0; j < (sg->length >> PAGE_SHIFT); j++) { From 94d568a93dc8c74a05660588d74898bc39e90d11 Mon Sep 17 00:00:00 2001 From: huangzq2 Date: Wed, 2 Nov 2022 13:11:27 +0800 Subject: [PATCH 175/698] Revert "mm: fix unexpected zeroed page mapping with zram swap" This reverts commit f098f8b9820fe3f2e41aefc4329dfe8a3859d1c1. Change-Id: I02afb5f962700b250c870eaf347ec425ea72e514 --- mm/page_io.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/mm/page_io.c b/mm/page_io.c index 06d6c49ec987..bc370c8e1667 100644 --- a/mm/page_io.c +++ b/mm/page_io.c @@ -71,6 +71,54 @@ void end_swap_bio_write(struct bio *bio) bio_put(bio); } +static void swap_slot_free_notify(struct page *page) +{ + struct swap_info_struct *sis; + struct gendisk *disk; + swp_entry_t entry; + + /* + * There is no guarantee that the page is in swap cache - the software + * suspend code (at least) uses end_swap_bio_read() against a non- + * swapcache page. So we must check PG_swapcache before proceeding with + * this optimization. + */ + if (unlikely(!PageSwapCache(page))) + return; + + sis = page_swap_info(page); + if (!(sis->flags & SWP_BLKDEV)) + return; + + /* + * The swap subsystem performs lazy swap slot freeing, + * expecting that the page will be swapped out again. + * So we can avoid an unnecessary write if the page + * isn't redirtied. + * This is good for real swap storage because we can + * reduce unnecessary I/O and enhance wear-leveling + * if an SSD is used as the as swap device. + * But if in-memory swap device (eg zram) is used, + * this causes a duplicated copy between uncompressed + * data in VM-owned memory and compressed data in + * zram-owned memory. So let's free zram-owned memory + * and make the VM-owned decompressed page *dirty*, + * so the page should be swapped out somewhere again if + * we again wish to reclaim it. + */ + disk = sis->bdev->bd_disk; + entry.val = page_private(page); + if (disk->fops->swap_slot_free_notify && __swap_count(entry) == 1) { + unsigned long offset; + + offset = swp_offset(entry); + + SetPageDirty(page); + disk->fops->swap_slot_free_notify(sis->bdev, + offset); + } +} + static void end_swap_bio_read(struct bio *bio) { struct page *page = bio_first_page_all(bio); @@ -86,6 +134,7 @@ static void end_swap_bio_read(struct bio *bio) } SetPageUptodate(page); + swap_slot_free_notify(page); out: unlock_page(page); WRITE_ONCE(bio->bi_private, NULL); @@ -333,6 +382,11 @@ int swap_readpage(struct page *page, bool synchronous) ret = bdev_read_page(sis->bdev, swap_page_sector(page), page); if (!ret) { + if (trylock_page(page)) { + swap_slot_free_notify(page); + unlock_page(page); + } + count_vm_event(PSWPIN); goto out; } From b9ebcb8b43f12043620b2b127437740f4dc4aa39 Mon Sep 17 00:00:00 2001 From: yangqh5 Date: Thu, 17 Sep 2020 10:52:25 +0800 Subject: [PATCH 176/698] Init denver kernel config Change-Id: I72e78a9919b7f42b3b7f7624e7e40e25255b669e Reviewed-on: https://gerrit.mot.com/1752050 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Submit-Approved: Jira Key Tested-by: Jira Key Reviewed-by: Lianlu Chen --- .../vendor/ext_config/debug-holi-denver.config | 16 ++++++++++++++++ .../vendor/ext_config/moto-holi-denver.config | 15 +++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 arch/arm64/configs/vendor/ext_config/debug-holi-denver.config create mode 100644 arch/arm64/configs/vendor/ext_config/moto-holi-denver.config diff --git a/arch/arm64/configs/vendor/ext_config/debug-holi-denver.config b/arch/arm64/configs/vendor/ext_config/debug-holi-denver.config new file mode 100644 index 000000000000..b987b9fd5c64 --- /dev/null +++ b/arch/arm64/configs/vendor/ext_config/debug-holi-denver.config @@ -0,0 +1,16 @@ +# +# Please avoid changing the Qualcomm defconfig files and use this file to +# add any Motorola-specific configuration changes that are applicable to +# userdebug, eng, and user builds. +# +# After building, a list of all of the config files that are used can be found +# at the top of: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/mapphone_defconfig +# +# The actual output of the kernel configuration system can be found at: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/.config +# +# You can check the .config file to verify that your configuration option is +# being set as expected. +# +CONFIG_SUSPEND_DEBUG=y diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-denver.config b/arch/arm64/configs/vendor/ext_config/moto-holi-denver.config new file mode 100644 index 000000000000..8b121eb8ce46 --- /dev/null +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-denver.config @@ -0,0 +1,15 @@ +# +# Please avoid changing the Qualcomm defconfig files and use this file to +# add any Motorola-specific configuration changes that are applicable to +# userdebug, eng, and user builds. +# +# After building, a list of all of the config files that are used can be found +# at the top of: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/mapphone_defconfig +# +# The actual output of the kernel configuration system can be found at: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/.config +# +# You can check the .config file to verify that your configuration option is +# being set as expected. +# From 1188d4ea63ec74234369839affc0f9b81903aee5 Mon Sep 17 00:00:00 2001 From: Sudheer Papothi Date: Fri, 29 Jan 2016 06:53:48 +0530 Subject: [PATCH 177/698] ASoC: msm: qdsp6v2: Handles additional flac metadata Currently, metadata such as min/max block size is sent only for first stream in FLAC gapless playback. This causes incorrect configuration and, subsequently, framedrops in decoding of second stream and onwards by sending these additional flac metadata, dsp receives stream-wise metadata and decodes without dropping Change-Id: Ibd4a9b24180622422ed719b075fd47bcd4ad0c9b Signed-off-by: Amit Shekhar Signed-off-by: Banajit Goswami Signed-off-by: Sudheer Papothi Signed-off-by: Meng Wang (cherry picked from commit feb23f7f5d63d7b890ba481d0b466b6e9a5eed15) Reviewed-on: https://gerrit.mot.com/1752137 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Submit-Approved: Jira Key Tested-by: Jira Key Reviewed-by: Lianlu Chen --- include/uapi/sound/compress_offload.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/uapi/sound/compress_offload.h b/include/uapi/sound/compress_offload.h index 674236afec31..81b7da409d02 100644 --- a/include/uapi/sound/compress_offload.h +++ b/include/uapi/sound/compress_offload.h @@ -171,6 +171,8 @@ enum sndrv_compress_encoder { SNDRV_COMPRESS_ENABLE_ADJUST_SESSION_CLOCK = 8, SNDRV_COMPRESS_ADJUST_SESSION_CLOCK = 9, SNDRV_COMPRESS_LATENCY_MODE = 10, + SNDRV_COMPRESS_MIN_BLK_SIZE = 11, + SNDRV_COMPRESS_MAX_BLK_SIZE = 12, }; #define SNDRV_COMPRESS_PATH_DELAY SNDRV_COMPRESS_PATH_DELAY @@ -183,6 +185,9 @@ enum sndrv_compress_encoder { #define SNDRV_COMPRESS_ADJUST_SESSION_CLOCK SNDRV_COMPRESS_ADJUST_SESSION_CLOCK #define SNDRV_COMPRESS_LATENCY_MODE SNDRV_COMPRESS_LATENCY_MODE +#define SNDRV_COMPRESS_MIN_BLK_SIZE SNDRV_COMPRESS_MIN_BLK_SIZE +#define SNDRV_COMPRESS_MAX_BLK_SIZE SNDRV_COMPRESS_MAX_BLK_SIZE + /** * struct snd_compr_metadata - compressed stream metadata * @key: key id From 2e75049063ab5a2045dc02047b56accef73df3e4 Mon Sep 17 00:00:00 2001 From: litong Date: Thu, 10 Sep 2020 15:00:26 +0800 Subject: [PATCH 178/698] workaround for the error of "__symbol_put " undefined ERROR: "__symbol_put" [../../motorola/kernel/modules/drivers/input/ touchscreen/touchscreen_mmi/touchscreen_mmi.ko] undefined! ERROR: "__symbol_get" [../../motorola/kernel/modules/drivers/input/ touchscreen/touchscreen_mmi/touchscreen_mmi.ko] undefined! Change-Id: I5ae7f9e395c61a1cd7f4b7ee7e914880ad767448 Reviewed-on: https://gerrit.mot.com/1745785 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Submit-Approved: Jira Key Tested-by: Jira Key Reviewed-by: Zhenxin Xi Reviewed-on: https://gerrit.mot.com/1755124 Reviewed-by: Lianlu Chen --- kernel/module.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/kernel/module.c b/kernel/module.c index adceceb6c49f..b42faf5691c0 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -1086,6 +1086,8 @@ void __symbol_put(const char *symbol) module_put(owner); preempt_enable(); } +/* MMI_STOPSHIP: touchscreen: export the symbol for temp rebase */ +EXPORT_SYMBOL(__symbol_put); /* Note this assumes addr is a function, which it currently always is. */ void symbol_put_addr(void *addr) @@ -2320,6 +2322,8 @@ fail: preempt_enable(); return NULL; } +/* MMI_STOPSHIP: touchscreen: export the symbol for temp rebase */ +EXPORT_SYMBOL(__symbol_get); /* * Ensure that an exported symbol [global namespace] does not already exist From 4e61dd033c918f2ff1a4b492f8fcf782c42d6ca0 Mon Sep 17 00:00:00 2001 From: Bang Nguyen Date: Tue, 30 Jul 2019 14:12:34 -0500 Subject: [PATCH 179/698] Add new macro MIPI_DSI_MSG_READ Add a new macro MIPI_DSI_MSG_READ (bit 4) in drm_mipi_dsi.h for MIPI DSI READ Message Change-Id: I8d6ed4aa10b915f7ff74339c8bdabe061c09ecd5 Signed-off-by: Bang Nguyen Reviewed-on: https://gerrit.mot.com/1697680 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Shuo Yan Reviewed-by: Guobin Zhang Submit-Approved: Jira Key --- include/drm/drm_mipi_dsi.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/drm/drm_mipi_dsi.h b/include/drm/drm_mipi_dsi.h index f307f014440b..2159df2ae857 100644 --- a/include/drm/drm_mipi_dsi.h +++ b/include/drm/drm_mipi_dsi.h @@ -22,6 +22,8 @@ struct mipi_dsi_device; #define MIPI_DSI_MSG_UNICAST BIT(2) /* Stack all commands until lastcommand bit and trigger all in one go */ #define MIPI_DSI_MSG_LASTCOMMAND BIT(3) +/* transmit message is a DSI read message */ +#define MIPI_DSI_MSG_READ BIT(4) /** * struct mipi_dsi_msg - read/write DSI buffer From d3e7540280c11b837d8ac926748b17ba6530873f Mon Sep 17 00:00:00 2001 From: jixj Date: Tue, 29 Sep 2020 15:46:45 +0800 Subject: [PATCH 180/698] soc: qcom: kconfig opt to build moto dtbs Introduce a new configuration MMI_DEVICE_DTBS that will allow the target to only build Motorola devices. Change-Id: I8eb2d1586dd2d99c696a3e198e5809a12cab6ad9 Reviewed-on: https://gerrit.mot.com/1762924 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Submit-Approved: Jira Key Tested-by: Jira Key Reviewed-by: Huosheng Liao --- drivers/soc/qcom/Kconfig | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index 145b60079b23..bcd80eb3a1d7 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -4,6 +4,14 @@ # menu "Qualcomm SoC drivers" +config MMI_DEVICE_DTBS + depends on ARCH_QCOM + default n + bool "Motorola Mobility Device DTBs" + help + Only include Motorola device specific DTBs to limit the number that + get built during kernel compilation. + config QCOM_AOSS_QMP tristate "Qualcomm AOSS Driver" depends on ARCH_QCOM || COMPILE_TEST From 0f89da75760994372509f1fe14f395ba6a20b5ff Mon Sep 17 00:00:00 2001 From: jixj Date: Tue, 29 Sep 2020 15:48:28 +0800 Subject: [PATCH 181/698] soc: qcom: kconfig opt to build denver dtbs Introduce a new configuration DENVER_DTB that will allow the target to only build denver devices. Change-Id: I766404bb7792c217d37eecd3a543d866fc018fae Reviewed-on: https://gerrit.mot.com/1762925 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Submit-Approved: Jira Key Tested-by: Jira Key Reviewed-by: Huosheng Liao --- drivers/soc/qcom/Kconfig | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index bcd80eb3a1d7..26afff931e94 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -12,6 +12,14 @@ config MMI_DEVICE_DTBS Only include Motorola device specific DTBs to limit the number that get built during kernel compilation. +config DENVER_DTB + depends on ARCH_QCOM + default n + bool "DENVER DTBs" + help + Only include DENVER specific DTBs to limit the number that + get built during kernel compilation. + config QCOM_AOSS_QMP tristate "Qualcomm AOSS Driver" depends on ARCH_QCOM || COMPILE_TEST From dee1ae4006136f3a2a55a128f642e99b19c58ce2 Mon Sep 17 00:00:00 2001 From: weimh1 Date: Thu, 8 Oct 2020 20:21:23 +0800 Subject: [PATCH 182/698] kernel/config: merge moto fragment configs Kernel configs compose of several parts.These parts will be merged into one final file such as "holi-qgki-debug_defconfig". The rule of Moto-product-config files from high order is: product debug config platform debug config, product config platform config Here is an example of product "denver" based on 4350 platform (holi): 1. factory build config list with order: factory-holi-denver.config factory-holi.config moto-holi-denver.config moto-holi.config 2. userdebug build config list with order: debug-holi-denver.config debug-holi.config moto-holi-denver.config moto-holi.config 3. user version config list with order: moto-holi-denver.config moto-holi.config Change-Id: Ie7512300581337ae6768bdfa618613a797f3c10f Signed-off-by: weimh1 Reviewed-on: https://gerrit.mot.com/1769363 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- .../ext_config/debug-holi-denver.config | 2 +- .../vendor/ext_config/debug-holi.config | 17 ++++ .../vendor/ext_config/factory-holi.config | 16 ++++ .../vendor/ext_config/holi_consolidate.config | 1 + .../vendor/ext_config/holi_debug.config | 1 + .../vendor/ext_config/moto-holi.config | 17 ++++ .../configs/vendor/holi_consolidate.config | 51 ++++++++++++ scripts/gki/fragment_motoconfig.sh | 78 +++++++++++++++++++ scripts/gki/generate_defconfig.sh | 3 + 9 files changed, 185 insertions(+), 1 deletion(-) create mode 100644 arch/arm64/configs/vendor/ext_config/debug-holi.config create mode 100644 arch/arm64/configs/vendor/ext_config/factory-holi.config create mode 120000 arch/arm64/configs/vendor/ext_config/holi_consolidate.config create mode 120000 arch/arm64/configs/vendor/ext_config/holi_debug.config create mode 100644 arch/arm64/configs/vendor/ext_config/moto-holi.config create mode 100644 arch/arm64/configs/vendor/holi_consolidate.config create mode 100755 scripts/gki/fragment_motoconfig.sh diff --git a/arch/arm64/configs/vendor/ext_config/debug-holi-denver.config b/arch/arm64/configs/vendor/ext_config/debug-holi-denver.config index b987b9fd5c64..830e8a22f610 100644 --- a/arch/arm64/configs/vendor/ext_config/debug-holi-denver.config +++ b/arch/arm64/configs/vendor/ext_config/debug-holi-denver.config @@ -13,4 +13,4 @@ # You can check the .config file to verify that your configuration option is # being set as expected. # -CONFIG_SUSPEND_DEBUG=y + diff --git a/arch/arm64/configs/vendor/ext_config/debug-holi.config b/arch/arm64/configs/vendor/ext_config/debug-holi.config new file mode 100644 index 000000000000..79d06d0a6e8e --- /dev/null +++ b/arch/arm64/configs/vendor/ext_config/debug-holi.config @@ -0,0 +1,17 @@ +# +# Please avoid changing the Qualcomm defconfig files and use this file to +# add any Motorola-specific configuration changes that are applicable to +# userdebug, eng, and user builds. +# +# After building, a list of all of the config files that are used can be found +# at the top of: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/mapphone_defconfig +# +# The actual output of the kernel configuration system can be found at: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/.config +# +# You can check the .config file to verify that your configuration option is +# being set as expected. +# +CONFIG_DEBUG_FS=y +CONFIG_CFI_PERMISSIVE=y diff --git a/arch/arm64/configs/vendor/ext_config/factory-holi.config b/arch/arm64/configs/vendor/ext_config/factory-holi.config new file mode 100644 index 000000000000..2f770fff3573 --- /dev/null +++ b/arch/arm64/configs/vendor/ext_config/factory-holi.config @@ -0,0 +1,16 @@ +# +# Please avoid changing the Qualcomm defconfig files and use this file to +# add any Motorola-specific configuration changes that are applicable to +# userdebug, eng, and user builds. +# +# After building, a list of all of the config files that are used can be found +# at the top of: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/mapphone_defconfig +# +# The actual output of the kernel configuration system can be found at: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/.config +# +# You can check the .config file to verify that your configuration option is +# being set as expected. +# +CONFIG_CFI_PERMISSIVE=y diff --git a/arch/arm64/configs/vendor/ext_config/holi_consolidate.config b/arch/arm64/configs/vendor/ext_config/holi_consolidate.config new file mode 120000 index 000000000000..e6f8e868a91d --- /dev/null +++ b/arch/arm64/configs/vendor/ext_config/holi_consolidate.config @@ -0,0 +1 @@ +../holi_consolidate.config \ No newline at end of file diff --git a/arch/arm64/configs/vendor/ext_config/holi_debug.config b/arch/arm64/configs/vendor/ext_config/holi_debug.config new file mode 120000 index 000000000000..c17d67945c2c --- /dev/null +++ b/arch/arm64/configs/vendor/ext_config/holi_debug.config @@ -0,0 +1 @@ +../holi_debug.config \ No newline at end of file diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi.config b/arch/arm64/configs/vendor/ext_config/moto-holi.config new file mode 100644 index 000000000000..16240795456e --- /dev/null +++ b/arch/arm64/configs/vendor/ext_config/moto-holi.config @@ -0,0 +1,17 @@ +# +# Please avoid changing the Qualcomm defconfig files and use this file to +# add any Motorola-specific configuration changes that are applicable to +# userdebug, eng, and user builds. +# +# After building, a list of all of the config files that are used can be found +# at the top of: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/mapphone_defconfig +# +# The actual output of the kernel configuration system can be found at: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/.config +# +# You can check the .config file to verify that your configuration option is +# being set as expected. +# +CONFIG_LOCALVERSION="-moto" +CONFIG_MMI_DEVICE_DTBS=y diff --git a/arch/arm64/configs/vendor/holi_consolidate.config b/arch/arm64/configs/vendor/holi_consolidate.config new file mode 100644 index 000000000000..2e6b0caad2af --- /dev/null +++ b/arch/arm64/configs/vendor/holi_consolidate.config @@ -0,0 +1,51 @@ +CONFIG_LOCALVERSION="-qgki-consolidate" +CONFIG_IOMMU_TLBSYNC_DEBUG=y +CONFIG_IOMMU_DEBUG=y +CONFIG_IOMMU_TESTS=y +CONFIG_IO_PGTABLE_PAGE_ACCOUNTING=y +CONFIG_CMA_DEBUGFS=y +CONFIG_CMA_DEBUG=y +CONFIG_DEBUG_PAGEALLOC=y +CONFIG_DEBUG_PAGEALLOC_ENABLE_DEFAULT=y +CONFIG_PAGE_OWNER=y +CONFIG_PAGE_OWNER_ENABLE_DEFAULT=y +CONFIG_PAGE_EXTENSION_PAGE_FREE=y +CONFIG_PSI_FTRACE=y +# CONFIG_DEBUG_DMA_BUF_REF is not set +CONFIG_EDAC_KRYO_ARM64_PANIC_ON_CE=y +CONFIG_QMP_DEBUGFS_CLIENT=y +CONFIG_ATOMIC64_SELFTEST=m +CONFIG_DETECT_HUNG_TASK=y +CONFIG_DEBUG_SPINLOCK=y +CONFIG_TEST_USER_COPY=m +CONFIG_OF_RESERVED_MEM_CHECK=y +CONFIG_BUG_ON_HW_MEM_ONLINE_FAIL=y +CONFIG_PANIC_ON_SCHED_BUG=y +CONFIG_PANIC_ON_RT_THROTTLING=y +CONFIG_LKDTM=m +CONFIG_RUNTIME_TESTING_MENU=y +CONFIG_PREEMPTIRQ_EVENTS=y +CONFIG_SERIAL_MSM_GENI_CONSOLE=y +CONFIG_QCOM_RTB=y +CONFIG_QCOM_RTB_SEPARATE_CPUS=y +CONFIG_QCOM_RTB_QGKI=y +CONFIG_DEBUG_CONSOLE_UNHASHED_POINTERS=y +CONFIG_COMMON_CLK_QCOM_DEBUG=y +CONFIG_CNSS2_DEBUG=y +CONFIG_NL80211_TESTMODE=y +CONFIG_EDAC_QCOM_LLCC_PANIC_ON_CE=y +CONFIG_LOCK_TORTURE_TEST=m +CONFIG_RCU_TORTURE_TEST=m +# CONFIG_CDNS_I3C_MASTER is not set +# CONFIG_DW_I3C_MASTER is not set +CONFIG_CORESIGHT_SOURCE_ETM4X=y +# CONFIG_CORESIGHT_CTI_SAVE_DISABLE is not set +CONFIG_MEM_SHARE_QMI_SERVICE=y +CONFIG_MHI_DEBUG=y +CONFIG_SM_DEBUGCC_HOLI=y +CONFIG_DEBUG_PANIC_ON_OOM=y +CONFIG_USB_F_FS_IPC_LOGGING=y +CONFIG_DYNAMIC_DEBUG=y +CONFIG_QTI_PMIC_GLINK_CLIENT_DEBUG=y +# CONFIG_HH_DISABLE_UART is not set +CONFIG_DEBUG_MODULE_LOAD_INFO=y diff --git a/scripts/gki/fragment_motoconfig.sh b/scripts/gki/fragment_motoconfig.sh new file mode 100755 index 000000000000..3143fce77372 --- /dev/null +++ b/scripts/gki/fragment_motoconfig.sh @@ -0,0 +1,78 @@ +#!/bin/bash +# Copyright (c) 2020, Motorola. All rights reserved. + +# Script to merge all Moto kernel config + +usage() { + echo "Usage: $0 $1" + echo "For example: $0 holi $1 qgki_defconfig" + echo "Note: The output is all valid moto kernel config files" + exit 1 +} + +if [ "$#" -ne 2 ]; then + echo "Error: Invalid number of arguments" + usage +fi + +#echo "framgement_moto: TARGET_PRODUCT=${TARGET_PRODUCT} TARGET_BUILD_VARIANT=${TARGET_BUILD_VARIANT}" + +TARGET_PRODUCT_NAME=${TARGET_PRODUCT%%_*} +TARGET_PRODUCT_TYPE=${TARGET_PRODUCT#*_} +LOCAL_PLATFORM_NAME=${1} +REQUIRED_DEFCONFIG=${2} +echo "moto framgement config: LOCAL_PLATFORM_NAME=${LOCAL_PLATFORM_NAME} TARGET_PRODUCT_NAME=$TARGET_PRODUCT_NAME TARGET_PRODUCT_TYPE=$TARGET_PRODUCT_TYPE" + +#skip msi products +if [ $TARGET_PRODUCT_NAME == "msi" ]; then + echo "This is msi, skip moto config fragements" + exit 0 +fi + +MOTO_CONFIG_DIR=$CONFIGS_DIR/ext_config +export MOTO_REQUIRED_CONFIG="" + +# merge factory config or userdebug config +if [ $TARGET_PRODUCT_TYPE == "factory" ]; then + if [ -e $MOTO_CONFIG_DIR/factory-${LOCAL_PLATFORM_NAME}-${TARGET_PRODUCT_NAME}.config ]; then + MOTO_REQUIRED_CONFIG+=" $MOTO_CONFIG_DIR/factory-${LOCAL_PLATFORM_NAME}-${TARGET_PRODUCT_NAME}.config" + fi + + if [ -e $MOTO_CONFIG_DIR/factory-${LOCAL_PLATFORM_NAME}.config ]; then + MOTO_REQUIRED_CONFIG+=" $MOTO_CONFIG_DIR/factory-${LOCAL_PLATFORM_NAME}.config" + fi +elif [ $TARGET_BUILD_VARIANT == "userdebug" ] && [ $REQUIRED_DEFCONFIG != ${LOCAL_PLATFORM_NAME}-gki_defconfig ]; then + if [ -e $MOTO_CONFIG_DIR/debug-${LOCAL_PLATFORM_NAME}-${TARGET_PRODUCT_NAME}.config ]; then + MOTO_REQUIRED_CONFIG+=" $MOTO_CONFIG_DIR/debug-${LOCAL_PLATFORM_NAME}-${TARGET_PRODUCT_NAME}.config" + fi + + if [ -e $MOTO_CONFIG_DIR/debug-${LOCAL_PLATFORM_NAME}.config ]; then + MOTO_REQUIRED_CONFIG+=" $MOTO_CONFIG_DIR/debug-${LOCAL_PLATFORM_NAME}.config" + fi + + if [ -e $MOTO_CONFIG_DIR/${LOCAL_PLATFORM_NAME}_debug.config ]; then + MOTO_REQUIRED_CONFIG+=" $MOTO_CONFIG_DIR/${LOCAL_PLATFORM_NAME}_debug.config" + if [ -e $MOTO_CONFIG_DIR/${LOCAL_PLATFORM_NAME}_consolidate.config ]; then + MOTO_REQUIRED_CONFIG+=" $MOTO_CONFIG_DIR/${LOCAL_PLATFORM_NAME}_consolidate.config" + fi + fi +fi + +#merge moto product config +if [ -e $MOTO_CONFIG_DIR/moto-${LOCAL_PLATFORM_NAME}-${TARGET_PRODUCT_NAME}.config ]; then + MOTO_REQUIRED_CONFIG+=" $MOTO_CONFIG_DIR/moto-${LOCAL_PLATFORM_NAME}-${TARGET_PRODUCT_NAME}.config" +fi + +#merge moto platform config +if [ -e $MOTO_CONFIG_DIR/moto-${LOCAL_PLATFORM_NAME}.config ]; then + MOTO_REQUIRED_CONFIG+=" $MOTO_CONFIG_DIR/moto-${LOCAL_PLATFORM_NAME}.config" +fi + +#merge moto platform config that depended on -QGKI.config +if [ $REQUIRED_DEFCONFIG != ${LOCAL_PLATFORM_NAME}-gki_defconfig ]; then + if [ -e $MOTO_CONFIG_DIR/moto-${LOCAL_PLATFORM_NAME}-depQGKI.config ]; then + MOTO_REQUIRED_CONFIG+=" $MOTO_CONFIG_DIR/moto-${LOCAL_PLATFORM_NAME}-depQGKI.config" + fi +fi + +echo "require moto blend configs:$MOTO_REQUIRED_CONFIG" diff --git a/scripts/gki/generate_defconfig.sh b/scripts/gki/generate_defconfig.sh index 04f4dff18e6e..a6e3d6eaea58 100755 --- a/scripts/gki/generate_defconfig.sh +++ b/scripts/gki/generate_defconfig.sh @@ -55,6 +55,9 @@ fi FINAL_DEFCONFIG_BLEND="" +source ${SCRIPTS_ROOT}/fragment_motoconfig.sh ${PLATFORM_NAME} ${REQUIRED_DEFCONFIG} +FINAL_DEFCONFIG_BLEND+=${MOTO_REQUIRED_CONFIG} + case "$REQUIRED_DEFCONFIG" in ${PLATFORM_NAME}-qgki-debug_defconfig ) FINAL_DEFCONFIG_BLEND+=" $QCOM_DEBUG_FRAG" From ddf492709b662d3a7d9e3ee1231efdc8297ff110 Mon Sep 17 00:00:00 2001 From: jixj Date: Fri, 9 Oct 2020 15:47:21 +0800 Subject: [PATCH 183/698] arm64/confgs: Enable denver dts Enable CONFIG_DENVER_DTB to only build denver dts, reduce the dtb image size. Change-Id: I512ec05ae8e45b14d26a3bc9dde91ce84e5c72cc Reviewed-on: https://gerrit.mot.com/1770156 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi-denver.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-denver.config b/arch/arm64/configs/vendor/ext_config/moto-holi-denver.config index 8b121eb8ce46..b265d209827c 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-denver.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-denver.config @@ -13,3 +13,4 @@ # You can check the .config file to verify that your configuration option is # being set as expected. # +CONFIG_DENVER_DTB=y From d4fb0ad41c7b9d29764d670544382cfb978f9c84 Mon Sep 17 00:00:00 2001 From: weimh1 Date: Sat, 10 Oct 2020 13:55:46 +0800 Subject: [PATCH 184/698] kernel/config: add product specific config files 1.add debug-holi-ibiza.config for product debug config 2.add moto-holi-ibiza.config for product specific config 3.add factory-holi-ibiza.config for product factory config Change-Id: I6b6eb65e9e19ed455447e609987438cd6b554b0c Signed-off-by: weimh1 Reviewed-on: https://gerrit.mot.com/1771042 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Hujun Liao Submit-Approved: Jira Key --- .../vendor/ext_config/debug-holi-ibiza.config | 16 ++++++++++++++++ .../vendor/ext_config/factory-holi-denver.config | 16 ++++++++++++++++ .../vendor/ext_config/factory-holi-ibiza.config | 16 ++++++++++++++++ .../vendor/ext_config/moto-holi-ibiza.config | 15 +++++++++++++++ 4 files changed, 63 insertions(+) create mode 100644 arch/arm64/configs/vendor/ext_config/debug-holi-ibiza.config create mode 100644 arch/arm64/configs/vendor/ext_config/factory-holi-denver.config create mode 100644 arch/arm64/configs/vendor/ext_config/factory-holi-ibiza.config create mode 100644 arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config diff --git a/arch/arm64/configs/vendor/ext_config/debug-holi-ibiza.config b/arch/arm64/configs/vendor/ext_config/debug-holi-ibiza.config new file mode 100644 index 000000000000..830e8a22f610 --- /dev/null +++ b/arch/arm64/configs/vendor/ext_config/debug-holi-ibiza.config @@ -0,0 +1,16 @@ +# +# Please avoid changing the Qualcomm defconfig files and use this file to +# add any Motorola-specific configuration changes that are applicable to +# userdebug, eng, and user builds. +# +# After building, a list of all of the config files that are used can be found +# at the top of: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/mapphone_defconfig +# +# The actual output of the kernel configuration system can be found at: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/.config +# +# You can check the .config file to verify that your configuration option is +# being set as expected. +# + diff --git a/arch/arm64/configs/vendor/ext_config/factory-holi-denver.config b/arch/arm64/configs/vendor/ext_config/factory-holi-denver.config new file mode 100644 index 000000000000..830e8a22f610 --- /dev/null +++ b/arch/arm64/configs/vendor/ext_config/factory-holi-denver.config @@ -0,0 +1,16 @@ +# +# Please avoid changing the Qualcomm defconfig files and use this file to +# add any Motorola-specific configuration changes that are applicable to +# userdebug, eng, and user builds. +# +# After building, a list of all of the config files that are used can be found +# at the top of: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/mapphone_defconfig +# +# The actual output of the kernel configuration system can be found at: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/.config +# +# You can check the .config file to verify that your configuration option is +# being set as expected. +# + diff --git a/arch/arm64/configs/vendor/ext_config/factory-holi-ibiza.config b/arch/arm64/configs/vendor/ext_config/factory-holi-ibiza.config new file mode 100644 index 000000000000..830e8a22f610 --- /dev/null +++ b/arch/arm64/configs/vendor/ext_config/factory-holi-ibiza.config @@ -0,0 +1,16 @@ +# +# Please avoid changing the Qualcomm defconfig files and use this file to +# add any Motorola-specific configuration changes that are applicable to +# userdebug, eng, and user builds. +# +# After building, a list of all of the config files that are used can be found +# at the top of: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/mapphone_defconfig +# +# The actual output of the kernel configuration system can be found at: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/.config +# +# You can check the .config file to verify that your configuration option is +# being set as expected. +# + diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config b/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config new file mode 100644 index 000000000000..8b121eb8ce46 --- /dev/null +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config @@ -0,0 +1,15 @@ +# +# Please avoid changing the Qualcomm defconfig files and use this file to +# add any Motorola-specific configuration changes that are applicable to +# userdebug, eng, and user builds. +# +# After building, a list of all of the config files that are used can be found +# at the top of: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/mapphone_defconfig +# +# The actual output of the kernel configuration system can be found at: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/.config +# +# You can check the .config file to verify that your configuration option is +# being set as expected. +# From c5cf78e9ba8da66217c41b391eb67f3bfac9691f Mon Sep 17 00:00:00 2001 From: jixj Date: Sat, 10 Oct 2020 15:36:07 +0800 Subject: [PATCH 185/698] enable ibiza dts - add IBIZA_DT for ibiza - enable CONFIG_IBIZA_DTB Change-Id: I93c2db316131c85195731016116fe0df66fc5695 Reviewed-on: https://gerrit.mot.com/1771104 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- .../configs/vendor/ext_config/moto-holi-ibiza.config | 1 + drivers/soc/qcom/Kconfig | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config b/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config index 8b121eb8ce46..08aae02d0462 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config @@ -13,3 +13,4 @@ # You can check the .config file to verify that your configuration option is # being set as expected. # +CONFIG_IBIZA_DTB=y diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index 26afff931e94..b81685e71f3a 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -20,6 +20,14 @@ config DENVER_DTB Only include DENVER specific DTBs to limit the number that get built during kernel compilation. +config IBIZA_DTB + depends on ARCH_QCOM + default n + bool "IBIZA DTBs" + help + Only include IBIZA specific DTBs to limit the number that + get built during kernel compilation. + config QCOM_AOSS_QMP tristate "Qualcomm AOSS Driver" depends on ARCH_QCOM || COMPILE_TEST From 0637aeab60a73da1a0becab686b7a2cc16c5941f Mon Sep 17 00:00:00 2001 From: Kenny Kessler Date: Wed, 27 Jun 2018 17:01:14 -0500 Subject: [PATCH 186/698] power: pmic-voter: Export Interfaces Export some pmic-voter interfaces for dlkm usage as well as create access functions that are exported for dlkm to manipulate the struct. Change-Id: I306c65c9890bd69dc49fcd722ac0981ddb908dc6 Signed-off-by: Kenny Kessler Reviewed-on: https://gerrit.mot.com/1200744 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Ryan Lattrel Reviewed-by: Ling Jin Reviewed-by: Kenneth Kessler Submit-Approved: Jira Key Reviewed-on: https://gerrit.mot.com/1770243 Reviewed-by: Huosheng Liao --- drivers/power/supply/qcom/pmic-voter.c | 30 ++++++++++++++++++++++++++ include/linux/pmic-voter.h | 4 ++++ 2 files changed, 34 insertions(+) diff --git a/drivers/power/supply/qcom/pmic-voter.c b/drivers/power/supply/qcom/pmic-voter.c index b10c2a060b10..438ad026f30d 100644 --- a/drivers/power/supply/qcom/pmic-voter.c +++ b/drivers/power/supply/qcom/pmic-voter.c @@ -340,6 +340,7 @@ int get_effective_result(struct votable *votable) unlock_votable(votable); return value; } +EXPORT_SYMBOL(get_effective_result); /** * get_effective_client() - @@ -498,6 +499,7 @@ out: unlock_votable(votable); return rc; } +EXPORT_SYMBOL(vote); /** * vote_override() - @@ -571,6 +573,7 @@ int rerun_election(struct votable *votable) unlock_votable(votable); return rc; } +EXPORT_SYMBOL(rerun_election); struct votable *find_votable(const char *name) { @@ -599,6 +602,7 @@ out: else return NULL; } +EXPORT_SYMBOL(find_votable); static int force_active_get(void *data, u64 *val) { @@ -645,6 +649,32 @@ out: DEFINE_DEBUGFS_ATTRIBUTE(votable_force_ops, force_active_get, force_active_set, "%lld\n"); +int pmic_vote_force_val_set(struct votable *votable, u32 val) { + if(votable) { + votable->force_val = val; + return 0; + } + + return -EINVAL; +} +EXPORT_SYMBOL(pmic_vote_force_val_set); + +int pmic_vote_force_active_get(struct votable *votable, u64 *val) { + if(votable) + return force_active_get(votable, val); + + return -EINVAL; +} +EXPORT_SYMBOL(pmic_vote_force_active_get); + +int pmic_vote_force_active_set(struct votable *votable, u64 val) { + if(votable) + return force_active_set(votable, val); + + return -EINVAL; +} +EXPORT_SYMBOL(pmic_vote_force_active_set); + static int show_votable_clients(struct seq_file *m, void *data) { struct votable *votable = m->private; diff --git a/include/linux/pmic-voter.h b/include/linux/pmic-voter.h index d1202928ddd8..78239ca19927 100644 --- a/include/linux/pmic-voter.h +++ b/include/linux/pmic-voter.h @@ -44,4 +44,8 @@ void destroy_votable(struct votable *votable); void lock_votable(struct votable *votable); void unlock_votable(struct votable *votable); +int pmic_vote_force_val_set(struct votable *votable, u32 val); +int pmic_vote_force_active_get(struct votable *votable, u64 *val); +int pmic_vote_force_active_set(struct votable *votable, u64 val); + #endif /* __PMIC_VOTER_H */ From a0ecbc9a1b4025526afc3a7cd1fee61e54120b80 Mon Sep 17 00:00:00 2001 From: mahj8 Date: Thu, 1 Oct 2020 15:39:32 +0800 Subject: [PATCH 187/698] power: supply/qcom: smb5-lib: Select PDO The charger driver should directly call into the policy engine and select the proper PDO. Otherwise the first PDO is selected. refer to https://gerrit.mot.com/1403773 Based on Gerrit https://gerrit.mot.com/#/c/1301691/ Change-Id: I73a2ef923393977e202aebc142d09c4301de4fbe Signed-off-by: mahj8 Reviewed-on: https://gerrit.mot.com/1770246 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- drivers/power/supply/qcom/smb5-lib.c | 77 +++++++++++++++++++++++++++- drivers/power/supply/qcom/smb5-lib.h | 6 +++ 2 files changed, 82 insertions(+), 1 deletion(-) diff --git a/drivers/power/supply/qcom/smb5-lib.c b/drivers/power/supply/qcom/smb5-lib.c index 538bd7116830..360af44261a6 100644 --- a/drivers/power/supply/qcom/smb5-lib.c +++ b/drivers/power/supply/qcom/smb5-lib.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -795,8 +796,9 @@ static int smblib_set_usb_pd_allowed_voltage(struct smb_charger *chg, int min_allowed_uv, int max_allowed_uv) { int rc, aicl_threshold; - u8 vbus_allowance; + u8 vbus_allowance = FORCE_NULL; +#ifdef QCOM_BASE if (chg->chg_param.smb_version == PMI632) return 0; @@ -831,6 +833,14 @@ static int smblib_set_usb_pd_allowed_voltage(struct smb_charger *chg, return rc; } +#else + if (chg->pd_active && (chg->pd_contract_uv <= 0)) { + cancel_delayed_work(&chg->pd_contract_work); + schedule_delayed_work(&chg->pd_contract_work, + msecs_to_jiffies(0)); + } +#endif + if (vbus_allowance != CONTINUOUS) return 0; @@ -3445,6 +3455,7 @@ int smblib_get_prop_usb_voltage_max_design(struct smb_charger *chg, { switch (chg->real_charger_type) { case QTI_POWER_SUPPLY_TYPE_USB_HVDCP: +#ifdef QCOM_BASE if (chg->qc2_unsupported_voltage == QC2_NON_COMPLIANT_9V) { val->intval = MICRO_5V; break; @@ -3484,13 +3495,22 @@ int smblib_get_prop_usb_voltage_max(struct smb_charger *chg, break; } /* else, fallthrough */ +#else + val->intval = MICRO_5V; + break; +#endif case QTI_POWER_SUPPLY_TYPE_USB_HVDCP_3P5: case QTI_POWER_SUPPLY_TYPE_USB_HVDCP_3: +#ifdef QCOM_BASE if (chg->chg_param.smb_version == PMI632) val->intval = MICRO_9V; else val->intval = MICRO_12V; break; +#else + val->intval = MICRO_5V; + break; +#endif case POWER_SUPPLY_TYPE_USB_PD: val->intval = chg->voltage_max_uv; break; @@ -4393,6 +4413,7 @@ int smblib_set_prop_pd_current_max(struct smb_charger *chg, int rc, icl; if (chg->pd_active) { + smblib_err(chg, "set pd current %d\n", val); icl = get_client_vote(chg->usb_icl_votable, PD_VOTER); rc = vote(chg->usb_icl_votable, PD_VOTER, true, val); if (val != icl) @@ -4714,6 +4735,8 @@ int smblib_set_prop_pd_voltage_max(struct smb_charger *chg, max_uv = max(val, chg->voltage_min_uv); if (chg->voltage_max_uv == max_uv) return 0; + else if (chg->pd_active) + chg->pd_contract_uv = 0; rc = smblib_set_usb_pd_fsw(chg, max_uv); if (rc < 0) { @@ -4784,6 +4807,11 @@ int smblib_set_prop_pd_active(struct smb_charger *chg, dev_err(chg->dev, "Couldn't enable secondary charger rc=%d\n", rc); } + if (chg->pd_contract_uv <= 0) { + cancel_delayed_work(&chg->pd_contract_work); + schedule_delayed_work(&chg->pd_contract_work, + msecs_to_jiffies(0)); + } } else { vote(chg->usb_icl_votable, PD_VOTER, false, 0); vote(chg->limited_irq_disable_votable, CHARGER_TYPE_VOTER, @@ -6409,6 +6437,7 @@ static void typec_src_removal(struct smb_charger *chg) chg->voltage_max_uv = MICRO_5V; chg->usbin_forced_max_uv = 0; chg->chg_param.forced_main_fcc = 0; + chg->pd_contract_uv = 0; /* Reset all CC mode votes */ vote(chg->fcc_main_votable, MAIN_FCC_VOTER, false, 0); @@ -7314,6 +7343,51 @@ int smblib_set_prop_pr_swap_in_progress(struct smb_charger *chg, /*************** * Work Queues * ***************/ +#define MAX_INPUT_PWR_UW 18000000 +static void smblib_pd_contract_work(struct work_struct *work) +{ + struct smb_charger *chg = container_of(work, struct smb_charger, + pd_contract_work.work); + int rc, max_ua; + + if (!chg->pd) { + chg->pd = devm_usbpd_get_by_phandle(chg->dev, + "qcom,usbpd-phandle"); + if (IS_ERR_OR_NULL(chg->pd)) { + pr_err("Error getting the pd phandle %ld\n", + PTR_ERR(chg->pd)); + chg->pd = NULL; + } + } + if (!chg->pd || !chg->pd_active) + return; + + chg->pd_contract_uv = usbpd_select_pdo_match(chg->pd); + + if (chg->pd_contract_uv == -ENOTSUPP) + return; + + if (chg->pd_contract_uv <= 0) { + schedule_delayed_work(&chg->pd_contract_work, + msecs_to_jiffies(100)); + return; + } else + power_supply_changed(chg->usb_psy); + + if (chg->pd_contract_uv >= MICRO_9V) + smblib_set_opt_switcher_freq(chg, chg->chg_freq.freq_9V); + else + smblib_set_opt_switcher_freq(chg, chg->chg_freq.freq_5V); + + max_ua = (MAX_INPUT_PWR_UW / (chg->pd_contract_uv / 1000)) * 1000; + smblib_err(chg, "smblib_pd_contract_work: %d uV, %d uA\n", + chg->pd_contract_uv, max_ua); + + rc = vote(chg->usb_icl_votable, PD_VOTER, true, max_ua); + if (rc < 0) + smblib_err(chg, "Error setting %d uA rc=%d\n", max_ua, rc); +} + static void smblib_pr_lock_clear_work(struct work_struct *work) { struct smb_charger *chg = container_of(work, struct smb_charger, @@ -8350,6 +8424,7 @@ int smblib_init(struct smb_charger *chg) smblib_pr_swap_detach_work); INIT_DELAYED_WORK(&chg->pr_lock_clear_work, smblib_pr_lock_clear_work); + INIT_DELAYED_WORK(&chg->pd_contract_work, smblib_pd_contract_work); timer_setup(&chg->apsd_timer, apsd_timer_cb, 0); INIT_DELAYED_WORK(&chg->role_reversal_check, diff --git a/drivers/power/supply/qcom/smb5-lib.h b/drivers/power/supply/qcom/smb5-lib.h index f3c38894650a..9071972a9a49 100644 --- a/drivers/power/supply/qcom/smb5-lib.h +++ b/drivers/power/supply/qcom/smb5-lib.h @@ -17,6 +17,7 @@ #include #include #include +#include #include "storm-watch.h" #include "battery.h" @@ -607,6 +608,11 @@ struct smb_charger { /* extcon for VBUS / ID notification to USB for uUSB */ struct extcon_dev *extcon; + /* USB PD interactions */ + struct usbpd *pd; + int pd_contract_uv; + struct delayed_work pd_contract_work; + /* battery profile */ int batt_profile_fcc_ua; int batt_profile_fv_uv; From 667b71ea21664412190ba5f0fdd38a0049bf61ba Mon Sep 17 00:00:00 2001 From: mahj8 Date: Thu, 1 Oct 2020 15:40:59 +0800 Subject: [PATCH 188/698] usb: pd: Add PDO Selection The PDO selection should be done by either the Kernel or User Space. Setup a callback that selects the PDO based on what the Voltage Max is set to when the function is called. refer to https://gerrit.mot.com/1403781 Based on Gerrit https://gerrit.mot.com/#/c/1301690/ Change-Id: I54a14b47e79637c681cc24c78a75a1206ecd903e Signed-off-by: mahj8 Reviewed-on: https://gerrit.mot.com/1770248 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- drivers/usb/pd/policy_engine.c | 103 +++++++++++++++++++++++++++++++++ include/linux/usb/usbpd.h | 5 ++ 2 files changed, 108 insertions(+) diff --git a/drivers/usb/pd/policy_engine.c b/drivers/usb/pd/policy_engine.c index 2839abb1d86c..53577aa7dd74 100644 --- a/drivers/usb/pd/policy_engine.c +++ b/drivers/usb/pd/policy_engine.c @@ -891,6 +891,32 @@ static int pd_select_pdo(struct usbpd *pd, int pdo_pos, int uv, int ua) pd->requested_current = curr; pd->requested_pdo = pdo_pos; + usbpd_warn(&pd->dev, "select_pdo: PDO:%d, %d uV, %d uA\n", + pdo_pos, uv, ua); + + return 0; +} + +static int pd_get_pdo(struct usbpd *pd, int pdo_pos, int *uv_max, int *uv_min, int *ua) +{ + u8 type; + u32 pdo = pd->received_pdos[pdo_pos - 1]; + + if (0 == pdo) + return -ENOTSUPP; + + type = PD_SRC_PDO_TYPE(pdo); + if (type == PD_SRC_PDO_TYPE_FIXED) { + *ua = PD_SRC_PDO_FIXED_MAX_CURR(pdo) * 10; + *uv_max = *uv_min = PD_SRC_PDO_FIXED_VOLTAGE(pdo) * 50 * 1000; + } else if (type == PD_SRC_PDO_TYPE_AUGMENTED) { + *uv_max = PD_APDO_MAX_VOLT(pdo) * 100000; + *uv_min = PD_APDO_MIN_VOLT(pdo) * 100000; + *ua = PD_APDO_MAX_CURR(pdo) * 50000; + } else { + usbpd_err(&pd->dev, "Only Fixed or Programmable PDOs supported\n"); + return -ENOTSUPP; + } return 0; } @@ -4228,6 +4254,83 @@ static ssize_t pdo_n_show(struct device *dev, struct device_attribute *attr, return -EINVAL; } +int usbpd_select_pdo_match(struct usbpd *pd) +{ + int uv_diff = 0, max_uv_diff = 0, pdo = 0; + int pdo_max_uv = 0, pdo_min_uv = 0, pdo_ua = 0; + int uv_in, i; + int ret; + union power_supply_propval val; + + if (!pd) + return -EINVAL; + + mutex_lock(&pd->swap_lock); + + /* Only allowed if we are already in explicit sink contract */ + if (pd->current_state != PE_SNK_READY || !is_sink_tx_ok(pd)) { + usbpd_err(&pd->dev, "select_pdo: Cannot select new PDO yet\n"); + ret = -EBUSY; + goto out; + } + + /* Check the Max Input Voltage from USBPSY */ + power_supply_get_property(pd->usb_psy, + POWER_SUPPLY_PROP_VOLTAGE_MAX, &val); + uv_in = val.intval; + /* start with 5 V */ + max_uv_diff = 5000000; + for (i = 1; i < 8; i++) { + if (!pd_get_pdo(pd, i, &pdo_max_uv, &pdo_min_uv, &pdo_ua)) { + if (pdo_max_uv <= uv_in) { + uv_diff = uv_in - pdo_max_uv; + if (uv_diff < max_uv_diff) { + max_uv_diff = uv_diff; + pdo = i; + } + } + } + } + + if (pdo < 1 || pdo > 7) { + usbpd_err(&pd->dev, "select_pdo: invalid PDO:%d\n", pdo); + ret = -EINVAL; + goto out; + } + + pd_get_pdo(pd, pdo, &pdo_max_uv, &pdo_min_uv, &pdo_ua); + ret = pd_select_pdo(pd, pdo, pdo_max_uv, pdo_ua); + if (ret) + goto out; + else + ret = pdo_max_uv; + + reinit_completion(&pd->is_ready); + pd->send_request = true; + kick_sm(pd, 0); + + /* wait for operation to complete */ + if (!wait_for_completion_timeout(&pd->is_ready, + msecs_to_jiffies(1000))) { + usbpd_err(&pd->dev, "select_pdo: request timed out\n"); + ret = -ETIMEDOUT; + goto out; + } + + /* determine if request was accepted/rejected */ + if (pd->selected_pdo != pd->requested_pdo || + pd->current_voltage != pd->requested_voltage) { + usbpd_err(&pd->dev, "select_pdo: request rejected\n"); + ret = -EINVAL; + } + +out: + pd->send_request = false; + mutex_unlock(&pd->swap_lock); + return ret; +} +EXPORT_SYMBOL(usbpd_select_pdo_match); + static ssize_t select_pdo_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { diff --git a/include/linux/usb/usbpd.h b/include/linux/usb/usbpd.h index 037abb0d25d0..378bbab17610 100644 --- a/include/linux/usb/usbpd.h +++ b/include/linux/usb/usbpd.h @@ -99,6 +99,11 @@ int usbpd_send_svdm(struct usbpd *pd, u16 svid, u8 cmd, enum usbpd_svdm_cmd_type cmd_type, int obj_pos, const u32 *vdos, int num_vdos); +/* + * Look for best match for PDO selection in Source Mode. + */ +int usbpd_select_pdo_match(struct usbpd *pd); + /* * Get current status of CC pin orientation. * From cdb6ff52ea2b518216d8d4f185d9d8e95b77c09f Mon Sep 17 00:00:00 2001 From: mahj8 Date: Thu, 1 Oct 2020 16:38:26 +0800 Subject: [PATCH 189/698] pd-policy: Only select FIXED pdo in usbpd_select_pdo_match Current Moto PD controlling policy only applies to FIXED pdo but not programmable pdo(PPS), which requires periodic PD output power acknowledgement(at least 10s interval). So it has to redesign current Moto PD controlling policy to support PPS pdo selection. In order to avoid any PD controlling policy conflict with third party disable the PD controlling policy modification interfaces for user space (may be used by hvdcp_opti daemon in Qcom platform). pdo selection is only available in sink power role, so just return unsupported to tell the caller not try any more. refer to https://gerrit.mot.com/1461360 Change-Id: I675a1f21e6547b1e4e8af01c5f4ebe4a89972c41 Signed-off-by: mahj8 Reviewed-on: https://gerrit.mot.com/1770250 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- drivers/usb/pd/policy_engine.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/drivers/usb/pd/policy_engine.c b/drivers/usb/pd/policy_engine.c index 53577aa7dd74..ae59318d30e0 100644 --- a/drivers/usb/pd/policy_engine.c +++ b/drivers/usb/pd/policy_engine.c @@ -4259,6 +4259,8 @@ int usbpd_select_pdo_match(struct usbpd *pd) int uv_diff = 0, max_uv_diff = 0, pdo = 0; int pdo_max_uv = 0, pdo_min_uv = 0, pdo_ua = 0; int uv_in, i; + int pdo_pos; + u8 type = -1; int ret; union power_supply_propval val; @@ -4267,6 +4269,12 @@ int usbpd_select_pdo_match(struct usbpd *pd) mutex_lock(&pd->swap_lock); + if (pd->current_pr == PR_SRC) { + usbpd_err(&pd->dev, "select_pdo: not support in source mode\n"); + ret = -ENOTSUPP; + goto out; + } + /* Only allowed if we are already in explicit sink contract */ if (pd->current_state != PE_SNK_READY || !is_sink_tx_ok(pd)) { usbpd_err(&pd->dev, "select_pdo: Cannot select new PDO yet\n"); @@ -4281,7 +4289,11 @@ int usbpd_select_pdo_match(struct usbpd *pd) /* start with 5 V */ max_uv_diff = 5000000; for (i = 1; i < 8; i++) { - if (!pd_get_pdo(pd, i, &pdo_max_uv, &pdo_min_uv, &pdo_ua)) { + pdo_pos = pd->received_pdos[i - 1]; + if (pdo_pos != 0) + type = PD_SRC_PDO_TYPE(pdo_pos); + if (type == PD_SRC_PDO_TYPE_FIXED && + pd_get_pdo(pd, i, &pdo_max_uv, &pdo_min_uv, &pdo_ua)) { if (pdo_max_uv <= uv_in) { uv_diff = uv_in - pdo_max_uv; if (uv_diff < max_uv_diff) { @@ -4294,7 +4306,7 @@ int usbpd_select_pdo_match(struct usbpd *pd) if (pdo < 1 || pdo > 7) { usbpd_err(&pd->dev, "select_pdo: invalid PDO:%d\n", pdo); - ret = -EINVAL; + ret = pd->current_voltage; goto out; } @@ -4334,6 +4346,7 @@ EXPORT_SYMBOL(usbpd_select_pdo_match); static ssize_t select_pdo_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { +#ifdef QCOM_BASE struct usbpd *pd = dev_get_drvdata(dev); int src_cap_id; int pdo, uv = 0, ua = 0; @@ -4395,6 +4408,9 @@ out: pd->send_request = false; mutex_unlock(&pd->swap_lock); return ret ? ret : size; +#else + return size; +#endif } static ssize_t select_pdo_show(struct device *dev, From f59ce68e5526367e531224e5c657bb4e9a935c8f Mon Sep 17 00:00:00 2001 From: Haijian Ma Date: Wed, 11 Sep 2019 16:15:18 +0800 Subject: [PATCH 190/698] smb5: get correct HW current In factory mode, mmi init input current 3A, so get ICL state is 3A. so mmi get HW current is 3A with SDP. HW current should base on charger type, don't base on ICL state. Change-Id: I3b0aab68392f863115721f96f3dd4788dc9e0df7 Signed-off-by: Haijian Ma Reviewed-on: https://gerrit.mot.com/1419455 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Yonghua Yan Reviewed-by: Huosheng Liao Submit-Approved: Jira Key Reviewed-on: https://gerrit.mot.com/1770253 --- drivers/power/supply/qcom/smb5-lib.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/power/supply/qcom/smb5-lib.c b/drivers/power/supply/qcom/smb5-lib.c index 360af44261a6..294180812f51 100644 --- a/drivers/power/supply/qcom/smb5-lib.c +++ b/drivers/power/supply/qcom/smb5-lib.c @@ -5094,12 +5094,15 @@ int smblib_get_charge_current(struct smb_charger *chg, case FLOAT_CHARGER_BIT: current_ua = DCP_CURRENT_UA; break; + case SDP_CHARGER_BIT: + current_ua = SDP_CURRENT_UA; + break; default: current_ua = 0; break; } - *total_current_ua = max(current_ua, val.intval); + *total_current_ua = current_ua; return 0; } @@ -5114,6 +5117,9 @@ int smblib_get_charge_current(struct smb_charger *chg, case FLOAT_CHARGER_BIT: current_ua = chg->default_icl_ua; break; + case SDP_CHARGER_BIT: + current_ua = SDP_CURRENT_UA; + break; default: current_ua = 0; break; @@ -5132,7 +5138,7 @@ int smblib_get_charge_current(struct smb_charger *chg, break; } - *total_current_ua = max(current_ua, val.intval); + *total_current_ua = current_ua; return 0; } From c51b3de0dead37d3f2a5d0ae95a59d335de80669 Mon Sep 17 00:00:00 2001 From: mahj8 Date: Fri, 9 Oct 2020 09:42:36 +0800 Subject: [PATCH 191/698] smb5-lib: config QC2.0 charging current 1.5A QC2.0 adapter only support 1.6A output current, so config 1.5A for QC2.0 charger. refer to https://gerrit.mot.com/1430172 Change-Id: I05bad6d5f9f59ccb19beb987271bc412c12ff7f1 Signed-off-by: mahj8 Reviewed-on: https://gerrit.mot.com/1770254 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- drivers/power/supply/qcom/smb5-lib.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/power/supply/qcom/smb5-lib.c b/drivers/power/supply/qcom/smb5-lib.c index 294180812f51..97cf82a58723 100644 --- a/drivers/power/supply/qcom/smb5-lib.c +++ b/drivers/power/supply/qcom/smb5-lib.c @@ -5079,7 +5079,10 @@ int smblib_get_charge_current(struct smb_charger *chg, typec_source_rd = smblib_get_prop_ufp_mode(chg); /* QC 2.0/3.0 adapter */ - if (apsd_result->bit & (QC_3P0_BIT | QC_2P0_BIT)) { + if (apsd_result->bit & QC_2P0_BIT) { + *total_current_ua = chg->chg_param.hvdcp2_max_icl_ua; + return 0; + } else if (apsd_result->bit & QC_3P0_BIT){ *total_current_ua = HVDCP_CURRENT_UA; return 0; } From c6b24a9e8b65a38414f8b8eee570b270d60102b0 Mon Sep 17 00:00:00 2001 From: cmsantos Date: Thu, 31 Oct 2019 19:52:41 -0500 Subject: [PATCH 192/698] qpnp-smb5: Add a parent supply for vconn VCONN can be turned on even without VBUS (which turns on the 5V supply). Hence add a parent supply for VCONN. Ported from: https://gerrit.mot.com/#/c/1232907/ Change-Id: I37b4fe5d0b2a38Montanad6674b496582519b8c35e47 Signed-off-by: cmsantos Reviewed-on: https://gerrit.mot.com/1447502 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Curtis Porter Reviewed-by: Ling Jin Submit-Approved: Jira Key Reviewed-on: https://gerrit.mot.com/1770255 Reviewed-by: Huosheng Liao --- drivers/power/supply/qcom/qpnp-smb5.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/power/supply/qcom/qpnp-smb5.c b/drivers/power/supply/qcom/qpnp-smb5.c index 8a25745698a3..8b755c70712c 100644 --- a/drivers/power/supply/qcom/qpnp-smb5.c +++ b/drivers/power/supply/qcom/qpnp-smb5.c @@ -1469,6 +1469,9 @@ static int smb5_init_vconn_regulator(struct smb5 *chip) chg->vconn_vreg->rdesc.of_match = "qcom,smb5-vconn"; chg->vconn_vreg->rdesc.name = "qcom,smb5-vconn"; + if (of_get_property(chg->dev->of_node, "vconn-parent-supply", NULL)) + chg->vconn_vreg->rdesc.supply_name = "vconn-parent"; + chg->vconn_vreg->rdev = devm_regulator_register(chg->dev, &chg->vconn_vreg->rdesc, &cfg); if (IS_ERR(chg->vconn_vreg->rdev)) { From 1baac9bfe0f4bc11b719f222259b8bc0b45edcc8 Mon Sep 17 00:00:00 2001 From: xuwt2 Date: Mon, 25 Nov 2019 11:12:46 +0800 Subject: [PATCH 193/698] smb5-lib: Remove Force_5V setting in PD active PD adapter allowance voltage was setted to FORCE_5V, that cause PD can't charge under the vbus up to 9v this issue is introduced by QCom Rebase. use QCOM_BASE to isolate FORCE_5V setting in PD active Change-Id: I73d925b87e657f62516d7d3ee475f4ef0306195d Signed-off-by: xuwt2 Reviewed-on: https://gerrit.mot.com/1460627 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Cesar Augusto Marcelino dos Santos Reviewed-by: Haijian Ma Reviewed-by: Yonghua Yan Reviewed-by: Jianqi Yang Submit-Approved: Jira Key Reviewed-on: https://gerrit.mot.com/1770256 Reviewed-by: Huosheng Liao --- drivers/power/supply/qcom/smb5-lib.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/power/supply/qcom/smb5-lib.c b/drivers/power/supply/qcom/smb5-lib.c index 97cf82a58723..da5c7347dbf5 100644 --- a/drivers/power/supply/qcom/smb5-lib.c +++ b/drivers/power/supply/qcom/smb5-lib.c @@ -4836,8 +4836,10 @@ int smblib_set_prop_pd_active(struct smb_charger *chg, } } +#ifdef QCOM_BASE smblib_usb_pd_adapter_allowance_override(chg, !!chg->pd_active ? FORCE_5V : FORCE_NULL); +#endif smblib_update_usb_type(chg); if (chg->real_charger_type == POWER_SUPPLY_TYPE_USB && From c20f525d75eb0da1882cfb282c5e7a619dc5fc63 Mon Sep 17 00:00:00 2001 From: xuwt2 Date: Tue, 4 Feb 2020 17:07:01 +0800 Subject: [PATCH 194/698] qpnp-smb5: enable IRQ and MISC debug_mask Enable the debug log or IRQ and MISC charger event for charger issue dignosis Change-Id: I68743f335eb4805bf4216035ac864811e5cc7452 Signed-off-by: xuwt2 Reviewed-on: https://gerrit.mot.com/1492207 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Jianqi Yang Submit-Approved: Jira Key Reviewed-on: https://gerrit.mot.com/1770257 Reviewed-by: Huosheng Liao --- drivers/power/supply/qcom/qpnp-smb5.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/power/supply/qcom/qpnp-smb5.c b/drivers/power/supply/qcom/qpnp-smb5.c index 8b755c70712c..21507267e9b8 100644 --- a/drivers/power/supply/qcom/qpnp-smb5.c +++ b/drivers/power/supply/qcom/qpnp-smb5.c @@ -229,7 +229,7 @@ struct smb5 { struct iio_chan_spec *iio_chan_ids; }; -static int __debug_mask; +static int __debug_mask = PR_MISC | PR_INTERRUPT; static ssize_t pd_disabled_show(struct device *dev, struct device_attribute *attr, char *buf) From 431ef6f563366c97072b1728bc6121c41170e6d5 Mon Sep 17 00:00:00 2001 From: Cesar Santos Date: Thu, 28 Nov 2019 15:45:20 -0300 Subject: [PATCH 195/698] drivers: qcom: Support debug accessory in sink mode Huawai P10 5A cable is considered a debug accessory cable in sink mode, so charging in such conditions needs to be configured by setting proper PMIC registers. Porter from: https://gerrit.mot.com/#/c/1447696/ Change-Id: I978911ae93436c8b073fa092548e13f673262bb9 Signed-off-by: Cesar Santos Reviewed-on: https://gerrit.mot.com/1463313 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Dong-Hua Yan Reviewed-by: Ling Jin Submit-Approved: Jira Key Reviewed-on: https://gerrit.mot.com/1770258 Reviewed-by: Huosheng Liao --- drivers/power/supply/qcom/qpnp-smb5.c | 13 +++++++++++++ drivers/power/supply/qcom/smb5-lib.c | 7 +++---- drivers/power/supply/qcom/smb5-reg.h | 3 +++ 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/drivers/power/supply/qcom/qpnp-smb5.c b/drivers/power/supply/qcom/qpnp-smb5.c index 21507267e9b8..37527fcf1a9c 100644 --- a/drivers/power/supply/qcom/qpnp-smb5.c +++ b/drivers/power/supply/qcom/qpnp-smb5.c @@ -1586,6 +1586,19 @@ static int smb5_configure_typec(struct smb_charger *chg) } } + /* + * Config SCHG_P_TYPEC_TYPE_C_CCOUT_CONTROL to 0x03 + * Enable detection of debug accessory in sink mode + */ + rc = smblib_masked_write(chg, TYPE_C_DEBUG_ACCESS_SINK_REG, + TYPEC_DEBUG_ACCESS_SINK_MASK, 0x03); + if (rc < 0) { + dev_err(chg->dev, + "Couldn't configure TYPE_C_DEBUG_ACCESS_SINK_REG rc=%d\n", + rc); + return rc; + } + if (chg->chg_param.smb_version != PMI632) { /* * Enable detection of unoriented debug diff --git a/drivers/power/supply/qcom/smb5-lib.c b/drivers/power/supply/qcom/smb5-lib.c index da5c7347dbf5..ce1134ad2d7b 100644 --- a/drivers/power/supply/qcom/smb5-lib.c +++ b/drivers/power/supply/qcom/smb5-lib.c @@ -3834,18 +3834,17 @@ static int smblib_get_prop_ufp_mode(struct smb_charger *chg) smblib_dbg(chg, PR_REGISTER, "TYPE_C_STATUS_1 = 0x%02x\n", stat); switch (stat & DETECTED_SRC_TYPE_MASK) { + case SNK_DAM_500MA_BIT: case SNK_RP_STD_BIT: return QTI_POWER_SUPPLY_TYPEC_SOURCE_DEFAULT; + case SNK_DAM_1500MA_BIT: case SNK_RP_1P5_BIT: return QTI_POWER_SUPPLY_TYPEC_SOURCE_MEDIUM; + case SNK_DAM_3000MA_BIT: case SNK_RP_3P0_BIT: return QTI_POWER_SUPPLY_TYPEC_SOURCE_HIGH; case SNK_RP_SHORT_BIT: return QTI_POWER_SUPPLY_TYPEC_NON_COMPLIANT; - case SNK_DAM_500MA_BIT: - case SNK_DAM_1500MA_BIT: - case SNK_DAM_3000MA_BIT: - return QTI_POWER_SUPPLY_TYPEC_SINK_DEBUG_ACCESSORY; default: break; } diff --git a/drivers/power/supply/qcom/smb5-reg.h b/drivers/power/supply/qcom/smb5-reg.h index 71b4de85c159..2f9976a659e4 100644 --- a/drivers/power/supply/qcom/smb5-reg.h +++ b/drivers/power/supply/qcom/smb5-reg.h @@ -395,6 +395,9 @@ enum { #define TYPEC_CCOUT_VALUE_BIT BIT(1) #define TYPEC_CCOUT_SRC_BIT BIT(0) +#define TYPE_C_DEBUG_ACCESS_SINK_REG (TYPEC_BASE + 0x4A) +#define TYPEC_DEBUG_ACCESS_SINK_MASK GENMASK(4, 0) + #define DEBUG_ACCESS_SRC_CFG_REG (TYPEC_BASE + 0x4C) #define EN_UNORIENTED_DEBUG_ACCESS_SRC_BIT BIT(0) From e31bf366e3203db940666e22f89e9c08fc4670c2 Mon Sep 17 00:00:00 2001 From: Yonghua Yan Date: Thu, 16 May 2019 22:15:15 +0800 Subject: [PATCH 196/698] smb5-lib: Skip USB ICL vote for high or medium typec When connect the device to the typec port of a PC with high or medium source advertise, the USB ICL is overridden by USB phy voter with 500mA. But for non-legacy typec, the typec source advertise should be prior to usb bc1.2. So add condition check when set the USB ICL vote from USB driver, if there is high or mid typec source advertise, and just skip the USB driver ICL voter. Change-Id: I519cf1afec40857ca640727fee6cc11f262af492 Signed-off-by: Yonghua Yan Reviewed-on: https://gerrit.mot.com/1355853 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Huosheng Liao Reviewed-by: Jianqi Yang Submit-Approved: Jira Key Reviewed-on: https://gerrit.mot.com/1770259 --- drivers/power/supply/qcom/smb5-lib.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/power/supply/qcom/smb5-lib.c b/drivers/power/supply/qcom/smb5-lib.c index ce1134ad2d7b..cbd1688f712e 100644 --- a/drivers/power/supply/qcom/smb5-lib.c +++ b/drivers/power/supply/qcom/smb5-lib.c @@ -4487,6 +4487,10 @@ static int smblib_handle_usb_current(struct smb_charger *chg, if (!rc && !val.intval) return 0; + typec_mode = smblib_get_prop_typec_mode(chg); + if (typec_rp_med_high(chg, typec_mode)) + return 0; + /* if flash is active force 500mA */ if ((usb_current < SDP_CURRENT_UA) && is_flash_active(chg)) usb_current = SDP_CURRENT_UA; From 62e7b0c46d41277705952e1612fb8ebd064266d4 Mon Sep 17 00:00:00 2001 From: Haijian Ma Date: Fri, 16 Nov 2018 12:45:53 +0800 Subject: [PATCH 197/698] battery: Fix Type-C audio adapter detection at boot. Commit "update parallel algorithm for ICL change" breaks type-C Analog Audio adapter detection at boot time. Avoid re-running AICL at boot (when icl_ua is unitialized) and also minimize the wait time for AICL to complete. refer to https://gerrit.mot.com/994075 Change-Id: I7ce1d76a9e10684f478cfff36cd631ed4066143b Signed-off-by: Haijian Ma Reviewed-on: https://gerrit.mot.com/1270015 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key Reviewed-on: https://gerrit.mot.com/1770260 --- drivers/power/supply/qcom/battery.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/power/supply/qcom/battery.c b/drivers/power/supply/qcom/battery.c index 5ba4510aad39..c2fd21158acc 100644 --- a/drivers/power/supply/qcom/battery.c +++ b/drivers/power/supply/qcom/battery.c @@ -1390,12 +1390,13 @@ static int usb_icl_vote_callback(struct votable *votable, void *data, } /* rerun AICL if new ICL is above settled ICL */ - if (icl_ua > val) + if (icl_ua != INT_MAX && icl_ua > val) rerun_aicl = true; if (rerun_aicl && (chip->wa_flags & AICL_RERUN_WA_BIT)) { /* set a lower ICL */ val = max(val - ICL_STEP_UA, ICL_STEP_UA); + pr_debug("****initial step icl setting %d\n", val); rc = chip->chg_param->iio_write(chip->dev, PSY_IIO_CURRENT_MAX, val); if (rc < 0) @@ -1404,6 +1405,7 @@ static int usb_icl_vote_callback(struct votable *votable, void *data, /* set the effective ICL */ val = icl_ua; + pr_debug("****final icl setting %d\n", val); rc = chip->chg_param->iio_write(chip->dev, PSY_IIO_CURRENT_MAX, val); if (rc < 0) pr_err("Couldn't set main current_max, rc=%d\n", rc); From 44bf0b8116bfb7d0ccb46056f6fe09a062b0c548 Mon Sep 17 00:00:00 2001 From: Yonghua Yan Date: Thu, 30 May 2019 21:42:24 +0800 Subject: [PATCH 198/698] smb5: report effective icl value for current max Attach Turbo charger to a phone, its screen shows the messages: "Charging", followed by "Slowly Charging" and then finally "TurboPower connected". Display messages are confusing. This is because the USB ICL takes a period time to get settled down from low icl to the target icl. So here just return the target ICL to avoid this situation. Change-Id: I1a3e4641c31fde6b59cc017e01b26a6ea12c6d15 Signed-off-by: Yonghua Yan Reviewed-on: https://gerrit.mot.com/1364059 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Haijian Ma Reviewed-by: Huosheng Liao Submit-Approved: Jira Key Reviewed-on: https://gerrit.mot.com/1770261 --- drivers/power/supply/qcom/qpnp-smb5.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/power/supply/qcom/qpnp-smb5.c b/drivers/power/supply/qcom/qpnp-smb5.c index 37527fcf1a9c..dd02103a5575 100644 --- a/drivers/power/supply/qcom/qpnp-smb5.c +++ b/drivers/power/supply/qcom/qpnp-smb5.c @@ -871,7 +871,7 @@ static int smb5_usb_get_prop(struct power_supply *psy, rc = smblib_get_prop_usb_current_now(chg, val); break; case POWER_SUPPLY_PROP_CURRENT_MAX: - rc = smblib_get_prop_input_current_max(chg, val); + val->intval = get_effective_result(chg->usb_icl_votable); break; case POWER_SUPPLY_PROP_TYPE: val->intval = POWER_SUPPLY_TYPE_USB_PD; From a8e77d8c58d1ec1546f50e4558b24cd98ac519ef Mon Sep 17 00:00:00 2001 From: Yonghua Yan Date: Fri, 14 Jun 2019 18:17:22 +0800 Subject: [PATCH 199/698] smb5: limit usb icl to 1000mA for OCP type Limit the usb icl to 1000mA for OCP chargers(BELKIN 5V/1A) to avoid sudden vbus loss when the current load over 1000mA. Change-Id: Iad650afcb0263e861171223967d3ab5a688346c3 Signed-off-by: Yonghua Yan Reviewed-on: https://gerrit.mot.com/1371196 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Haijian Ma Reviewed-by: Huosheng Liao Submit-Approved: Jira Key Reviewed-on: https://gerrit.mot.com/1770268 --- drivers/power/supply/qcom/smb5-lib.c | 3 +++ drivers/power/supply/qcom/smb5-lib.h | 1 + 2 files changed, 4 insertions(+) diff --git a/drivers/power/supply/qcom/smb5-lib.c b/drivers/power/supply/qcom/smb5-lib.c index cbd1688f712e..dfaf35b9a9b3 100644 --- a/drivers/power/supply/qcom/smb5-lib.c +++ b/drivers/power/supply/qcom/smb5-lib.c @@ -5991,6 +5991,9 @@ static void smblib_handle_apsd_done(struct smb_charger *chg, bool rising) smblib_notify_device_mode(chg, true); break; case OCP_CHARGER_BIT: + vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, true, + OCP_CURRENT_UA); + break; case DCP_CHARGER_BIT: break; default: diff --git a/drivers/power/supply/qcom/smb5-lib.h b/drivers/power/supply/qcom/smb5-lib.h index 9071972a9a49..3428fd690991 100644 --- a/drivers/power/supply/qcom/smb5-lib.h +++ b/drivers/power/supply/qcom/smb5-lib.h @@ -96,6 +96,7 @@ enum print_reason { #define SDP_100_MA 100000 #define SDP_CURRENT_UA 500000 +#define OCP_CURRENT_UA 1000000 #define CDP_CURRENT_UA 1500000 #define DCP_CURRENT_UA 1500000 #define HVDCP_CURRENT_UA 3000000 From 89ecc01a29f823f6740020cefa1cd3d17e90f985 Mon Sep 17 00:00:00 2001 From: Yonghua Yan Date: Tue, 23 Jul 2019 21:04:26 +0800 Subject: [PATCH 200/698] smb5: handle cc pin floated cable removal When use the CC pin floated USB cable to connect to PC or charger, typec mode cannot be detected, so it cannot use the typec removal when USB cable is removed. Since this USB cable make the device function as micro usb, so just call the micro usb removal. Change-Id: I6cf9fbcffa1fe05bade64dfce9309977e782eba4 Signed-off-by: Yonghua Yan Reviewed-on: https://gerrit.mot.com/1390306 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Jianqi Yang Submit-Approved: Jira Key Reviewed-on: https://gerrit.mot.com/1770289 Reviewed-by: Huosheng Liao --- drivers/power/supply/qcom/smb5-lib.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/power/supply/qcom/smb5-lib.c b/drivers/power/supply/qcom/smb5-lib.c index dfaf35b9a9b3..1e6f981afff1 100644 --- a/drivers/power/supply/qcom/smb5-lib.c +++ b/drivers/power/supply/qcom/smb5-lib.c @@ -5780,7 +5780,8 @@ static void smblib_usb_plugin_locked(struct smb_charger *chg) smblib_update_usb_type(chg); } - if (chg->connector_type == QTI_POWER_SUPPLY_CONNECTOR_MICRO_USB) + if (chg->connector_type == QTI_POWER_SUPPLY_CONNECTOR_MICRO_USB || + chg->typec_mode == QTI_POWER_SUPPLY_TYPEC_NONE) smblib_micro_usb_plugin(chg, vbus_rising); vote(chg->temp_change_irq_disable_votable, DEFAULT_VOTER, From 018560f4b8f80f1ccc6a6d03b6e5e8faffc949e2 Mon Sep 17 00:00:00 2001 From: mahj8 Date: Sat, 10 Oct 2020 09:57:38 +0800 Subject: [PATCH 201/698] smb5: adjust USBIN OV debounce condition Adjust the USBIN OV debounce trigger condition. Use chg_done help to decide charge FULL state. Change-Id: If8d77be7884e809aab859ce45ef4238565a27338 Reviewed-on: https://gerrit.mot.com/1770943 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- drivers/power/supply/qcom/smb5-iio.c | 1 + drivers/power/supply/qcom/smb5-lib.c | 23 ++++++++++++----------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/drivers/power/supply/qcom/smb5-iio.c b/drivers/power/supply/qcom/smb5-iio.c index 0935331c8506..62eeafd92b66 100644 --- a/drivers/power/supply/qcom/smb5-iio.c +++ b/drivers/power/supply/qcom/smb5-iio.c @@ -486,6 +486,7 @@ int smb5_iio_set_prop(struct smb_charger *chg, int channel, int val) msleep(50); vote(chg->chg_disable_votable, FORCE_RECHARGE_VOTER, false, 0); + chg->chg_done = 0; break; case PSY_IIO_FCC_STEPPER_ENABLE: chg->fcc_stepper_enable = val; diff --git a/drivers/power/supply/qcom/smb5-lib.c b/drivers/power/supply/qcom/smb5-lib.c index 1e6f981afff1..6b8c830ba09b 100644 --- a/drivers/power/supply/qcom/smb5-lib.c +++ b/drivers/power/supply/qcom/smb5-lib.c @@ -1323,6 +1323,7 @@ static void smblib_uusb_removal(struct smb_charger *chg) cancel_delayed_work_sync(&chg->usbov_dbc_work); vote(chg->awake_votable, USBOV_DBC_VOTER, false, 0); chg->dbc_usbov = false; + chg->chg_done = 0; chg->voltage_min_uv = MICRO_5V; chg->voltage_max_uv = MICRO_5V; @@ -2156,7 +2157,10 @@ int smblib_get_prop_batt_status(struct smb_charger *chg, * charging path is un-suspended. */ if (pval.intval && !suspend) { - val->intval = POWER_SUPPLY_STATUS_CHARGING; + if (chg->chg_done) + val->intval = POWER_SUPPLY_STATUS_FULL; + else + val->intval = POWER_SUPPLY_STATUS_CHARGING; return 0; } } @@ -5267,6 +5271,7 @@ static void smblib_eval_chg_termination(struct smb_charger *chg, u8 batt_status) chg->cc_soc_ref = 0; chg->last_cc_soc = 0; chg->term_vbat_uv = 0; + chg->chg_done = 1; alarm_start_relative(&chg->chg_termination_alarm, ms_to_ktime(CHG_TERM_WA_ENTRY_DELAY_MS)); } else if (pval.intval < 100) { @@ -6448,6 +6453,7 @@ static void typec_src_removal(struct smb_charger *chg) cancel_delayed_work_sync(&chg->usbov_dbc_work); vote(chg->awake_votable, USBOV_DBC_VOTER, false, 0); chg->dbc_usbov = false; + chg->chg_done = 0; chg->pulse_cnt = 0; chg->usb_icl_delta_ua = 0; @@ -7258,17 +7264,12 @@ irqreturn_t smb5_usbin_ov_irq_handler(int irq, void *data) * differentiate between OV IRQ glitch and real OV_IRQ, add a debounce * period for evaluation. */ - if (stat & USBIN_OV_RT_STS_BIT) { - chg->dbc_usbov = true; - vote(chg->awake_votable, USBOV_DBC_VOTER, true, 0); - schedule_delayed_work(&chg->usbov_dbc_work, - msecs_to_jiffies(USB_OV_DBC_PERIOD_MS)); - } else { - cancel_delayed_work_sync(&chg->usbov_dbc_work); - chg->dbc_usbov = false; - vote(chg->awake_votable, USBOV_DBC_VOTER, false, 0); - } + chg->dbc_usbov = true; + vote(chg->awake_votable, USBOV_DBC_VOTER, true, 0); + schedule_delayed_work(&chg->usbov_dbc_work, + msecs_to_jiffies(USB_OV_DBC_PERIOD_MS)); + power_supply_changed(chg->batt_psy); smblib_dbg(chg, PR_MISC, "USBOV debounce status %d\n", chg->dbc_usbov); return IRQ_HANDLED; From aa30dcf596e9d2eb058176b73385c504c943f86d Mon Sep 17 00:00:00 2001 From: yanyh2 Date: Thu, 12 Sep 2019 16:08:03 +0800 Subject: [PATCH 202/698] smb5: rerun apsd right after the first time apsd done Sometimes, a charger may be detected as SDP after apsd for the first it plugins, add rerun APSD to reduce the APSD failure for the first time. Set the initial USB ICL to 500mA in case USB controller never complete enumeration to set the target ICL. Change-Id: I60aedd478fe890f1c40a202e3b0df4e64658cMontana Signed-off-by: yanyh2 Reviewed-on: https://gerrit.mot.com/1420421 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Haijian Ma Reviewed-by: Huosheng Liao Submit-Approved: Jira Key Reviewed-on: https://gerrit.mot.com/1502930 Reviewed-on: https://gerrit.mot.com/1770982 --- drivers/power/supply/qcom/smb5-lib.c | 47 ++++++++++++++++++---------- drivers/power/supply/qcom/smb5-lib.h | 1 + 2 files changed, 31 insertions(+), 17 deletions(-) diff --git a/drivers/power/supply/qcom/smb5-lib.c b/drivers/power/supply/qcom/smb5-lib.c index 6b8c830ba09b..bb8cef8a8390 100644 --- a/drivers/power/supply/qcom/smb5-lib.c +++ b/drivers/power/supply/qcom/smb5-lib.c @@ -4492,8 +4492,11 @@ static int smblib_handle_usb_current(struct smb_charger *chg, return 0; typec_mode = smblib_get_prop_typec_mode(chg); - if (typec_rp_med_high(chg, typec_mode)) + if (typec_rp_med_high(chg, typec_mode)) { + vote(chg->usb_icl_votable, USB_PSY_VOTER, + false, 0); return 0; + } /* if flash is active force 500mA */ if ((usb_current < SDP_CURRENT_UA) && is_flash_active(chg)) @@ -5935,40 +5938,29 @@ static void update_sw_icl_max(struct smb_charger *chg, int val) if (typec_rp_med_high(chg, typec_mode)) { rp_ua = get_rp_based_dcp_current(chg, typec_mode); vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, true, rp_ua); + vote(chg->usb_icl_votable, USB_PSY_VOTER, false, 0); return; } /* rp-std or legacy, USB BC 1.2 */ switch (val) { case POWER_SUPPLY_TYPE_USB: - /* - * USB_PSY will vote to increase the current to 500/900mA once - * enumeration is done. - */ - if (!is_client_vote_enabled(chg->usb_icl_votable, - USB_PSY_VOTER)) { - /* if flash is active force 500mA */ - vote(chg->usb_icl_votable, USB_PSY_VOTER, true, - is_flash_active(chg) ? - SDP_CURRENT_UA : SDP_100_MA); - } + vote(chg->usb_icl_votable, USB_PSY_VOTER, true, SDP_CURRENT_UA); vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, false, 0); break; case POWER_SUPPLY_TYPE_USB_CDP: vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, true, CDP_CURRENT_UA); + vote(chg->usb_icl_votable, USB_PSY_VOTER, false, 0); break; case POWER_SUPPLY_TYPE_USB_DCP: rp_ua = get_rp_based_dcp_current(chg, typec_mode); vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, true, rp_ua); + vote(chg->usb_icl_votable, USB_PSY_VOTER, false, 0); break; case QTI_POWER_SUPPLY_TYPE_USB_FLOAT: - /* - * limit ICL to 100mA, the USB driver will enumerate to check - * if this is a SDP and appropriately set the current - */ vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, true, - SDP_100_MA); + SDP_CURRENT_UA); break; case POWER_SUPPLY_TYPE_UNKNOWN: default: @@ -6040,6 +6032,26 @@ irqreturn_t smb5_usb_source_change_irq_handler(int irq, void *data) return IRQ_HANDLED; } + if ((chg->connector_type == QTI_POWER_SUPPLY_CONNECTOR_TYPEC) + && (stat & APSD_DTC_STATUS_DONE_BIT) + && !chg->typec_apsd_rerun_done) { + const struct apsd_result *apsd_result = + smblib_update_usb_type(chg); + /* + * Force re-run APSD to handle slow insertion related + * charger-mis-detection. + */ + if (apsd_result->bit == SDP_CHARGER_BIT || + apsd_result->bit == OCP_CHARGER_BIT || + apsd_result->bit == FLOAT_CHARGER_BIT) { + smblib_dbg(chg, PR_INTERRUPT, "IRQ: rerun apsd for %s\n", + apsd_result->name); + chg->typec_apsd_rerun_done = true; + smblib_rerun_apsd_if_required(chg); + return IRQ_HANDLED; + } + } + smblib_handle_apsd_done(chg, (bool)(stat & APSD_DTC_STATUS_DONE_BIT)); @@ -6462,6 +6474,7 @@ static void typec_src_removal(struct smb_charger *chg) chg->usbin_forced_max_uv = 0; chg->chg_param.forced_main_fcc = 0; chg->pd_contract_uv = 0; + chg->typec_apsd_rerun_done = false; /* Reset all CC mode votes */ vote(chg->fcc_main_votable, MAIN_FCC_VOTER, false, 0); diff --git a/drivers/power/supply/qcom/smb5-lib.h b/drivers/power/supply/qcom/smb5-lib.h index 3428fd690991..1ab71148c767 100644 --- a/drivers/power/supply/qcom/smb5-lib.h +++ b/drivers/power/supply/qcom/smb5-lib.h @@ -533,6 +533,7 @@ struct smb_charger { int default_icl_ua; int otg_cl_ua; bool uusb_apsd_rerun_done; + bool typec_apsd_rerun_done; bool typec_present; int fake_input_current_limited; int typec_mode; From e9fc550caff22a1ac126a2db701c4fafea30465f Mon Sep 17 00:00:00 2001 From: Haijian Ma Date: Wed, 4 Dec 2019 17:48:04 +0800 Subject: [PATCH 203/698] smb5-lib: fixed BC1.2 current override type-c current ICL is set to 1000ma when BC1.2 result is OCP charger with med or high type-c rp current. (think plus usb-c book charger pack) So don't override USB icl when type-c rp current is med or high. Change-Id: Id3f9daedfbcf905b99612ba1977b2c710a764cba Signed-off-by: Haijian Ma Reviewed-on: https://gerrit.mot.com/1465715 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Lu Chai Reviewed-by: Huosheng Liao Submit-Approved: Jira Key Reviewed-by: Yonghua Yan Reviewed-on: https://gerrit.mot.com/1503915 Reviewed-on: https://gerrit.mot.com/1770998 --- drivers/power/supply/qcom/smb5-lib.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/power/supply/qcom/smb5-lib.c b/drivers/power/supply/qcom/smb5-lib.c index bb8cef8a8390..184f8cb93255 100644 --- a/drivers/power/supply/qcom/smb5-lib.c +++ b/drivers/power/supply/qcom/smb5-lib.c @@ -5973,6 +5973,7 @@ static void update_sw_icl_max(struct smb_charger *chg, int val) static void smblib_handle_apsd_done(struct smb_charger *chg, bool rising) { const struct apsd_result *apsd_result; + int typec_mode; if (!rising) return; @@ -5989,8 +5990,11 @@ static void smblib_handle_apsd_done(struct smb_charger *chg, bool rising) smblib_notify_device_mode(chg, true); break; case OCP_CHARGER_BIT: - vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, true, - OCP_CURRENT_UA); + typec_mode = smblib_get_prop_typec_mode(chg); + if (!typec_rp_med_high(chg, typec_mode)) { + vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, true, + OCP_CURRENT_UA); + } break; case DCP_CHARGER_BIT: break; From 5ad50d865083c3102ddaaff662e844367a17f6a7 Mon Sep 17 00:00:00 2001 From: yanyh2 Date: Fri, 27 Mar 2020 17:53:21 +0800 Subject: [PATCH 204/698] Reset USB real_charger_type to unknown for apsd rerun In current factory environment, after USB OTG test(USB pins will be reconnected), the typec mode detection is prior to vbus detection sometimes, and the typec mode will be DEFAULT. Then after the first time of apsd, the apsd result and real_charger_type become SDP. As a workaround for APSD detection issue, there will be APSD rerun if the first APSD is SDP. If there comes a usb_source_change irq right after apsd rerun, the pd policy will receive the usb power change event and check the typec mode, and real_charger_type, finally, it starts the USB enumeration as typec mode greater than DEFAULT and real_charger_type is SDP. At that time, APSD rerun and USB enumeration may collide and make conflict, which is the reason why the second APSD gets a wrong result(DCP/HVDCP2) and USB connection gets lost. In order to avoid this situation, reset the real_charger_type to unknown when rerun apsd, so that the USB enumeration will not be triggered by pd policy unexpectedly but by charger driver. Change-Id: Ifdde0a847ef18518a204f67843e61c6b5a9e7401 Signed-off-by: yanyh2 Reviewed-on: https://gerrit.mot.com/1523010 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Jianqi Yang Submit-Approved: Jira Key Reviewed-on: https://gerrit.mot.com/1771030 Reviewed-by: Huosheng Liao --- drivers/power/supply/qcom/smb5-lib.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/power/supply/qcom/smb5-lib.c b/drivers/power/supply/qcom/smb5-lib.c index 184f8cb93255..53dad590cf07 100644 --- a/drivers/power/supply/qcom/smb5-lib.c +++ b/drivers/power/supply/qcom/smb5-lib.c @@ -1204,6 +1204,8 @@ void smblib_rerun_apsd(struct smb_charger *chg) APSD_RERUN_BIT, APSD_RERUN_BIT); if (rc < 0) smblib_err(chg, "Couldn't re-run APSD rc=%d\n", rc); + else + chg->real_charger_type = POWER_SUPPLY_TYPE_UNKNOWN; } static const struct apsd_result *smblib_update_usb_type(struct smb_charger *chg) From 466554f88405a1b74a4297bcb8c42c3c8a2f3173 Mon Sep 17 00:00:00 2001 From: Kenny Kessler Date: Fri, 12 Oct 2018 11:46:22 -0500 Subject: [PATCH 205/698] power: qcom: smb5: Add MMI Factory Mode Old ticket (CR) MMI Factory mode needs to be followed so change base QCOM. This patch is needed to ensure that from the time smb5 loads to the mmi DLKM loads there is no charging. Only needed for Factory purposes. Change-Id: I3011dbfc3382d382be2fb3c07c02597bfa953d77 Signed-off-by: Kenny Kessler Reviewed-on: https://gerrit.mot.com/1255092 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Kenneth Kessler Submit-Approved: Jira Key Reviewed-on: https://gerrit.mot.com/1526255 Reviewed-by: Ling Jin Reviewed-on: https://gerrit.mot.com/1771036 Reviewed-by: Huosheng Liao --- drivers/power/supply/qcom/smb5-lib.c | 38 ++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/drivers/power/supply/qcom/smb5-lib.c b/drivers/power/supply/qcom/smb5-lib.c index 53dad590cf07..f8065ace4153 100644 --- a/drivers/power/supply/qcom/smb5-lib.c +++ b/drivers/power/supply/qcom/smb5-lib.c @@ -8259,10 +8259,27 @@ relax: pm_relax(chg->dev); } +static bool mmi_factory_mode; +static void smblib_mmi_factory_check(void) +{ + struct device_node *np = of_find_node_by_path("/chosen"); + + if (np) + mmi_factory_mode = of_property_read_bool(np, + "mmi,factory-cable"); + + of_node_put(np); + + return; +} + static int smblib_create_votables(struct smb_charger *chg) { int rc = 0; + mmi_factory_mode = false; + smblib_mmi_factory_check(); + chg->fcc_votable = find_votable("FCC"); if (chg->fcc_votable == NULL) { rc = -EINVAL; @@ -8394,6 +8411,27 @@ static int smblib_create_votables(struct smb_charger *chg) return rc; } + if (mmi_factory_mode) { + smblib_err(chg, "MMI Factory Mode Force Charge Values!\n"); + if(chg->chg_disable_votable) { + pmic_vote_force_val_set(chg->chg_disable_votable, 1); + pmic_vote_force_active_set(chg->chg_disable_votable, 1); + } + if(chg->fcc_votable) { + pmic_vote_force_val_set(chg->fcc_votable, 100000); + pmic_vote_force_active_set(chg->fcc_votable, 1); + } + if(chg->fv_votable) { + pmic_vote_force_val_set(chg->fv_votable, 4400000); + pmic_vote_force_active_set(chg->fv_votable, 1); + } + if(chg->usb_icl_votable) { + pmic_vote_force_val_set(chg->usb_icl_votable, + 3000000); + pmic_vote_force_active_set(chg->usb_icl_votable, 1); + } + } + return rc; } From 3b3a3844ac8a32fa14de04fb2def18486862f4f1 Mon Sep 17 00:00:00 2001 From: yanyh2 Date: Tue, 28 Apr 2020 15:50:05 +0800 Subject: [PATCH 206/698] skip icl override again after setting sdp icl As icl override has been done in sdp icl setting, so there is no need to set icl override again after sdp icl settting. The icl override for the second time will use HW_AUTO_MODE so the HC mode in register 0x1366 will be enabled. In that case, the USB ICL settled will exceed 500mA with SDP APSD result if a non-standard USBA-C cable is attached. When use this USB cable, the typec orientation cannot be detected as it always shows 0, but typec mode can be detected. pm7250b_charger: smblib_update_usb_type: APSD=SDP PD=0 QC3P5=0 pm7250b_charger: smblib_icl_change_work: icl_settled=2450000 Change-Id: I3dee9b17a296d1f3a7f57f78a0162ced02f71c7e Signed-off-by: yanyh2 Reviewed-on: https://gerrit.mot.com/1544008 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Reviewed-by: Haijian Ma Tested-by: Jira Key Reviewed-by: Jianqi Yang Submit-Approved: Jira Key Reviewed-on: https://gerrit.mot.com/1771041 Reviewed-by: Huosheng Liao --- drivers/power/supply/qcom/smb5-lib.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/power/supply/qcom/smb5-lib.c b/drivers/power/supply/qcom/smb5-lib.c index f8065ace4153..eab526c66c0a 100644 --- a/drivers/power/supply/qcom/smb5-lib.c +++ b/drivers/power/supply/qcom/smb5-lib.c @@ -1537,6 +1537,7 @@ int smblib_set_icl_current(struct smb_charger *chg, int icl_ua) smblib_err(chg, "Couldn't set SDP ICL rc=%d\n", rc); goto out; } + goto unsuspend; } else { /* * Try USB 2.0/3,0 option first on USB path when maximum input From dc8fd61192eaa8abb657a73872e031cd65d00818 Mon Sep 17 00:00:00 2001 From: mahj8 Date: Thu, 7 May 2020 17:52:50 +0800 Subject: [PATCH 207/698] qg: add sdam-magic-number parameter add sdam-magic-number parameter to judge if using the different battery profile. we need clear sdam when using different battery profile. Change-Id: I248edf52f767abbadb1934328b88f8048af4a782 Signed-off-by: mahj8 Reviewed-on: https://gerrit.mot.com/1549720 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Lu Chai Reviewed-by: Yonghua Yan Reviewed-by: Huosheng Liao Submit-Approved: Jira Key Reviewed-on: https://gerrit.mot.com/1553272 Reviewed-on: https://gerrit.mot.com/1771064 --- drivers/power/supply/qcom/qg-core.h | 1 + drivers/power/supply/qcom/qpnp-qg.c | 15 +++++++++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/power/supply/qcom/qg-core.h b/drivers/power/supply/qcom/qg-core.h index 2796e16c2a11..28bf72d26c27 100644 --- a/drivers/power/supply/qcom/qg-core.h +++ b/drivers/power/supply/qcom/qg-core.h @@ -21,6 +21,7 @@ struct qg_batt_props { int vbatt_full_mv; int fastchg_curr_ma; int qg_profile_version; + u32 sdam_magic_number; }; struct qg_irq_info { diff --git a/drivers/power/supply/qcom/qpnp-qg.c b/drivers/power/supply/qcom/qpnp-qg.c index 4c8839273140..5f9983845054 100644 --- a/drivers/power/supply/qcom/qpnp-qg.c +++ b/drivers/power/supply/qcom/qpnp-qg.c @@ -3037,6 +3037,7 @@ static int get_batt_id_ohm(struct qpnp_qg *chip, u32 *batt_id_ohm) return 0; } +#define SDAM_MAGIC_NUMBER 0x12345678 static int qg_load_battery_profile(struct qpnp_qg *chip) { struct device_node *node = chip->dev->of_node; @@ -3106,6 +3107,13 @@ static int qg_load_battery_profile(struct qpnp_qg *chip) chip->bp.fastchg_curr_ma = -EINVAL; } + rc = of_property_read_u32(profile_node, "qcom,sdam-magic-number", + &chip->bp.sdam_magic_number); + if (rc < 0) { + pr_err("Failed to read sdam magic number rc:%d\n", rc); + chip->bp.sdam_magic_number = SDAM_MAGIC_NUMBER; + } + /* * Update the max fcc values based on QG subtype including * error margins. @@ -3458,7 +3466,6 @@ static int qg_set_wa_flags(struct qpnp_qg *chip) return 0; } -#define SDAM_MAGIC_NUMBER 0x12345678 static int qg_sanitize_sdam(struct qpnp_qg *chip) { int rc = 0; @@ -3470,10 +3477,10 @@ static int qg_sanitize_sdam(struct qpnp_qg *chip) return rc; } - if (data == SDAM_MAGIC_NUMBER) { + if (data == chip->bp.sdam_magic_number) { qg_dbg(chip, QG_DEBUG_PON, "SDAM valid\n"); } else if (data == 0) { - rc = qg_sdam_write(SDAM_MAGIC, SDAM_MAGIC_NUMBER); + rc = qg_sdam_write(SDAM_MAGIC, chip->bp.sdam_magic_number); if (!rc) qg_dbg(chip, QG_DEBUG_PON, "First boot. SDAM initilized\n"); chip->first_profile_load = true; @@ -3482,7 +3489,7 @@ static int qg_sanitize_sdam(struct qpnp_qg *chip) rc = qg_sdam_clear(); if (!rc) { pr_err("SDAM uninitialized, SDAM reset\n"); - rc = qg_sdam_write(SDAM_MAGIC, SDAM_MAGIC_NUMBER); + rc = qg_sdam_write(SDAM_MAGIC, chip->bp.sdam_magic_number); } chip->first_profile_load = true; } From c1717e45fa5ffeba2644f60e0ee8b66c26f4eef3 Mon Sep 17 00:00:00 2001 From: xuwt2 Date: Mon, 25 Nov 2019 19:18:47 +0800 Subject: [PATCH 208/698] smb5: Only allow Moto pd policy to set pdo voltage max Base on Kernel built-in Moto PD controlling policy, pdo select depends on PD voltage max, so the product should decide which USB PD voltage is allowed, including the USB PD input power(Hardcode 18W in current code). Different product design may require different USB PD voltage allowance and USB PD input power max allowance. Current Moto PD controlling policy only applies to FIXED pdo but not programmable pdo(PPS), which requires periodic PD output power acknowledgement(at least 10s interval). So it has to redesign current Moto PD controlling policy to support PPS pdo selection. In order to avoid any PD controlling policy conflict with third party disable the PD controlling policy modification interfaces for user space (may be used by hvdcp_opti daemon in Qcom platform). Change-Id: I7565e187e2619252bc6d611b7f4aabc90b72c687 Signed-off-by: xuwt2 Reviewed-on: https://gerrit.mot.com/1461008 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Haijian Ma Reviewed-by: Yonghua Yan Reviewed-by: Jianqi Yang Submit-Approved: Jira Key Reviewed-on: https://gerrit.mot.com/1771065 Reviewed-by: Huosheng Liao --- drivers/power/supply/qcom/smb5-iio.c | 4 ++++ drivers/power/supply/qcom/smb5-lib.c | 17 +++++++++++++++++ drivers/power/supply/qcom/smb5-lib.h | 1 + 3 files changed, 22 insertions(+) diff --git a/drivers/power/supply/qcom/smb5-iio.c b/drivers/power/supply/qcom/smb5-iio.c index 62eeafd92b66..c3cdd4416588 100644 --- a/drivers/power/supply/qcom/smb5-iio.c +++ b/drivers/power/supply/qcom/smb5-iio.c @@ -314,10 +314,14 @@ int smb5_iio_set_prop(struct smb_charger *chg, int channel, int val) rc = smblib_set_prop_pr_swap_in_progress(chg, val); break; case PSY_IIO_PD_VOLTAGE_MAX: +#ifdef QCOM_BASE rc = smblib_set_prop_pd_voltage_max(chg, val); +#endif break; case PSY_IIO_PD_VOLTAGE_MIN: +#ifdef QCOM_BASE rc = smblib_set_prop_pd_voltage_min(chg, val); +#endif break; case PSY_IIO_CONNECTOR_HEALTH: chg->connector_health = val; diff --git a/drivers/power/supply/qcom/smb5-lib.c b/drivers/power/supply/qcom/smb5-lib.c index eab526c66c0a..1446086625c4 100644 --- a/drivers/power/supply/qcom/smb5-lib.c +++ b/drivers/power/supply/qcom/smb5-lib.c @@ -7401,6 +7401,23 @@ static void smblib_pd_contract_work(struct work_struct *work) if (!chg->pd || !chg->pd_active) return; + if (!chg->pd_voltage_max_uv) { + rc = of_property_read_u32(chg->dev->of_node, + "qcom,pd-voltage-max-uv", + &chg->pd_voltage_max_uv); + if (rc < 0) { + chg->pd_voltage_max_uv = MICRO_5V; + smblib_err(chg, "Failed to get pd_voltage_max_uv" + "from device tree, rc = %d\n", rc); + } + + if (chg->pd_voltage_max_uv < MICRO_5V) + chg->pd_voltage_max_uv = MICRO_5V; + else if (chg->pd_voltage_max_uv > MICRO_12V) + chg->pd_voltage_max_uv = MICRO_12V; + } + chg->voltage_max_uv = chg->pd_voltage_max_uv; + chg->pd_contract_uv = usbpd_select_pdo_match(chg->pd); if (chg->pd_contract_uv == -ENOTSUPP) diff --git a/drivers/power/supply/qcom/smb5-lib.h b/drivers/power/supply/qcom/smb5-lib.h index 1ab71148c767..48df4a16c97c 100644 --- a/drivers/power/supply/qcom/smb5-lib.h +++ b/drivers/power/supply/qcom/smb5-lib.h @@ -613,6 +613,7 @@ struct smb_charger { /* USB PD interactions */ struct usbpd *pd; int pd_contract_uv; + int pd_voltage_max_uv; struct delayed_work pd_contract_work; /* battery profile */ From 9a07f7885f8a6583ffb23644b815b068b6fbb1e7 Mon Sep 17 00:00:00 2001 From: xuwt2 Date: Mon, 22 Jun 2020 17:29:40 +0800 Subject: [PATCH 209/698] power: smb5-lib: Vote USB_ICL after PD active the usb_icl_votable has been voted at policy-engine through the PD communication protocol, In smblib_pd_contract_work, we actually needn't override its setting, if want to re-vote it, the value must not be greater than the result after PD contract. Change-Id: I4a9c7c52709c60fa51a6d1aa2125bbafb52e81df Signed-off-by: xuwt2 Reviewed-on: https://gerrit.mot.com/1636223 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Yonghua Yan Reviewed-by: Haijian Ma Reviewed-by: Huosheng Liao Submit-Approved: Jira Key Reviewed-on: https://gerrit.mot.com/1771126 --- drivers/power/supply/qcom/smb5-lib.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/power/supply/qcom/smb5-lib.c b/drivers/power/supply/qcom/smb5-lib.c index 1446086625c4..52708b3f2423 100644 --- a/drivers/power/supply/qcom/smb5-lib.c +++ b/drivers/power/supply/qcom/smb5-lib.c @@ -7436,6 +7436,10 @@ static void smblib_pd_contract_work(struct work_struct *work) smblib_set_opt_switcher_freq(chg, chg->chg_freq.freq_5V); max_ua = (MAX_INPUT_PWR_UW / (chg->pd_contract_uv / 1000)) * 1000; + + if (get_client_vote(chg->usb_icl_votable, PD_VOTER) > 0) + max_ua = min(max_ua, get_client_vote(chg->usb_icl_votable, PD_VOTER)); + smblib_err(chg, "smblib_pd_contract_work: %d uV, %d uA\n", chg->pd_contract_uv, max_ua); From c34aae49b07bf9290610ec83944c5a8c3e7d5477 Mon Sep 17 00:00:00 2001 From: xuwt2 Date: Fri, 10 Jul 2020 15:56:56 +0800 Subject: [PATCH 210/698] smb5: Add DCP curr settings Read usb_dcp configration from the properity of "mmi.usb_dcp" the setting is in vhw.xml. Different sku have different requirements for DCP current Change-Id: Id01a4aa02b69b273a272835054ce1d97b50f3ff9 Signed-off-by: xuwt2 Reviewed-on: https://gerrit.mot.com/1673650 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Haijian Ma Reviewed-by: Yonghua Yan Reviewed-by: Lu Chai Reviewed-by: Huosheng Liao Submit-Approved: Jira Key Reviewed-on: https://gerrit.mot.com/1771130 --- drivers/power/supply/qcom/qpnp-smb5.c | 38 +++++++++++++++++++++++++++ drivers/power/supply/qcom/smb5-lib.c | 2 ++ drivers/power/supply/qcom/smb5-lib.h | 1 + 3 files changed, 41 insertions(+) diff --git a/drivers/power/supply/qcom/qpnp-smb5.c b/drivers/power/supply/qcom/qpnp-smb5.c index dd02103a5575..485ff2d2ca93 100644 --- a/drivers/power/supply/qcom/qpnp-smb5.c +++ b/drivers/power/supply/qcom/qpnp-smb5.c @@ -763,6 +763,40 @@ static int smb5_parse_sdam(struct smb5 *chip, struct device_node *node) return 0; } +#define DCP_CURRENT_1500MA 1500000 +#define DCP_CURRENT_2000MA 2000000 +static int smb5_parse_dt_mmi(struct smb5 *chip, struct device_node *node) +{ + struct smb_charger *chg = &chip->chg; + struct device_node *np; + const char *dcp_curr = NULL; + int retval; + + np = of_find_node_by_path("/chosen"); + + if (!np) + return -EINVAL; + + retval = of_property_read_string(np, "mmi,usb_dcp", + &dcp_curr); + + if ((retval == -EINVAL) || !dcp_curr) { + pr_err("mmi,usb_dcp unused\n"); + of_node_put(np); + return -EINVAL; + } else + pr_err("usb_dcp = %s\n", dcp_curr); + + if (strstr(dcp_curr, "1.5A")) + chg->usb_dcp_curr_max = DCP_CURRENT_1500MA; + else if (strstr(dcp_curr, "2A")) + chg->usb_dcp_curr_max = DCP_CURRENT_2000MA; + + of_node_put(np); + + return 0; +} + static int smb5_parse_dt(struct smb5 *chip) { struct smb_charger *chg = &chip->chg; @@ -794,6 +828,10 @@ static int smb5_parse_dt(struct smb5 *chip) if (rc < 0) return rc; + rc = smb5_parse_dt_mmi(chip, node); + if (rc < 0) + return rc; + return 0; } diff --git a/drivers/power/supply/qcom/smb5-lib.c b/drivers/power/supply/qcom/smb5-lib.c index 52708b3f2423..aa256e484e28 100644 --- a/drivers/power/supply/qcom/smb5-lib.c +++ b/drivers/power/supply/qcom/smb5-lib.c @@ -4404,6 +4404,8 @@ static int get_rp_based_dcp_current(struct smb_charger *chg, int typec_mode) /* fall through */ default: rp_ua = DCP_CURRENT_UA; + if (chg->usb_dcp_curr_max > 0) + rp_ua = chg->usb_dcp_curr_max; } return rp_ua; diff --git a/drivers/power/supply/qcom/smb5-lib.h b/drivers/power/supply/qcom/smb5-lib.h index 48df4a16c97c..2dea1c0aff4b 100644 --- a/drivers/power/supply/qcom/smb5-lib.h +++ b/drivers/power/supply/qcom/smb5-lib.h @@ -638,6 +638,7 @@ struct smb_charger { int dcin_uv_count; ktime_t dcin_uv_last_time; int last_wls_vout; + int usb_dcp_curr_max; }; int smblib_read(struct smb_charger *chg, u16 addr, u8 *val); From e6d15ef2b342e81821cc7ccbac0b22bf99cafff7 Mon Sep 17 00:00:00 2001 From: xuwt2 Date: Tue, 14 Jul 2020 13:54:12 +0800 Subject: [PATCH 211/698] smb5: modify error handing in smb5_parse_dt_mmi kernel panic occurs in smb5_prob when the usb_dcp is not set in vhw.xml. modify error handing in smb5_parse_dt_mmi to avoid this case Change-Id: I12218ef1c067c5c23dd689c9fb88eb41ef8fa606 Signed-off-by: xuwt2 Reviewed-on: https://gerrit.mot.com/1681297 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Haijian Ma Reviewed-by: Huosheng Liao Submit-Approved: Jira Key Reviewed-on: https://gerrit.mot.com/1771131 --- drivers/power/supply/qcom/qpnp-smb5.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/power/supply/qcom/qpnp-smb5.c b/drivers/power/supply/qcom/qpnp-smb5.c index 485ff2d2ca93..1acff1ad6633 100644 --- a/drivers/power/supply/qcom/qpnp-smb5.c +++ b/drivers/power/supply/qcom/qpnp-smb5.c @@ -763,8 +763,6 @@ static int smb5_parse_sdam(struct smb5 *chip, struct device_node *node) return 0; } -#define DCP_CURRENT_1500MA 1500000 -#define DCP_CURRENT_2000MA 2000000 static int smb5_parse_dt_mmi(struct smb5 *chip, struct device_node *node) { struct smb_charger *chg = &chip->chg; @@ -772,28 +770,30 @@ static int smb5_parse_dt_mmi(struct smb5 *chip, struct device_node *node) const char *dcp_curr = NULL; int retval; + chg->usb_dcp_curr_max = 0; np = of_find_node_by_path("/chosen"); if (!np) - return -EINVAL; + goto out; retval = of_property_read_string(np, "mmi,usb_dcp", &dcp_curr); if ((retval == -EINVAL) || !dcp_curr) { - pr_err("mmi,usb_dcp unused\n"); + pr_info("mmi,usb_dcp unused\n"); of_node_put(np); - return -EINVAL; + goto out; } else - pr_err("usb_dcp = %s\n", dcp_curr); + pr_info("usb_dcp = %s\n", dcp_curr); if (strstr(dcp_curr, "1.5A")) - chg->usb_dcp_curr_max = DCP_CURRENT_1500MA; + chg->usb_dcp_curr_max = 1500000; else if (strstr(dcp_curr, "2A")) - chg->usb_dcp_curr_max = DCP_CURRENT_2000MA; + chg->usb_dcp_curr_max = 2000000; of_node_put(np); +out: return 0; } From afae98dffef32927995ce3e5abac8c622ddea389 Mon Sep 17 00:00:00 2001 From: xuwt2 Date: Thu, 16 Jul 2020 19:30:05 +0800 Subject: [PATCH 212/698] smb5: Add syfs node to offer usb_dcp_icl_ua setting To provide a sysfs node to reset the usb_dcp_icl_ua threshold, For handle different DCP icl setting for different SKU regions, Add a sysfs node in smb5 for that. Force rerun APSD after rewriting usb_dcp_icl_ua Change-Id: If7fcd97de95457dea5bcabcb41612bd1c9abdecb Signed-off-by: xuwt2 Reviewed-on: https://gerrit.mot.com/1686899 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Yonghua Yan Reviewed-by: Jianqi Yang Submit-Approved: Jira Key Reviewed-on: https://gerrit.mot.com/1771138 Reviewed-by: Huosheng Liao --- drivers/power/supply/qcom/qpnp-smb5.c | 29 +++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/drivers/power/supply/qcom/qpnp-smb5.c b/drivers/power/supply/qcom/qpnp-smb5.c index 1acff1ad6633..3208bb25c552 100644 --- a/drivers/power/supply/qcom/qpnp-smb5.c +++ b/drivers/power/supply/qcom/qpnp-smb5.c @@ -281,9 +281,38 @@ static ssize_t weak_chg_icl_ua_store(struct device *dev, struct device_attribute } static DEVICE_ATTR_RW(weak_chg_icl_ua); +static ssize_t usb_dcp_icl_ua_show(struct device *dev, struct device_attribute + *attr, char *buf) +{ + struct smb5 *chip = dev_get_drvdata(dev); + struct smb_charger *chg = &chip->chg; + + return snprintf(buf, PAGE_SIZE, "%d\n", chg->usb_dcp_curr_max); +} + +static ssize_t usb_dcp_icl_ua_store(struct device *dev, struct device_attribute + *attr, const char *buf, size_t count) +{ + int val; + struct smb5 *chip = dev_get_drvdata(dev); + struct smb_charger *chg = &chip->chg; + + if (kstrtos32(buf, 0, &val)) + return -EINVAL; + + chg->usb_dcp_curr_max = val; + pr_info("USB dcp icl was rewritten as %dua\n", chg->usb_dcp_curr_max); + if (chg->real_charger_type == POWER_SUPPLY_TYPE_USB_DCP) + smblib_rerun_apsd_if_required(chg); + + return count; +} +static DEVICE_ATTR_RW(usb_dcp_icl_ua); + static struct attribute *smb5_attrs[] = { &dev_attr_pd_disabled.attr, &dev_attr_weak_chg_icl_ua.attr, + &dev_attr_usb_dcp_icl_ua.attr, NULL, }; ATTRIBUTE_GROUPS(smb5); From 7cd790dd941484e184f7dbd633a7d716834c540f Mon Sep 17 00:00:00 2001 From: yanyh2 Date: Tue, 22 May 2018 14:58:35 +0800 Subject: [PATCH 213/698] Find the battery profile by serial number Support the way to find the battery profile by serial number of battery in battid utags. Change-Id: I05b3368e151b153ba20417b34cd1c73cfe3c9754 Signed-off-by: yanyh2 Reviewed-on: https://gerrit.mot.com/1178205 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Lu Chai Reviewed-by: Jianqi Yang Submit-Approved: Jira Key Reviewed-on: https://gerrit.mot.com/1338748 Reviewed-by: Huosheng Liao Reviewed-by: Haijian Ma Reviewed-on: https://gerrit.mot.com/1447561 Reviewed-on: https://gerrit.mot.com/1771166 --- .../supply/qcom/battery-profile-loader.c | 86 +++++++++++++++++++ 1 file changed, 86 insertions(+) diff --git a/drivers/power/supply/qcom/battery-profile-loader.c b/drivers/power/supply/qcom/battery-profile-loader.c index 287ddb9e5403..5dfe2ebb966d 100644 --- a/drivers/power/supply/qcom/battery-profile-loader.c +++ b/drivers/power/supply/qcom/battery-profile-loader.c @@ -42,6 +42,88 @@ static int of_batterydata_read_batt_id_kohm(const struct device_node *np, return 0; } +static const char *get_battery_serialnumber(void) +{ + struct device_node *np = of_find_node_by_path("/chosen"); + const char *battsn_buf; + int retval; + + battsn_buf = NULL; + + if (np) + retval = of_property_read_string(np, "mmi,battid", + &battsn_buf); + else + return NULL; + + if ((retval == -EINVAL) || !battsn_buf) { + pr_err("Battsn unused\n"); + of_node_put(np); + return NULL; + + } else + pr_err("Battsn = %s\n", battsn_buf); + + of_node_put(np); + + return battsn_buf; +} + +static struct device_node *get_profile_by_serialnumber( + const struct device_node *np) +{ + struct device_node *node, *df_node, *sn_node; + const char *sn_buf, *df_sn, *dev_sn; + int rc; + + if (!np) + return NULL; + + dev_sn = NULL; + df_sn = NULL; + sn_buf = NULL; + df_node = NULL; + sn_node = NULL; + + dev_sn = get_battery_serialnumber(); + + rc = of_property_read_string(np, "df-serialnum", + &df_sn); + if (rc) + pr_warn("No Default Serial Number defined\n"); + else if (df_sn) + pr_info("Default Serial Number %s\n", df_sn); + + for_each_child_of_node(np, node) { + rc = of_property_read_string(node, "serialnum", + &sn_buf); + if (!rc && sn_buf) { + if (dev_sn) + if (strnstr(dev_sn, sn_buf, 32)) + sn_node = node; + if (df_sn) + if (strnstr(df_sn, sn_buf, 32)) + df_node = node; + } + } + + if (sn_node) { + node = sn_node; + df_node = NULL; + pr_info("Battery Match Found using %s\n", sn_node->name); + } else if (df_node) { + node = df_node; + sn_node = NULL; + pr_info("Battery Match Found using default %s\n", + df_node->name); + } else { + pr_warn("No Battery Match Found!\n"); + return NULL; + } + + return node; +} + struct device_node *of_batterydata_get_best_profile( const struct device_node *batterydata_container_node, int batt_id_kohm, const char *batt_type) @@ -66,6 +148,10 @@ struct device_node *of_batterydata_get_best_profile( } } + best_node = get_profile_by_serialnumber(batterydata_container_node); + if (best_node) + return best_node; + /* * Find the battery data with a battery id resistor closest to this one */ From a34cb705aa6684f03a7fe1ce9d47d81e46bf15c4 Mon Sep 17 00:00:00 2001 From: liaohs Date: Thu, 27 Dec 2018 16:11:53 +0800 Subject: [PATCH 214/698] pmic: add power-off reason registers value add PMIC power-off reason registers' value : PON_POFF_REASON1 PON_OFF_REASON PON_FAULT_REASON1 PON_FAULT_REASON2 PON_S3_RESET_REASON Change-Id: I696dd9fbda3e6df111aa8282827fabea4260d297 Reviewed-on: https://gerrit.mot.com/1287551 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Haijian Ma Reviewed-by: Huosheng Liao Submit-Approved: Jira Key Reviewed-on: https://gerrit.mot.com/1470872 Reviewed-by: Zhenxin Xi Reviewed-on: https://gerrit.mot.com/1771184 --- drivers/input/misc/qpnp-power-on.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/input/misc/qpnp-power-on.c b/drivers/input/misc/qpnp-power-on.c index 49c00750dfe4..39255cd19086 100644 --- a/drivers/input/misc/qpnp-power-on.c +++ b/drivers/input/misc/qpnp-power-on.c @@ -2085,6 +2085,8 @@ static int qpnp_pon_read_gen2_pon_off_reason(struct qpnp_pon *pon, u16 *reason, rc = qpnp_pon_read(pon, QPNP_PON_OFF_REASON(pon), ®); if (rc) return rc; + dev_info(pon->dev, "PON Register , addr=0x%04X, val=0x%x\n", + QPNP_PON_OFF_REASON(pon), (u8)reg); if (reg & QPNP_GEN2_POFF_SEQ) { rc = qpnp_pon_read(pon, QPNP_POFF_REASON1(pon), ®1); @@ -2092,6 +2094,8 @@ static int qpnp_pon_read_gen2_pon_off_reason(struct qpnp_pon *pon, u16 *reason, return rc; *reason = (u8)reg1; *reason_index_offset = 0; + dev_info(pon->dev, "PON Register , addr=0x%04X, val=0x%x\n", + QPNP_POFF_REASON1(pon), (u8)buf[0]); } else if (reg & QPNP_GEN2_FAULT_SEQ) { rc = regmap_bulk_read(pon->regmap, QPNP_FAULT_REASON1(pon), buf, 2); @@ -2102,12 +2106,18 @@ static int qpnp_pon_read_gen2_pon_off_reason(struct qpnp_pon *pon, u16 *reason, } *reason = buf[0] | (u16)(buf[1] << 8); *reason_index_offset = POFF_REASON_FAULT_OFFSET; + dev_info(pon->dev, "PON Register , addr=0x%04X, val=0x%x\n", + QPNP_FAULT_REASON1(pon), (u8)buf[0]); + dev_info(pon->dev, "PON Register , addr=0x%04X, val=0x%x\n", + QPNP_FAULT_REASON1(pon), (u8)buf[1]); } else if (reg & QPNP_GEN2_S3_RESET_SEQ) { rc = qpnp_pon_read(pon, QPNP_S3_RESET_REASON(pon), ®1); if (rc) return rc; *reason = (u8)reg1; *reason_index_offset = POFF_REASON_S3_RESET_OFFSET; + dev_info(pon->dev, "PON Register , addr=0x%04X, val=0x%x\n", + QPNP_S3_RESET_REASON(pon), (u8)buf[0]); } return 0; From 9be11bcf241645464dd7e6b708c0ce334416dc0e Mon Sep 17 00:00:00 2001 From: liaohs Date: Mon, 28 Jan 2019 18:50:48 +0800 Subject: [PATCH 215/698] PMIC : print PMIC keys code default Keys or combo Keys code from PMIC: Power key, Volume down key and Power Key + Volume down combo key . Default print these code log to monitor PMIC interrupt. Change-Id: Iaea43e97acc1c43bd5dda37664bf89572f012794 Reviewed-on: https://gerrit.mot.com/1302037 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key Reviewed-by: Haijian Ma Reviewed-on: https://gerrit.mot.com/1470888 Reviewed-by: Zhenxin Xi Reviewed-on: https://gerrit.mot.com/1771188 --- drivers/input/misc/qpnp-power-on.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/misc/qpnp-power-on.c b/drivers/input/misc/qpnp-power-on.c index 39255cd19086..64123c678fb2 100644 --- a/drivers/input/misc/qpnp-power-on.c +++ b/drivers/input/misc/qpnp-power-on.c @@ -1030,7 +1030,7 @@ static int qpnp_pon_input_dispatch(struct qpnp_pon *pon, u32 pon_type) return -EINVAL; } - pr_debug("PMIC input: code=%d, status=0x%02X\n", cfg->key_code, + pr_info("PMIC input: code=%d, status=0x%02X\n", cfg->key_code, pon_rt_sts); key_status = pon_rt_sts & pon_rt_bit; From 12017041d62e735ffe840a2e4e2cef4353de322a Mon Sep 17 00:00:00 2001 From: Ling Jin Date: Wed, 13 Mar 2019 16:33:46 -0500 Subject: [PATCH 216/698] qpnp-power-on: Print system timestamp on Power key event Print system timestamp on Power key press and release events. This would make debugging easy Ported from: https://gerrit.mot.com/#/c/1320467/ Change-Id: I2c810e4b59c2d3bd8a705d407a339d9efe6fad3d Reviewed-on: https://gerrit.mot.com/1320467 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Ryan Lattrel Reviewed-by: Ling Jin Submit-Approved: Jira Key Reviewed-on: https://gerrit.mot.com/1456668 Reviewed-on: https://gerrit.mot.com/1771193 Reviewed-by: Huosheng Liao --- drivers/input/misc/qpnp-power-on.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/input/misc/qpnp-power-on.c b/drivers/input/misc/qpnp-power-on.c index 64123c678fb2..1a990b2a145a 100644 --- a/drivers/input/misc/qpnp-power-on.c +++ b/drivers/input/misc/qpnp-power-on.c @@ -26,6 +26,7 @@ #include #include #include +#include #define PMIC_VER_8941 0x01 #define PMIC_VERSION_REG 0x0105 @@ -986,6 +987,10 @@ static int qpnp_pon_input_dispatch(struct qpnp_pon *pon, u32 pon_type) uint pon_rt_sts; u64 elapsed_us; int rc; + struct timespec64 now; + struct timeval timestamp; + struct tm tm; + char buff[255]; cfg = qpnp_get_cfg(pon, pon_type); if (!cfg) @@ -1014,6 +1019,19 @@ static int qpnp_pon_input_dispatch(struct qpnp_pon *pon, u32 pon_type) pon_rt_bit = is_pon_gen3(pon) ? QPNP_PON_GEN3_KPDPWR_N_SET : QPNP_PON_KPDPWR_N_SET; + + /* get the time stamp in readable format to print*/ + ktime_get_real_ts64(&now); + timestamp.tv_sec = now.tv_sec; + timestamp.tv_usec = now.tv_nsec/1000; + time64_to_tm((time64_t)(timestamp.tv_sec), 0, &tm); + snprintf(buff, sizeof(buff), + "%u-%02d-%02d %02d:%02d:%02d UTC", + (int) tm.tm_year + 1900, tm.tm_mon + 1, + tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); + + pr_info("Report pwrkey %s event at: %s\n", pon_rt_bit & + pon_rt_sts ? "press" : "release", buff); break; case PON_RESIN: pon_rt_bit = is_pon_gen3(pon) From 4b6ab207016c40f5ae79f0907ea4f0a5a0e41901 Mon Sep 17 00:00:00 2001 From: xizx Date: Thu, 30 Apr 2020 19:36:55 +0800 Subject: [PATCH 217/698] pwrkey: change printk level to output to console In user version, Moto kernel policy will mask all KERN_INFO log to console, so change the power key press or release event log level to make it work in user versions. Change-Id: Ia4e7c33819f1e50b6a7778ea186bd1c83890b818 Reviewed-on: https://gerrit.mot.com/1545783 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Zhenxin Xi Submit-Approved: Jira Key Reviewed-on: https://gerrit.mot.com/1771194 Reviewed-by: Huosheng Liao --- drivers/input/misc/qpnp-power-on.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/misc/qpnp-power-on.c b/drivers/input/misc/qpnp-power-on.c index 1a990b2a145a..ca72926a5c34 100644 --- a/drivers/input/misc/qpnp-power-on.c +++ b/drivers/input/misc/qpnp-power-on.c @@ -1030,7 +1030,7 @@ static int qpnp_pon_input_dispatch(struct qpnp_pon *pon, u32 pon_type) (int) tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); - pr_info("Report pwrkey %s event at: %s\n", pon_rt_bit & + pr_warn("Report pwrkey %s event at: %s\n", pon_rt_bit & pon_rt_sts ? "press" : "release", buff); break; case PON_RESIN: From 3f86f1e242138cc59dca871433ac388dfa55fbdc Mon Sep 17 00:00:00 2001 From: jixj Date: Wed, 14 Oct 2020 10:18:09 +0800 Subject: [PATCH 218/698] include/dt-bindings: add a header file for ramoops ramoops,wdog,tzlog,annotate address are continues, it is easy to make mistakes for manual calculation address. Change-Id: If0666017363d2a3d7840f4e2fe197a03c589fec2 Reviewed-on: https://gerrit.mot.com/1773394 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- include/dt-bindings/moto/moto-mem-reserve.h | 37 +++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 include/dt-bindings/moto/moto-mem-reserve.h diff --git a/include/dt-bindings/moto/moto-mem-reserve.h b/include/dt-bindings/moto/moto-mem-reserve.h new file mode 100644 index 000000000000..98093729d3f3 --- /dev/null +++ b/include/dt-bindings/moto/moto-mem-reserve.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2016 Motorola Mobility LLC + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#ifndef __MOTO_MEM_RESERVE_H +#define __MOTO_MEM_RESERVE_H + +#define RAMOOPS_CONSOLE_SIZE 0x40000 +#define RAMOOPS_PMSG_SIZE 0x40000 +#define RAMOOPS_RECORD_SIZE 0x3f800 +#define RAMOOPS_SIZE (RAMOOPS_CONSOLE_SIZE + RAMOOPS_PMSG_SIZE + RAMOOPS_RECORD_SIZE) +#define RAMOOPS_BASE_ADDR 0xaf000000 + +#define WDOG_CPUCTX_SIZE_PERCPU 0x5c00 /* sizeof(struct msm_wdog_cpuctx) */ +#define WDOG_CPUCTX_SIZE_8CPUS (WDOG_CPUCTX_SIZE_PERCPU * 8) +#define WDOG_CPUCTX_SIZE_4CPUS (WDOG_CPUCTX_SIZE_PERCPU * 4) + +#define WDOG_CPUCTX_END_ADDR RAMOOPS_BASE_ADDR + +#define WDOG_CPUCTX_SIZE WDOG_CPUCTX_SIZE_8CPUS +#define WDOG_CPUCTX_BASE (WDOG_CPUCTX_END_ADDR - WDOG_CPUCTX_SIZE_8CPUS) + +#define TZLOG_BCK_SIZE 0x30000 +#define TZLOG_BCK_BASE (WDOG_CPUCTX_BASE - TZLOG_BCK_SIZE) + +#define MMI_ANNOTATE_SIZE 0x800 +#define MMI_ANNOTATE_BASE (TZLOG_BCK_BASE - MMI_ANNOTATE_SIZE) + +#endif /* __MOTO_MEM_RESERVE_H */ From 6d1c3b7e793c351b0faf22273e3c521ccec74e21 Mon Sep 17 00:00:00 2001 From: Xianshan Wang Date: Thu, 28 Nov 2019 15:13:45 +0800 Subject: [PATCH 219/698] defconfig: lito: turn off pstore compress Disable compression of the pstore, so the bootloader can read it more easily. Change-Id: If2d33f1b097f6612a0d810eae79354b086251b19 Signed-off-by: Xianshan Wang Reviewed-on: https://gerrit.mot.com/1462923 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Reviewed-by: Zhenxin Xi Tested-by: Jira Key Submit-Approved: Jira Key Reviewed-on: https://gerrit.mot.com/1773806 Reviewed-by: Huosheng Liao --- fs/pstore/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/fs/pstore/Kconfig b/fs/pstore/Kconfig index 9fe46cc26403..6900f8914462 100644 --- a/fs/pstore/Kconfig +++ b/fs/pstore/Kconfig @@ -16,7 +16,6 @@ config PSTORE config PSTORE_DEFLATE_COMPRESS tristate "DEFLATE (ZLIB) compression" - default y depends on PSTORE select CRYPTO_DEFLATE help From e1753b0bac96ed060f1fa1e6b4f1f5272ea41597 Mon Sep 17 00:00:00 2001 From: jixj Date: Wed, 14 Oct 2020 15:41:47 +0800 Subject: [PATCH 220/698] arm64/defconfig: enable pstore Enable pstore for kpanic logs. CONFIG_PSTORE=y CONFIG_PSTORE_CONSOLE=y CONFIG_PSTORE_RAM=y CONFIG_PSTORE_PMSG=y Change-Id: I7f1d1367b1e709c3613d75737e3dfc99b90e2eb1 Reviewed-on: https://gerrit.mot.com/1773807 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi.config | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi.config b/arch/arm64/configs/vendor/ext_config/moto-holi.config index 16240795456e..d2e826726306 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi.config @@ -15,3 +15,7 @@ # CONFIG_LOCALVERSION="-moto" CONFIG_MMI_DEVICE_DTBS=y +CONFIG_PSTORE=y +CONFIG_PSTORE_CONSOLE=y +CONFIG_PSTORE_RAM=y +CONFIG_PSTORE_PMSG=y From 6e40b6b76bb9880c5e0c29a78a95d473c5ba3e0c Mon Sep 17 00:00:00 2001 From: linyx10 Date: Thu, 15 Oct 2020 14:19:44 +0800 Subject: [PATCH 221/698] Do not unload prov TZ app. From (CR) This app manages secure state as set by bootloader. Reloading would clear the state. This solution is limted by some alternate way to force unloading our prov TA and then restarting it outside bootloader. Change-Id: Ic219f60d12ce202a55af70dfa95c1c7d7cfdf121 Signed-off-by: linyx10 Reviewed-on: https://gerrit.mot.com/1774860 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Binsheng Que Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- drivers/misc/qseecom.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c index 2eeabe55d6ca..423b96f0f0c3 100644 --- a/drivers/misc/qseecom.c +++ b/drivers/misc/qseecom.c @@ -3138,6 +3138,11 @@ static int qseecom_unload_app(struct qseecom_dev_handle *data, goto unload_exit; } + if (!memcmp(data->client.app_name, "prov", strlen("prov"))) { + pr_debug("Do not unload prov app from tz\n"); + goto unload_exit; + } + __qseecom_cleanup_app(data); __qseecom_reentrancy_check_if_no_app_blocked(TZ_OS_APP_SHUTDOWN_ID); From c12db773b50a5bc651393ad1692e3f980c2e2d7a Mon Sep 17 00:00:00 2001 From: Ryan Lattrel Date: Tue, 12 May 2020 16:45:27 +0800 Subject: [PATCH 222/698] (CR): drivers: enable step-wise and qmi tz logs Change step-wise temperature trip and qmi cdev logging from debug to warning to better track thermal engine changes. Change-Id: Ieaf0c3b796e2aa321220ba2e0adb3b9f24c41d5b Signed-off-by: Ryan Lattrel Reviewed-on: https://gerrit.mot.com/1339510 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Kenneth Kessler Submit-Approved: Jira Key Reviewed-on: https://gerrit.mot.com/1554966 Reviewed-by: Lu Chai Reviewed-by: Huosheng Liao Reviewed-on: https://gerrit.mot.com/1778283 --- drivers/thermal/qcom/qmi_cooling.c | 2 +- drivers/thermal/step_wise.c | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/thermal/qcom/qmi_cooling.c b/drivers/thermal/qcom/qmi_cooling.c index 22a0ee9ac2c5..d4077ae421ae 100644 --- a/drivers/thermal/qcom/qmi_cooling.c +++ b/drivers/thermal/qcom/qmi_cooling.c @@ -173,7 +173,7 @@ static int qmi_tmd_send_state_request(struct qmi_cooling_device *qmi_cdev, goto qmi_send_exit; } ret = 0; - pr_debug("Requested qmi state:%d for %s\n", state, qmi_cdev->cdev_name); + pr_warn("Requested qmi state:%d for %s\n", state, qmi_cdev->cdev_name); qmi_send_exit: mutex_unlock(&tmd->mutex); diff --git a/drivers/thermal/step_wise.c b/drivers/thermal/step_wise.c index 8978951c03b4..0f73f04a0409 100644 --- a/drivers/thermal/step_wise.c +++ b/drivers/thermal/step_wise.c @@ -188,8 +188,11 @@ static void update_passive_instance(struct thermal_zone_device *tz, * If value is +1, activate a passive instance. * If value is -1, deactivate a passive instance. */ - if (type == THERMAL_TRIP_PASSIVE || type == THERMAL_TRIPS_NONE) + if (type == THERMAL_TRIP_PASSIVE || type == THERMAL_TRIPS_NONE) { tz->passive += value; + dev_warn(&tz->device, "[%s] temp=%d, passive=%d\n", + tz->type, tz->temperature, tz->passive); + } } #ifdef CONFIG_QTI_THERMAL From bfcc95d87abb2c89c84b1cae558217ce12cb6643 Mon Sep 17 00:00:00 2001 From: Ryan Lattrel Date: Tue, 7 Jul 2020 16:22:48 -0500 Subject: [PATCH 223/698] (CR): alarmtimer: add debug to identify alarmtimers Based on KBA-200505201040 Print out timer wake-up info to debug the sources of pm8xxx_rtc_alarm wake-ups. Change-Id: I39f24dad0613a08844eefcd25076831589256e52 Signed-off-by: Ryan Lattrel Reviewed-on: https://gerrit.mot.com/1668046 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Ling Jin Submit-Approved: Jira Key Reviewed-on: https://gerrit.mot.com/1778266 Reviewed-by: Huosheng Liao --- fs/timerfd.c | 6 ++++++ kernel/time/alarmtimer.c | 17 +++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/fs/timerfd.c b/fs/timerfd.c index 48305ba41e3c..c2d289795686 100644 --- a/fs/timerfd.c +++ b/fs/timerfd.c @@ -238,6 +238,12 @@ static __poll_t timerfd_poll(struct file *file, poll_table *wait) spin_lock_irqsave(&ctx->wqh.lock, flags); if (ctx->ticks) events |= EPOLLIN; + + if (ctx->expired && isalarm(ctx)) + pr_info("%s: comm:%s pid:%d exp:%llu\n", __func__, + current->comm, current->pid, + ktime_to_ms(ctx->t.alarm.node.expires)); + spin_unlock_irqrestore(&ctx->wqh.lock, flags); return events; diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c index 9bd4e492823b..1e716c953fcd 100644 --- a/kernel/time/alarmtimer.c +++ b/kernel/time/alarmtimer.c @@ -60,6 +60,7 @@ static struct wakeup_source *ws; /* rtc timer and device for setting alarm wakeups at suspend */ static struct rtc_timer rtctimer; static struct rtc_device *rtcdev; +static int alarm_debug = 0; static DEFINE_SPINLOCK(rtcdev_lock); /** @@ -215,6 +216,12 @@ static enum hrtimer_restart alarmtimer_fired(struct hrtimer *timer) alarmtimer_dequeue(base, alarm); spin_unlock_irqrestore(&base->lock, flags); + if(alarm_debug & 0x1){ + pr_info("%s: type=%d, func=%pf, exp:%llu\n", __func__, + alarm->type, alarm->function, ktime_to_ms(alarm->node.expires)); + alarm_debug &= 0xFE; + } + if (alarm->function) restart = alarm->function(alarm, base->gettime()); @@ -255,6 +262,7 @@ static int alarmtimer_suspend(struct device *dev) struct rtc_device *rtc; unsigned long flags; struct rtc_time tm; + struct alarm* min_timer = NULL; spin_lock_irqsave(&freezer_delta_lock, flags); min = freezer_delta; @@ -281,6 +289,7 @@ static int alarmtimer_suspend(struct device *dev) continue; delta = ktime_sub(next->expires, base->gettime()); if (!min || (delta < min)) { + min_timer = container_of(next, struct alarm, node); expires = next->expires; min = delta; type = i; @@ -289,6 +298,14 @@ static int alarmtimer_suspend(struct device *dev) if (min == 0) return 0; + if (min_timer){ + pr_info("%s: [%p]type=%d, func=%pf, exp:%llu\n", __func__, + min_timer, min_timer->type, min_timer->function, + ktime_to_ms(min_timer->node.expires)); + min_timer = NULL; + } + alarm_debug = 0x1; + if (ktime_to_ns(min) < 2 * NSEC_PER_SEC) { __pm_wakeup_event(ws, 2 * MSEC_PER_SEC); return -EBUSY; From a9922aa62d88b83c134f2e4e193fee4a905daa25 Mon Sep 17 00:00:00 2001 From: wuwl10 Date: Mon, 19 Oct 2020 14:20:41 +0800 Subject: [PATCH 224/698] arm64/config: ibiza: enable qti nfc driver Enable default qti nfc driver to bring up PN557 for Ibiza. Change-Id: I40cf677cb4057711c87656714be7a450202c66ce Signed-off-by: wuwl10 Reviewed-on: https://gerrit.mot.com/1778379 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config b/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config index 08aae02d0462..637e43692c6b 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config @@ -14,3 +14,4 @@ # being set as expected. # CONFIG_IBIZA_DTB=y +CONFIG_NFC_QTI_I2C=y From 9e9542e9878e8933d40992376ab30415fbab296a Mon Sep 17 00:00:00 2001 From: Todd Poynor Date: Tue, 29 May 2012 17:33:56 -0700 Subject: [PATCH 225/698] PM/Suspend:Print wall time at suspend entry and exit Cherry pick this commit from defender to print "PM: suspend" with wall time when enter and exit suspend. Change-Id: I92f252414c013b018b9a392eae1ee039aa0e89dc Signed-off-by: Todd Poynor Signed-off-by: yangjq Reviewed-on: https://gerrit.mot.com/1477734 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Jialei Hao Reviewed-by: Jianqi Yang Submit-Approved: Jira Key Reviewed-on: https://gerrit.mot.com/1778522 Reviewed-by: Huosheng Liao --- kernel/power/suspend.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c index 3a231ceefa94..b584c67f57ab 100644 --- a/kernel/power/suspend.c +++ b/kernel/power/suspend.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -608,6 +609,18 @@ static int enter_state(suspend_state_t state) return error; } +static void pm_suspend_marker(char *annotation) +{ + struct timespec ts; + struct rtc_time tm; + + getnstimeofday(&ts); + rtc_time_to_tm(ts.tv_sec, &tm); + pr_info("PM: suspend %s %d-%02d-%02d %02d:%02d:%02d.%09lu UTC\n", + annotation, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, + tm.tm_hour, tm.tm_min, tm.tm_sec, ts.tv_nsec); +} + /** * pm_suspend - Externally visible function for suspending the system. * @state: System sleep state to enter. @@ -622,6 +635,7 @@ int pm_suspend(suspend_state_t state) if (state <= PM_SUSPEND_ON || state >= PM_SUSPEND_MAX) return -EINVAL; + pm_suspend_marker("entry"); pr_info("suspend entry (%s)\n", mem_sleep_labels[state]); error = enter_state(state); if (error) { @@ -630,6 +644,7 @@ int pm_suspend(suspend_state_t state) } else { suspend_stats.success++; } + pm_suspend_marker("exit"); pr_info("suspend exit\n"); return error; } From f702a1f0dc9d32f3f92f76b11ac5c2260ba30719 Mon Sep 17 00:00:00 2001 From: Ryan Lattrel Date: Mon, 11 Dec 2017 17:40:38 -0600 Subject: [PATCH 226/698] msm-poweroff: Store restart reason After cold reset is introduced, the phone is cold reset instead of warm reset, such as panic. In this case, the power up reason saved in shared memory will be lost. Consequently, the power up reason on next boot up time will be normal boot instead of correct ones. To resolve this issue, we can use the two spared pmic registers which are power lost safe to save the restart reason for these cases. Motorola definition of AP panic bit set in extra info pmic reg conflicts with QC definition of Warm reboot bit set in extra info reg move Mot bit to available position to avoid conflict Force a cold reboot for the command "adb reboot bootloader" to avoid the warm boot when user tries to continue boot from boot menu. For early kernel panic before PMIC is initialized, the function qpnp_pon_store_extra_reset_info will fail. Need to set IMEM flag for fail safe in this case. For post-panic, post-wdt, post-pmicwdt reboot, we do cold reset. And set the PMIC register accordingly, to nofity BL the special reboot behavior. Configure panic as warm restart, so that we have chance to get panic logs. According to SR 01277290, 0x88D and 0x88E are spare registers for PMIC where we could store oem specific reset information Ported from: https://gerrit.mot.com/#/c/1211826/ Change-Id: Id3a010b8a52e72180685b1f92491d9616b2cb714 Signed-off-by: Andrew Abbott Reviewed-on: https://gerrit.mot.com/1446282 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Cesar Augusto Marcelino dos Santos Reviewed-by: Ling Jin Submit-Approved: Jira Key Reviewed-on: https://gerrit.mot.com/1778582 Reviewed-by: Huosheng Liao --- drivers/input/misc/qpnp-power-on.c | 46 +++++++++++++++++++++++++++++ drivers/power/reset/msm-poweroff.c | 34 ++++++++++++++++++++- include/linux/input/qpnp-power-on.h | 12 ++++++++ 3 files changed, 91 insertions(+), 1 deletion(-) diff --git a/drivers/input/misc/qpnp-power-on.c b/drivers/input/misc/qpnp-power-on.c index ca72926a5c34..f51965839d1b 100644 --- a/drivers/input/misc/qpnp-power-on.c +++ b/drivers/input/misc/qpnp-power-on.c @@ -100,6 +100,8 @@ enum qpnp_pon_version { #define QPNP_PON_S3_DBC_CTL(pon) ((pon)->base + 0x75) #define QPNP_PON_SMPL_CTL(pon) ((pon)->base + 0x7F) #define QPNP_PON_TRIGGER_EN(pon) ((pon)->base + 0x80) +#define QPNP_PON_PERPH_RB_SPARE(pon) ((pon)->base + 0x8C) +#define QPNP_PON_DVDD_RB_SPARE(pon) ((pon)->base + 0x8D) #define QPNP_PON_XVDD_RB_SPARE(pon) ((pon)->base + 0x8E) #define QPNP_PON_SOFT_RB_SPARE(pon) ((pon)->base + 0x8F) #define QPNP_PON_SEC_ACCESS(pon) ((pon)->base + 0xD0) @@ -452,6 +454,50 @@ int qpnp_pon_set_restart_reason(enum pon_restart_reason reason) } EXPORT_SYMBOL(qpnp_pon_set_restart_reason); +/** + * qpnp_pon_store_extra_reset_info - Store extra reset info in PMIC register. + * + * Returns = 0 if PMIC feature is not available or store restart reason + * successfully. + * Returns > 0 for errors + * + * This function is used to store extra reset info in PMIC spare register + * which can be preserved during reset. + */ +int qpnp_pon_store_extra_reset_info(u16 mask, u16 val) +{ + int rc = 0; + struct qpnp_pon *pon = sys_reset_dev; + + if (!pon) + return 0; + + if (mask & 0xFF) { + rc = qpnp_pon_masked_write(pon, QPNP_PON_DVDD_RB_SPARE(pon), + (mask & 0xFF), (val & 0xFF)); + if (rc) { + dev_err(pon->dev, + "Failed to store extra reset info to 0x%x\n", + QPNP_PON_DVDD_RB_SPARE(pon)); + return rc; + } + } + + if (mask & 0xFF00) { + rc = qpnp_pon_masked_write(pon, QPNP_PON_XVDD_RB_SPARE(pon), + ((mask >> 8) & 0xFF), ((val >> 8) & 0xFF)); + if (rc) { + dev_err(pon->dev, + "Failed to store extra reset info to 0x%x\n", + QPNP_PON_XVDD_RB_SPARE(pon)); + return rc; + } + } + + return rc; +} +EXPORT_SYMBOL(qpnp_pon_store_extra_reset_info); + /* * qpnp_pon_check_hard_reset_stored() - Checks if the PMIC need to * store hard reset reason. diff --git a/drivers/power/reset/msm-poweroff.c b/drivers/power/reset/msm-poweroff.c index 8db5b7286ac3..0c3efe9abf7c 100644 --- a/drivers/power/reset/msm-poweroff.c +++ b/drivers/power/reset/msm-poweroff.c @@ -426,7 +426,7 @@ static void msm_restart_prepare(const char *cmd) pr_info("Forcing a warm reset of the system\n"); /* Hard reset the PMIC unless memory contents must be maintained. */ - if (force_warm_reboot || need_warm_reset) + if (force_warm_reboot || in_panic) qpnp_pon_system_pwr_off(PON_POWER_OFF_WARM_RESET); else qpnp_pon_system_pwr_off(PON_POWER_OFF_HARD_RESET); @@ -435,6 +435,14 @@ static void msm_restart_prepare(const char *cmd) if (!strncmp(cmd, "bootloader", 10)) { reason = PON_RESTART_REASON_BOOTLOADER; __raw_writel(0x77665500, restart_reason); + /* set reboot_bl flag in PMIC for cold reset */ + qpnp_pon_store_extra_reset_info(RESET_EXTRA_REBOOT_BL_REASON, + RESET_EXTRA_REBOOT_BL_REASON); + /* + * force cold reboot here to avoid unexpected + * warm boot from bootloader. + */ + qpnp_pon_system_pwr_off(PON_POWER_OFF_HARD_RESET); } else if (!strncmp(cmd, "recovery", 8)) { reason = PON_RESTART_REASON_RECOVERY; __raw_writel(0x77665502, restart_reason); @@ -460,6 +468,24 @@ static void msm_restart_prepare(const char *cmd) restart_reason); } else if (!strncmp(cmd, "edl", 3)) { enable_emergency_dload_mode(); + } else if (!strncmp(cmd, "post-wdt", 8)) { + /* set flag in PMIC to nofity BL post watchdog reboot */ + qpnp_pon_store_extra_reset_info(RESET_EXTRA_POST_REBOOT_MASK, + RESET_EXTRA_POST_WDT_REASON); + /* force cold reboot */ + qpnp_pon_system_pwr_off(PON_POWER_OFF_HARD_RESET); + } else if (!strncmp(cmd, "post-pmicwdt", 12)) { + /* set flag in PMIC to nofity BL post pmic watchdog reboot */ + qpnp_pon_store_extra_reset_info(RESET_EXTRA_POST_REBOOT_MASK, + RESET_EXTRA_POST_PMICWDT_REASON); + /* force cold reboot */ + qpnp_pon_system_pwr_off(PON_POWER_OFF_HARD_RESET); + } else if (!strncmp(cmd, "post-panic", 10)) { + /* set flag in PMIC to nofity BL post panic reboot */ + qpnp_pon_store_extra_reset_info(RESET_EXTRA_POST_REBOOT_MASK, + RESET_EXTRA_POST_PANIC_REASON); + /* force cold reboot */ + qpnp_pon_system_pwr_off(PON_POWER_OFF_HARD_RESET); } else { __raw_writel(0x77665501, restart_reason); } @@ -469,6 +495,12 @@ static void msm_restart_prepare(const char *cmd) else qpnp_pon_set_restart_reason( (enum pon_restart_reason)reason); + } else if (in_panic == 1) { + __raw_writel(0x77665505, restart_reason); + qpnp_pon_store_extra_reset_info(RESET_EXTRA_PANIC_REASON, + RESET_EXTRA_PANIC_REASON); + } else { + __raw_writel(0x77665501, restart_reason); } /*outer_flush_all is not supported by 64bit kernel*/ diff --git a/include/linux/input/qpnp-power-on.h b/include/linux/input/qpnp-power-on.h index 5e4f39ac9298..01c65317d4ca 100644 --- a/include/linux/input/qpnp-power-on.h +++ b/include/linux/input/qpnp-power-on.h @@ -57,6 +57,13 @@ enum pon_restart_reason { PON_RESTART_REASON_KEYS_CLEAR = 0x06, }; +#define RESET_EXTRA_POST_PANIC_REASON (BIT(4) | BIT(5)) +#define RESET_EXTRA_POST_PMICWDT_REASON BIT(5) +#define RESET_EXTRA_POST_WDT_REASON BIT(4) +#define RESET_EXTRA_POST_REBOOT_MASK (BIT(4) | BIT(5) | BIT(6)) +#define RESET_EXTRA_PANIC_REASON BIT(3) +#define RESET_EXTRA_REBOOT_BL_REASON BIT(2) + #if IS_ENABLED(CONFIG_INPUT_QPNP_POWER_ON) int qpnp_pon_system_pwr_off(enum pon_power_off_type type); int qpnp_pon_is_warm_reset(void); @@ -65,6 +72,7 @@ int qpnp_pon_wd_config(bool enable); int qpnp_pon_set_restart_reason(enum pon_restart_reason reason); bool qpnp_pon_check_hard_reset_stored(void); int qpnp_pon_modem_pwr_off(enum pon_power_off_type type); +int qpnp_pon_store_extra_reset_info(u16 mask, u16 val); #else @@ -104,6 +112,10 @@ static inline int qpnp_pon_modem_pwr_off(enum pon_power_off_type type) return -ENODEV; } +static inline int qpnp_pon_store_extra_reset_info(u16 mask, u16 val) +{ + return -ENODEV; +} #endif #endif From 45f6f796b2a82f43293aff5a490e0ba5c12111db Mon Sep 17 00:00:00 2001 From: xizx Date: Tue, 9 Jan 2018 17:06:19 +0800 Subject: [PATCH 227/698] add system restart warm and panic mode add two debug interfaces: 1.when set cmdline "sys_restart_mode=warm", the kernel will reset with WARM way. 2.when set cmdline "sys_restart_mode=panic", the kernel will enter into ramdump when it normal reset. Change-Id: Id70063bac7d0951622c6e074c2ba2ec024374022 Signed-off-by: xizx Reviewed-on: https://gerrit.mot.com/1117501 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Submit-Approved: Jira Key Reviewed-on: https://gerrit.mot.com/1345290 Reviewed-on: https://gerrit.mot.com/1406867 Reviewed-on: https://gerrit.mot.com/1463612 Reviewed-on: https://gerrit.mot.com/1778583 Reviewed-by: Huosheng Liao --- drivers/power/reset/msm-poweroff.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/drivers/power/reset/msm-poweroff.c b/drivers/power/reset/msm-poweroff.c index 0c3efe9abf7c..1003d705079b 100644 --- a/drivers/power/reset/msm-poweroff.c +++ b/drivers/power/reset/msm-poweroff.c @@ -395,6 +395,20 @@ void msm_set_restart_mode(int mode) } EXPORT_SYMBOL(msm_set_restart_mode); +#define DEBUG_SYS_RESETART_WARM 1 +#define DEBUG_SYS_RESETART_PANIC 2 +static int debug_sys_restart_mode; +static int __init set_sys_restart_mode(char *str) +{ + if (!strcmp(str, "warm")) + debug_sys_restart_mode = DEBUG_SYS_RESETART_WARM; + else if (!strcmp(str, "panic")) + debug_sys_restart_mode = DEBUG_SYS_RESETART_PANIC; + pr_info("sys_restart_mode is set to %d\n", debug_sys_restart_mode); + return 1; +} + +__setup("sys_restart_mode=", set_sys_restart_mode); static void msm_restart_prepare(const char *cmd) { @@ -405,6 +419,11 @@ static void msm_restart_prepare(const char *cmd) * Kill download mode if master-kill switch is set */ + if (debug_sys_restart_mode == DEBUG_SYS_RESETART_PANIC) { + in_panic = 1; + pr_info("force system enter into ramdump for debug\n"); + } + if (cmd != NULL && !strcmp(cmd, "qcom_dload")) restart_mode = RESTART_DLOAD; @@ -503,6 +522,11 @@ static void msm_restart_prepare(const char *cmd) __raw_writel(0x77665501, restart_reason); } + if (debug_sys_restart_mode == DEBUG_SYS_RESETART_WARM) { + qpnp_pon_system_pwr_off(PON_POWER_OFF_WARM_RESET); + pr_info("set system warmreset mode for debug\n"); + } + /*outer_flush_all is not supported by 64bit kernel*/ #ifndef CONFIG_ARM64 outer_flush_all(); From a7c7f70bb5927afa6f049668394ca7e73bc7556f Mon Sep 17 00:00:00 2001 From: Qing Chang Date: Tue, 24 Mar 2020 12:18:22 -0500 Subject: [PATCH 228/698] power: reset: Use warm reset for dload mode dload mode requires memory contents to be maintained, so we have to use warm reset during reboot. Change-Id: Idb4a01685e7164cc6a5272d0287934bc6fe6307f Signed-off-by: Qing Chang Reviewed-on: https://gerrit.mot.com/1520641 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Dong-Hua Yan Reviewed-by: Qing Chang Submit-Approved: Jira Key Reviewed-on: https://gerrit.mot.com/1778585 Reviewed-by: Huosheng Liao --- drivers/power/reset/msm-poweroff.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/power/reset/msm-poweroff.c b/drivers/power/reset/msm-poweroff.c index 1003d705079b..d4cd4fa4c451 100644 --- a/drivers/power/reset/msm-poweroff.c +++ b/drivers/power/reset/msm-poweroff.c @@ -445,7 +445,7 @@ static void msm_restart_prepare(const char *cmd) pr_info("Forcing a warm reset of the system\n"); /* Hard reset the PMIC unless memory contents must be maintained. */ - if (force_warm_reboot || in_panic) + if (force_warm_reboot || need_warm_reset || in_panic) qpnp_pon_system_pwr_off(PON_POWER_OFF_WARM_RESET); else qpnp_pon_system_pwr_off(PON_POWER_OFF_HARD_RESET); From f97ae225f28bc892b2ef059c001c26e4de389451 Mon Sep 17 00:00:00 2001 From: xizx Date: Fri, 17 Apr 2020 20:33:15 +0800 Subject: [PATCH 229/698] Reboot: trigger warm reset when receive hw_warmreset cmd The "hw_warmreset" reboot command, it indicates the kernel to trigger warm reset for saving lastkmsg. After the system warm reboot, the AP will save last kmsg logs and call a clean cold reboot with the "post-hw_warmreset" command. Change-Id: I3a25735a4e9ff0ab72c05d3ba2914d80477d30dc Reviewed-on: https://gerrit.mot.com/1536789 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Zhenxin Xi Submit-Approved: Jira Key Reviewed-on: https://gerrit.mot.com/1778586 Reviewed-by: Huosheng Liao --- drivers/power/reset/msm-poweroff.c | 11 +++++++++++ include/linux/input/qpnp-power-on.h | 2 ++ 2 files changed, 13 insertions(+) diff --git a/drivers/power/reset/msm-poweroff.c b/drivers/power/reset/msm-poweroff.c index d4cd4fa4c451..5ce3ba641c32 100644 --- a/drivers/power/reset/msm-poweroff.c +++ b/drivers/power/reset/msm-poweroff.c @@ -505,6 +505,17 @@ static void msm_restart_prepare(const char *cmd) RESET_EXTRA_POST_PANIC_REASON); /* force cold reboot */ qpnp_pon_system_pwr_off(PON_POWER_OFF_HARD_RESET); + } else if (!strncmp(cmd, "hw_warmreset", 13)) { + qpnp_pon_set_restart_reason( + PON_RESTART_REASON_HW_WARMRESET); + qpnp_pon_system_pwr_off(PON_POWER_OFF_WARM_RESET); + pr_info("set system hw warmreset mode\n"); + } else if (!strncmp(cmd, "post-hw_warmreset", 17)) { + /* set flag in PMIC to nofity BL post hw_warmreset reboot */ + qpnp_pon_store_extra_reset_info(RESET_EXTRA_POST_REBOOT_MASK, + RESET_EXTRA_POST_HWWARM_RESET_REASON); + /* force cold reboot */ + qpnp_pon_system_pwr_off(PON_POWER_OFF_HARD_RESET); } else { __raw_writel(0x77665501, restart_reason); } diff --git a/include/linux/input/qpnp-power-on.h b/include/linux/input/qpnp-power-on.h index 01c65317d4ca..92d81b30849f 100644 --- a/include/linux/input/qpnp-power-on.h +++ b/include/linux/input/qpnp-power-on.h @@ -55,8 +55,10 @@ enum pon_restart_reason { PON_RESTART_REASON_DMVERITY_CORRUPTED = 0x04, PON_RESTART_REASON_DMVERITY_ENFORCE = 0x05, PON_RESTART_REASON_KEYS_CLEAR = 0x06, + PON_RESTART_REASON_HW_WARMRESET = 0x18, }; +#define RESET_EXTRA_POST_HWWARM_RESET_REASON BIT(6) #define RESET_EXTRA_POST_PANIC_REASON (BIT(4) | BIT(5)) #define RESET_EXTRA_POST_PMICWDT_REASON BIT(5) #define RESET_EXTRA_POST_WDT_REASON BIT(4) From c4210a99349e190c8df4ab4e2ad178336e24775d Mon Sep 17 00:00:00 2001 From: yuedl1 Date: Wed, 13 May 2020 18:18:25 +0800 Subject: [PATCH 230/698] ufs:fixed ufshcd wait doorbell clear timeout when devfreq ufs, ufshcd wait doorbell clear timeout. some operations maybe take time longer than 1s. such as unmap operation. so change the timeout to 2s. error log as bellow: 01-07 09:50:34.508 0 0 E ufshcd-qcom 1d84000.ufshc: ufshcd_wait_for_doorbell_clr: timedout waiting for doorbell to clear (tm=0x0, tr=0x2000000) 01-07 09:50:34.508 0 0 E devfreq 1d84000.ufshc: dvfs failed with (-16) error Change-Id: Ie33481603a6f96c710e0180bfdd61b7d88eb003b Signed-off-by: yuedl1 Reviewed-on: https://gerrit.mot.com/1554341 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Chuanchun Zhu Reviewed-by: Huosheng Liao Reviewed-by: Shi-Yong Li Submit-Approved: Jira Key Reviewed-on: https://gerrit.mot.com/1779344 --- drivers/scsi/ufs/ufshcd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 13f5f4626322..569d2efbf783 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -1232,7 +1232,7 @@ static int ufshcd_scale_gear(struct ufs_hba *hba, bool scale_up) static int ufshcd_clock_scaling_prepare(struct ufs_hba *hba) { - #define DOORBELL_CLR_TOUT_US (1000 * 1000) /* 1 sec */ + #define DOORBELL_CLR_TOUT_US (2000 * 1000) /* 2 sec */ int ret = 0; /* * make sure that there are no outstanding requests when From ff35fee51a55fe21d92cbe7b38103e28fb4358a5 Mon Sep 17 00:00:00 2001 From: xuwt2 Date: Fri, 2 Aug 2019 14:27:13 +0800 Subject: [PATCH 231/698] mmc/sd: Add sys entry to read card speed Card speed class and UHS speed grade is useful properies. Thos properties can be read from SD status. Change-Id: I0252dd63b661fd2c33849cf0033b08f367a928a9 Signed-off-by: xuwt2 Reviewed-on: https://gerrit.mot.com/1395940 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Jialei Hao Reviewed-by: Jianqi Yang Submit-Approved: Jira Key Reviewed-on: https://gerrit.mot.com/1515687 Reviewed-by: Wentao Xu Reviewed-by: Huosheng Liao Reviewed-on: https://gerrit.mot.com/1779345 --- drivers/mmc/core/sd.c | 33 +++++++++++++++++++++++++++------ include/linux/mmc/card.h | 2 ++ 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index 9607ff927ea4..1df11ba30aec 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -52,6 +52,10 @@ static const unsigned int sd_au_size[] = { SZ_16M / 512, (SZ_16M + SZ_8M) / 512, SZ_32M / 512, SZ_64M / 512, }; +static const unsigned int sd_speed_class[] = { + 0, 2, 4, 6, 10, +}; + #define UNSTUFF_BITS(resp,start,size) \ ({ \ const int __size = size; \ @@ -297,6 +301,12 @@ static int mmc_read_ssr(struct mmc_card *card) card->erase_arg = (card->scr.sda_specx && discard_support) ? SD_DISCARD_ARG : SD_ERASE_ARG; + card->ssr.speed_class = sd_speed_class[UNSTUFF_BITS(card->raw_ssr, 440 - 384, 8)]; + card->ssr.uhs_speed_grade = UNSTUFF_BITS(card->raw_ssr, 396 - 384, 4); + pr_info("%s: card speed is C%d. uhs grade is %d\n", + mmc_hostname(card->host), + card->ssr.speed_class, + card->ssr.uhs_speed_grade); return 0; } @@ -439,28 +449,34 @@ static void sd_update_bus_speed_mode(struct mmc_card *card) */ if (!mmc_host_uhs(card->host)) { card->sd_bus_speed = 0; + pr_info("%s: not UHS\n", mmc_hostname(card->host)); return; } if ((card->host->caps & MMC_CAP_UHS_SDR104) && (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_SDR104)) { - card->sd_bus_speed = UHS_SDR104_BUS_SPEED; + card->sd_bus_speed = UHS_SDR104_BUS_SPEED; + pr_info("%s: selected SDR104\n", mmc_hostname(card->host)); } else if ((card->host->caps & MMC_CAP_UHS_DDR50) && (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_DDR50)) { - card->sd_bus_speed = UHS_DDR50_BUS_SPEED; + card->sd_bus_speed = UHS_DDR50_BUS_SPEED; + pr_info("%s: selected DDR50\n", mmc_hostname(card->host)); } else if ((card->host->caps & (MMC_CAP_UHS_SDR104 | MMC_CAP_UHS_SDR50)) && (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_SDR50)) { - card->sd_bus_speed = UHS_SDR50_BUS_SPEED; + card->sd_bus_speed = UHS_SDR50_BUS_SPEED; + pr_info("%s: selected SDR50\n", mmc_hostname(card->host)); } else if ((card->host->caps & (MMC_CAP_UHS_SDR104 | MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR25)) && (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_SDR25)) { - card->sd_bus_speed = UHS_SDR25_BUS_SPEED; + card->sd_bus_speed = UHS_SDR25_BUS_SPEED; + pr_info("%s: selected SDR25\n", mmc_hostname(card->host)); } else if ((card->host->caps & (MMC_CAP_UHS_SDR104 | MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR25 | MMC_CAP_UHS_SDR12)) && (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_SDR12)) { - card->sd_bus_speed = UHS_SDR12_BUS_SPEED; + card->sd_bus_speed = UHS_SDR12_BUS_SPEED; + pr_info("%s: selected SDR12\n", mmc_hostname(card->host)); } } @@ -749,7 +765,8 @@ MMC_DEV_ATTR(oemid, "0x%04x\n", card->cid.oemid); MMC_DEV_ATTR(serial, "0x%08x\n", card->cid.serial); MMC_DEV_ATTR(ocr, "0x%08x\n", card->ocr); MMC_DEV_ATTR(rca, "0x%04x\n", card->rca); - +MMC_DEV_ATTR(speed_class, "%u\n", card->ssr.speed_class); +MMC_DEV_ATTR(uhs_speed_grade, "%u\n", card->ssr.uhs_speed_grade); static ssize_t mmc_dsr_show(struct device *dev, struct device_attribute *attr, @@ -784,6 +801,8 @@ static struct attribute *sd_std_attrs[] = { &dev_attr_ocr.attr, &dev_attr_rca.attr, &dev_attr_dsr.attr, + &dev_attr_speed_class.attr, + &dev_attr_uhs_speed_grade.attr, NULL, }; ATTRIBUTE_GROUPS(sd_std); @@ -1125,10 +1144,12 @@ retry: /* Initialization sequence for UHS-I cards */ if (rocr & SD_ROCR_S18A && mmc_host_uhs(host)) { + pr_info("%s: card is UHS\n", mmc_hostname(card->host)); err = mmc_sd_init_uhs_card(card); if (err) goto free_card; } else { + pr_info("%s: card is legacy\n", mmc_hostname(card->host)); /* * Attempt to change to high-speed (if supported) */ diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index 5bdf6d70e0a9..aff5a1f93735 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h @@ -154,6 +154,8 @@ struct sd_ssr { unsigned int au; /* In sectors */ unsigned int erase_timeout; /* In milliseconds */ unsigned int erase_offset; /* In milliseconds */ + unsigned int speed_class; + unsigned int uhs_speed_grade; }; struct sd_switch_caps { From f8422649820ebaa4c0fdb1a36ed8f90b214a6b81 Mon Sep 17 00:00:00 2001 From: Shiyong Li Date: Tue, 2 May 2017 08:53:36 -0700 Subject: [PATCH 232/698] fs: support debug of eventpoll wakeup source While eventpoll waking up from suspend, just very vague information gets printed as below, which is not helpful to track wake up source: [ 292.536658,2] last active wakeup source: eventpoll Append process command name and PID to wake source name at registering to make the name more informative. With this change, log would be l(CR): [ 130.478865,2] last active wakeup source: eventpoll-healthd-905 Change-Id: I0b0d4bbb3396a11a533141e87f08f10454260411 Signed-off-by: Shiyong Li Reviewed-on: https://gerrit.mot.com/987224 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Igor Kovalenko Submit-Approved: Jira Key Signed-off-by: xuwt2 Reviewed-on: https://gerrit.mot.com/1533155 SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Jianqi Yang Submit-Approved: Jira Key Reviewed-on: https://gerrit.mot.com/1779323 Reviewed-by: Huosheng Liao --- fs/Kconfig | 7 +++++++ fs/eventpoll.c | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/fs/Kconfig b/fs/Kconfig index f9b97a8b4e80..f4638142e51b 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -15,6 +15,13 @@ config VALIDATE_FS_PARSER Enable this to perform validation of the parameter description for a filesystem when it is registered. +config FS_EPOLL_WAKEUP_DEBUG + bool "debug eventpoll wakeup source" + default n + help + This option enables printing thread ID and name of eventpoll wakeup source + while waking up system for debug purpose. Keep it off if not sure. + if BLOCK config FS_IOMAP diff --git a/fs/eventpoll.c b/fs/eventpoll.c index f2f92e3ec072..67e3e48919ad 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c @@ -1458,7 +1458,14 @@ static int ep_create_wakeup_source(struct epitem *epi) struct wakeup_source *ws; if (!epi->ep->ws) { +#ifdef CONFIG_FS_EPOLL_WAKEUP_DEBUG + char full_ep_name[64]; + snprintf(full_ep_name, 64, "eventpoll-%s-%d", + current->comm, current->pid); + epi->ep->ws = wakeup_source_register(NULL, full_ep_name); +#else epi->ep->ws = wakeup_source_register(NULL, "eventpoll"); +#endif if (!epi->ep->ws) return -ENOMEM; } From 45356fce973adeaace4c7af2596c115b3ce2b1a2 Mon Sep 17 00:00:00 2001 From: jixj Date: Tue, 20 Oct 2020 11:01:54 +0800 Subject: [PATCH 233/698] arm64/configs: Enable uart console config for factory image Add CONFIG_SERIAL_MSM_GENI_CONSOLE=y and we can use "fastboot oem config console true" to open uart log. Change-Id: I0aa1aa7d3610a9e0fdaa4e873ba9a7aeaa041cfa Reviewed-on: https://gerrit.mot.com/1779363 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/factory-holi.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/vendor/ext_config/factory-holi.config b/arch/arm64/configs/vendor/ext_config/factory-holi.config index 2f770fff3573..098ff7521c6d 100644 --- a/arch/arm64/configs/vendor/ext_config/factory-holi.config +++ b/arch/arm64/configs/vendor/ext_config/factory-holi.config @@ -14,3 +14,4 @@ # being set as expected. # CONFIG_CFI_PERMISSIVE=y +CONFIG_SERIAL_MSM_GENI_CONSOLE=y From 89731bcf705907623a64f44e5e44442691f703f5 Mon Sep 17 00:00:00 2001 From: jixj Date: Tue, 20 Oct 2020 11:02:53 +0800 Subject: [PATCH 234/698] arm64/configs: Enable uart console config for user sw Add CONFIG_SERIAL_MSM_GENI_CONSOLE=y and we can use "fastboot oem config console true" to open uart log. Change-Id: Iec772f26501293af548084bc5cf163321e4b2e92 Reviewed-on: https://gerrit.mot.com/1779364 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi.config b/arch/arm64/configs/vendor/ext_config/moto-holi.config index d2e826726306..40b42cbd808e 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi.config @@ -19,3 +19,4 @@ CONFIG_PSTORE=y CONFIG_PSTORE_CONSOLE=y CONFIG_PSTORE_RAM=y CONFIG_PSTORE_PMSG=y +CONFIG_SERIAL_MSM_GENI_CONSOLE=y From 12f62eb21d32871a065c76679c26aa1ce341d5b3 Mon Sep 17 00:00:00 2001 From: jixj Date: Tue, 20 Oct 2020 14:49:44 +0800 Subject: [PATCH 235/698] power/reset: Fix GKI build error When build GKI, this driver will be built as module but "__setup" is unavailable for module, so remove it on GKI Change-Id: Ia49f07220c2515e19bd04f78bd7ffaf4bd316d20 Reviewed-on: https://gerrit.mot.com/1779563 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- drivers/power/reset/msm-poweroff.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/power/reset/msm-poweroff.c b/drivers/power/reset/msm-poweroff.c index 5ce3ba641c32..f61b1a219bd7 100644 --- a/drivers/power/reset/msm-poweroff.c +++ b/drivers/power/reset/msm-poweroff.c @@ -398,6 +398,8 @@ EXPORT_SYMBOL(msm_set_restart_mode); #define DEBUG_SYS_RESETART_WARM 1 #define DEBUG_SYS_RESETART_PANIC 2 static int debug_sys_restart_mode; + +#ifdef CONFIG_QGKI static int __init set_sys_restart_mode(char *str) { if (!strcmp(str, "warm")) @@ -409,6 +411,7 @@ static int __init set_sys_restart_mode(char *str) } __setup("sys_restart_mode=", set_sys_restart_mode); +#endif static void msm_restart_prepare(const char *cmd) { From a51614615c71678d04af513e5e60e9a2721f8ec4 Mon Sep 17 00:00:00 2001 From: houdz1 Date: Mon, 19 Oct 2020 14:35:35 +0800 Subject: [PATCH 236/698] wled: suppor for setting brightness step by step WLED_SINK work at different mode with the different brightness. When swithing between these modes, that will cuase ovp and ocp issue. This is hardware issue from qcom.Qcom can not fix it with hardware solution,So add brightness step control workaround for pfm issue. We define the step with "qcom,wled-bl-step-sequence" Port of: 6fa66a51e95748f92919ad7e647e13b162dbc2c4 Change-Id: Ib252f2b47819b3e358c5f995d577a5e0085c3f8f Reviewed-on: https://gerrit.mot.com/1778397 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- drivers/video/backlight/qcom-spmi-wled.c | 172 +++++++++++++++++++++++ 1 file changed, 172 insertions(+) diff --git a/drivers/video/backlight/qcom-spmi-wled.c b/drivers/video/backlight/qcom-spmi-wled.c index 3ac367e1ec32..2fc09ff0340c 100644 --- a/drivers/video/backlight/qcom-spmi-wled.c +++ b/drivers/video/backlight/qcom-spmi-wled.c @@ -243,6 +243,16 @@ struct wled_flash_config { int safety_timer; }; +struct bl_step_seq { + u32 level; + u32 sleep_ms; +}; + +struct bl_step_config { + struct bl_step_seq *sequence; + u32 count; +}; + struct wled { const char *name; struct platform_device *pdev; @@ -283,6 +293,8 @@ struct wled { u8 num_strings; u32 leds_per_string; u32 exp_map[EXP_DIMMING_TABLE_SIZE]; + bool bl_step_up_enable; + struct bl_step_config bl_step_cfg; }; enum wled5_mod_sel { @@ -320,6 +332,8 @@ static const char *const wled_iio_prop_names[] = { static int wled_flash_setup(struct wled *wled); +static int wled_set_brightness_step(struct wled *wled, u16 brightness); + static inline bool is_wled4(struct wled *wled) { if (*wled->version == WLED_PMI8998 || *wled->version == WLED_PM660L) @@ -545,6 +559,13 @@ static int wled_update_status(struct backlight_device *bl) mutex_lock(&wled->lock); if (brightness) { + if (wled->bl_step_up_enable) { + rc = wled_set_brightness_step(wled, brightness); + if (rc < 0) { + pr_err("wled failed to set brightness step rc:%d\n", rc); + goto unlock_mutex; + } + } rc = wled_set_brightness(wled, brightness); if (rc < 0) { pr_err("wled failed to set brightness rc:%d\n", rc); @@ -2541,6 +2562,152 @@ static int wled_configure(struct wled *wled, struct device *dev) return 0; } +static int wled_parse_bl_step_sequence(struct wled *wled) +{ + int rc = 0; + int i; + u32 length = 0; + u32 count = 0; + u32 size = 0; + u32 *arr_32 = NULL; + const u32 *arr; + struct bl_step_seq *seq; + struct device *dev = &wled->pdev->dev; + + wled->bl_step_up_enable = false; + wled->bl_step_up_enable = of_property_read_bool(dev->of_node, + "qcom,wled-bl-step-up"); + + if (!wled->bl_step_up_enable) goto error; + + arr = of_get_property(dev->of_node, + "qcom,wled-bl-step-sequence", &length); + + if (!arr) { + pr_err(" wled-bl-step-sequence not found\n"); + rc = -EINVAL; + goto error; + } + if (length & 0x1) { + pr_err("syntax error for wled-bl-step-sequence\n"); + rc = -EINVAL; + goto error; + } + + pr_debug("BL STEP SEQ LENGTH = %d\n", length); + length = length / sizeof(u32); + + size = length * sizeof(u32); + + arr_32 = kzalloc(size, GFP_KERNEL); + if (!arr_32) { + rc = -ENOMEM; + goto error; + } + + rc = of_property_read_u32_array(dev->of_node, "qcom,wled-bl-step-sequence", + arr_32, length); + if (rc) { + pr_err("cannot read wled-bl-step-sequence\n"); + goto error_free_arr_32; + } + + count = length / 2; + size = count * sizeof(*seq); + seq = kzalloc(size, GFP_KERNEL); + if (!seq) { + rc = -ENOMEM; + goto error_free_arr_32; + } + + wled->bl_step_cfg.sequence = seq; + wled->bl_step_cfg.count = count; + + for (i = 0; i < length; i += 2) { + seq->level = arr_32[i]; + seq->sleep_ms = arr_32[i + 1]; + pr_debug(" %d: level %d sleep_ms %d\n", i, seq->level, seq->sleep_ms); + seq++; + } + + +error_free_arr_32: + kfree(arr_32); + +error: + return rc; +} + + +/* +* This is workaround for pmic 6150/7150 wled boost current issue, QC HW team confirm that +* PMIC WLED low brightness(<255) is pfm mode, high brightness(>255) is pwm mode, when +* brightness from pfm mode to pwm mode transfer fastly, this mode switch will caused +* a higher boost current, in Liberty, it may reach 1.7A, this is a risk for hardware, +* even pmic damage +*/ + +static int wled_set_brightness_step(struct wled *wled, u16 brightness) +{ + int rc = 0; + int i, start_index, end_index; + struct bl_step_seq *seq = wled->bl_step_cfg.sequence; + u32 count = wled->bl_step_cfg.count; + + if (!seq || !count) { + rc = -EINVAL; + goto exit; + } + + if ((wled->brightness >= seq[count-1].level) || + (brightness <= seq[0].level) || (wled->brightness >= brightness)) + goto exit; + + start_index = 0; + end_index = 0; + for (i = 0; i < count; i++) { + if ( wled->brightness < seq[i].level) { + start_index = i; + break; + } + } + + for (i = count-1; i >= 0; i--) { + if ( brightness > seq[i].level) { + end_index = i; + break; + } + } + + if ( end_index < start_index) goto exit; + + pr_info(" set_brightness_step : %d -> [%d, %d]-> %d\n", + wled->brightness, seq[start_index].level, seq[end_index].level, brightness); + + for (i = start_index; i <= end_index; i++) + { + rc = wled_set_brightness(wled, seq[i].level); + if (rc < 0) { + pr_err("wled failed to set brightness high_threshold:%d\n", rc); + goto exit; + } + mdelay(seq[i].sleep_ms); + + pr_debug("set brightness %d, sleep %d ms\n", seq[i].level, seq[i].sleep_ms); + + if (!!brightness != wled->prev_state) { + rc = wled_module_enable(wled, !!brightness); + if (rc < 0) { + pr_err("wled enable failed rc:%d\n", rc); + goto exit; + } + wled->prev_state = !!brightness; + } + } +exit: + return rc; +} + static const struct backlight_ops wled_ops = { .update_status = wled_update_status, .get_brightness = wled_get_brightness, @@ -2594,6 +2761,11 @@ static int wled_probe(struct platform_device *pdev) return rc; } + rc = wled_parse_bl_step_sequence(wled); + if (rc < 0) { + dev_err(&pdev->dev, "wled parse bl_step_sequence rc:%d\n", rc); + } + mutex_init(&wled->lock); val = WLED_DEFAULT_BRIGHTNESS; From 54189125c5e9146f4f412b383069ad30e15e1fab Mon Sep 17 00:00:00 2001 From: wangyq13 Date: Mon, 19 Oct 2020 14:59:02 +0800 Subject: [PATCH 237/698] Backlight/wled: disable wled CABC under low brightness For Pmi7150, when cabc enabled , there is backlight flicker, under the low brightness ,the issue is caused by the accuracy of wled accumulation. Qcom do not recommend use cabc under the low brightness. (CR) wled: disable cabc when bl off or bl lower than threshold Disable cabc when bl off or bl value lower than threshold Enable wled when bl value bigger than threshold Port of : 9738ea6226f244dc7b97ac90226707c2c5e249cb ce90bd688748bf7aa9e84b1e40e883456a1a2378 Change-Id: Ia8a2e1c954482f633d308a3c1f730bee15d3f0b8 Reviewed-on: https://gerrit.mot.com/1778412 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- drivers/video/backlight/qcom-spmi-wled.c | 55 ++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/drivers/video/backlight/qcom-spmi-wled.c b/drivers/video/backlight/qcom-spmi-wled.c index 2fc09ff0340c..b857f4744e7d 100644 --- a/drivers/video/backlight/qcom-spmi-wled.c +++ b/drivers/video/backlight/qcom-spmi-wled.c @@ -253,6 +253,12 @@ struct bl_step_config { u32 count; }; +struct low_bl_config { + int low_bl_threshold; + int low_bl_remap_percent; + int low_bl_delay_ms; +}; + struct wled { const char *name; struct platform_device *pdev; @@ -293,6 +299,8 @@ struct wled { u8 num_strings; u32 leds_per_string; u32 exp_map[EXP_DIMMING_TABLE_SIZE]; + bool low_bl_force_cabc_disable; + struct low_bl_config low_bl_cfg; bool bl_step_up_enable; struct bl_step_config bl_step_cfg; }; @@ -558,6 +566,16 @@ static int wled_update_status(struct backlight_device *bl) brightness = 0; mutex_lock(&wled->lock); + + if (wled->low_bl_force_cabc_disable && brightness <= wled->low_bl_cfg.low_bl_threshold) { + brightness = brightness * wled->low_bl_cfg.low_bl_remap_percent/100; + if (!wled->cabc_disabled) { + wled->cabc_config(wled, false); + wled->cabc_disabled = true; + pr_info("low brightness(%d), disable cabc\n", brightness); + } + } + if (brightness) { if (wled->bl_step_up_enable) { rc = wled_set_brightness_step(wled, brightness); @@ -572,6 +590,14 @@ static int wled_update_status(struct backlight_device *bl) goto unlock_mutex; } + if (wled->low_bl_force_cabc_disable && brightness > wled->low_bl_cfg.low_bl_threshold + && wled->brightness <= wled->low_bl_cfg.low_bl_threshold && wled->cabc_disabled) { + msleep(wled->low_bl_cfg.low_bl_delay_ms); + wled->cabc_disabled = false; + wled->cabc_config(wled, true); + pr_info("enable wled cabc\n"); + } + if (is_wled5(wled)) { rc = wled5_sample_hold_control(wled, brightness, false); if (rc < 0) { @@ -1269,6 +1295,32 @@ exp_dimm_fail: return rc; } +static int parse_low_bl_config(struct wled *wled) +{ + struct device *dev = &wled->pdev->dev; + u32 val = 0; + + if (of_property_read_bool(dev->of_node, "mmi,low-bl-force-cabc-disable")) + wled->low_bl_force_cabc_disable = true; + + if (wled->low_bl_force_cabc_disable) { + of_property_read_u32(dev->of_node, "mmi,low-bl-threshold", &val); + wled->low_bl_cfg.low_bl_threshold = val; + + of_property_read_u32(dev->of_node, "mmi,low-bl-remap-percent", &val); + wled->low_bl_cfg.low_bl_remap_percent = val; + + of_property_read_u32(dev->of_node, "mmi,low-bl-delay-ms", &val); + wled->low_bl_cfg.low_bl_delay_ms = val; + + pr_info(" low-bl-force-cabc-disbale enabled, low-bl-threshold %d low-bl-remap_percent %d low_bl_delay_ms %d\n", + wled->low_bl_cfg.low_bl_threshold, wled->low_bl_cfg.low_bl_remap_percent, wled->low_bl_cfg.low_bl_delay_ms); + + wled->cabc_disabled = false; + } + return 0; +} + static int wled5_setup(struct wled *wled) { int rc, temp, i; @@ -1331,6 +1383,9 @@ static int wled5_setup(struct wled *wled) if (rc < 0) return rc; + wled->low_bl_force_cabc_disable = false; + if (wled->cfg.cabc_sel) parse_low_bl_config(wled); + /* Enable one of the modulators A or B based on mod_sel */ addr = wled->sink_addr + WLED5_SINK_MOD_A_EN_REG; val = (wled->cfg.mod_sel == MOD_A) ? WLED5_SINK_MOD_EN : 0; From 8da2da76a2ee1f75c199e7039dfb32ca921b6104 Mon Sep 17 00:00:00 2001 From: wengjun1 Date: Wed, 21 Oct 2020 10:57:56 +0800 Subject: [PATCH 238/698] Update qcom whitelist for touchscreen The "kobject_get_path" functions can be found in the latest google whitelist, so update the qcom whitelist for touchscreen. Change-Id: Iddf594aa3376c3473398127439de8c42026d48cc Signed-off-by: wengjun1 Reviewed-on: https://gerrit.mot.com/1780553 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Xiaojun Ji Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- android/abi_gki_aarch64_qcom | 1 + 1 file changed, 1 insertion(+) diff --git a/android/abi_gki_aarch64_qcom b/android/abi_gki_aarch64_qcom index ac6f0fc833ee..9116d2a7f09a 100644 --- a/android/abi_gki_aarch64_qcom +++ b/android/abi_gki_aarch64_qcom @@ -1328,6 +1328,7 @@ kmemdup_nul kobject_create_and_add kobject_del + kobject_get_path kobject_init_and_add kobject_put kobject_uevent From 2e150ee1d0da37e0292093264bbc0a8069421adf Mon Sep 17 00:00:00 2001 From: liaohj Date: Wed, 21 Oct 2020 14:10:28 +0800 Subject: [PATCH 239/698] soc: qcom: service-locator: enlarge timeout value pick from (CR) Some dogfood users reported call has no sound problem, it happens on the first bootup after BOTA upgrading, if reboot again, everything will be okay. According to kernel log, filesystem mount timed out, causes locator service timed out. [libfs_mgr]Retrying mount (source=/dev/block/bootdevice/by-name/ userdata,target=/data,type=f2fs)=-1(11): Try again servloc : init_service_locator: init_service_locator:wait for locator service timed out After discussing with Qcom, they suggest to enlarge this timeout value. Change-Id: I73386e97fca953775f88e6f673c9bab6b9aabd06 Signed-off-by: liaohj Reviewed-on: https://gerrit.mot.com/1780699 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Wanlong Zhou Reviewed-by: Yuesheng Huang Submit-Approved: Jira Key --- drivers/soc/qcom/service-locator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/qcom/service-locator.c b/drivers/soc/qcom/service-locator.c index 7f336477b24f..197e07fe90d3 100644 --- a/drivers/soc/qcom/service-locator.c +++ b/drivers/soc/qcom/service-locator.c @@ -25,7 +25,7 @@ #define QMI_SERVREG_LOC_SERVER_INITIAL_TIMEOUT 2000 #define QMI_SERVREG_LOC_SERVER_TIMEOUT 2000 #define INITIAL_TIMEOUT 100000 -#define LOCATOR_SERVICE_TIMEOUT 300000 +#define LOCATOR_SERVICE_TIMEOUT 900000 #define LOCATOR_NOT_PRESENT 0 #define LOCATOR_PRESENT 1 From 9fac50a85867206bf0dc7a84ce940a8dcb81ff3d Mon Sep 17 00:00:00 2001 From: liaohj Date: Wed, 21 Oct 2020 14:21:16 +0800 Subject: [PATCH 240/698] usb audio: Let the usb sound card index from 1 Prop from (CR) If we have usb digital headphone pulled in during bootup. It will occupy index 0. primary sound card can only use index 1. But in our most audio code, We assume the primary sound card is 0. This will cause no sound issue when we use primary sound card to playback and record. Change-Id: If6635c4b7adef0925af8145d4b728f3cc481b9ad Signed-off-by: liaohj Reviewed-on: https://gerrit.mot.com/1780715 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Yuesheng Huang Submit-Approved: Jira Key --- include/sound/initval.h | 1 + sound/usb/card.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/include/sound/initval.h b/include/sound/initval.h index 3ddae2b4177e..46c35c069d56 100644 --- a/include/sound/initval.h +++ b/include/sound/initval.h @@ -22,6 +22,7 @@ #define SNDRV_DEFAULT_PTR1 SNDRV_DEFAULT_STR1 #define SNDRV_DEFAULT_IDX { [0 ... (SNDRV_CARDS-1)] = -1 } +#define SNDRV_DEFAULT_IDX_N { 1, [1 ... (SNDRV_CARDS-1)] = -1 } #define SNDRV_DEFAULT_STR { [0 ... (SNDRV_CARDS-1)] = NULL } #define SNDRV_DEFAULT_ENABLE { 1, [1 ... (SNDRV_CARDS-1)] = 0 } #define SNDRV_DEFAULT_ENABLE_PNP { [0 ... (SNDRV_CARDS-1)] = 1 } diff --git a/sound/usb/card.c b/sound/usb/card.c index e5a2fee4f38f..684dae3a28a4 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -62,7 +62,7 @@ MODULE_LICENSE("GPL"); MODULE_SUPPORTED_DEVICE("{{Generic,USB Audio}}"); -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ +static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX_N; /* Index 0-MAX */ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;/* Enable this card */ /* Vendor/product IDs for this card */ From 418d89456b535faaf9a9cec75132df2f1a62d54c Mon Sep 17 00:00:00 2001 From: Dmitry Ornatsky Date: Mon, 21 Dec 2015 12:54:28 -0600 Subject: [PATCH 241/698] pinctrl: pinctrl-msm: do not dump unallocated GPIOs Do not dump GPIOS that are not allocated by HLOS. This is a temporary change to avoid TZ exceptions. origin CR:(CR) Change-Id: I7b231457d186cbdc0a900b153bc8b09e9ccffddd Signed-off-by: Dmitry Ornatsky Reviewed-on: http://gerrit.mot.com/808904 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Igor Kovalenko Submit-Approved: Jira Key Reviewed-on: https://gerrit.mot.com/1230533 SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiaopeng Li Reviewed-by: Konstantin Makariev Submit-Approved: Jira Key Reviewed-on: https://gerrit.mot.com/1400180 Reviewed-on: https://gerrit.mot.com/1436604 Reviewed-on: https://gerrit.mot.com/1509717 Reviewed-by: Wang Wang Reviewed-on: https://gerrit.mot.com/1780444 Reviewed-by: Huosheng Liao --- drivers/pinctrl/qcom/pinctrl-msm.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c index 707183744178..3408d57bcfb0 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm.c +++ b/drivers/pinctrl/qcom/pinctrl-msm.c @@ -594,6 +594,11 @@ static void msm_gpio_dbg_show_one(struct seq_file *s, if (!gpiochip_line_is_valid(chip, offset)) return; + if (!gpiochip_is_requested(chip, offset)) { + seq_printf(s, " gpio%d: is not allocated in gpiolib\n", offset); + return; + } + g = &pctrl->soc->groups[offset]; ctl_reg = msm_readl_ctl(pctrl, g); io_reg = msm_readl_io(pctrl, g); From e5431690a3fd1d91d075a1548ac1f3f1dd880c5c Mon Sep 17 00:00:00 2001 From: weiweij Date: Tue, 10 Mar 2020 15:45:26 +0800 Subject: [PATCH 242/698] driver/tlmm: add gpiochip base value checking origin CR: (CR) For nomal gpiochip add logic, gpiochip base value will be down from 1278. And as a result, tlmm gpiochip base value may be a random value next to 1278. If we want to use tlmm gpio as its real number( for example, number 21 for gpio21), tlmm gpiochip base must be 0. So we add this logic to check if its base value need to be defined by dts configuration. Change-Id: Ic4ccdf9791673ce81ea49a8653449adabe0b0a4f Signed-off-by: weiweij Reviewed-on: https://gerrit.mot.com/1509841 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key Reviewed-on: https://gerrit.mot.com/1780451 --- drivers/pinctrl/qcom/pinctrl-msm.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c index 3408d57bcfb0..de43c64c1dab 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm.c +++ b/drivers/pinctrl/qcom/pinctrl-msm.c @@ -1329,6 +1329,11 @@ static int msm_gpio_init(struct msm_pinctrl *pctrl) chip = &pctrl->chip; chip->base = -1; + if (!of_property_read_u32(pctrl->dev->of_node, "qcom,base-value", &ret)) { + chip->base = ret; + dev_info(pctrl->dev, "set base value as %d\n", chip->base); + } + chip->ngpio = ngpio; chip->label = dev_name(pctrl->dev); chip->parent = pctrl->dev; From dfb79dcfd49a10beb9a5004957715fb517023bd9 Mon Sep 17 00:00:00 2001 From: Konstantin Makariev Date: Fri, 8 Jun 2018 16:43:22 -0500 Subject: [PATCH 243/698] printk: increase log buffer size to 2k Kernel command line print statement is truncated, need increase the buffer size. Change-Id: I0e353563a138e85de2fb84ca89074e564337967a Signed-off-by: Konstantin Makariev Reviewed-on: https://gerrit.mot.com/1780859 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- kernel/printk/printk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index d3bd137fa747..a495c45ee649 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -451,7 +451,7 @@ static u32 clear_idx; #else #define PREFIX_MAX 32 #endif -#define LOG_LINE_MAX (1024 - PREFIX_MAX) +#define LOG_LINE_MAX (3072 - PREFIX_MAX) #define LOG_LEVEL(v) ((v) & 0x07) #define LOG_FACILITY(v) ((v) >> 3 & 0xff) From 6f1c92bafb356bdfc7e1f1eaf7090506b67ae0f2 Mon Sep 17 00:00:00 2001 From: mahj8 Date: Fri, 23 Oct 2020 15:09:50 +0800 Subject: [PATCH 244/698] arm/config: disable smb1398 and smb1355 our project don't use parallel charging so disable smb1398 and smb1355 driver Change-Id: I0cd618770ef56af0b59b9a51c5177a0a432d8410 Signed-off-by: mahj8 Reviewed-on: https://gerrit.mot.com/1783169 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi.config | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi.config b/arch/arm64/configs/vendor/ext_config/moto-holi.config index 40b42cbd808e..bed080a111f2 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi.config @@ -20,3 +20,5 @@ CONFIG_PSTORE_CONSOLE=y CONFIG_PSTORE_RAM=y CONFIG_PSTORE_PMSG=y CONFIG_SERIAL_MSM_GENI_CONSOLE=y +# CONFIG_SMB1398_CHARGER is not set +# CONFIG_SMB1355_SLAVE_CHARGER is not set From d35f57212972dd222239e42eed86c4e2d4acfdb5 Mon Sep 17 00:00:00 2001 From: zhucc2 Date: Fri, 23 Oct 2020 15:54:20 +0800 Subject: [PATCH 245/698] qcom: whitelist: Add necessary api for Exfat dlkm. The new added api is necessary for building Exfat DLKM. All of them could be found in the latest abi_gki_aarch64*.xml file. Change-Id: I53a02ecd583a83b6d44b37e869f8d33784094e00 Reviewed-on: https://gerrit.mot.com/1783216 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Xiaojun Ji Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- android/abi_gki_aarch64_qcom | 53 ++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/android/abi_gki_aarch64_qcom b/android/abi_gki_aarch64_qcom index 9116d2a7f09a..971dc5eec139 100644 --- a/android/abi_gki_aarch64_qcom +++ b/android/abi_gki_aarch64_qcom @@ -103,9 +103,11 @@ blk_status_to_errno blk_update_request blk_verify_command + __blockdev_direct_IO blocking_notifier_call_chain blocking_notifier_chain_register blocking_notifier_chain_unregister + block_write_full_page bpf_prog_add bpf_prog_put bpf_prog_sub @@ -124,6 +126,8 @@ bpf_warn_invalid_xdp_action bprm_change_interp __break_lease + __bread_gfp + __brelse build_skb bus_find_device bus_for_each_dev @@ -252,6 +256,7 @@ __const_udelay consume_skb contig_page_data + cont_write_begin _copy_from_iter_full copy_page copy_strings_kernel @@ -514,6 +519,7 @@ dev_uc_sync_multiple dev_uc_unsync _dev_warn + d_find_alias dget_parent d_instantiate disable_irq @@ -594,6 +600,7 @@ dma_resv_wait_timeout_rcu dma_set_coherent_mask dma_set_mask + d_move do_exit do_wait_intr down @@ -891,6 +898,7 @@ dump_stack enable_irq enable_percpu_irq + end_buffer_write_sync eth_commit_mac_addr_change ether_setup eth_mac_addr @@ -916,6 +924,8 @@ fasync_helper fd_install fget + filemap_fdatawait_range + filemap_fdatawrite_range file_path find_last_bit find_next_bit @@ -961,17 +971,25 @@ fwnode_property_read_u32_array fwnode_usb_role_switch_get gcd + generic_block_bmap + generic_cont_expand_simple generic_delete_inode generic_device_group + generic_fh_to_dentry + generic_fh_to_parent generic_file_llseek generic_file_mmap generic_file_read_iter generic_file_splice_read + generic_fillattr generic_handle_irq generic_mii_ioctl generic_permission generic_read_dir generic_shutdown_super + generic_write_end + generic_file_fsync + generic_file_write_iter genlmsg_put genl_register_family genl_unregister_family @@ -1010,6 +1028,7 @@ get_random_u32 __get_task_comm get_task_pid + __getblk_gfp get_tree_single get_unmapped_area get_unused_fd_flags @@ -1149,10 +1168,13 @@ iio_channel_release iio_read_channel_processed iio_write_channel_raw + ilookup import_iovec in_egroup_p + inc_nlink init_dummy_netdev init_net + in_group_p __init_rwsem init_srcu_struct init_timer_key @@ -1180,12 +1202,15 @@ input_unregister_device input_unregister_handle input_unregister_handler + __insert_inode_hash interval_tree_insert interval_tree_iter_first interval_tree_iter_next interval_tree_remove int_to_scsilun invalidate_mapping_pages + invalidate_bdev + invalidate_inode_buffers iomem_resource iommu_alloc_resv_region iommu_attach_device @@ -1282,6 +1307,7 @@ irq_work_queue iterate_dir iterate_fd + iunique jiffies jiffies_to_msecs jiffies_to_usecs @@ -1312,6 +1338,7 @@ kfree_skb kfree_skb_list kill_anon_super + kill_block_super kill_fasync kill_litter_super kimage_vaddr @@ -1400,16 +1427,22 @@ list_sort llist_add_batch llist_reverse_order + load_nls __local_bh_enable_ip lockref_get + __lock_buffer lock_rename lock_sock_nested lookup_one_len LZ4_decompress_safe mac_pton + mark_buffer_dirty + __mark_inode_dirty mark_page_accessed match_int + match_octal match_string + match_strdup match_token mbox_chan_received_data mbox_chan_txdone @@ -1479,6 +1512,10 @@ __module_get module_layout module_put + mount_bdev + mpage_readpage + mpage_readpages + mpage_writepages __msecs_to_jiffies msleep msleep_interruptible @@ -2020,6 +2057,7 @@ remap_pfn_range remap_vmalloc_range remove_arg_zero + __remove_inode_hash remove_proc_entry remove_wait_queue report_iommu_fault @@ -2087,6 +2125,8 @@ rtnl_unregister_all save_stack_trace save_stack_trace_tsk + sb_min_blocksize + sb_set_blocksize sched_clock sched_setattr sched_setscheduler @@ -2167,6 +2207,7 @@ serial8250_suspend_port serial8250_unregister_port set_anon_super + setattr_copy set_cpus_allowed_ptr set_disk_ro set_freezable @@ -2426,13 +2467,17 @@ strscpy_pad strsep strstr + submit_bh __sw_hweight32 __sw_hweight64 __sw_hweight8 swiotlb_max_segment + sync_blockdev + sync_dirty_buffer sync_file_create sync_file_get_fence sync_filesystem + sync_mapping_buffers synchronize_hardirq synchronize_irq synchronize_net @@ -2483,6 +2528,7 @@ timer_unstable_counter_workaround timespec64_to_jiffies _totalram_pages + touch_buffer trace_array_create trace_array_destroy __trace_bprintk @@ -2504,6 +2550,7 @@ trace_seq_printf tracing_off truncate_inode_pages + truncate_pagecache try_module_get try_wait_for_completion tty_flip_buffer_push @@ -2569,6 +2616,8 @@ __uio_register_device uhid_hid_driver uio_unregister_device + unload_nls + unlock_buffer unlock_new_inode unlock_page unlock_rename @@ -2753,6 +2802,8 @@ __usecs_to_jiffies user_path_at_empty usleep_range + utf16s_to_utf8s + utf8s_to_utf16s v4l2_ctrl_find v4l2_ctrl_g_ctrl v4l2_ctrl_get_name @@ -2905,6 +2956,7 @@ wait_for_completion_killable wait_for_completion_timeout wait_woken + __wait_on_buffer __wake_up __wake_up_locked wake_up_process @@ -2919,6 +2971,7 @@ woken_wake_function work_busy would_dump + write_inode_now ww_mutex_lock ww_mutex_lock_interruptible ww_mutex_unlock From 3f8f755df5d95bdafaebd72182e8dcf1fcc0a6f6 Mon Sep 17 00:00:00 2001 From: zhucc2 Date: Fri, 23 Oct 2020 16:13:40 +0800 Subject: [PATCH 246/698] qcom: whitelist: Add necessary api for aw882xx_k419 dlkm The new added api is necessary for building Exfat DLKM. All of them could be found in the latest abi_gki_aarch64*.xml file. Change-Id: I81e08474e7a4196967a557cdd36fc0cad3b5da36 Reviewed-on: https://gerrit.mot.com/1783232 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Xiaojun Ji Reviewed-by: Hujun Liao Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- android/abi_gki_aarch64_qcom | 1 + 1 file changed, 1 insertion(+) diff --git a/android/abi_gki_aarch64_qcom b/android/abi_gki_aarch64_qcom index 971dc5eec139..bb92e5fe4960 100644 --- a/android/abi_gki_aarch64_qcom +++ b/android/abi_gki_aarch64_qcom @@ -423,6 +423,7 @@ devm_gpio_request_one devm_iio_channel_get devm_iio_device_alloc + devm_gpio_free __devm_iio_device_register devm_input_allocate_device devm_ioremap From 8f4ce5da847cd090e4eecb27231e14894c478088 Mon Sep 17 00:00:00 2001 From: chenyb1 Date: Tue, 20 Oct 2020 10:36:02 +0800 Subject: [PATCH 247/698] kernel/config enable fs eventpoll debug Print thread ID and name of eventpoll wake up source for debug purpose. Change-Id: I4d97e74a3ba61bc33600f4c3a3c557ee4d1d0b87 Reviewed-on: https://gerrit.mot.com/1779375 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Hongshu Lou Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi-denver.config | 1 + arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-denver.config b/arch/arm64/configs/vendor/ext_config/moto-holi-denver.config index b265d209827c..4fa2599b9d6b 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-denver.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-denver.config @@ -14,3 +14,4 @@ # being set as expected. # CONFIG_DENVER_DTB=y +CONFIG_FS_EPOLL_WAKEUP_DEBUG=y diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config b/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config index 637e43692c6b..bd3fb5625009 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config @@ -15,3 +15,4 @@ # CONFIG_IBIZA_DTB=y CONFIG_NFC_QTI_I2C=y +CONFIG_FS_EPOLL_WAKEUP_DEBUG=y \ No newline at end of file From 315a01917e7548bf592e3f2afb06b5399bb61c28 Mon Sep 17 00:00:00 2001 From: huangzq2 Date: Wed, 8 Jul 2020 13:29:04 +0800 Subject: [PATCH 248/698] disable SPLIT_RSS_COUNTING to fix zero RSS issue rss in statm sometimes is zero value which will affect lmk kill as it depends on the rss size of each process in lmkd. Change-Id: Iee0bdf2534fee660e64d8e8221c4dc571e13921e Signed-off-by: huangzq2 Reviewed-on: https://gerrit.mot.com/1668699 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key Reviewed-by: Bingqian Yang (cherry picked from commit 09b4d0ed5f4710c7ee6f263a2faca67846565256) Reviewed-on: https://gerrit.mot.com/1673149 Reviewed-by: Zhenxin Xi Reviewed-on: https://gerrit.mot.com/1783212 Reviewed-by: Yonghui Jia Reviewed-by: Huosheng Liao --- mm/Kconfig | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/mm/Kconfig b/mm/Kconfig index b1dc1e321d49..fe6c22bc562c 100644 --- a/mm/Kconfig +++ b/mm/Kconfig @@ -208,11 +208,17 @@ config MEMORY_HOTREMOVE # PA-RISC 7xxx's spinlock_t would enlarge struct page from 32 to 44 bytes. # DEBUG_SPINLOCK and DEBUG_LOCK_ALLOC spinlock_t also enlarge struct page. # +# Moto huangzq2: disable SPLIT_RSS_COUNTING if we have ulmk. +# ulmk fully relies on rss in proc/pid/statm, but rss in statm sometimes +# is zero if we enabled SPLIT_RSS_COUNTING, checked with Google, +# they agree to disalbe this. Also, our performance test didn't show any +# performance downgrade. config SPLIT_PTLOCK_CPUS int default "999999" if !MMU default "999999" if ARM && !CPU_CACHE_VIPT default "999999" if PARISC && !PA20 + default "999999" if HAVE_USERSPACE_LOW_MEMORY_KILLER default "4" config ARCH_ENABLE_SPLIT_PMD_PTLOCK From 670e79efe6c787f363160e9bd8f0a145b216d701 Mon Sep 17 00:00:00 2001 From: jixj Date: Fri, 22 Feb 2019 15:54:44 +0800 Subject: [PATCH 249/698] usb/gadget/f_fs: fix invalid ffs to cause ramdump QC patch("usb: gadget: f_fs: Fix NULL pointer issues in ffs driver") fix multiple mounted issue, it will return "ERR_PTR(-EBUSY)" in ffs_data_new(), but ffs driver only check ffs if is a NULL point, the next code using ffs still cause ramdump. origin-CR: (CR) Change-Id: Ib2d21b2854163883f07475ef97e1e09a1742c617 Reviewed-on: https://gerrit.mot.com/1313122 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Huosheng Liao Reviewed-by: Yuecai Liu Submit-Approved: Jira Key Reviewed-on: https://gerrit.mot.com/1338906 Reviewed-on: https://gerrit.mot.com/1449057 Reviewed-on: https://gerrit.mot.com/1751135 Reviewed-by: Xiaojun Ji Reviewed-on: https://gerrit.mot.com/1785338 --- drivers/usb/gadget/function/f_fs.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index 55b94532c43a..b399dacbd839 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c @@ -1768,6 +1768,7 @@ static int ffs_fs_get_tree(struct fs_context *fc) return invalf(fc, "No source specified"); ffs = ffs_data_new(fc->source); + if (IS_ERR_OR_NULL(ffs)) { if (!ffs) return -ENOMEM; @@ -1775,6 +1776,9 @@ static int ffs_fs_get_tree(struct fs_context *fc) return PTR_ERR(ffs); } + if (IS_ERR(ffs)) + return PTR_ERR(ffs); + ffs->file_perms = ctx->perms; ffs->no_disconnect = ctx->no_disconnect; From 8b3d7897c21f00bb37f8a6ff6f36cd379f235c1b Mon Sep 17 00:00:00 2001 From: Ravi Vembu Date: Tue, 7 Jun 2016 11:58:44 -0500 Subject: [PATCH 250/698] usb: gadget: storage: Support READ_TOC for MacOS Modify READ_TOC handling to add support for both Windows and MacOS host environments. Change-Id: I4bf3c6a8fbec95387608869efbacb6f0537c7bbf Signed-off-by: Ravi Vembu Moto-CRs-fixed: (CR) Reviewed-on: http://gerrit.mot.com/864910 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Submit-Approved: Jira Key Signed-off-by: Rav(CR) Vembu Reviewed-on: https://gerrit.mot.com/944111 Reviewed-on: https://gerrit.mot.com/1167320 SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Lu Chai Reviewed-by: Jianqi Yang Submit-Approved: Jira Key Reviewed-on: https://gerrit.mot.com/1262841 Reviewed-by: Huosheng Liao Reviewed-on: https://gerrit.mot.com/1338861 Reviewed-on: https://gerrit.mot.com/1449077 Reviewed-on: https://gerrit.mot.com/1751139 Reviewed-by: Zonghua Liu Reviewed-on: https://gerrit.mot.com/1785339 --- drivers/usb/gadget/function/f_mass_storage.c | 115 ++++++++++++++++--- 1 file changed, 101 insertions(+), 14 deletions(-) diff --git a/drivers/usb/gadget/function/f_mass_storage.c b/drivers/usb/gadget/function/f_mass_storage.c index 40730a7dbb9d..9ad998e9db33 100644 --- a/drivers/usb/gadget/function/f_mass_storage.c +++ b/drivers/usb/gadget/function/f_mass_storage.c @@ -1181,12 +1181,105 @@ static int do_read_header(struct fsg_common *common, struct fsg_buffhd *bh) return 8; } +struct toc_header { + u8 data_len_msb; + u8 data_len_lsb; + u8 first_track_number; + u8 last_track_number; +}; + +struct toc_descriptor { + u8 ctrl; + u8 adr; + u8 tno; + u8 point; + u8 min; + u8 sec; + u8 frame; + u8 zero; + u8 pmin; + u8 psec; + u8 pframe; +}; + +static int build_toc_response_buf(u8 *dest) +{ + struct toc_header *pheader = (struct toc_header *)dest; + struct toc_descriptor *pdesc; + + /* build header */ + pheader->data_len_msb = 0x00; + pheader->data_len_lsb = 0x2E; /* TOC data length */ + pheader->first_track_number = 0x01; + pheader->last_track_number = 0x01; + + /* toc descriptor 1 */ + pdesc = (struct toc_descriptor *)&dest[4]; + pdesc->ctrl = 0x01; + pdesc->adr = 0x16; + pdesc->tno = 0x00; + pdesc->point = 0xA0; + pdesc->min = 0x00; + pdesc->sec = 0x00; + pdesc->frame = 0x00; + pdesc->zero = 0x00; + pdesc->pmin = 0x01; /* first track number */ + pdesc->psec = 0x00; + pdesc->pframe = 0x00; + + /* toc descriptor 2 */ + pdesc = pdesc + 1; + pdesc->ctrl = 0x01; + pdesc->adr = 0x16; + pdesc->tno = 0x00; + pdesc->point = 0xA1; + pdesc->min = 0x00; + pdesc->sec = 0x00; + pdesc->frame = 0x00; + pdesc->zero = 0x00; + pdesc->pmin = 0x01; /* last track number */ + pdesc->psec = 0x00; + pdesc->pframe = 0x00; + + /* toc descriptor 3 */ + pdesc = pdesc + 1; + pdesc->ctrl = 0x01; + pdesc->adr = 0x16; + pdesc->tno = 0x00; + pdesc->point = 0xA2; + pdesc->min = 0x00; + pdesc->sec = 0x00; + pdesc->frame = 0x00; + pdesc->zero = 0x00; + pdesc->pmin = 0x4F; /* pmin, psec, pframe represents */ + pdesc->psec = 0x21; /* start position of lead-out */ + pdesc->pframe = 0x029; + + /* toc descriptor 4 */ + pdesc = pdesc + 1; + pdesc->ctrl = 0x01; + pdesc->adr = 0x14; + pdesc->tno = 0x00; + pdesc->point = 0x01; + pdesc->min = 0x00; + pdesc->sec = 0x00; + pdesc->frame = 0x00; + pdesc->zero = 0x00; + pdesc->pmin = 0x00; /* pmin, psec, pframe represents */ + pdesc->psec = 0x02; /* start position of track */ + pdesc->pframe = 0x00; + + /* return total packet length */ + return (sizeof(struct toc_descriptor)*4) + sizeof(struct toc_header); +} + + static int do_read_toc(struct fsg_common *common, struct fsg_buffhd *bh) { struct fsg_lun *curlun = common->curlun; - int msf = common->cmnd[1] & 0x02; int start_track = common->cmnd[6]; u8 *buf = (u8 *)bh->buf; + int toc_buf_len = 0; if ((common->cmnd[1] & ~0x02) != 0 || /* Mask away MSF */ start_track > 1) { @@ -1194,18 +1287,8 @@ static int do_read_toc(struct fsg_common *common, struct fsg_buffhd *bh) return -EINVAL; } - memset(buf, 0, 20); - buf[1] = (20-2); /* TOC data length */ - buf[2] = 1; /* First track number */ - buf[3] = 1; /* Last track number */ - buf[5] = 0x16; /* Data track, copying allowed */ - buf[6] = 0x01; /* Only track is number 1 */ - store_cdrom_address(&buf[8], msf, 0); - - buf[13] = 0x16; /* Lead-out track is data */ - buf[14] = 0xAA; /* Lead-out track number */ - store_cdrom_address(&buf[16], msf, curlun->num_sectors); - return 20; + toc_buf_len = build_toc_response_buf(buf); + return toc_buf_len; } static int do_mode_sense(struct fsg_common *common, struct fsg_buffhd *bh) @@ -1931,8 +2014,12 @@ static int do_scsi_command(struct fsg_common *common) goto unknown_cmnd; common->data_size_from_cmnd = get_unaligned_be16(&common->cmnd[7]); + /* Set bit 9 to 1 in the mask because Mac Sends a value in byte + * 9 of the READ_TOC . Windows does not set it, but changing + * the mask covers both host envs. + */ reply = check_command(common, 10, DATA_DIR_TO_HOST, - (7<<6) | (1<<1), 1, + (0xf<<6) | (1<<1), 1, "READ TOC"); if (reply == 0) reply = do_read_toc(common, bh); From b4bf1d6d54f98b86971eb67d5fc59a7f51b679d7 Mon Sep 17 00:00:00 2001 From: liuyc20 Date: Tue, 9 Jul 2019 09:54:37 +0800 Subject: [PATCH 251/698] gadget: bcdUSB version back to 2.0 when not SuperSpeed Some of PC USB3.0 port don't support bcdUSB 2.1 version. But the phone bcdUSB will focus on bcdUSB 2.1.then USB gadget will reset continually.Change bcdUSB to 2.0 to compat all PC USB port type. 07-02 08:05:34.853 0 0 D dwc3 a600000.dwc3: Notify OTG from dwc3_gadget_reset_interrupt 07-02 08:05:35.182 0 0 D dwc3 a600000.dwc3: Notify OTG from dwc3_gadget_reset_interrupt 07-02 08:05:35.415 0 0 D dwc3 a600000.dwc3: Notify OTG from dwc3_gadget_reset_interrupt 07-02 08:05:35.647 0 0 D dwc3 a600000.dwc3: Notify OTG from dwc3_gadget_reset_interrupt 07-02 08:05:44.171 0 0 D dwc3 a600000.dwc3: Notify OTG from dwc3_gadget_reset_interrupt origin-CR: (CR) Change-Id: Icb46a95226caecc9778c6889a85654f97fa85012 Signed-off-by: liuyc20 Reviewed-on: https://gerrit.mot.com/1383246 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Xiaojun Ji Reviewed-by: Huosheng Liao Submit-Approved: Jira Key Reviewed-on: https://gerrit.mot.com/1449152 Reviewed-by: Yuecai Liu Reviewed-on: https://gerrit.mot.com/1751275 Reviewed-by: Zonghua Liu Reviewed-on: https://gerrit.mot.com/1785341 --- drivers/usb/gadget/composite.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 3730ea7f5d35..e107f2690b54 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -1743,7 +1743,7 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) cdev->desc.bcdUSB = cpu_to_le16(0x0320); cdev->desc.bMaxPacketSize0 = 9; } else { - cdev->desc.bcdUSB = cpu_to_le16(0x0210); + cdev->desc.bcdUSB = cpu_to_le16(0x0200); } } else { if (gadget->lpm_capable) From c5c976211dc9c4f633301a68910831c86edf5682 Mon Sep 17 00:00:00 2001 From: chenyb1 Date: Mon, 26 Oct 2020 11:03:15 +0800 Subject: [PATCH 252/698] Showing CPU freq The command "kpitrace --stdout --interval=1 --freq --no-proc-cpu" is not showing freq for each CPU for Racer_turbo (kernel msm-4.19). It happens because the following file is not present in device /sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state. To get cpu power stats, CONFIG_CPU_FREQ_STAT should be enabled in kernel config file. Change-Id: I6929322cf7ef86a7b8beb19727251f2aa3df1e57 Reviewed-on: https://gerrit.mot.com/1784458 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Yonghui Jia Reviewed-by: Minghui Wei Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/debug-holi.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/vendor/ext_config/debug-holi.config b/arch/arm64/configs/vendor/ext_config/debug-holi.config index 79d06d0a6e8e..d83003e63cb3 100644 --- a/arch/arm64/configs/vendor/ext_config/debug-holi.config +++ b/arch/arm64/configs/vendor/ext_config/debug-holi.config @@ -15,3 +15,4 @@ # CONFIG_DEBUG_FS=y CONFIG_CFI_PERMISSIVE=y +CONFIG_CPU_FREQ_STAT=y From 82b81ff8109340f5abbc11a050c0e1fafbec5732 Mon Sep 17 00:00:00 2001 From: chenyb1 Date: Mon, 26 Oct 2020 10:28:28 +0800 Subject: [PATCH 253/698] therm: Disable THERMAL_STATISTICS It cause (CR) if cooling device have many levels. There are NOT any processes to use thermal statistics and it occupy about 6.7K memory, so disable it, also see this CR. Change-Id: Ie37378c0a45cb6573be49e6c18b6af18f39f1d74 Reviewed-on: https://gerrit.mot.com/1784457 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Lu Chai Reviewed-by: Jichao Zou Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi-denver.config | 1 + arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-denver.config b/arch/arm64/configs/vendor/ext_config/moto-holi-denver.config index 4fa2599b9d6b..5d327884d72f 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-denver.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-denver.config @@ -15,3 +15,4 @@ # CONFIG_DENVER_DTB=y CONFIG_FS_EPOLL_WAKEUP_DEBUG=y +# CONFIG_THERMAL_STATISTICS is not set diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config b/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config index bd3fb5625009..c742165c27f9 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config @@ -15,4 +15,5 @@ # CONFIG_IBIZA_DTB=y CONFIG_NFC_QTI_I2C=y -CONFIG_FS_EPOLL_WAKEUP_DEBUG=y \ No newline at end of file +CONFIG_FS_EPOLL_WAKEUP_DEBUG=y +# CONFIG_THERMAL_STATISTICS is not set From 28c524fc00ee2d4f69736877af9c8a9b4204242c Mon Sep 17 00:00:00 2001 From: weimh1 Date: Tue, 27 Oct 2020 16:13:43 +0800 Subject: [PATCH 254/698] kernel/config: Enable kernel configs for Android Enterprise From Igor's review with Google, Google requires us to add the following kernel configs for customer build to enhance the security: CONFIG_SLUB_DEBUG=y # CONFIG_SLUB_DEBUG_ON is not set # CONFIG_SLUB_DEBUG_PANIC_ON is not set CONFIG_BUG_ON_DATA_CORRUPTION=y CONFIG_SCHED_STACK_END_CHECK=y Change-Id: Ibccec957ebc66f31c77fddff1419b5bcb6c8f635 Signed-off-by: weimh1 Reviewed-on: https://gerrit.mot.com/1785753 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi.config | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi.config b/arch/arm64/configs/vendor/ext_config/moto-holi.config index bed080a111f2..31820bead232 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi.config @@ -22,3 +22,8 @@ CONFIG_PSTORE_PMSG=y CONFIG_SERIAL_MSM_GENI_CONSOLE=y # CONFIG_SMB1398_CHARGER is not set # CONFIG_SMB1355_SLAVE_CHARGER is not set +CONFIG_SLUB_DEBUG=y +# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_SLUB_DEBUG_PANIC_ON is not set +CONFIG_BUG_ON_DATA_CORRUPTION=y +CONFIG_SCHED_STACK_END_CHECK=y From d19025e7ddf2dc137155e91b16d6c2cf6cececb2 Mon Sep 17 00:00:00 2001 From: Ravikumar Vembu Date: Wed, 18 Jan 2017 14:57:21 -0600 Subject: [PATCH 255/698] usb: mass_storage: Add support for SC_REBOOT Add support for a vendor specific SCSI pass through command to trigger reboot. SC_REBOOT (0xd7) - triggers reboot into fastboot mode SC_REBOOT_1 (0xd8) - triggers reboot into normal mode. Propagated from (CR) Change-Id: I4fc4839968135a63c594dca69b1dc93699e4a9bc Reviewed-on: https://gerrit.mot.com/1750946 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Zonghua Liu Reviewed-by: Yuecai Liu Reviewed-by: Jianqi Yang Submit-Approved: Jira Key Reviewed-on: https://gerrit.mot.com/1785335 Reviewed-by: Huosheng Liao --- drivers/usb/gadget/function/f_mass_storage.c | 67 ++++++++++++++++++++ include/scsi/scsi_proto.h | 2 + 2 files changed, 69 insertions(+) diff --git a/drivers/usb/gadget/function/f_mass_storage.c b/drivers/usb/gadget/function/f_mass_storage.c index 9ad998e9db33..59fdd37674e6 100644 --- a/drivers/usb/gadget/function/f_mass_storage.c +++ b/drivers/usb/gadget/function/f_mass_storage.c @@ -209,6 +209,7 @@ #include #include #include +#include #include #include #include @@ -231,6 +232,13 @@ #define FSG_DRIVER_DESC "Mass Storage Function" #define FSG_DRIVER_VERSION "2009/09/11" +enum fsg_restart_type { + FSG_RESTART_NONE, + FSG_REBOOT, + FSG_REBOOT_BL, +}; + + static const char fsg_string_interface[] = "Mass Storage"; #include "storage_common.h" @@ -314,6 +322,9 @@ struct fsg_common { void *private_data; char inquiry_string[INQUIRY_STRING_LEN]; + + enum fsg_restart_type restart_type; + struct delayed_work restart_work; }; struct fsg_dev { @@ -2115,6 +2126,35 @@ static int do_scsi_command(struct fsg_common *common) reply = do_write(common); break; + case SC_REBOOT: + common->data_size_from_cmnd = 0; + reply = check_command(common, common->cmnd_size, + DATA_DIR_NONE, 0, 0, "REBOOT BL"); + if (reply == 0) { + common->curlun->sense_data = SS_INVALID_COMMAND; + reply = -EINVAL; + } else { + pr_err("Triggered Reboot from SCSI Command\n"); + common->restart_type = FSG_REBOOT; + schedule_delayed_work(&common->restart_work, + msecs_to_jiffies(1000)); + } + break; + case SC_REBOOT_2: + common->data_size_from_cmnd = 0; + reply = check_command(common, common->cmnd_size, + DATA_DIR_NONE, 0, 0, "REBOOT"); + if (reply == 0) { + common->curlun->sense_data = SS_INVALID_COMMAND; + reply = -EINVAL; + } else { + pr_err("Triggered Reboot BL from SCSI Command\n"); + common->restart_type = FSG_REBOOT_BL; + schedule_delayed_work(&common->restart_work, + msecs_to_jiffies(1000)); + } + break; + /* * Some mandatory commands that we recognize but don't implement. * They don't mean much in this setting. It's left as an exercise @@ -2661,6 +2701,32 @@ static void fsg_lun_release(struct device *dev) /* Nothing needs to be done */ } +static int disable_restarts; +module_param(disable_restarts, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(disable_restarts, "Disable SCSI Initiated Reboots"); +static void fsg_restart_work(struct work_struct *work) +{ + struct fsg_common *common = container_of(work, + struct fsg_common, + restart_work.work); + + if (disable_restarts) { + pr_err("SCSI Reboots Disabled\n"); + return; + } + + switch (common->restart_type) { + case FSG_REBOOT: + kernel_restart(""); + break; + case FSG_REBOOT_BL: + kernel_restart("bootloader"); + break; + default: + break; + } +} + static struct fsg_common *fsg_common_setup(struct fsg_common *common) { if (!common) { @@ -2676,6 +2742,7 @@ static struct fsg_common *fsg_common_setup(struct fsg_common *common) init_completion(&common->thread_notifier); init_waitqueue_head(&common->io_wait); init_waitqueue_head(&common->fsg_wait); + INIT_DELAYED_WORK(&common->restart_work, fsg_restart_work); common->state = FSG_STATE_TERMINATED; memset(common->luns, 0, sizeof(common->luns)); diff --git a/include/scsi/scsi_proto.h b/include/scsi/scsi_proto.h index c36860111932..fca5a614cd45 100644 --- a/include/scsi/scsi_proto.h +++ b/include/scsi/scsi_proto.h @@ -169,6 +169,8 @@ /* Vendor specific CDBs start here */ #define VENDOR_SPECIFIC_CDB 0xc0 +#define SC_REBOOT 0xd7 +#define SC_REBOOT_2 0xd8 /* * SCSI command lengths From 5d7a7200a4c5a25493cc4b7dbee8daf8e4e3216e Mon Sep 17 00:00:00 2001 From: Ravi Vembu Date: Tue, 21 Mar 2017 14:17:12 -0500 Subject: [PATCH 256/698] usb: configfs: Implement secure attribute Implement the secure attribute for locking USB access from the gadget driver. echo 1 > /sys/class/android_usb/android0/secure will lock USB access and disable USB enumeration. Change-Id: I9c7bcb27cfd4ce4f28520d938c604607ec6c2431 Moto-CRs-fixed: (CR) Reviewed-on: https://gerrit.mot.com/1750996 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Zonghua Liu Reviewed-by: Yuecai Liu Reviewed-by: Jianqi Yang Submit-Approved: Jira Key Reviewed-on: https://gerrit.mot.com/1785337 Reviewed-by: Huosheng Liao --- drivers/usb/gadget/configfs.c | 88 ++++++++++++++++++++++++++++++++--- 1 file changed, 82 insertions(+), 6 deletions(-) diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c index 7ed6bb988eaf..849dce3f31c1 100644 --- a/drivers/usb/gadget/configfs.c +++ b/drivers/usb/gadget/configfs.c @@ -96,6 +96,7 @@ struct gadget_info { struct work_struct work; struct device *dev; #endif + bool secure; }; static inline struct gadget_info *to_gadget_info(struct config_item *item) @@ -291,11 +292,19 @@ static int unregister_gadget(struct gadget_info *gi) if (!gi->composite.gadget_driver.udc_name) return -ENODEV; + if (gi->secure) { + gi->unbinding = false; + kfree(gi->composite.gadget_driver.udc_name); + gi->composite.gadget_driver.udc_name = NULL; + return 0; + } + gi->unbinding = true; ret = usb_gadget_unregister_driver(&gi->composite.gadget_driver); - if (ret) + if (ret) { + pr_err("unregister gadget failed, ret = %d\n", ret); return ret; - + } gi->unbinding = false; kfree(gi->composite.gadget_driver.udc_name); gi->composite.gadget_driver.udc_name = NULL; @@ -318,6 +327,8 @@ static ssize_t gadget_dev_desc_UDC_store(struct config_item *item, if (name[len - 1] == '\n') name[len - 1] = '\0'; + pr_debug("UDC store = %s\n", name); + mutex_lock(&gi->lock); if (!strlen(name) || strcmp(name, "none") == 0) { @@ -331,10 +342,12 @@ static ssize_t gadget_dev_desc_UDC_store(struct config_item *item, goto err; } gi->composite.gadget_driver.udc_name = name; - ret = usb_gadget_probe_driver(&gi->composite.gadget_driver); - if (ret) { - gi->composite.gadget_driver.udc_name = NULL; - goto err; + if (!gi->secure) { + ret = usb_gadget_probe_driver(&gi->composite.gadget_driver); + if (ret) { + gi->composite.gadget_driver.udc_name = NULL; + goto err; + } } #ifdef CONFIG_USB_CONFIGFS_UEVENT schedule_work(&gi->work); @@ -1786,8 +1799,71 @@ out: static DEVICE_ATTR(state, S_IRUGO, state_show, NULL); +static ssize_t secure_show(struct device *pdev, struct device_attribute *attr, + char *buf) +{ + struct gadget_info *gi = dev_get_drvdata(pdev); + + if (!gi) + return -ENODEV; + + return scnprintf(buf, PAGE_SIZE, "%d\n", gi->secure); +} + +static ssize_t secure_store(struct device *pdev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct gadget_info *gi = dev_get_drvdata(pdev); + unsigned long mode, r; + int ret; + + if (!gi) + return -ENODEV; + + r = kstrtoul(buf, 0, &mode); + if (r) { + dev_err(pdev, "Invalid value = %lu\n", mode); + return -EINVAL; + } + + mode = !!mode; + if (mode == gi->secure) + return count; + + mutex_lock(&gi->lock); + + gi->secure = mode; + + if (!gi->composite.gadget_driver.udc_name) { + mutex_unlock(&gi->lock); + return count; + } + pr_debug("Secure Store , UDC = %s, secure = %d\n", + gi->composite.gadget_driver.udc_name, + gi->secure); + + if (gi->secure) { + ret = usb_gadget_unregister_driver( + &gi->composite.gadget_driver); + if (ret) + pr_err("Failed detaching UDC from gadget %d\n", ret); + } else { + ret = usb_gadget_probe_driver(&gi->composite.gadget_driver); + if (ret) { + gi->composite.gadget_driver.udc_name = NULL; + pr_err("Failed attaching UDC to gadget %d\n", ret); + } + } + mutex_unlock(&gi->lock); + + return count; +} + +static DEVICE_ATTR(secure, S_IRUGO | S_IWUSR, secure_show, secure_store); + static struct device_attribute *android_usb_attributes[] = { &dev_attr_state, + &dev_attr_secure, NULL }; From 99d798170e78d711fee904c7cf60b36f3feebd8a Mon Sep 17 00:00:00 2001 From: weimh1 Date: Wed, 28 Oct 2020 11:29:50 +0800 Subject: [PATCH 257/698] kernel/config: Enable RTB log on factory version Enable RTB log on factory version. Some crash issues need RTB log to get more information. Change-Id: I274d94d73221516f6cff55bb68ceaeca6b9a6291 Signed-off-by: weimh1 Reviewed-on: https://gerrit.mot.com/1786711 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/factory-holi.config | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm64/configs/vendor/ext_config/factory-holi.config b/arch/arm64/configs/vendor/ext_config/factory-holi.config index 098ff7521c6d..3c8927499698 100644 --- a/arch/arm64/configs/vendor/ext_config/factory-holi.config +++ b/arch/arm64/configs/vendor/ext_config/factory-holi.config @@ -15,3 +15,6 @@ # CONFIG_CFI_PERMISSIVE=y CONFIG_SERIAL_MSM_GENI_CONSOLE=y +CONFIG_QCOM_RTB=y +CONFIG_QCOM_RTB_QGKI=y +CONFIG_QCOM_RTB_SEPARATE_CPUS=y From c209226deaf8c907ce88f3b8d132d14ad7b6fe39 Mon Sep 17 00:00:00 2001 From: Ravi Vembu Date: Tue, 15 Nov 2016 11:17:37 -0600 Subject: [PATCH 258/698] usb: configfs: Reset the use_os_desc flag os_desc support can be turned off via userspace. Kernel also needs to correspondingly reset its state if userspace has changed it. Otherwise this cause os descs to be advertised on drivers that have no os desc support. Change-Id: Iee760ba45ceea1f26f4e33b4e52c06be7fd20e44 Moto-CRs-fixed: (CR) Reviewed-on: https://gerrit.mot.com/1750957 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Zonghua Liu Reviewed-by: Yuecai Liu Reviewed-by: Jianqi Yang Submit-Approved: Jira Key Reviewed-on: https://gerrit.mot.com/1785336 Reviewed-by: Huosheng Liao --- drivers/usb/gadget/configfs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c index 849dce3f31c1..39e7d1e6b5d4 100644 --- a/drivers/usb/gadget/configfs.c +++ b/drivers/usb/gadget/configfs.c @@ -1449,7 +1449,8 @@ static int configfs_composite_bind(struct usb_gadget *gadget, cdev->use_os_string = true; cdev->b_vendor_code = gi->b_vendor_code; memcpy(cdev->qw_sign, gi->qw_sign, OS_STRING_QW_SIGN_LEN); - } + } else + cdev->use_os_string = false; if (gadget_is_otg(gadget) && !otg_desc[0]) { struct usb_descriptor_header *usb_desc; From 81e4c889aa00ac505172d1f947139e2cf8888871 Mon Sep 17 00:00:00 2001 From: Kenny Kessler Date: Thu, 24 Jan 2019 14:04:42 -0600 Subject: [PATCH 259/698] usb/dwc3: msm: Enable all Debug Logs Force all logs to print. origin-CR: (CR) The USB DWC3 is very important and tracking dmesg is much easier when everything is ON. Port-of: https://gerrit.mot.com/1307019 Change-Id: Iebde3d9feadde8a3e92acb10baeb97c5ba7e07cf Signed-off-by: Kenny Kessler Reviewed-on: https://gerrit.mot.com/1332192 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key Reviewed-on: https://gerrit.mot.com/1391225 Reviewed-by: Jianqi Yang Reviewed-on: https://gerrit.mot.com/1449174 Reviewed-on: https://gerrit.mot.com/1786719 Reviewed-by: Yuecai Liu --- drivers/usb/dwc3/dwc3-msm.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c index c4ad1fd62601..f28fe021e7bc 100644 --- a/drivers/usb/dwc3/dwc3-msm.c +++ b/drivers/usb/dwc3/dwc3-msm.c @@ -65,6 +65,11 @@ /* AHB2PHY read/write waite value */ #define ONE_READ_WRITE_WAIT 0x11 +#undef dev_dbg +#undef pr_debug +#define dev_dbg dev_err +#define pr_debug pr_err + /* XHCI registers */ #define USB3_HCSPARAMS1 (0x4) #define USB3_PORTSC (0x420) From d1e0d1354bc7634712d76ecc473006fd51357832 Mon Sep 17 00:00:00 2001 From: weiweij Date: Wed, 28 Oct 2020 11:16:14 +0800 Subject: [PATCH 260/698] arm64/config: support UAS of usb storage With UAS (USB Attached SCSI), the tested Samsung SSD read and write speed gets 3x and 2x respectively on Nash. Testing results for Samsung 256GB Portable SSD T5: Seq. read: 244 MB/s v.s. 84 MB/s Seq. write: 161 MB/s v.s. 94 MB/s Port of (CR) on kernel 4.4. Change-Id: Idf5d5445dcc599c21bedda64c7eff62f860ff05b Reviewed-on: https://gerrit.mot.com/1278853 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key Reviewed-on: https://gerrit.mot.com/1471644 Reviewed-by: Jianqi Yang Reviewed-on: https://gerrit.mot.com/1786700 Reviewed-by: Yuecai Liu --- arch/arm64/configs/vendor/ext_config/moto-holi.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi.config b/arch/arm64/configs/vendor/ext_config/moto-holi.config index 31820bead232..b85cde1175eb 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi.config @@ -26,4 +26,5 @@ CONFIG_SLUB_DEBUG=y # CONFIG_SLUB_DEBUG_ON is not set # CONFIG_SLUB_DEBUG_PANIC_ON is not set CONFIG_BUG_ON_DATA_CORRUPTION=y +CONFIG_USB_UAS=y CONFIG_SCHED_STACK_END_CHECK=y From b329f69c46e5bf8d9ea42ce1e3f8a65b3cde5bd4 Mon Sep 17 00:00:00 2001 From: weiweij Date: Wed, 28 Oct 2020 11:12:03 +0800 Subject: [PATCH 261/698] config: add usb-video driver PROPAGATED from (CR) CONFIG_MEDIA_USB_SUPPORT=y CONFIG_USB_VIDEO_CLASS=y Change-Id: I9322e4de815faf477cffdde8efa912ab74031d23 Signed-off-by: liuyc20 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Yonghua Yan Reviewed-by: Xiaojun Ji Reviewed-by: Huosheng Liao Submit-Approved: Jira Key Signed-off-by: Robert Cabral Reviewed-on: https://gerrit.mot.com/1715152 Reviewed-on: https://gerrit.mot.com/1786699 Reviewed-by: Yuecai Liu --- arch/arm64/configs/vendor/ext_config/moto-holi.config | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi.config b/arch/arm64/configs/vendor/ext_config/moto-holi.config index b85cde1175eb..e19fe201b8e0 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi.config @@ -28,3 +28,6 @@ CONFIG_SLUB_DEBUG=y CONFIG_BUG_ON_DATA_CORRUPTION=y CONFIG_USB_UAS=y CONFIG_SCHED_STACK_END_CHECK=y + +CONFIG_MEDIA_USB_SUPPORT=y +CONFIG_USB_VIDEO_CLASS=y From 6de14ba6a999deb35ee9ebd75b91c0004b017b33 Mon Sep 17 00:00:00 2001 From: Bo He Date: Mon, 14 Jan 2019 09:48:32 +0200 Subject: [PATCH 262/698] sb: dwc3: gadget: synchronize_irq dwc irq in suspend [ Upstream commit 01c10880d24291a96a4ab0da773e3c5ce4d12da8 ] We see dwc3 endpoint stopped by unwanted irq during suspend resume test, which is caused dwc3 ep can't be started with error "No Resource". Here, add synchronize_irq before suspend to sync the pending IRQ handlers complete. origin-CRs: (CR) Change-Id: Ice15ecc8286f417a95935ad3bf3368f2a71ae736 Signed-off-by: Bo He Signed-off-by: Yu Wang Signed-off-by: Felipe Balbi Signed-off-by: Sasha Levin Reviewed-on: https://gerrit.mot.com/1373264 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key Reviewed-on: https://gerrit.mot.com/1379348 Reviewed-by: Jianqi Yang Reviewed-on: https://gerrit.mot.com/1449150 Reviewed-on: https://gerrit.mot.com/1751270 Reviewed-by: Zonghua Liu Reviewed-by: Yuecai Liu Reviewed-on: https://gerrit.mot.com/1785340 --- drivers/usb/dwc3/gadget.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 3f55565cda18..fdef1944080a 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -4545,6 +4545,8 @@ int dwc3_gadget_suspend(struct dwc3 *dwc) dwc3_disconnect_gadget(dwc); __dwc3_gadget_stop(dwc); + synchronize_irq(dwc->irq_gadget); + return 0; } From 9ce7a731ed683b88e5c41c875f1874eb63c1b5e0 Mon Sep 17 00:00:00 2001 From: zhucc2 Date: Mon, 26 Oct 2020 15:48:48 +0800 Subject: [PATCH 263/698] : denver/ibiza: perf:optimize the debug perf. Refer to:https://gerrit.mot.com/#/c/1479008/ Propogated from (CR) Change-Id: I392a97d85a28f03f47483c80227d923ee23a0159 Reviewed-on: https://gerrit.mot.com/1784673 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- .../configs/vendor/ext_config/debug-holi-denver.config | 9 +++++++++ .../configs/vendor/ext_config/debug-holi-ibiza.config | 9 +++++++++ 2 files changed, 18 insertions(+) diff --git a/arch/arm64/configs/vendor/ext_config/debug-holi-denver.config b/arch/arm64/configs/vendor/ext_config/debug-holi-denver.config index 830e8a22f610..13f71e03c466 100644 --- a/arch/arm64/configs/vendor/ext_config/debug-holi-denver.config +++ b/arch/arm64/configs/vendor/ext_config/debug-holi-denver.config @@ -14,3 +14,12 @@ # being set as expected. # +# CONFIG_CGROUP_DEBUG is not set +# CONFIG_CLEANCACHE is not set +# CONFIG_CMA_ALLOW_WRITE_DEBUGFS is not set +# CONFIG_CMA_DEBUG is not set +# CONFIG_PREEMPTIRQ_EVENTS is not set +# CONFIG_PREEMPT_TRACER is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_TEST_USER_COPY is not set diff --git a/arch/arm64/configs/vendor/ext_config/debug-holi-ibiza.config b/arch/arm64/configs/vendor/ext_config/debug-holi-ibiza.config index 830e8a22f610..13f71e03c466 100644 --- a/arch/arm64/configs/vendor/ext_config/debug-holi-ibiza.config +++ b/arch/arm64/configs/vendor/ext_config/debug-holi-ibiza.config @@ -14,3 +14,12 @@ # being set as expected. # +# CONFIG_CGROUP_DEBUG is not set +# CONFIG_CLEANCACHE is not set +# CONFIG_CMA_ALLOW_WRITE_DEBUGFS is not set +# CONFIG_CMA_DEBUG is not set +# CONFIG_PREEMPTIRQ_EVENTS is not set +# CONFIG_PREEMPT_TRACER is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_TEST_USER_COPY is not set From ac9e62a0159c0a10a67049daad9292b935581aca Mon Sep 17 00:00:00 2001 From: jixj Date: Wed, 28 Oct 2020 11:32:24 +0800 Subject: [PATCH 264/698] Revert "(CR): defconfig: lito: turn off pstore compress" No need it on kernel5.4. Use ZLIB compression, bootloader also can dump kernel panic log. This reverts commit 2fc22e11d2fd8c99a306e0d0d41a9ec5e716ff77. Change-Id: I77323996b0bad2348a121a64d4b46c5c1987747c Reviewed-on: https://gerrit.mot.com/1786966 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- fs/pstore/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/pstore/Kconfig b/fs/pstore/Kconfig index 6900f8914462..9fe46cc26403 100644 --- a/fs/pstore/Kconfig +++ b/fs/pstore/Kconfig @@ -16,6 +16,7 @@ config PSTORE config PSTORE_DEFLATE_COMPRESS tristate "DEFLATE (ZLIB) compression" + default y depends on PSTORE select CRYPTO_DEFLATE help From 07453b7c34da64ae9dbd83113b6bf7d44bd1d5fe Mon Sep 17 00:00:00 2001 From: mahj8 Date: Wed, 28 Oct 2020 11:07:48 +0800 Subject: [PATCH 265/698] power: qpnp-smb5: Change Power supply Move "battery" to "qcom_battery" and change type from BATTERY to MAIN. This will allow another driver to control "battery" and the system will passthrough it to get the information. Change-Id: I5409be01d769805065a64d05fb5b1666c81fed6b Signed-off-by: mahj8 Reviewed-on: https://gerrit.mot.com/1786691 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Lu Chai Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- drivers/power/supply/qcom/qpnp-smb5.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/power/supply/qcom/qpnp-smb5.c b/drivers/power/supply/qcom/qpnp-smb5.c index 3208bb25c552..46064da22037 100644 --- a/drivers/power/supply/qcom/qpnp-smb5.c +++ b/drivers/power/supply/qcom/qpnp-smb5.c @@ -1433,8 +1433,8 @@ static int smb5_batt_prop_is_writeable(struct power_supply *psy, } static const struct power_supply_desc batt_psy_desc = { - .name = "battery", - .type = POWER_SUPPLY_TYPE_BATTERY, + .name = "qcom_battery", + .type = POWER_SUPPLY_TYPE_MAINS, .properties = smb5_batt_props, .num_properties = ARRAY_SIZE(smb5_batt_props), .get_property = smb5_batt_get_prop, From 076032ea2e5c2cf2f5dd6bd417c549286217c46d Mon Sep 17 00:00:00 2001 From: quebs2 Date: Wed, 28 Oct 2020 15:36:04 +0800 Subject: [PATCH 266/698] Remove CONFIG_CONSOLE_UNHASHED_POINTERS on userdebug. Remove the CONFIG_CONSOLE_UNHASHED_POINTERS to address STS case in CVE_2016_6752 on userdebug build. Propagated from: (CR). Change-Id: I6881210947fec60689894411d84a4865aea70df4 Signed-off-by: quebs2 Reviewed-on: https://gerrit.mot.com/1786973 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- arch/arm64/configs/vendor/holi_consolidate.config | 2 +- arch/arm64/configs/vendor/holi_debug.config | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/configs/vendor/holi_consolidate.config b/arch/arm64/configs/vendor/holi_consolidate.config index 2e6b0caad2af..b373865fe005 100644 --- a/arch/arm64/configs/vendor/holi_consolidate.config +++ b/arch/arm64/configs/vendor/holi_consolidate.config @@ -29,7 +29,7 @@ CONFIG_SERIAL_MSM_GENI_CONSOLE=y CONFIG_QCOM_RTB=y CONFIG_QCOM_RTB_SEPARATE_CPUS=y CONFIG_QCOM_RTB_QGKI=y -CONFIG_DEBUG_CONSOLE_UNHASHED_POINTERS=y +#CONFIG_DEBUG_CONSOLE_UNHASHED_POINTERS is not set CONFIG_COMMON_CLK_QCOM_DEBUG=y CONFIG_CNSS2_DEBUG=y CONFIG_NL80211_TESTMODE=y diff --git a/arch/arm64/configs/vendor/holi_debug.config b/arch/arm64/configs/vendor/holi_debug.config index 74a3f1b4b1d5..8cf2926d45f4 100644 --- a/arch/arm64/configs/vendor/holi_debug.config +++ b/arch/arm64/configs/vendor/holi_debug.config @@ -29,7 +29,7 @@ CONFIG_QCOM_RTB_QGKI=y CONFIG_IPA_DEBUG=y CONFIG_IPA_UT=y CONFIG_MSM_ADSPRPC=y -CONFIG_DEBUG_CONSOLE_UNHASHED_POINTERS=y +#CONFIG_DEBUG_CONSOLE_UNHASHED_POINTERS is not set CONFIG_COMMON_CLK_QCOM_DEBUG=y CONFIG_I2C_MSM_GENI=y CONFIG_SPI_MSM_GENI=y From c620ee51e428a277554be6b921d1d7db06aedba5 Mon Sep 17 00:00:00 2001 From: guhong Date: Wed, 28 Oct 2020 15:45:19 +0800 Subject: [PATCH 267/698] expose ssr_reason to ss_ramdump expose ssr_reason to ss_ramdump so that bug2go can show it in their record. Change-Id: Id8fdaa1b5aa279f6a70a42c278c324007b27e758 Reviewed-on: https://gerrit.mot.com/1786969 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Yifu Lin Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- drivers/soc/qcom/subsys-pil-tz.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/soc/qcom/subsys-pil-tz.c b/drivers/soc/qcom/subsys-pil-tz.c index ddd30f512b0d..f256c812e1f5 100644 --- a/drivers/soc/qcom/subsys-pil-tz.c +++ b/drivers/soc/qcom/subsys-pil-tz.c @@ -46,6 +46,10 @@ #define desc_to_data(d) container_of(d, struct pil_tz_data, desc) #define subsys_to_data(d) container_of(d, struct pil_tz_data, subsys_desc) +static char pil_ssr_reason[MAX_SSR_REASON_LEN]; +static char *ssr_reason = pil_ssr_reason; +module_param(ssr_reason, charp, S_IRUGO); + /** * struct reg_info - regulator info * @reg: regulator handle @@ -761,7 +765,7 @@ static struct pil_reset_ops pil_ops_trusted = { static void log_failure_reason(const struct pil_tz_data *d) { size_t size; - char *smem_reason, reason[MAX_SSR_REASON_LEN]; + char *smem_reason; const char *name = d->subsys_desc.name; if (d->smem_id == -1) @@ -778,8 +782,8 @@ static void log_failure_reason(const struct pil_tz_data *d) return; } - strlcpy(reason, smem_reason, min(size, (size_t)MAX_SSR_REASON_LEN)); - pr_err("%s subsystem failure reason: %s.\n", name, reason); + strlcpy(pil_ssr_reason, smem_reason, min((size_t)size, (size_t)sizeof(pil_ssr_reason))); + pr_err("%s subsystem failure reason: %s.\n", name, pil_ssr_reason); } static int subsys_shutdown(const struct subsys_desc *subsys, bool force_stop) From 29f34870c15a926946ca63e21f3e13f2cd47ca64 Mon Sep 17 00:00:00 2001 From: jixj Date: Thu, 29 Oct 2020 14:48:47 +0800 Subject: [PATCH 268/698] qcom/gki-whitelist: add "remove_proc_subtree" for utags.ko This abi is used in utags.ko and it has been added to GKI whitelist so add it to qcom whitelist Change-Id: I32d9122e5e685ed6390b9f574a57a216e914065e Reviewed-on: https://gerrit.mot.com/1788243 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Zhenxin Xi Submit-Approved: Jira Key --- android/abi_gki_aarch64_qcom | 1 + 1 file changed, 1 insertion(+) diff --git a/android/abi_gki_aarch64_qcom b/android/abi_gki_aarch64_qcom index bb92e5fe4960..871b0a33e066 100644 --- a/android/abi_gki_aarch64_qcom +++ b/android/abi_gki_aarch64_qcom @@ -2060,6 +2060,7 @@ remove_arg_zero __remove_inode_hash remove_proc_entry + remove_proc_subtree remove_wait_queue report_iommu_fault request_firmware From 018eb758fbdacbc7721e01b47ae9a83924f0be4e Mon Sep 17 00:00:00 2001 From: liuwang2 Date: Fri, 30 Oct 2020 13:06:43 +0800 Subject: [PATCH 269/698] ibiza: add some api to qcom whitelist [detail] These api exists in google whitelist abi_gki_aarch64.xml. Change-Id: I3dbc41b216fc71e341901ab4ff5e133fd25859dc Signed-off-by: liuwang2 Reviewed-on: https://gerrit.mot.com/1789286 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Dawei Wang Reviewed-by: Zhenxin Xi Submit-Approved: Jira Key --- android/abi_gki_aarch64_qcom | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/android/abi_gki_aarch64_qcom b/android/abi_gki_aarch64_qcom index 871b0a33e066..b859ff53c560 100644 --- a/android/abi_gki_aarch64_qcom +++ b/android/abi_gki_aarch64_qcom @@ -1977,6 +1977,7 @@ __rcu_read_lock __rcu_read_unlock rdev_get_drvdata + rdev_get_id reboot_mode refcount_dec_and_lock refcount_dec_and_test_checked @@ -2029,17 +2030,22 @@ regulator_count_voltages regulator_disable regulator_disable_deferred + regulator_disable_regmap regulator_enable + regulator_enable_regmap regulator_get regulator_get_current_limit regulator_get_drvdata regulator_get_mode regulator_get_voltage + regulator_get_voltage_sel_regmap regulator_is_enabled + regulator_is_enabled_regmap regulator_is_supported_voltage regulator_list_voltage regulator_list_voltage_linear regulator_lock + regulator_map_voltage_linear regulator_notifier_call_chain regulator_put regulator_register @@ -2048,6 +2054,7 @@ regulator_set_load regulator_set_mode regulator_set_voltage + regulator_set_voltage_sel_regmap regulator_unlock regulator_unregister regulator_unregister_notifier From 633ebc419cd5950de9c09267aa9ce40c084d253f Mon Sep 17 00:00:00 2001 From: wuwl10 Date: Fri, 30 Oct 2020 11:23:38 +0800 Subject: [PATCH 270/698] qcom: Update qcom whitelist for chipone fps The "wakeup_source_add" and "wakeup_source_remove" functions can be found in the latest google whitelist, so update the qcom whitelist for chipone fps. Change-Id: I5332205b17b5228927f482ac991cd1fe893f72fd Signed-off-by: wuwl10 Reviewed-on: https://gerrit.mot.com/1789294 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- android/abi_gki_aarch64_qcom | 2 ++ 1 file changed, 2 insertions(+) diff --git a/android/abi_gki_aarch64_qcom b/android/abi_gki_aarch64_qcom index b859ff53c560..28ea1091ac17 100644 --- a/android/abi_gki_aarch64_qcom +++ b/android/abi_gki_aarch64_qcom @@ -2969,6 +2969,8 @@ __wake_up __wake_up_locked wake_up_process + wakeup_source_add + wakeup_source_remove wakeup_source_register wakeup_source_unregister __warn_printk From 8df86193da74da0dec2502aa43d9ab468898840d Mon Sep 17 00:00:00 2001 From: wangyq13 Date: Fri, 23 Oct 2020 10:09:35 +0800 Subject: [PATCH 271/698] wled: enable cabc before set brightness when adjust bl As https://gerrit.mot.com/#/c/1743071/ do, if enable cabc after setting brightness when adjust brightness, may cause backlight flicker. So move cabc enable before setting brightness when adjust brightness. But still enable cabc after setting brihtness if phone screen on to avoid peak current. Change-Id: I625f6cdc8cd6c30e049c13994850932b9653dde9 Reviewed-on: https://gerrit.mot.com/1782873 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Yeqing Wang Reviewed-by: Shanshan Dai Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- drivers/video/backlight/qcom-spmi-wled.c | 47 ++++++++++++++++-------- 1 file changed, 31 insertions(+), 16 deletions(-) diff --git a/drivers/video/backlight/qcom-spmi-wled.c b/drivers/video/backlight/qcom-spmi-wled.c index b857f4744e7d..5ecbc9aeb10f 100644 --- a/drivers/video/backlight/qcom-spmi-wled.c +++ b/drivers/video/backlight/qcom-spmi-wled.c @@ -566,17 +566,24 @@ static int wled_update_status(struct backlight_device *bl) brightness = 0; mutex_lock(&wled->lock); - - if (wled->low_bl_force_cabc_disable && brightness <= wled->low_bl_cfg.low_bl_threshold) { - brightness = brightness * wled->low_bl_cfg.low_bl_remap_percent/100; - if (!wled->cabc_disabled) { - wled->cabc_config(wled, false); - wled->cabc_disabled = true; - pr_info("low brightness(%d), disable cabc\n", brightness); - } - } - if (brightness) { + if (wled->low_bl_force_cabc_disable && wled->brightness) { + if (brightness <= wled->low_bl_cfg.low_bl_threshold) { + brightness = brightness * wled->low_bl_cfg.low_bl_remap_percent/100; + if (!wled->cabc_disabled) { + wled->cabc_config(wled, false); + wled->cabc_disabled = true; + pr_info("under low brightness(%d), will disable cabc\n", brightness); + } + + } + else if ((wled->brightness < wled->low_bl_cfg.low_bl_threshold) && (wled->cabc_disabled)) { + wled->cabc_disabled = false; + wled->cabc_config(wled, true); + pr_info("exit low brightness(%d), will enable cabc\n", brightness); + } + } + if (wled->bl_step_up_enable) { rc = wled_set_brightness_step(wled, brightness); if (rc < 0) { @@ -590,12 +597,15 @@ static int wled_update_status(struct backlight_device *bl) goto unlock_mutex; } - if (wled->low_bl_force_cabc_disable && brightness > wled->low_bl_cfg.low_bl_threshold - && wled->brightness <= wled->low_bl_cfg.low_bl_threshold && wled->cabc_disabled) { - msleep(wled->low_bl_cfg.low_bl_delay_ms); - wled->cabc_disabled = false; - wled->cabc_config(wled, true); - pr_info("enable wled cabc\n"); + if (wled->cabc_disabled && wled->low_bl_force_cabc_disable && !wled->brightness) { + if (brightness <= wled->low_bl_cfg.low_bl_threshold) + pr_info("keep cabc disabled\n"); + else { + msleep(wled->low_bl_cfg.low_bl_delay_ms); + wled->cabc_disabled = false; + wled->cabc_config(wled, true); + pr_info("enable wled cabc\n"); + } } if (is_wled5(wled)) { @@ -645,6 +655,11 @@ static int wled_update_status(struct backlight_device *bl) } } + if (!wled->cabc_disabled && wled->low_bl_force_cabc_disable) { + wled->cabc_config(wled, false); + wled->cabc_disabled = true; + pr_info("disable wled cabc\n"); + } rc = wled_module_enable(wled, brightness); if (rc < 0) { pr_err("wled disable failed rc:%d\n", rc); From e33628008f5e80de791ac39a122276f691776a6a Mon Sep 17 00:00:00 2001 From: weiweij Date: Tue, 20 Oct 2020 17:56:59 +0800 Subject: [PATCH 272/698] i2c: i2c-qcom-geni: Add support for noise cancellation on I2C lines Add support for noise cancellation on I2C lines. CRs-fixed: (CR) Change-Id: Icd35ab460ae56e951128efdefeb21f121bfc39a1 Signed-off-by: Vipin Deep Kaur Reviewed-on: https://gerrit.mot.com/1497524 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Jianqi Yang Submit-Approved: Jira Key Reviewed-on: https://gerrit.mot.com/1780418 Reviewed-by: Huosheng Liao --- drivers/i2c/busses/i2c-qcom-geni.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/i2c/busses/i2c-qcom-geni.c b/drivers/i2c/busses/i2c-qcom-geni.c index c73b997899af..511f5a64b73b 100644 --- a/drivers/i2c/busses/i2c-qcom-geni.c +++ b/drivers/i2c/busses/i2c-qcom-geni.c @@ -19,6 +19,7 @@ #define SE_I2C_TX_TRANS_LEN 0x26c #define SE_I2C_RX_TRANS_LEN 0x270 #define SE_I2C_SCL_COUNTERS 0x278 +#define SE_I2C_NOISE_CANCEL_CTL (0x234) #define SE_I2C_ERR (M_CMD_OVERRUN_EN | M_ILLEGAL_CMD_EN | M_CMD_FAILURE_EN |\ M_GP_IRQ_1_EN | M_GP_IRQ_3_EN | M_GP_IRQ_4_EN) @@ -90,6 +91,8 @@ struct geni_i2c_dev { void *dma_buf; size_t xfer_len; dma_addr_t dma_addr; + u32 noise_rjct_scl; + u32 noise_rjct_sda; }; struct geni_i2c_err_log { @@ -164,6 +167,9 @@ static void qcom_geni_i2c_conf(struct geni_i2c_dev *gi2c) val |= itr->t_low_cnt << LOW_COUNTER_SHFT; val |= itr->t_cycle_cnt; writel_relaxed(val, gi2c->se.base + SE_I2C_SCL_COUNTERS); + if (gi2c->noise_rjct_scl || gi2c->noise_rjct_sda) + geni_write_reg(gi2c->noise_rjct_scl << 1 | + gi2c->noise_rjct_sda << 3, gi2c->base, SE_I2C_NOISE_CANCEL_CTL); } static void geni_i2c_err_misc(struct geni_i2c_dev *gi2c) @@ -559,6 +565,14 @@ static int geni_i2c_probe(struct platform_device *pdev) if (has_acpi_companion(&pdev->dev)) ACPI_COMPANION_SET(&gi2c->adap.dev, ACPI_COMPANION(&pdev->dev)); + gi2c->noise_rjct_scl = 0; + gi2c->noise_rjct_sda = 0; + + of_property_read_u32(pdev->dev.of_node, "qcom,noise-rjct-scl", + &gi2c->noise_rjct_scl); + of_property_read_u32(pdev->dev.of_node, "qcom,noise-rjct-sda", + &gi2c->noise_rjct_sda); + gi2c->irq = platform_get_irq(pdev, 0); if (gi2c->irq < 0) { dev_err(&pdev->dev, "IRQ error for i2c-geni\n"); From 46ee4c2d3a4a187ddf9ba188dc0266e8c7fb6e8c Mon Sep 17 00:00:00 2001 From: zhucc2 Date: Mon, 2 Nov 2020 14:24:42 +0800 Subject: [PATCH 273/698] arm64/config: remove EDAC_KRYO_ARM64_PANIC_ON_CE on debug version. for EDAC will cause some unuseful panics on debug version, we have to disable these configs on debug verison, which have been disable on user version as default. Change-Id: Ic34b9fb3a516911dfed41eaf38ad29466fdf65bb Reviewed-on: https://gerrit.mot.com/1790701 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/debug-holi.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/vendor/ext_config/debug-holi.config b/arch/arm64/configs/vendor/ext_config/debug-holi.config index d83003e63cb3..530741083869 100644 --- a/arch/arm64/configs/vendor/ext_config/debug-holi.config +++ b/arch/arm64/configs/vendor/ext_config/debug-holi.config @@ -16,3 +16,4 @@ CONFIG_DEBUG_FS=y CONFIG_CFI_PERMISSIVE=y CONFIG_CPU_FREQ_STAT=y +# CONFIG_EDAC_KRYO_ARM64_PANIC_ON_CE is not set From 35917e16791c9544c5d9c8a7e89490a4f33057b2 Mon Sep 17 00:00:00 2001 From: wengjun1 Date: Mon, 2 Nov 2020 14:22:00 +0800 Subject: [PATCH 274/698] Denver: arch/configs: Cleanup touch unused config - Since some touch configurations are unused by Denver, so cleanup these items. Change-Id: Ifaf0e1eb2b62886ee1c5799f64523d4978b57510 Signed-off-by: wengjun1 Reviewed-on: https://gerrit.mot.com/1790692 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi-denver.config | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-denver.config b/arch/arm64/configs/vendor/ext_config/moto-holi-denver.config index 5d327884d72f..bc02edbfb9ea 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-denver.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-denver.config @@ -16,3 +16,6 @@ CONFIG_DENVER_DTB=y CONFIG_FS_EPOLL_WAKEUP_DEBUG=y # CONFIG_THERMAL_STATISTICS is not set +# CONFIG_TOUCHSCREEN_SYNAPTICS_TCM is not set +# CONFIG_TOUCHSCREEN_SYNAPTICS_DSX is not set +# CONFIG_TOUCHSCREEN_FTS is not set \ No newline at end of file From ae26b5ff07e12849c698d4043814fec5b8be26e5 Mon Sep 17 00:00:00 2001 From: wuwl10 Date: Tue, 3 Nov 2020 11:18:18 +0800 Subject: [PATCH 275/698] nfc: support tcmd test TCMD use 32bit system, we need to add new ioctl to make sure tcmd test pass Change-Id: I255862644691755fb91727c5c0b856a3a80d3670 Signed-off-by: wuwl10 Reviewed-on: https://gerrit.mot.com/1791777 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- drivers/nfc/qti/nfc_common.c | 34 ++++++++++++++++++++++++++++++++++ drivers/nfc/qti/nfc_common.h | 3 +++ drivers/nfc/qti/nfc_i2c_drv.c | 3 +++ 3 files changed, 40 insertions(+) diff --git a/drivers/nfc/qti/nfc_common.c b/drivers/nfc/qti/nfc_common.c index 9b593f8bd51d..38a8578a3b6b 100644 --- a/drivers/nfc/qti/nfc_common.c +++ b/drivers/nfc/qti/nfc_common.c @@ -651,6 +651,40 @@ unsigned int nfc_ioctl_nfcc_info(struct file *filp, unsigned long arg) * * @return 0 on success, error code for failures. */ + +#ifdef CONFIG_COMPAT +long nfc_compat_dev_ioctl(struct file *pfile, unsigned int cmd, unsigned long arg) +{ + int ret = 0; + struct nfc_dev *nfc_dev = pfile->private_data; + + arg = (compat_u64)arg; + pr_debug("%s cmd = %x arg = %zx\n", __func__, cmd, arg); + + switch (cmd) { + case NFC_SET_PWR: + ret = nfc_ioctl_power_states(nfc_dev, arg); + break; + case ESE_SET_PWR: + ret = nfc_ese_pwr(nfc_dev, arg); + break; + case ESE_GET_PWR: + ret = nfc_ese_pwr(nfc_dev, ESE_POWER_STATE); + break; + case NFCC_GET_INFO: + ret = nfc_ioctl_nfcc_info(pfile, arg); + break; + case NFC_GET_PLATFORM_TYPE: + ret = nfc_dev->interface; + break; + default: + pr_err("%s bad cmd %lu\n", __func__, arg); + ret = -ENOIOCTLCMD; + } + return ret; +} +#endif + long nfc_dev_ioctl(struct file *pfile, unsigned int cmd, unsigned long arg) { int ret = 0; diff --git a/drivers/nfc/qti/nfc_common.h b/drivers/nfc/qti/nfc_common.h index 2dc31036c1e7..a4ed5348ab0d 100644 --- a/drivers/nfc/qti/nfc_common.h +++ b/drivers/nfc/qti/nfc_common.h @@ -254,6 +254,9 @@ struct nfc_dev { int nfc_dev_open(struct inode *inode, struct file *filp); int nfc_dev_close(struct inode *inode, struct file *filp); long nfc_dev_ioctl(struct file *pfile, unsigned int cmd, unsigned long arg); +#ifdef CONFIG_COMPAT +long nfc_compat_dev_ioctl(struct file *pfile, unsigned int cmd, unsigned long arg); +#endif int nfc_parse_dt(struct device *dev, struct platform_gpio *nfc_gpio, struct platform_ldo *ldo, uint8_t interface); int nfc_misc_probe(struct nfc_dev *nfc_dev, diff --git a/drivers/nfc/qti/nfc_i2c_drv.c b/drivers/nfc/qti/nfc_i2c_drv.c index fee83a9f9a2e..e5480a1afd58 100644 --- a/drivers/nfc/qti/nfc_i2c_drv.c +++ b/drivers/nfc/qti/nfc_i2c_drv.c @@ -266,6 +266,9 @@ static const struct file_operations nfc_i2c_dev_fops = { .open = nfc_dev_open, .release = nfc_dev_close, .unlocked_ioctl = nfc_dev_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = nfc_compat_dev_ioctl, +#endif }; int nfc_i2c_dev_probe(struct i2c_client *client, const struct i2c_device_id *id) From e008ef10629303ca39a7138e349780e4d67b764c Mon Sep 17 00:00:00 2001 From: Wei Wei Date: Tue, 3 Nov 2020 20:45:16 -0600 Subject: [PATCH 276/698] Revert "(CR): arm64/config: support UAS of usb storage" This reverts commit 23cf0cbef716d48c3cc0a8f8382da9c0e9e586eb. Change-Id: Ia984f65f4a69503041c0d75fb20843d16cfe38f1 Reviewed-on: https://gerrit.mot.com/1792953 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Huosheng Liao Reviewed-by: Yuecai Liu Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi.config | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi.config b/arch/arm64/configs/vendor/ext_config/moto-holi.config index e19fe201b8e0..aef6a24d0481 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi.config @@ -26,7 +26,6 @@ CONFIG_SLUB_DEBUG=y # CONFIG_SLUB_DEBUG_ON is not set # CONFIG_SLUB_DEBUG_PANIC_ON is not set CONFIG_BUG_ON_DATA_CORRUPTION=y -CONFIG_USB_UAS=y CONFIG_SCHED_STACK_END_CHECK=y CONFIG_MEDIA_USB_SUPPORT=y From b6a7ab72bd6e6547c917d5ffed9f415369e658c3 Mon Sep 17 00:00:00 2001 From: Haijian Ma Date: Wed, 4 Nov 2020 14:43:36 +0800 Subject: [PATCH 277/698] spi: disable_depth > 0 when pm runtime get sync Port the spi changes from bq-6125. when unit suspend, pm_runtime_disalbe() would be called. And then dev.power.disable_depth number will +1. And its value will be -1 when pm_runtime_enable() is called. And if spi bus want to work as soon as system resume, it will call pm_runtime_get_sync(), which would check the value of disable_depth. If its value is not 0, spi operation will fail. The sequence is as following: runtime_suspend pm_runtime_disable()-> disable_depth +1 rumtime_resume pm_runtime_eanble() -> disable_depth -1 spi_sync() pm_runtime_get_sync -> check the value of disable_depth But for sometimes, spi operation will earlier than pm_runtime_enable() called. Then spi_sync() will fail duel to non-zero disable_depth value. So we add a checking logic before pm_runtime_get_sync() to make sure disable_depth is 0. Change-Id: I673363bfd861402b5c54874137b12700ef2df14d Signed-off-by: wengjun1 Reviewed-on: https://gerrit.mot.com/1793166 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Wei Wei Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- drivers/spi/spi-msm-geni.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/spi/spi-msm-geni.c b/drivers/spi/spi-msm-geni.c index 200955a3a6db..4a20a269906e 100644 --- a/drivers/spi/spi-msm-geni.c +++ b/drivers/spi/spi-msm-geni.c @@ -1366,6 +1366,12 @@ static int spi_geni_prepare_transfer_hardware(struct spi_master *spi) "%s: Error %d pinctrl_select_state\n", __func__, ret); } + if (mas->dev->power.disable_depth > 0) { + dev_err(mas->dev, "%s:disable_depth not zero %d\n", + __func__, mas->dev->power.disable_depth); + pm_runtime_enable(mas->dev); + } + if (!mas->setup || !mas->shared_ee) { ret = pm_runtime_get_sync(mas->dev); if (ret < 0) { From 076ab2592b7f11cf348b2f4610e7bbac93dc0fae Mon Sep 17 00:00:00 2001 From: liaohj Date: Thu, 5 Nov 2020 16:21:29 +0800 Subject: [PATCH 278/698] qcom: whitelist: Add necessary api for aw882xx dlkm add "flip_open/filp_close" white list for aw882xx All of them could be found in the latest abi_gki_aarch64*.xml file. Change-Id: Ia89d6371a7c097dee12fa78dd9d5acb72e2f581b Signed-off-by: liaohj Reviewed-on: https://gerrit.mot.com/1794660 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- android/abi_gki_aarch64_qcom | 2 ++ 1 file changed, 2 insertions(+) diff --git a/android/abi_gki_aarch64_qcom b/android/abi_gki_aarch64_qcom index 28ea1091ac17..feeb451e44a6 100644 --- a/android/abi_gki_aarch64_qcom +++ b/android/abi_gki_aarch64_qcom @@ -928,6 +928,8 @@ filemap_fdatawait_range filemap_fdatawrite_range file_path + filp_close + filp_open find_last_bit find_next_bit find_next_zero_bit From 31762154d1df23ad5c842e28eb6c889a0f895ff2 Mon Sep 17 00:00:00 2001 From: mahj8 Date: Fri, 6 Nov 2020 15:17:11 +0800 Subject: [PATCH 279/698] bcl: enable charger bcl feature When SOC < 10% will mitigate CPU.For improved performance, at turbo charging scene. will not mitigate CPU. Change-Id: I593542e735c11227192367327d8aeaf51a03a06d Signed-off-by: mahj8 Reviewed-on: https://gerrit.mot.com/1795816 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- drivers/thermal/qcom/bcl_soc.c | 81 +++++++++++++++++++++++++++++++++- 1 file changed, 80 insertions(+), 1 deletion(-) diff --git a/drivers/thermal/qcom/bcl_soc.c b/drivers/thermal/qcom/bcl_soc.c index 71e04377fe78..3ba3b2be47b0 100644 --- a/drivers/thermal/qcom/bcl_soc.c +++ b/drivers/thermal/qcom/bcl_soc.c @@ -15,7 +15,7 @@ #include #include #include - +#include #include "../thermal_core.h" #define BCL_DRIVER_NAME "bcl_soc_peripheral" @@ -30,10 +30,55 @@ struct bcl_device { bool irq_enabled; struct thermal_zone_device *tz_dev; struct thermal_zone_of_device_ops ops; + int bcl_not_mitigate_icl; + struct iio_channel **ext_iio_chans; }; static struct bcl_device *bcl_perph; +enum bcl_mmi_ext_iio_channels { + SMB5_HW_CURRENT_MAX = 0, +}; + +static const char * const bcl_mmi_ext_iio_chan_name[] = { + [SMB5_HW_CURRENT_MAX] = "usb_hw_current_max", +}; + +static bool is_chan_valid(enum bcl_mmi_ext_iio_channels chan) +{ + int rc; + + if (IS_ERR(bcl_perph->ext_iio_chans[chan])) + return false; + + if (!bcl_perph->ext_iio_chans[chan]) { + bcl_perph->ext_iio_chans[chan] = iio_channel_get(bcl_perph->dev, + bcl_mmi_ext_iio_chan_name[chan]); + if (IS_ERR(bcl_perph->ext_iio_chans[chan])) { + rc = PTR_ERR(bcl_perph->ext_iio_chans[chan]); + bcl_perph->ext_iio_chans[chan] = NULL; + pr_err("Failed to get IIO channel %s, rc=%d\n", + bcl_mmi_ext_iio_chan_name[chan], rc); + return false; + } + } + + return true; +} + +int bcl_mmi_read_iio_chan(enum bcl_mmi_ext_iio_channels chan, int *val) +{ + int rc; + + if (is_chan_valid(chan)) { + rc = iio_read_channel_processed( + bcl_perph->ext_iio_chans[chan], val); + return (rc < 0) ? rc : 0; + } + + return -EINVAL; +} + static int bcl_set_soc(void *data, int low, int high) { if (high == bcl_perph->trip_temp) @@ -61,6 +106,18 @@ static int bcl_read_soc(void *data, int *val) int err = 0; *val = 0; + + if (bcl_perph->bcl_not_mitigate_icl) { + err = bcl_mmi_read_iio_chan(SMB5_HW_CURRENT_MAX, &ret.intval); + if (err) + pr_err("HW current max read error:%d\n", err); + else if ((ret.intval /1000) >= bcl_perph->bcl_not_mitigate_icl) { + pr_debug("charger current more than bcl_not_mitigate_icl %dmA\n", + bcl_perph->bcl_not_mitigate_icl); + return err; + } + } + if (!batt_psy) batt_psy = power_supply_get_by_name("battery"); if (batt_psy) { @@ -127,6 +184,18 @@ static int bcl_soc_remove(struct platform_device *pdev) return 0; } +static int bcl_mmi_init_iio_psy(struct platform_device *pdev) +{ + bcl_perph->ext_iio_chans = devm_kcalloc(bcl_perph->dev, + ARRAY_SIZE(bcl_mmi_ext_iio_chan_name), + sizeof(*bcl_perph->ext_iio_chans), + GFP_KERNEL); + if (!bcl_perph->ext_iio_chans) + return -ENOMEM; + + return 0; +} + static int bcl_soc_probe(struct platform_device *pdev) { int ret = 0; @@ -157,6 +226,16 @@ static int bcl_soc_probe(struct platform_device *pdev) bcl_perph->tz_dev = NULL; goto bcl_soc_probe_exit; } + + bcl_mmi_init_iio_psy(pdev); + + ret = of_property_read_u32(pdev->dev.of_node, + "qcom,bcl-not-mitigate-icl", + &bcl_perph->bcl_not_mitigate_icl); + if (ret < 0) { + bcl_perph->bcl_not_mitigate_icl = 0; + } + thermal_zone_device_update(bcl_perph->tz_dev, THERMAL_DEVICE_UP); schedule_work(&bcl_perph->soc_eval_work); From cc019a95ff3408a1ba70f274b78bf41668a2df5b Mon Sep 17 00:00:00 2001 From: mahj8 Date: Mon, 9 Nov 2020 14:35:17 +0800 Subject: [PATCH 280/698] qpnp-qg: Add CHARGE_NOW psy property in qpnp-qg Add charger_now property into bms psy for battery health test Change-Id: If51f2396d06cdb13c75f306c6869ead12dd11e62 Signed-off-by: mahj8 Reviewed-on: https://gerrit.mot.com/1797305 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Lu Chai Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- drivers/power/supply/qcom/qpnp-qg.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/power/supply/qcom/qpnp-qg.c b/drivers/power/supply/qcom/qpnp-qg.c index 5f9983845054..5c58952cd9c7 100644 --- a/drivers/power/supply/qcom/qpnp-qg.c +++ b/drivers/power/supply/qcom/qpnp-qg.c @@ -2717,14 +2717,19 @@ static int qg_psy_get_property(struct power_supply *psy, enum power_supply_property psp, union power_supply_propval *pval) { + struct qpnp_qg *chip = power_supply_get_drvdata(psy); + if (psp == POWER_SUPPLY_PROP_TYPE) pval->intval = POWER_SUPPLY_TYPE_MAINS; + else if (psp == POWER_SUPPLY_PROP_CHARGE_NOW) + pval->intval = chip->cl->init_cap_uah; return 0; } static enum power_supply_property qg_psy_props[] = { POWER_SUPPLY_PROP_TYPE, + POWER_SUPPLY_PROP_CHARGE_NOW, }; static const struct power_supply_desc qg_psy_desc = { From 34153b6226472f366db437a528b96de438bed324 Mon Sep 17 00:00:00 2001 From: wengjun1 Date: Mon, 9 Nov 2020 14:25:33 +0800 Subject: [PATCH 281/698] Update qcom whitelist for chipone touchscreen The "rt_mutex_lock" and "rt_mutex_unlock" functions can be found in the latest google whitelist, so update the qcom whitelist for chipone touchscreen. Change-Id: I01c538b544d130b7c0dfe6999219c9af7fd8836f Signed-off-by: wengjun1 Reviewed-on: https://gerrit.mot.com/1797282 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Jianqiu Huang Reviewed-by: Xiaojun Ji Reviewed-by: Yeqing Wang Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- android/abi_gki_aarch64_qcom | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/abi_gki_aarch64_qcom b/android/abi_gki_aarch64_qcom index feeb451e44a6..cae3af2d2d3e 100644 --- a/android/abi_gki_aarch64_qcom +++ b/android/abi_gki_aarch64_qcom @@ -2123,8 +2123,8 @@ rtc_update_irq rtc_valid_tm rt_mutex_lock - rt_mutex_trylock rt_mutex_unlock + rt_mutex_trylock rtnl_is_locked rtnl_link_register rtnl_link_unregister From 864ead901f3ffbb2c60a80ed0279006ef44621c4 Mon Sep 17 00:00:00 2001 From: wengjun1 Date: Wed, 11 Nov 2020 10:48:22 +0800 Subject: [PATCH 282/698] Revert "(CR): workaround for the error of "__symbol_put " undefined" Now we don't use touchscreen_mmi in br-4350, so this change is not necessary for us. This reverts commit 899bedf4ac94d0c1b3769787d779226d107655f6. Change-Id: I59f0ec8474350f2a796f9446c5cb9b1d77e9df9e Signed-off-by: wengjun1 Reviewed-on: https://gerrit.mot.com/1799286 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Jianqiu Huang Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- kernel/module.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/kernel/module.c b/kernel/module.c index b42faf5691c0..adceceb6c49f 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -1086,8 +1086,6 @@ void __symbol_put(const char *symbol) module_put(owner); preempt_enable(); } -/* MMI_STOPSHIP: touchscreen: export the symbol for temp rebase */ -EXPORT_SYMBOL(__symbol_put); /* Note this assumes addr is a function, which it currently always is. */ void symbol_put_addr(void *addr) @@ -2322,8 +2320,6 @@ fail: preempt_enable(); return NULL; } -/* MMI_STOPSHIP: touchscreen: export the symbol for temp rebase */ -EXPORT_SYMBOL(__symbol_get); /* * Ensure that an exported symbol [global namespace] does not already exist From da258472468dfdb0a28d71d138e96b68b256b1a8 Mon Sep 17 00:00:00 2001 From: jiayh2 Date: Thu, 12 Nov 2020 17:05:39 +0800 Subject: [PATCH 283/698] Denver remove kernel config for PASR kernel configs enabled to support PASR which can hotplug RAM banks we don't have multiple RAM slots in devices, disable this feature to avoid potential performance penalty Change-Id: I399b0e45001679c7650715600cdbbc9fb8f75476 Signed-off-by: jiayh2 Reviewed-on: https://gerrit.mot.com/1786864 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Bingqian Yang Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- .../configs/vendor/ext_config/moto-holi-denver.config | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-denver.config b/arch/arm64/configs/vendor/ext_config/moto-holi-denver.config index bc02edbfb9ea..b5ce580695ba 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-denver.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-denver.config @@ -16,6 +16,13 @@ CONFIG_DENVER_DTB=y CONFIG_FS_EPOLL_WAKEUP_DEBUG=y # CONFIG_THERMAL_STATISTICS is not set +# CONFIG_MEMORY_HOTPLUG is not set +# CONFIG_MEMORY_HOTPLUG_DEFAULT_ONLINE is not set +# CONFIG_MEMORY_HOTPLUG_MOVABLE_NODE is not set +# CONFIG_MEMORY_HOTREMOVE is not set +# CONFIG_OVERRIDE_MEMORY_LIMIT is not set +# CONFIG_HOTPLUG_SIZE_BITS is not set +# CONFIG_QCOM_MEM_OFFLINE is not set # CONFIG_TOUCHSCREEN_SYNAPTICS_TCM is not set # CONFIG_TOUCHSCREEN_SYNAPTICS_DSX is not set # CONFIG_TOUCHSCREEN_FTS is not set \ No newline at end of file From b5163438f34d2815d911204c7f3846d6556bf0a5 Mon Sep 17 00:00:00 2001 From: jiayh2 Date: Fri, 13 Nov 2020 15:59:10 +0800 Subject: [PATCH 284/698] Ibiza remove kernel config for PASR kernel configs enabled to support PASR which can hotplug RAM banks we don't have multiple RAM slots in devices, disable this feature to avoid potential performance penalty Change-Id: Ibd1d5d3837a39a1d0ce90da49b40861f128aeb2a Signed-off-by: jiayh2 Reviewed-on: https://gerrit.mot.com/1801914 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Chuanchun Zhu Reviewed-by: Huosheng Liao Reviewed-by: Bingqian Yang Submit-Approved: Jira Key --- .../arm64/configs/vendor/ext_config/moto-holi-ibiza.config | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config b/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config index c742165c27f9..a441e2248e05 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config @@ -17,3 +17,10 @@ CONFIG_IBIZA_DTB=y CONFIG_NFC_QTI_I2C=y CONFIG_FS_EPOLL_WAKEUP_DEBUG=y # CONFIG_THERMAL_STATISTICS is not set +# CONFIG_MEMORY_HOTPLUG is not set +# CONFIG_MEMORY_HOTPLUG_DEFAULT_ONLINE is not set +# CONFIG_MEMORY_HOTPLUG_MOVABLE_NODE is not set +# CONFIG_MEMORY_HOTREMOVE is not set +# CONFIG_OVERRIDE_MEMORY_LIMIT is not set +# CONFIG_HOTPLUG_SIZE_BITS is not set +# CONFIG_QCOM_MEM_OFFLINE is not set From e9b26c8a46e4d8115aa70e94b221229040f65395 Mon Sep 17 00:00:00 2001 From: mahj8 Date: Mon, 16 Nov 2020 15:20:06 +0800 Subject: [PATCH 285/698] pd: fix vbus can't reach 9V with PD charger fix vbus can't reach 9V with PD charger the return value of pd_get_pdo is 0 Change-Id: I811a94d8d81e2e09df440e04cf8c78b60e34cb16 Signed-off-by: mahj8 Reviewed-on: https://gerrit.mot.com/1803288 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- drivers/usb/pd/policy_engine.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/pd/policy_engine.c b/drivers/usb/pd/policy_engine.c index ae59318d30e0..818be0ecda61 100644 --- a/drivers/usb/pd/policy_engine.c +++ b/drivers/usb/pd/policy_engine.c @@ -4293,7 +4293,7 @@ int usbpd_select_pdo_match(struct usbpd *pd) if (pdo_pos != 0) type = PD_SRC_PDO_TYPE(pdo_pos); if (type == PD_SRC_PDO_TYPE_FIXED && - pd_get_pdo(pd, i, &pdo_max_uv, &pdo_min_uv, &pdo_ua)) { + !pd_get_pdo(pd, i, &pdo_max_uv, &pdo_min_uv, &pdo_ua)) { if (pdo_max_uv <= uv_in) { uv_diff = uv_in - pdo_max_uv; if (uv_diff < max_uv_diff) { From 71fbd43f47ed3d38f419622251119e9ea0ba3e9c Mon Sep 17 00:00:00 2001 From: chenyb1 Date: Tue, 17 Nov 2020 16:26:49 +0800 Subject: [PATCH 286/698] Thermal: Fix Thermal Compiling Error. Add " thermal_zone_device_unregister" to fix compling error. Specific for user build Change-Id: I6a872ea85ce6bb856a73b5e40dd34c72d3abb016 Reviewed-on: https://gerrit.mot.com/1804395 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Lu Chai Reviewed-by: Xiaojun Ji Reviewed-by: Hujun Liao Submit-Approved: Jira Key --- android/abi_gki_aarch64_qcom | 1 + 1 file changed, 1 insertion(+) diff --git a/android/abi_gki_aarch64_qcom b/android/abi_gki_aarch64_qcom index cae3af2d2d3e..0cd6139923db 100644 --- a/android/abi_gki_aarch64_qcom +++ b/android/abi_gki_aarch64_qcom @@ -2530,6 +2530,7 @@ thermal_cooling_device_unregister thermal_of_cooling_device_register thermal_zone_device_register + thermal_zone_device_unregister thermal_zone_device_update thermal_zone_get_temp thermal_zone_get_zone_by_name From 5aa83849c72d3f6480388910c51b696416173552 Mon Sep 17 00:00:00 2001 From: mahj8 Date: Tue, 17 Nov 2020 15:10:15 +0800 Subject: [PATCH 287/698] smb5: add dcp max current config by dts some product all sku inbox charger is 10W, so don't need config usb_dcp in vhw.xml. add dcp max current by dts to config all sku. some product which don't have 10W charger in all sku can overlay dts by mmi,usb_dcp in vhw.xml Change-Id: Ie9ddb6c47d42b039d6bfe306e1263168688dac36 Signed-off-by: mahj8 Reviewed-on: https://gerrit.mot.com/1804249 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- drivers/power/supply/qcom/qpnp-smb5.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/power/supply/qcom/qpnp-smb5.c b/drivers/power/supply/qcom/qpnp-smb5.c index 46064da22037..01f96db6d6c7 100644 --- a/drivers/power/supply/qcom/qpnp-smb5.c +++ b/drivers/power/supply/qcom/qpnp-smb5.c @@ -795,6 +795,7 @@ static int smb5_parse_sdam(struct smb5 *chip, struct device_node *node) static int smb5_parse_dt_mmi(struct smb5 *chip, struct device_node *node) { struct smb_charger *chg = &chip->chg; + struct device_node *npoint = chg->dev->of_node; struct device_node *np; const char *dcp_curr = NULL; int retval; @@ -802,6 +803,13 @@ static int smb5_parse_dt_mmi(struct smb5 *chip, struct device_node *node) chg->usb_dcp_curr_max = 0; np = of_find_node_by_path("/chosen"); + retval = of_property_read_u32(npoint, "qcom,dcp-curr-max", + &chg->usb_dcp_curr_max); + if (retval) { + chg->usb_dcp_curr_max = 1500000; + goto out; + } + if (!np) goto out; @@ -810,7 +818,6 @@ static int smb5_parse_dt_mmi(struct smb5 *chip, struct device_node *node) if ((retval == -EINVAL) || !dcp_curr) { pr_info("mmi,usb_dcp unused\n"); - of_node_put(np); goto out; } else pr_info("usb_dcp = %s\n", dcp_curr); @@ -820,9 +827,9 @@ static int smb5_parse_dt_mmi(struct smb5 *chip, struct device_node *node) else if (strstr(dcp_curr, "2A")) chg->usb_dcp_curr_max = 2000000; - of_node_put(np); - out: + if (np) + of_node_put(np); return 0; } From 55237e2db5135eb18e9e78efc23e621d1d2e6190 Mon Sep 17 00:00:00 2001 From: zhucc2 Date: Wed, 18 Nov 2020 14:36:18 +0800 Subject: [PATCH 288/698] arm64/config: remove slub debug configs on debug version. For kernel usage is higher if enbale slub debug configs, we remove them to improve the debug performance. Change-Id: I45543d406ef24c324a5ae9ba768ad809b3e23542 Reviewed-on: https://gerrit.mot.com/1805306 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Yonghui Jia Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/debug-holi.config | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/configs/vendor/ext_config/debug-holi.config b/arch/arm64/configs/vendor/ext_config/debug-holi.config index 530741083869..dd3bdae2285d 100644 --- a/arch/arm64/configs/vendor/ext_config/debug-holi.config +++ b/arch/arm64/configs/vendor/ext_config/debug-holi.config @@ -17,3 +17,5 @@ CONFIG_DEBUG_FS=y CONFIG_CFI_PERMISSIVE=y CONFIG_CPU_FREQ_STAT=y # CONFIG_EDAC_KRYO_ARM64_PANIC_ON_CE is not set +# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_SLUB_DEBUG_PANIC_ON is not set From 3b09b350364e8164c43981b8c5d7f2226635c7e7 Mon Sep 17 00:00:00 2001 From: zhucc2 Date: Fri, 20 Nov 2020 14:59:03 +0800 Subject: [PATCH 289/698] arm64/config: remove some configs on debug version For improve debug verison performance, remove some unnessary configs. If some guys need debug the special issue, need enable them at local. Change-Id: I120b4fdbd03fc72d61825c708897b90d2ef38b2e Reviewed-on: https://gerrit.mot.com/1807723 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Jun Weng Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- .../configs/vendor/ext_config/debug-holi.config | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/arch/arm64/configs/vendor/ext_config/debug-holi.config b/arch/arm64/configs/vendor/ext_config/debug-holi.config index dd3bdae2285d..b304c322a92e 100644 --- a/arch/arm64/configs/vendor/ext_config/debug-holi.config +++ b/arch/arm64/configs/vendor/ext_config/debug-holi.config @@ -19,3 +19,20 @@ CONFIG_CPU_FREQ_STAT=y # CONFIG_EDAC_KRYO_ARM64_PANIC_ON_CE is not set # CONFIG_SLUB_DEBUG_ON is not set # CONFIG_SLUB_DEBUG_PANIC_ON is not set +# CONFIG_CORESIGHT is not set +# CONFIG_DEBUG_PAGEALLOC is not set +# CONFIG_DEBUG_PAGEALLOC_ENABLE_DEFAULT is not set +# CONFIG_DEBUG_PANIC_ON_OOM is not set +# CONFIG_DEBUG_PREEMPT is not set +# CONFIG_TOUCHSCREEN_FTS is not set +# CONFIG_TOUCHSCREEN_SYNAPTICS_DSX is not set +# CONFIG_TOUCHSCREEN_SYNAPTICS_TCM is not set +# CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_CORE is not set +# CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_TOUCH is not set +# CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_DEVICE is not set +# CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_TESTING is not set +# CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_REFLASH is not set +# CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_RECOVERY is not set +# CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_ZEROFLASH is not set +# CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_DIAGNOSTICS is not set +# CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_I2C is not set From 4630d357240a34c5ac6276ce167d33c79f45c7a2 Mon Sep 17 00:00:00 2001 From: liuyc20 Date: Mon, 23 Nov 2020 14:44:04 +0800 Subject: [PATCH 290/698] configure cfi permissve for user build As CFI will panic at moto_usbnet module in user build, so configure CFI permissive for moto_usbnet in factory mode. <4>[ 36.691491] Workqueue: ipv6_addrconf addrconf_dad_work <4>[ 36.696653] pstate: 80c00005 (Nzcv daif +PAN +UAO) <4>[ 36.701478] pc : __cfi_check_fail+0x14/0x18 [moto_f_usbnet] <4>[ 36.707080] lr : __cfi_check+0x340/0x390 [moto_f_usbnet] Change-Id: I66990320048ee2150afb03f0b97a61806a908224 Signed-off-by: liuyc20 Reviewed-on: https://gerrit.mot.com/1808698 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi.config b/arch/arm64/configs/vendor/ext_config/moto-holi.config index aef6a24d0481..df9dad2b7e62 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi.config @@ -30,3 +30,4 @@ CONFIG_SCHED_STACK_END_CHECK=y CONFIG_MEDIA_USB_SUPPORT=y CONFIG_USB_VIDEO_CLASS=y +CONFIG_CFI_PERMISSIVE=y From 5e978368a54bd8b3cad7c687c268653cef8f60a1 Mon Sep 17 00:00:00 2001 From: jixj Date: Tue, 24 Nov 2020 10:42:11 +0800 Subject: [PATCH 291/698] power/reset: store extra reset info in panic_prep_restart() On sm4350 R,the priority of do_msm_restart is 200,the priority of restart_wdog_handler is 255. when kernel panic happens, restart_wdog_handler will be invoked first and trigger a watchdog, but do_msm_restart will not be invoked so bootloader can not read reset info. The panic notifier (panic_prep_restart) still invoke, so store the extra reset info for kernel panic Change-Id: Ia263ebfb2eda4424555ddb937239325048ea846f Reviewed-on: https://gerrit.mot.com/1809656 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- drivers/power/reset/msm-poweroff.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/power/reset/msm-poweroff.c b/drivers/power/reset/msm-poweroff.c index f61b1a219bd7..91c8360a5e6a 100644 --- a/drivers/power/reset/msm-poweroff.c +++ b/drivers/power/reset/msm-poweroff.c @@ -132,6 +132,10 @@ static int panic_prep_restart(struct notifier_block *this, unsigned long event, void *ptr) { in_panic = 1; + __raw_writel(0x77665505, restart_reason); + qpnp_pon_store_extra_reset_info(RESET_EXTRA_PANIC_REASON, + RESET_EXTRA_PANIC_REASON); + pr_info("panic_prep_restart store extra reset info\n"); return NOTIFY_DONE; } From c1649eb8f90c73539cc8bf6ea6b3dd6d4b0cb21e Mon Sep 17 00:00:00 2001 From: jixj Date: Mon, 23 Nov 2020 17:00:31 +0800 Subject: [PATCH 292/698] power/reset: Fix "hw_warmreset" can't be set Fix https://gerrit.mot.com/1778586 propagation error. The "reason" is default PON_RESTART_REASON_UNKNOWN (0), At the end, QC will set restart reg with "reason" so this reg will be override to 0 Change-Id: I3a0092edb6a29a1d3edd9fa79428115b7c590ffb Reviewed-on: https://gerrit.mot.com/1808858 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- drivers/power/reset/msm-poweroff.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/power/reset/msm-poweroff.c b/drivers/power/reset/msm-poweroff.c index 91c8360a5e6a..2ea1865d448b 100644 --- a/drivers/power/reset/msm-poweroff.c +++ b/drivers/power/reset/msm-poweroff.c @@ -513,8 +513,7 @@ static void msm_restart_prepare(const char *cmd) /* force cold reboot */ qpnp_pon_system_pwr_off(PON_POWER_OFF_HARD_RESET); } else if (!strncmp(cmd, "hw_warmreset", 13)) { - qpnp_pon_set_restart_reason( - PON_RESTART_REASON_HW_WARMRESET); + reason = PON_RESTART_REASON_HW_WARMRESET; qpnp_pon_system_pwr_off(PON_POWER_OFF_WARM_RESET); pr_info("set system hw warmreset mode\n"); } else if (!strncmp(cmd, "post-hw_warmreset", 17)) { From 5b298f511c18b7f61bcbf69d7fa95889f1ed49ab Mon Sep 17 00:00:00 2001 From: liuwang2 Date: Thu, 26 Nov 2020 11:09:23 +0800 Subject: [PATCH 293/698] ion: dmabuf improve debugfs Improvements made to ION to add an additional debugfs file to display allocation/reference information for all ION buffers. rb tree was deleted becaused of unused, add it back to track ion buffer alloc. Migrated from (CR): https://gerrit.mot.com/#/c/1535657/ https://gerrit.mot.com/#/c/1535658/ Change-Id: I1e42d3dac61d4fc856ba8d749cfd2123e40529d9 Signed-off-by: liuwang2 Reviewed-on: https://gerrit.mot.com/1811670 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Zhilong Wang Reviewed-by: Ji Zhao Reviewed-by: Bolei Shang Reviewed-by: Zilong Zhang Reviewed-by: Dawei Wang Reviewed-by: Zhenxin Xi Submit-Approved: Jira Key --- drivers/dma-buf/dma-buf.c | 4 ++ drivers/staging/android/ion/ion.c | 56 +++++++++++++++++++++++ drivers/staging/android/ion/ion_buffer.c | 37 +++++++++++++++ drivers/staging/android/ion/ion_dma_buf.c | 25 ++++++++++ drivers/staging/android/ion/ion_private.h | 4 ++ include/linux/dma-buf.h | 10 ++++ include/linux/ion.h | 11 ++++- include/uapi/linux/dma-buf.h | 1 + 8 files changed, 147 insertions(+), 1 deletion(-) diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c index d60b7ced21cb..1630f66dc6d4 100644 --- a/drivers/dma-buf/dma-buf.c +++ b/drivers/dma-buf/dma-buf.c @@ -434,6 +434,10 @@ static long dma_buf_ioctl(struct file *file, return ret; + case DMA_BUF_IOCTL_IMPORT_BUF_ADD_BY_MOTO: + dmabuf->ops->import_buf_add_by_moto(dmabuf); + return 0; + case DMA_BUF_SET_NAME_A: case DMA_BUF_SET_NAME_B: return dma_buf_set_name(dmabuf, (const char __user *)arg); diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 61d2a8cbf894..d86e54f1f912 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -481,6 +481,54 @@ static int ion_init_sysfs(void) return 0; } +static int ion_debug_allbufs_show(struct seq_file *s, void *unused) +{ + struct ion_device *dev = s->private; + struct rb_node *n; + int i; + unsigned long total_len = 0; + + seq_printf(s, "%16.s %16.s %12.s %12.s %20.s %s\n", "heap", + "buffer", "size", "ref cnt", "allocator", "references"); + + down_read(&dev->lock); + mutex_lock(&dev->buffer_lock); + for (n = rb_first(&dev->buffers); n; n = rb_next(n)) { + struct ion_buffer *buf = rb_entry(n, struct ion_buffer, node); + int buf_refcount = buf->ref_cnt; + total_len += buf->size; + seq_printf(s, "%16.s %16pK %12.x %12.d %20.d %s", + buf->heap->name, buf, (int)buf->size, + buf_refcount, buf->pid, ""); + + for(i = 0; i < buf->ref_cnt && i < MAX_CLIENTS_NUM; i++) + seq_printf(s, "%u, ", buf->client_pids[i]); + + seq_puts(s, "\n"); + } + + if (s->file && s->file->f_path.dentry + && !strcmp(s->file->f_path.dentry->d_iname, "check_all_bufs_total")) + seq_printf(s, "%16.s %s is: %lld(%lld KB)\n", + "heap", "total size", total_len, total_len/1024); + + mutex_unlock(&dev->buffer_lock); + up_read(&dev->lock); + return 0; +} + +static int ion_debug_allbufs_open(struct inode *inode, struct file *file) +{ + return single_open(file, ion_debug_allbufs_show, inode->i_private); +} + +static const struct file_operations debug_allbufs_fops = { + .open = ion_debug_allbufs_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + static int ion_device_create(void) { struct ion_device *idev; @@ -506,10 +554,18 @@ static int ion_device_create(void) goto err_sysfs; } + idev->buffers = RB_ROOT; + mutex_init(&idev->buffer_lock); idev->debug_root = debugfs_create_dir("ion", NULL); init_rwsem(&idev->lock); plist_head_init(&idev->heaps); internal_dev = idev; + + debugfs_create_file("check_all_bufs", 0664, idev->debug_root, idev, + &debug_allbufs_fops); + debugfs_create_file("check_all_bufs_total", 0664, idev->debug_root, idev, + &debug_allbufs_fops); + return 0; err_sysfs: diff --git a/drivers/staging/android/ion/ion_buffer.c b/drivers/staging/android/ion/ion_buffer.c index eb0e4d285a57..e63944935b6b 100644 --- a/drivers/staging/android/ion/ion_buffer.c +++ b/drivers/staging/android/ion/ion_buffer.c @@ -31,6 +31,31 @@ static void track_buffer_destroyed(struct ion_buffer *buffer) trace_ion_stat(buffer->sg_table, -buffer->size, total); } +/* this function should only be called while dev->buffer_lock is held */ +static void ion_buffer_add(struct ion_device *dev, struct ion_buffer *buffer) +{ + struct rb_node **p = &dev->buffers.rb_node; + struct rb_node *parent = NULL; + struct ion_buffer *entry; + + while (*p) { + parent = *p; + entry = rb_entry(parent, struct ion_buffer, node); + + if (buffer < entry) { + p = &(*p)->rb_left; + } else if (buffer > entry) { + p = &(*p)->rb_right; + } else { + pr_err("%s: buffer already found.", __func__); + BUG(); + } + } + + rb_link_node(&buffer->node, parent, p); + rb_insert_color(&buffer->node, &dev->buffers); +} + /* this function should only be called while dev->lock is held */ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap, struct ion_device *dev, @@ -84,6 +109,14 @@ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap, INIT_LIST_HEAD(&buffer->attachments); mutex_init(&buffer->lock); track_buffer_created(buffer); + + mutex_lock(&dev->buffer_lock); + ion_buffer_add(dev, buffer); + mutex_unlock(&dev->buffer_lock); + + buffer->pid = task_pid_nr(current->group_leader); + buffer->client_pids[buffer->ref_cnt++] = buffer->pid; + return buffer; err1: @@ -240,6 +273,10 @@ int ion_buffer_destroy(struct ion_device *dev, struct ion_buffer *buffer) return -EINVAL; } + mutex_lock(&dev->buffer_lock); + rb_erase(&buffer->node, &dev->buffers); + mutex_unlock(&dev->buffer_lock); + heap = buffer->heap; track_buffer_destroyed(buffer); diff --git a/drivers/staging/android/ion/ion_dma_buf.c b/drivers/staging/android/ion/ion_dma_buf.c index b7295fee31c7..dd9189228113 100644 --- a/drivers/staging/android/ion/ion_dma_buf.c +++ b/drivers/staging/android/ion/ion_dma_buf.c @@ -259,6 +259,28 @@ static void *ion_dma_buf_map(struct dma_buf *dmabuf, unsigned long offset) return ion_buffer_kmap_get(buffer) + offset * PAGE_SIZE; } +static int ion_dma_buf_import_buf_add_by_moto(struct dma_buf *dmabuf) +{ + struct ion_buffer *buffer = dmabuf->priv; + int i; + int found_pid = 0; + pid_t task_pid = task_pid_nr(current->group_leader); + + mutex_lock(&buffer->lock); + for (i = 0; i < buffer->ref_cnt && i < MAX_CLIENTS_NUM; i++) { + if (buffer->client_pids[i] == task_pid) { + found_pid = 1; + break; + } + } + if (!found_pid && buffer->ref_cnt < MAX_CLIENTS_NUM) + buffer->client_pids[buffer->ref_cnt++] = task_pid; + + mutex_unlock(&buffer->lock); + + return 0; +} + static int ion_dma_buf_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma) { struct ion_buffer *buffer = dmabuf->priv; @@ -278,6 +300,8 @@ static int ion_dma_buf_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma) mutex_unlock(&buffer->lock); } + ion_dma_buf_import_buf_add_by_moto(dmabuf); + if (ret) pr_err("%s: failure mapping buffer to userspace\n", __func__); @@ -353,6 +377,7 @@ static const struct dma_buf_ops dma_buf_ops = { .vmap = ion_dma_buf_vmap, .vunmap = ion_dma_buf_vunmap, .get_flags = ion_dma_buf_get_flags, + .import_buf_add_by_moto = ion_dma_buf_import_buf_add_by_moto, }; struct dma_buf *ion_dmabuf_alloc(struct ion_device *dev, size_t len, diff --git a/drivers/staging/android/ion/ion_private.h b/drivers/staging/android/ion/ion_private.h index db4e90683f4c..0ff6d5ccfa55 100644 --- a/drivers/staging/android/ion/ion_private.h +++ b/drivers/staging/android/ion/ion_private.h @@ -20,6 +20,8 @@ /** * struct ion_device - the metadata of the ion device node + * @buffers: an rb tree of all the existing buffers + * @buffer_lock: lock protecting the tree of buffers * @dev: the actual misc device * @lock: rwsem protecting the tree of heaps, heap_bitmap and * clients @@ -32,6 +34,8 @@ struct ion_device { struct plist_head heaps; struct dentry *debug_root; int heap_cnt; + struct rb_root buffers; + struct mutex buffer_lock; }; /* ion_buffer manipulators */ diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h index accce2b534e7..db780978805a 100644 --- a/include/linux/dma-buf.h +++ b/include/linux/dma-buf.h @@ -348,6 +348,16 @@ struct dma_buf_ops { * will be populated with the buffer's flags. */ int (*get_flags)(struct dma_buf *dmabuf, unsigned long *flags); + + /** + * @import_buf_add_by_moto: + * + * This is called by gr_ion_alloc added by Motorola + * + * Returns: + * always return 0 + */ + int (*import_buf_add_by_moto)(struct dma_buf *); }; /** diff --git a/include/linux/ion.h b/include/linux/ion.h index 80c6fdeb4822..ce9c9692d22f 100644 --- a/include/linux/ion.h +++ b/include/linux/ion.h @@ -20,8 +20,11 @@ #include #include +#define MAX_CLIENTS_NUM 16 + /** * struct ion_buffer - metadata for a particular buffer + * @node: node in the ion_device buffers tree * @list: element in list of deferred freeable buffers * @heap: back pointer to the heap the buffer came from * @flags: buffer specific flags @@ -36,7 +39,10 @@ * @attachments: list of devices attached to this buffer */ struct ion_buffer { - struct list_head list; + union { + struct rb_node node; + struct list_head list; + }; struct ion_heap *heap; unsigned long flags; unsigned long private_flags; @@ -47,6 +53,9 @@ struct ion_buffer { void *vaddr; struct sg_table *sg_table; struct list_head attachments; + pid_t pid; + pid_t client_pids[MAX_CLIENTS_NUM]; + int ref_cnt; }; /** diff --git a/include/uapi/linux/dma-buf.h b/include/uapi/linux/dma-buf.h index f76d11725c6c..83e118dd84f3 100644 --- a/include/uapi/linux/dma-buf.h +++ b/include/uapi/linux/dma-buf.h @@ -39,6 +39,7 @@ struct dma_buf_sync { #define DMA_BUF_BASE 'b' #define DMA_BUF_IOCTL_SYNC _IOW(DMA_BUF_BASE, 0, struct dma_buf_sync) +#define DMA_BUF_IOCTL_IMPORT_BUF_ADD_BY_MOTO _IO(DMA_BUF_BASE, 0xCC) /* 32/64bitness of this uapi was botched in android, there's no difference * between them in actual uapi, they're just different numbers. From 1fbec1a378b9b873eb36d7786b2447a4c27a6068 Mon Sep 17 00:00:00 2001 From: mahj8 Date: Thu, 3 Dec 2020 11:20:40 +0800 Subject: [PATCH 294/698] arch/config: disable CONFIG_STATIC_USERMODEHELPER disable CONFIG_STATIC_USERMODEHELPER in userdebug and factory version for orderly_poweroff api can work. Change-Id: Ic71a8471cfd4228d32556f898eaecbbc6ec40b17 Signed-off-by: mahj8 Reviewed-on: https://gerrit.mot.com/1817533 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Xiaojun Ji Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/debug-holi.config | 1 + arch/arm64/configs/vendor/ext_config/factory-holi.config | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/arm64/configs/vendor/ext_config/debug-holi.config b/arch/arm64/configs/vendor/ext_config/debug-holi.config index b304c322a92e..1ece44d83334 100644 --- a/arch/arm64/configs/vendor/ext_config/debug-holi.config +++ b/arch/arm64/configs/vendor/ext_config/debug-holi.config @@ -36,3 +36,4 @@ CONFIG_CPU_FREQ_STAT=y # CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_ZEROFLASH is not set # CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_DIAGNOSTICS is not set # CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_I2C is not set +# CONFIG_STATIC_USERMODEHELPER is not set diff --git a/arch/arm64/configs/vendor/ext_config/factory-holi.config b/arch/arm64/configs/vendor/ext_config/factory-holi.config index 3c8927499698..edb127862aa0 100644 --- a/arch/arm64/configs/vendor/ext_config/factory-holi.config +++ b/arch/arm64/configs/vendor/ext_config/factory-holi.config @@ -18,3 +18,4 @@ CONFIG_SERIAL_MSM_GENI_CONSOLE=y CONFIG_QCOM_RTB=y CONFIG_QCOM_RTB_QGKI=y CONFIG_QCOM_RTB_SEPARATE_CPUS=y +# CONFIG_STATIC_USERMODEHELPER is not set From 4100bb2c012e213952aa84c47c2113ccf3d5cad7 Mon Sep 17 00:00:00 2001 From: mahj8 Date: Thu, 3 Dec 2020 10:25:44 +0800 Subject: [PATCH 295/698] gki: add orderly_poweroff api for mmi-smbcharger-iio add orderly_poweroff api for mmi-smbcharger-iio LKM Change-Id: I65873ce599f651cce2350131606166fa8427f39b Signed-off-by: mahj8 Reviewed-on: https://gerrit.mot.com/1817449 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Xiaojun Ji Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- android/abi_gki_aarch64_qcom | 1 + 1 file changed, 1 insertion(+) diff --git a/android/abi_gki_aarch64_qcom b/android/abi_gki_aarch64_qcom index 0cd6139923db..0f570e744ca7 100644 --- a/android/abi_gki_aarch64_qcom +++ b/android/abi_gki_aarch64_qcom @@ -1706,6 +1706,7 @@ of_usb_host_tpl_support oops_in_progress override_creds + orderly_poweroff pagecache_get_page panic panic_notifier_list From cc220ff68a216e4ed6eaa1220032ead9d1f09532 Mon Sep 17 00:00:00 2001 From: zhucc2 Date: Thu, 3 Dec 2020 14:29:16 +0800 Subject: [PATCH 296/698] arm64/config: enlarge kernel log buffer size. CONFIG_LOG_BUF_SHIFT is default set as 17 =>128KB, however, for sm4350, 128KB is not enough, after bringup, early bringup kermel log is overwrite, we have to enlarge the valuse to 18=>256KB, to make kernel bringup log complete. Change-Id: Icae1058520b73fc0b979efa5977b5bdce73604a0 Reviewed-on: https://gerrit.mot.com/1817725 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/debug-holi.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/vendor/ext_config/debug-holi.config b/arch/arm64/configs/vendor/ext_config/debug-holi.config index 1ece44d83334..dabd9876d6c3 100644 --- a/arch/arm64/configs/vendor/ext_config/debug-holi.config +++ b/arch/arm64/configs/vendor/ext_config/debug-holi.config @@ -37,3 +37,4 @@ CONFIG_CPU_FREQ_STAT=y # CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_DIAGNOSTICS is not set # CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_I2C is not set # CONFIG_STATIC_USERMODEHELPER is not set +CONFIG_LOG_BUF_SHIFT=18 From 4a8c8cd617ce563fb75119d29b971fd90e798972 Mon Sep 17 00:00:00 2001 From: liuyc20 Date: Fri, 4 Dec 2020 09:59:59 +0800 Subject: [PATCH 297/698] Revert "(CR): configure cfi permissve for user build" This reverts commit f371f58ee5306333560fb67bfdec51145059087a. correct usb_ether_xmit API return value type Mot-CRs-fixed:(CR) Change-Id: Ifa420b2e0a3ef17d1900be1b45790c9d8599a160 Reviewed-on: https://gerrit.mot.com/1818887 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Yonghua Yan Reviewed-by: Xiaojun Ji Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/debug-holi.config | 1 - arch/arm64/configs/vendor/ext_config/factory-holi.config | 1 - arch/arm64/configs/vendor/ext_config/moto-holi.config | 1 - 3 files changed, 3 deletions(-) diff --git a/arch/arm64/configs/vendor/ext_config/debug-holi.config b/arch/arm64/configs/vendor/ext_config/debug-holi.config index dabd9876d6c3..26bda5b0d09d 100644 --- a/arch/arm64/configs/vendor/ext_config/debug-holi.config +++ b/arch/arm64/configs/vendor/ext_config/debug-holi.config @@ -14,7 +14,6 @@ # being set as expected. # CONFIG_DEBUG_FS=y -CONFIG_CFI_PERMISSIVE=y CONFIG_CPU_FREQ_STAT=y # CONFIG_EDAC_KRYO_ARM64_PANIC_ON_CE is not set # CONFIG_SLUB_DEBUG_ON is not set diff --git a/arch/arm64/configs/vendor/ext_config/factory-holi.config b/arch/arm64/configs/vendor/ext_config/factory-holi.config index edb127862aa0..1ae7affe3eec 100644 --- a/arch/arm64/configs/vendor/ext_config/factory-holi.config +++ b/arch/arm64/configs/vendor/ext_config/factory-holi.config @@ -13,7 +13,6 @@ # You can check the .config file to verify that your configuration option is # being set as expected. # -CONFIG_CFI_PERMISSIVE=y CONFIG_SERIAL_MSM_GENI_CONSOLE=y CONFIG_QCOM_RTB=y CONFIG_QCOM_RTB_QGKI=y diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi.config b/arch/arm64/configs/vendor/ext_config/moto-holi.config index df9dad2b7e62..aef6a24d0481 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi.config @@ -30,4 +30,3 @@ CONFIG_SCHED_STACK_END_CHECK=y CONFIG_MEDIA_USB_SUPPORT=y CONFIG_USB_VIDEO_CLASS=y -CONFIG_CFI_PERMISSIVE=y From 9f2edd3674c2f54a31d837dcfebd11e9717de643 Mon Sep 17 00:00:00 2001 From: Yonghui Jia Date: Wed, 9 Dec 2020 19:49:08 -0600 Subject: [PATCH 298/698] Revert "(CR): Denver remove kernel config for PASR" Remove PASR will impact GKI So revert the changes This reverts commit 5e0fa830adf5aa819732004a1e30dfd31e024c42. Change-Id: Ie06043ef33418c59daf881cc2296522b57f9b824 Reviewed-on: https://gerrit.mot.com/1823951 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Reviewed-by: Chuanchun Zhu Tested-by: Jira Key Reviewed-by: Hujun Liao Reviewed-by: Xiaojun Ji Submit-Approved: Jira Key --- .../configs/vendor/ext_config/moto-holi-denver.config | 7 ------- 1 file changed, 7 deletions(-) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-denver.config b/arch/arm64/configs/vendor/ext_config/moto-holi-denver.config index b5ce580695ba..bc02edbfb9ea 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-denver.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-denver.config @@ -16,13 +16,6 @@ CONFIG_DENVER_DTB=y CONFIG_FS_EPOLL_WAKEUP_DEBUG=y # CONFIG_THERMAL_STATISTICS is not set -# CONFIG_MEMORY_HOTPLUG is not set -# CONFIG_MEMORY_HOTPLUG_DEFAULT_ONLINE is not set -# CONFIG_MEMORY_HOTPLUG_MOVABLE_NODE is not set -# CONFIG_MEMORY_HOTREMOVE is not set -# CONFIG_OVERRIDE_MEMORY_LIMIT is not set -# CONFIG_HOTPLUG_SIZE_BITS is not set -# CONFIG_QCOM_MEM_OFFLINE is not set # CONFIG_TOUCHSCREEN_SYNAPTICS_TCM is not set # CONFIG_TOUCHSCREEN_SYNAPTICS_DSX is not set # CONFIG_TOUCHSCREEN_FTS is not set \ No newline at end of file From 1ed2acbc2cbafbf057a170bdd7b3c152728e7929 Mon Sep 17 00:00:00 2001 From: Yonghui Jia Date: Wed, 9 Dec 2020 19:49:28 -0600 Subject: [PATCH 299/698] Revert "(CR): Ibiza remove kernel config for PASR" Remove PASR will impact GKI So revert the changes This reverts commit 8cd7ac5016d01623b92c01e2485640c155938330. Change-Id: I587650c4b5fdb7474c98fa0754e51d4fa917b24f Reviewed-on: https://gerrit.mot.com/1823952 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Reviewed-by: Chuanchun Zhu Tested-by: Jira Key Reviewed-by: Hujun Liao Reviewed-by: Xiaojun Ji Submit-Approved: Jira Key --- .../arm64/configs/vendor/ext_config/moto-holi-ibiza.config | 7 ------- 1 file changed, 7 deletions(-) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config b/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config index a441e2248e05..c742165c27f9 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config @@ -17,10 +17,3 @@ CONFIG_IBIZA_DTB=y CONFIG_NFC_QTI_I2C=y CONFIG_FS_EPOLL_WAKEUP_DEBUG=y # CONFIG_THERMAL_STATISTICS is not set -# CONFIG_MEMORY_HOTPLUG is not set -# CONFIG_MEMORY_HOTPLUG_DEFAULT_ONLINE is not set -# CONFIG_MEMORY_HOTPLUG_MOVABLE_NODE is not set -# CONFIG_MEMORY_HOTREMOVE is not set -# CONFIG_OVERRIDE_MEMORY_LIMIT is not set -# CONFIG_HOTPLUG_SIZE_BITS is not set -# CONFIG_QCOM_MEM_OFFLINE is not set From c6852b254e0792edef8ef2f2c82b99b17d8cb100 Mon Sep 17 00:00:00 2001 From: wangxf14 Date: Thu, 10 Dec 2020 15:02:35 +0800 Subject: [PATCH 300/698] drivers: rtc: add debug log into rtc module According to the guideline from Qualcomm support, I add RTC log in kernel so that we can trace the issue from unexpected RTC reset Change-Id: Ia26f18ecebcf7627df167dd146582717c8e3414c Signed-off-by: wangxf14 Reviewed-on: https://gerrit.mot.com/1824238 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Haijian Ma Reviewed-by: Hujun Liao Submit-Approved: Jira Key --- drivers/rtc/rtc-pm8xxx.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/rtc/rtc-pm8xxx.c b/drivers/rtc/rtc-pm8xxx.c index 2904b2ad5851..567981e5ab1f 100644 --- a/drivers/rtc/rtc-pm8xxx.c +++ b/drivers/rtc/rtc-pm8xxx.c @@ -63,6 +63,13 @@ struct pm8xxx_rtc { spinlock_t ctrl_reg_lock; }; +/* MMI_STOPSHIP BSP: Debug unexpected RTC reset */ + +#ifdef dev_dbg +#undef dev_dbg +#define dev_dbg dev_err +#endif + /* * Steps to write the RTC registers. * 1. Disable alarm if enabled. @@ -358,6 +365,9 @@ static irqreturn_t pm8xxx_alarm_trigger(int irq, void *dev_id) rtc_update_irq(rtc_dd->rtc, 1, RTC_IRQF | RTC_AF); + dev_dbg(rtc_dd->rtc_dev, + "motorola debug rtc : enter %s\n", __func__); + spin_lock_irqsave(&rtc_dd->ctrl_reg_lock, irq_flags); /* Clear the alarm enable bit */ From e4ecf9469c04c17a1b2b5c206d53e1977c33da0b Mon Sep 17 00:00:00 2001 From: Chuanchun Zhu Date: Thu, 10 Dec 2020 04:19:33 -0600 Subject: [PATCH 301/698] Revert "(CR): mmc/sd: Add sys entry to read card speed" This reverts commit ed5f0747d0723d8fd5ac93aea375d503642a5537. Change-Id: I9ea66b3e6d66098466e0a4bad547ae9935452943 Mot-CRs-fixed:(CR) [3.312547] init: Failed to insmod '/lib/modules/5.4-gki/cqhci.ko' with args '' [3.319900] init: LoadWithAliases was unable to load /lib/modules/5.4-gki/cqhci.ko [3.327496] init: LoadWithAliases was unable to load sdhci_msm [3.333348] init: moto LoadListedModules failed sdhci_msm Change-Id: I9ea66b3e6d66098466e0a4bad547ae9935452943 Reviewed-on: https://gerrit.mot.com/1824484 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Xiaojun Ji Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- drivers/mmc/core/sd.c | 33 ++++++--------------------------- include/linux/mmc/card.h | 2 -- 2 files changed, 6 insertions(+), 29 deletions(-) diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index 1df11ba30aec..9607ff927ea4 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -52,10 +52,6 @@ static const unsigned int sd_au_size[] = { SZ_16M / 512, (SZ_16M + SZ_8M) / 512, SZ_32M / 512, SZ_64M / 512, }; -static const unsigned int sd_speed_class[] = { - 0, 2, 4, 6, 10, -}; - #define UNSTUFF_BITS(resp,start,size) \ ({ \ const int __size = size; \ @@ -301,12 +297,6 @@ static int mmc_read_ssr(struct mmc_card *card) card->erase_arg = (card->scr.sda_specx && discard_support) ? SD_DISCARD_ARG : SD_ERASE_ARG; - card->ssr.speed_class = sd_speed_class[UNSTUFF_BITS(card->raw_ssr, 440 - 384, 8)]; - card->ssr.uhs_speed_grade = UNSTUFF_BITS(card->raw_ssr, 396 - 384, 4); - pr_info("%s: card speed is C%d. uhs grade is %d\n", - mmc_hostname(card->host), - card->ssr.speed_class, - card->ssr.uhs_speed_grade); return 0; } @@ -449,34 +439,28 @@ static void sd_update_bus_speed_mode(struct mmc_card *card) */ if (!mmc_host_uhs(card->host)) { card->sd_bus_speed = 0; - pr_info("%s: not UHS\n", mmc_hostname(card->host)); return; } if ((card->host->caps & MMC_CAP_UHS_SDR104) && (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_SDR104)) { - card->sd_bus_speed = UHS_SDR104_BUS_SPEED; - pr_info("%s: selected SDR104\n", mmc_hostname(card->host)); + card->sd_bus_speed = UHS_SDR104_BUS_SPEED; } else if ((card->host->caps & MMC_CAP_UHS_DDR50) && (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_DDR50)) { - card->sd_bus_speed = UHS_DDR50_BUS_SPEED; - pr_info("%s: selected DDR50\n", mmc_hostname(card->host)); + card->sd_bus_speed = UHS_DDR50_BUS_SPEED; } else if ((card->host->caps & (MMC_CAP_UHS_SDR104 | MMC_CAP_UHS_SDR50)) && (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_SDR50)) { - card->sd_bus_speed = UHS_SDR50_BUS_SPEED; - pr_info("%s: selected SDR50\n", mmc_hostname(card->host)); + card->sd_bus_speed = UHS_SDR50_BUS_SPEED; } else if ((card->host->caps & (MMC_CAP_UHS_SDR104 | MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR25)) && (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_SDR25)) { - card->sd_bus_speed = UHS_SDR25_BUS_SPEED; - pr_info("%s: selected SDR25\n", mmc_hostname(card->host)); + card->sd_bus_speed = UHS_SDR25_BUS_SPEED; } else if ((card->host->caps & (MMC_CAP_UHS_SDR104 | MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR25 | MMC_CAP_UHS_SDR12)) && (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_SDR12)) { - card->sd_bus_speed = UHS_SDR12_BUS_SPEED; - pr_info("%s: selected SDR12\n", mmc_hostname(card->host)); + card->sd_bus_speed = UHS_SDR12_BUS_SPEED; } } @@ -765,8 +749,7 @@ MMC_DEV_ATTR(oemid, "0x%04x\n", card->cid.oemid); MMC_DEV_ATTR(serial, "0x%08x\n", card->cid.serial); MMC_DEV_ATTR(ocr, "0x%08x\n", card->ocr); MMC_DEV_ATTR(rca, "0x%04x\n", card->rca); -MMC_DEV_ATTR(speed_class, "%u\n", card->ssr.speed_class); -MMC_DEV_ATTR(uhs_speed_grade, "%u\n", card->ssr.uhs_speed_grade); + static ssize_t mmc_dsr_show(struct device *dev, struct device_attribute *attr, @@ -801,8 +784,6 @@ static struct attribute *sd_std_attrs[] = { &dev_attr_ocr.attr, &dev_attr_rca.attr, &dev_attr_dsr.attr, - &dev_attr_speed_class.attr, - &dev_attr_uhs_speed_grade.attr, NULL, }; ATTRIBUTE_GROUPS(sd_std); @@ -1144,12 +1125,10 @@ retry: /* Initialization sequence for UHS-I cards */ if (rocr & SD_ROCR_S18A && mmc_host_uhs(host)) { - pr_info("%s: card is UHS\n", mmc_hostname(card->host)); err = mmc_sd_init_uhs_card(card); if (err) goto free_card; } else { - pr_info("%s: card is legacy\n", mmc_hostname(card->host)); /* * Attempt to change to high-speed (if supported) */ diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index aff5a1f93735..5bdf6d70e0a9 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h @@ -154,8 +154,6 @@ struct sd_ssr { unsigned int au; /* In sectors */ unsigned int erase_timeout; /* In milliseconds */ unsigned int erase_offset; /* In milliseconds */ - unsigned int speed_class; - unsigned int uhs_speed_grade; }; struct sd_switch_caps { From d49939332d0672f50ac65e6f038d5f41040603df Mon Sep 17 00:00:00 2001 From: jixj Date: Thu, 10 Dec 2020 15:58:40 +0800 Subject: [PATCH 302/698] ion: dmabuf improve debugfs it will cause ion related ABI CRC mismatch, wrap CONFIG_DEBUG_FS for them Change-Id: I162143205847323eaa0fbb52e7b337607e57b07a Signed-off-by: jixj Reviewed-on: https://gerrit.mot.com/1825354 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- drivers/dma-buf/dma-buf.c | 3 ++- drivers/staging/android/ion/ion.c | 6 ++++++ drivers/staging/android/ion/ion_buffer.c | 6 ++++++ drivers/staging/android/ion/ion_dma_buf.c | 6 ++++++ drivers/staging/android/ion/ion_private.h | 2 ++ include/linux/dma-buf.h | 2 ++ include/linux/ion.h | 8 ++++++++ 7 files changed, 32 insertions(+), 1 deletion(-) diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c index 1630f66dc6d4..9b774277b75e 100644 --- a/drivers/dma-buf/dma-buf.c +++ b/drivers/dma-buf/dma-buf.c @@ -433,10 +433,11 @@ static long dma_buf_ioctl(struct file *file, ret = dma_buf_begin_cpu_access(dmabuf, direction); return ret; - + #ifdef CONFIG_DEBUG_FS case DMA_BUF_IOCTL_IMPORT_BUF_ADD_BY_MOTO: dmabuf->ops->import_buf_add_by_moto(dmabuf); return 0; + #endif case DMA_BUF_SET_NAME_A: case DMA_BUF_SET_NAME_B: diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index d86e54f1f912..ce974bdfc7d0 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -481,6 +481,7 @@ static int ion_init_sysfs(void) return 0; } +#ifdef CONFIG_DEBUG_FS static int ion_debug_allbufs_show(struct seq_file *s, void *unused) { struct ion_device *dev = s->private; @@ -528,6 +529,7 @@ static const struct file_operations debug_allbufs_fops = { .llseek = seq_lseek, .release = single_release, }; +#endif static int ion_device_create(void) { @@ -554,17 +556,21 @@ static int ion_device_create(void) goto err_sysfs; } + #ifdef CONFIG_DEBUG_FS idev->buffers = RB_ROOT; mutex_init(&idev->buffer_lock); + #endif idev->debug_root = debugfs_create_dir("ion", NULL); init_rwsem(&idev->lock); plist_head_init(&idev->heaps); internal_dev = idev; + #ifdef CONFIG_DEBUG_FS debugfs_create_file("check_all_bufs", 0664, idev->debug_root, idev, &debug_allbufs_fops); debugfs_create_file("check_all_bufs_total", 0664, idev->debug_root, idev, &debug_allbufs_fops); + #endif return 0; diff --git a/drivers/staging/android/ion/ion_buffer.c b/drivers/staging/android/ion/ion_buffer.c index e63944935b6b..acfff735ff4e 100644 --- a/drivers/staging/android/ion/ion_buffer.c +++ b/drivers/staging/android/ion/ion_buffer.c @@ -31,6 +31,7 @@ static void track_buffer_destroyed(struct ion_buffer *buffer) trace_ion_stat(buffer->sg_table, -buffer->size, total); } +#ifdef CONFIG_DEBUG_FS /* this function should only be called while dev->buffer_lock is held */ static void ion_buffer_add(struct ion_device *dev, struct ion_buffer *buffer) { @@ -55,6 +56,7 @@ static void ion_buffer_add(struct ion_device *dev, struct ion_buffer *buffer) rb_link_node(&buffer->node, parent, p); rb_insert_color(&buffer->node, &dev->buffers); } +#endif /* this function should only be called while dev->lock is held */ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap, @@ -110,12 +112,14 @@ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap, mutex_init(&buffer->lock); track_buffer_created(buffer); + #ifdef CONFIG_DEBUG_FS mutex_lock(&dev->buffer_lock); ion_buffer_add(dev, buffer); mutex_unlock(&dev->buffer_lock); buffer->pid = task_pid_nr(current->group_leader); buffer->client_pids[buffer->ref_cnt++] = buffer->pid; + #endif return buffer; @@ -273,9 +277,11 @@ int ion_buffer_destroy(struct ion_device *dev, struct ion_buffer *buffer) return -EINVAL; } + #ifdef CONFIG_DEBUG_FS mutex_lock(&dev->buffer_lock); rb_erase(&buffer->node, &dev->buffers); mutex_unlock(&dev->buffer_lock); + #endif heap = buffer->heap; track_buffer_destroyed(buffer); diff --git a/drivers/staging/android/ion/ion_dma_buf.c b/drivers/staging/android/ion/ion_dma_buf.c index dd9189228113..ece61efe4583 100644 --- a/drivers/staging/android/ion/ion_dma_buf.c +++ b/drivers/staging/android/ion/ion_dma_buf.c @@ -259,6 +259,7 @@ static void *ion_dma_buf_map(struct dma_buf *dmabuf, unsigned long offset) return ion_buffer_kmap_get(buffer) + offset * PAGE_SIZE; } +#ifdef CONFIG_DEBUG_FS static int ion_dma_buf_import_buf_add_by_moto(struct dma_buf *dmabuf) { struct ion_buffer *buffer = dmabuf->priv; @@ -280,6 +281,7 @@ static int ion_dma_buf_import_buf_add_by_moto(struct dma_buf *dmabuf) return 0; } +#endif static int ion_dma_buf_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma) { @@ -300,7 +302,9 @@ static int ion_dma_buf_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma) mutex_unlock(&buffer->lock); } + #ifdef CONFIG_DEBUG_FS ion_dma_buf_import_buf_add_by_moto(dmabuf); + #endif if (ret) pr_err("%s: failure mapping buffer to userspace\n", __func__); @@ -377,7 +381,9 @@ static const struct dma_buf_ops dma_buf_ops = { .vmap = ion_dma_buf_vmap, .vunmap = ion_dma_buf_vunmap, .get_flags = ion_dma_buf_get_flags, + #ifdef CONFIG_DEBUG_FS .import_buf_add_by_moto = ion_dma_buf_import_buf_add_by_moto, + #endif }; struct dma_buf *ion_dmabuf_alloc(struct ion_device *dev, size_t len, diff --git a/drivers/staging/android/ion/ion_private.h b/drivers/staging/android/ion/ion_private.h index 0ff6d5ccfa55..9c2aa833f3ee 100644 --- a/drivers/staging/android/ion/ion_private.h +++ b/drivers/staging/android/ion/ion_private.h @@ -34,8 +34,10 @@ struct ion_device { struct plist_head heaps; struct dentry *debug_root; int heap_cnt; + #ifdef CONFIG_DEBUG_FS struct rb_root buffers; struct mutex buffer_lock; + #endif }; /* ion_buffer manipulators */ diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h index db780978805a..dee33939822c 100644 --- a/include/linux/dma-buf.h +++ b/include/linux/dma-buf.h @@ -357,7 +357,9 @@ struct dma_buf_ops { * Returns: * always return 0 */ + #ifdef CONFIG_DEBUG_FS int (*import_buf_add_by_moto)(struct dma_buf *); + #endif }; /** diff --git a/include/linux/ion.h b/include/linux/ion.h index ce9c9692d22f..8767a3ae0e38 100644 --- a/include/linux/ion.h +++ b/include/linux/ion.h @@ -20,7 +20,9 @@ #include #include +#ifdef CONFIG_DEBUG_FS #define MAX_CLIENTS_NUM 16 +#endif /** * struct ion_buffer - metadata for a particular buffer @@ -39,10 +41,14 @@ * @attachments: list of devices attached to this buffer */ struct ion_buffer { + #ifdef CONFIG_DEBUG_FS union { struct rb_node node; struct list_head list; }; + #else + struct list_head list; + #endif struct ion_heap *heap; unsigned long flags; unsigned long private_flags; @@ -53,9 +59,11 @@ struct ion_buffer { void *vaddr; struct sg_table *sg_table; struct list_head attachments; + #ifdef CONFIG_DEBUG_FS pid_t pid; pid_t client_pids[MAX_CLIENTS_NUM]; int ref_cnt; + #endif }; /** From 303f09a9d10e8219705025252b27556f1263048d Mon Sep 17 00:00:00 2001 From: mahj8 Date: Wed, 9 Dec 2020 13:57:27 +0800 Subject: [PATCH 303/698] kernel: export some api symbol of pmic vote Export some pmic-voter interfaces for dlkm usage as well as create access functions that are exported for dlkm to manipulate the struct. charging DLKM need some api of pmic vote, but pmic_voter.o is included by both qpnp-smb5-main.ko and qcom-qpnp-qg.ko, KMI don't allow double export one function in two DLKM modules. Change-Id: I56f96b663d9ee2228d91bd2efc6977a13f270de4 Signed-off-by: mahj8 Reviewed-on: https://gerrit.mot.com/1822930 Reviewed-by: Huosheng Liao SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Haijian Ma Submit-Approved: Jira Key --- drivers/power/supply/qcom/Makefile | 2 +- drivers/power/supply/qcom/mmi-pmic-voter.c | 60 ++++++++++++++++++++++ include/linux/mmi-pmic-voter.h | 19 +++++++ 3 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 drivers/power/supply/qcom/mmi-pmic-voter.c create mode 100644 include/linux/mmi-pmic-voter.h diff --git a/drivers/power/supply/qcom/Makefile b/drivers/power/supply/qcom/Makefile index f08dd44c9dba..8f632f9d3ca0 100644 --- a/drivers/power/supply/qcom/Makefile +++ b/drivers/power/supply/qcom/Makefile @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-only obj-$(CONFIG_QPNP_SMB5) += qpnp-smb5-main.o -qpnp-smb5-main-y += step-chg-jeita.o battery.o qpnp-smb5.o smb5-lib.o pmic-voter.o storm-watch.o schgm-flash.o battery-profile-loader.o smb5-iio.o +qpnp-smb5-main-y += step-chg-jeita.o battery.o qpnp-smb5.o smb5-lib.o pmic-voter.o mmi-pmic-voter.o storm-watch.o schgm-flash.o battery-profile-loader.o smb5-iio.o obj-$(CONFIG_QPNP_QG) += qcom-qpnp-qg.o qcom-qpnp-qg-y += qpnp-qg.o battery-profile-loader.o pmic-voter.o qg-util.o qg-soc.o qg-sdam.o qg-battery-profile.o qg-profile-lib.o fg-alg.o obj-$(CONFIG_SMB1398_CHARGER) += qcom-smb1398-charger.o diff --git a/drivers/power/supply/qcom/mmi-pmic-voter.c b/drivers/power/supply/qcom/mmi-pmic-voter.c new file mode 100644 index 000000000000..cac27fa884f4 --- /dev/null +++ b/drivers/power/supply/qcom/mmi-pmic-voter.c @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2015-2017, 2019-2020, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include + +int mmi_get_effective_result(struct votable *votable) +{ + if(votable) + return get_effective_result(votable); + + return -EINVAL; +} +EXPORT_SYMBOL(mmi_get_effective_result); + +int mmi_vote(struct votable *votable, const char *client_str, bool enabled, int val) +{ + if(votable) + return vote(votable, client_str, enabled, val); + + return -EINVAL; +} +EXPORT_SYMBOL(mmi_vote); + +int mmi_rerun_election(struct votable *votable) +{ + if(votable) + return rerun_election(votable); + + return -EINVAL; +} +EXPORT_SYMBOL(mmi_rerun_election); + +struct votable *mmi_find_votable(const char *name) +{ + return find_votable(name); +} +EXPORT_SYMBOL(mmi_find_votable); + +int mmi_pmic_vote_force_val_set(struct votable *votable, u32 val) +{ + return pmic_vote_force_val_set(votable, val); +} +EXPORT_SYMBOL(mmi_pmic_vote_force_val_set); + +int mmi_pmic_vote_force_active_get(struct votable *votable, u64 *val) +{ + return pmic_vote_force_active_get(votable, val); +} +EXPORT_SYMBOL(mmi_pmic_vote_force_active_get); + +int mmi_pmic_vote_force_active_set(struct votable *votable, u64 val) +{ + return pmic_vote_force_active_set(votable, val); +} +EXPORT_SYMBOL(mmi_pmic_vote_force_active_set); + diff --git a/include/linux/mmi-pmic-voter.h b/include/linux/mmi-pmic-voter.h new file mode 100644 index 000000000000..2879839600cc --- /dev/null +++ b/include/linux/mmi-pmic-voter.h @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2015-2017, 2019-2020, The Linux Foundation. All rights reserved. + */ + + #ifndef __MMI_PMIC_VOTER_H +#define __MMI_PMIC_VOTER_H + +#include + +int mmi_get_effective_result(struct votable *votable); +int mmi_vote(struct votable *votable, const char *client_str, bool enabled, int val); +int mmi_rerun_election(struct votable *votable); +struct votable *mmi_find_votable(const char *name); +int mmi_pmic_vote_force_val_set(struct votable *votable, u32 val); +int mmi_pmic_vote_force_active_get(struct votable *votable, u64 *val); +int mmi_pmic_vote_force_active_set(struct votable *votable, u64 val); + +#endif /* __MMI_PMIC_VOTER_H */ From 73a0d9455bd4f427758a15a39d1d1a00540423c3 Mon Sep 17 00:00:00 2001 From: mahj8 Date: Wed, 9 Dec 2020 17:19:35 +0800 Subject: [PATCH 304/698] kernel: remove export symbol in pmic-voter.c Because GKI, pmic-voter.o is included by both qcom-qpnp-qg.ko and qpnp-smb5-main.ko, so can't export symbol in pmic-voter.c Change-Id: I3c9266531de4a4e2461e872bade0bd7dfcaa0eec Signed-off-by: mahj8 Reviewed-on: https://gerrit.mot.com/1822938 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- drivers/power/supply/qcom/pmic-voter.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/power/supply/qcom/pmic-voter.c b/drivers/power/supply/qcom/pmic-voter.c index 438ad026f30d..257771842183 100644 --- a/drivers/power/supply/qcom/pmic-voter.c +++ b/drivers/power/supply/qcom/pmic-voter.c @@ -340,7 +340,6 @@ int get_effective_result(struct votable *votable) unlock_votable(votable); return value; } -EXPORT_SYMBOL(get_effective_result); /** * get_effective_client() - @@ -499,7 +498,6 @@ out: unlock_votable(votable); return rc; } -EXPORT_SYMBOL(vote); /** * vote_override() - @@ -573,7 +571,6 @@ int rerun_election(struct votable *votable) unlock_votable(votable); return rc; } -EXPORT_SYMBOL(rerun_election); struct votable *find_votable(const char *name) { @@ -602,7 +599,6 @@ out: else return NULL; } -EXPORT_SYMBOL(find_votable); static int force_active_get(void *data, u64 *val) { @@ -657,7 +653,6 @@ int pmic_vote_force_val_set(struct votable *votable, u32 val) { return -EINVAL; } -EXPORT_SYMBOL(pmic_vote_force_val_set); int pmic_vote_force_active_get(struct votable *votable, u64 *val) { if(votable) @@ -665,7 +660,6 @@ int pmic_vote_force_active_get(struct votable *votable, u64 *val) { return -EINVAL; } -EXPORT_SYMBOL(pmic_vote_force_active_get); int pmic_vote_force_active_set(struct votable *votable, u64 val) { if(votable) @@ -673,7 +667,6 @@ int pmic_vote_force_active_set(struct votable *votable, u64 val) { return -EINVAL; } -EXPORT_SYMBOL(pmic_vote_force_active_set); static int show_votable_clients(struct seq_file *m, void *data) { From f7c3400a6454217472c19021b1e78aa1fb7e0404 Mon Sep 17 00:00:00 2001 From: mahj8 Date: Fri, 11 Dec 2020 13:48:22 +0800 Subject: [PATCH 305/698] QG: qg prob must after rtc prob qg use alarm timer, so qg must prob after rtc prob. when qg can't get rtc dev, return -517 to retry. Change-Id: I36603856536505c52151d8ef7d685b4ccc3e96e6 Signed-off-by: mahj8 Reviewed-on: https://gerrit.mot.com/1825304 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- drivers/power/supply/qcom/qpnp-qg.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/power/supply/qcom/qpnp-qg.c b/drivers/power/supply/qcom/qpnp-qg.c index 5c58952cd9c7..91f91a43dd57 100644 --- a/drivers/power/supply/qcom/qpnp-qg.c +++ b/drivers/power/supply/qcom/qpnp-qg.c @@ -4710,6 +4710,10 @@ static int qpnp_qg_probe(struct platform_device *pdev) struct iio_dev *indio_dev; struct qg_config *config; + if (!alarmtimer_get_rtcdev()) { + pr_err("Failed:qpnp qg probe failed, wait rtc prob\n"); + return -EPROBE_DEFER; + } indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*chip)); if (!indio_dev) return -ENOMEM; From 517749f7668becad06eb9e86ea284d9c02b0c4a3 Mon Sep 17 00:00:00 2001 From: wangxf14 Date: Fri, 18 Dec 2020 16:47:04 +0800 Subject: [PATCH 306/698] drivers: rtc: revert debug log from rtc module According to debug, denver's unexpected RTC reset was caused by PMIC issue. So I rever the monitor change. This reverts commit 2a62d1dc1ccb40b698b33d4cff83f8cdf3d4c95c. Change-Id: I6ef1049ccdfd32b1f12df3aef748c5755a469a64 Reviewed-on: https://gerrit.mot.com/1831952 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- drivers/rtc/rtc-pm8xxx.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/drivers/rtc/rtc-pm8xxx.c b/drivers/rtc/rtc-pm8xxx.c index 567981e5ab1f..2904b2ad5851 100644 --- a/drivers/rtc/rtc-pm8xxx.c +++ b/drivers/rtc/rtc-pm8xxx.c @@ -63,13 +63,6 @@ struct pm8xxx_rtc { spinlock_t ctrl_reg_lock; }; -/* MMI_STOPSHIP BSP: Debug unexpected RTC reset */ - -#ifdef dev_dbg -#undef dev_dbg -#define dev_dbg dev_err -#endif - /* * Steps to write the RTC registers. * 1. Disable alarm if enabled. @@ -365,9 +358,6 @@ static irqreturn_t pm8xxx_alarm_trigger(int irq, void *dev_id) rtc_update_irq(rtc_dd->rtc, 1, RTC_IRQF | RTC_AF); - dev_dbg(rtc_dd->rtc_dev, - "motorola debug rtc : enter %s\n", __func__); - spin_lock_irqsave(&rtc_dd->ctrl_reg_lock, irq_flags); /* Clear the alarm enable bit */ From 56a85f8a0da0364cc0750689c5878174816f3e2c Mon Sep 17 00:00:00 2001 From: chailu1 Date: Thu, 24 Dec 2020 20:38:03 +0800 Subject: [PATCH 307/698] smb5-lib: Update USB ICL for USB phy speed Override the SDP current if it needs to increase for SDP USB2.0 500mA or USB3.0 900mA. Porting from (CR) Change-Id: Ib0136a2674e8f9ac6e7e5646a82052971a4bbf08 Reviewed-on: https://gerrit.mot.com/1836523 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Haijian Ma Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- drivers/power/supply/qcom/smb5-lib.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/power/supply/qcom/smb5-lib.c b/drivers/power/supply/qcom/smb5-lib.c index aa256e484e28..c75e1e091e40 100644 --- a/drivers/power/supply/qcom/smb5-lib.c +++ b/drivers/power/supply/qcom/smb5-lib.c @@ -5950,7 +5950,11 @@ static void update_sw_icl_max(struct smb_charger *chg, int val) /* rp-std or legacy, USB BC 1.2 */ switch (val) { case POWER_SUPPLY_TYPE_USB: - vote(chg->usb_icl_votable, USB_PSY_VOTER, true, SDP_CURRENT_UA); + if (get_client_vote(chg->usb_icl_votable, + USB_PSY_VOTER) < SDP_CURRENT_UA) { + vote(chg->usb_icl_votable, USB_PSY_VOTER, true, + SDP_CURRENT_UA); + } vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, false, 0); break; case POWER_SUPPLY_TYPE_USB_CDP: From 7555c913a700e75402239224002fd58797d56d11 Mon Sep 17 00:00:00 2001 From: duqiu2 Date: Fri, 8 Jan 2021 15:25:47 +0800 Subject: [PATCH 308/698] wisl: ibiza: Modify nfc driver to ko module for GKI issue GKI image should not support nfc. Nfc dirver is built to our kernel. And nfc can't work after flashing GKI. So we change the nfc dirver as a ko module. Change-Id: I602e308fb636695aa6a4969341324bae11dca385 Signed-off-by: duqiu2 Reviewed-on: https://gerrit.mot.com/1846765 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Bin Liu Reviewed-by: Weilong Wu Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config b/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config index c742165c27f9..832db8c7008f 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config @@ -14,6 +14,6 @@ # being set as expected. # CONFIG_IBIZA_DTB=y -CONFIG_NFC_QTI_I2C=y +# CONFIG_NFC_QTI_I2C is not set CONFIG_FS_EPOLL_WAKEUP_DEBUG=y # CONFIG_THERMAL_STATISTICS is not set From cf0e6955f7b8a8cc9b5e9cf9954c6df08015f8b3 Mon Sep 17 00:00:00 2001 From: mahj8 Date: Mon, 11 Jan 2021 12:43:31 +0800 Subject: [PATCH 309/698] qg: add bms voltage ocv prop node add bms voltage ocv prop node for battery parameter test Change-Id: I2956fe82c95311d7d76f408cda8295dc93bd3784 Signed-off-by: mahj8 Reviewed-on: https://gerrit.mot.com/1848075 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Lu Chai Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- drivers/power/supply/qcom/qpnp-qg.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/power/supply/qcom/qpnp-qg.c b/drivers/power/supply/qcom/qpnp-qg.c index 91f91a43dd57..42f6b5f3d4a9 100644 --- a/drivers/power/supply/qcom/qpnp-qg.c +++ b/drivers/power/supply/qcom/qpnp-qg.c @@ -2718,18 +2718,22 @@ static int qg_psy_get_property(struct power_supply *psy, union power_supply_propval *pval) { struct qpnp_qg *chip = power_supply_get_drvdata(psy); + int rc = 0; if (psp == POWER_SUPPLY_PROP_TYPE) pval->intval = POWER_SUPPLY_TYPE_MAINS; else if (psp == POWER_SUPPLY_PROP_CHARGE_NOW) pval->intval = chip->cl->init_cap_uah; + else if (psp == POWER_SUPPLY_PROP_VOLTAGE_OCV) + rc = qg_sdam_read(SDAM_OCV_UV, &pval->intval); - return 0; + return rc; } static enum power_supply_property qg_psy_props[] = { POWER_SUPPLY_PROP_TYPE, POWER_SUPPLY_PROP_CHARGE_NOW, + POWER_SUPPLY_PROP_VOLTAGE_OCV, }; static const struct power_supply_desc qg_psy_desc = { From 45cfb22658158e0cfda040cea5c8fa2245ae19d6 Mon Sep 17 00:00:00 2001 From: chailu1 Date: Wed, 13 Jan 2021 13:26:31 +0800 Subject: [PATCH 310/698] charge: modify charge done condition by mmi charge full mmi charge decide charge terminal current. So modify charge done condition by mmi charge status. Otherwise could not got correct charge done status. Change-Id: I3f41582518bbb83bca9f5519a65f7ce311835b91 Reviewed-on: https://gerrit.mot.com/1850451 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Haijian Ma Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- drivers/power/supply/qcom/smb5-lib.c | 31 +++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/drivers/power/supply/qcom/smb5-lib.c b/drivers/power/supply/qcom/smb5-lib.c index c75e1e091e40..b17f5b356c74 100644 --- a/drivers/power/supply/qcom/smb5-lib.c +++ b/drivers/power/supply/qcom/smb5-lib.c @@ -2436,6 +2436,32 @@ int smblib_get_prop_batt_iterm(struct smb_charger *chg, return rc; } +static bool is_mmi_charge_full(struct smb_charger *chg) +{ int rc = 0; + union power_supply_propval prop = {0, }; + static struct power_supply *mmi_batt_psy = NULL; + + if (!mmi_batt_psy) { + mmi_batt_psy = power_supply_get_by_name("battery"); + if (!mmi_batt_psy) { + smblib_err(chg, "Couldn't get mmi batt prop\n"); + return false; + } + } + + rc = power_supply_get_property(mmi_batt_psy, + POWER_SUPPLY_PROP_STATUS, &prop); + if (rc < 0) { + smblib_err(chg, "Couldn't get mmi batt status, rc=%d\n", rc); + return false; + } + + if (POWER_SUPPLY_STATUS_FULL == prop.intval) + return true; + else + return false; +} + int smblib_get_prop_batt_charge_done(struct smb_charger *chg, int *val) { @@ -2451,6 +2477,9 @@ int smblib_get_prop_batt_charge_done(struct smb_charger *chg, stat = stat & BATTERY_CHARGER_STATUS_MASK; *val = (stat == TERMINATE_CHARGE); + + if (is_mmi_charge_full(chg)) + *val = true; return 0; } @@ -5273,7 +5302,7 @@ static void smblib_eval_chg_termination(struct smb_charger *chg, u8 batt_status) * battery. Trigger the charge termination WA once charging is completed * to prevent overcharing. */ - if ((batt_status == TERMINATE_CHARGE) && (pval.intval == 100) && + if (((batt_status == TERMINATE_CHARGE) || is_mmi_charge_full(chg)) && (pval.intval == 100) && (ktime_to_ms(alarm_expires_remaining(/* alarm not pending */ &chg->chg_termination_alarm)) <= 0)) { chg->cc_soc_ref = 0; From 41dca8df83bfdbf3138f8c1dd5ac99c036060fab Mon Sep 17 00:00:00 2001 From: jiayh2 Date: Wed, 20 Jan 2021 19:22:20 +0800 Subject: [PATCH 311/698] enable zram writeback kconfig on SM4350 Enable CONFIG_ZRAM_WRITEBACK config This config allow zram writeback Change-Id: I089985d2f82478e37ad85a5d65149b03c4254885 Reviewed-on: https://gerrit.mot.com/1856194 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Zhizhong Ge Reviewed-by: Zhangqing Huang Reviewed-by: Zhenxin Xi Reviewed-by: Bingqian Yang Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi.config b/arch/arm64/configs/vendor/ext_config/moto-holi.config index aef6a24d0481..1e6ec5bf06d3 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi.config @@ -30,3 +30,4 @@ CONFIG_SCHED_STACK_END_CHECK=y CONFIG_MEDIA_USB_SUPPORT=y CONFIG_USB_VIDEO_CLASS=y +CONFIG_ZRAM_WRITEBACK=y From cefa3020041166c38b1d488292b0d1f42d48391b Mon Sep 17 00:00:00 2001 From: huangzq2 Date: Wed, 17 Jun 2020 13:55:18 +0800 Subject: [PATCH 312/698] disable watermark boost Disable watermark boost on kernel 5.4 As it is not working fine Change-Id: I7f13f763382f1a54616079bc8258997c7f732d91 Signed-off-by: huangzq2 Reviewed-on: https://gerrit.mot.com/1625704 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key (cherry picked from commit d391f5c240aa5d5bb196c6b4c1e21c17b46f069a) Reviewed-on: https://gerrit.mot.com/1630007 Reviewed-by: Debora Raimundo Reviewed-by: Bingqian Yang Reviewed-by: Zhenxin Xi Reviewed-on: https://gerrit.mot.com/1783219 Reviewed-by: Yonghui Jia Reviewed-by: Zhizhong Ge --- mm/page_alloc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index cdf8931732de..7d51ecf3504a 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -334,7 +334,8 @@ int user_min_free_kbytes = -1; */ int watermark_boost_factor __read_mostly; #else -int watermark_boost_factor __read_mostly = 15000; +/* Moto huangzq2: Disable watermark boost as it's not working fine on kernel 4.19 */ +int watermark_boost_factor __read_mostly = 0; #endif int watermark_scale_factor = 10; From 7dd7895691d3d818c120a8ebea1d91a53515d626 Mon Sep 17 00:00:00 2001 From: fuxm1 Date: Tue, 2 Feb 2021 19:59:26 +0800 Subject: [PATCH 313/698] set max_timeout_counter to 0 for large card do BLKDISCARD Remark: vold doformat() will call ioctl(BLKDISCARD) before unmount this blocked sdhci layer for current driver. So, set max_timeout_counter to 0 to ensure larger discard size by always setting max_busy_timeout to zero. the change is from temp patch drop by QC SR:05069564 next QC drop will include the formal patch. that time we can drop this commit. Change-Id: I2950b42c01e04bd9cfb9a2a739d00cd35da800f3 Signed-off-by: fuxm1 Reviewed-on: https://gerrit.mot.com/1868453 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Chuanchun Zhu Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- drivers/mmc/host/sdhci-msm.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c index 91cc197d5e20..b12c3dd8607e 100644 --- a/drivers/mmc/host/sdhci-msm.c +++ b/drivers/mmc/host/sdhci-msm.c @@ -1717,11 +1717,11 @@ static void sdhci_msm_set_uhs_signaling(struct sdhci_host *host, /* * Ensure larger discard size by always setting max_busy_timeout to zero. * This will always return max_busy_timeout as zero to the sdhci layer. - */ +*/ -static unsigned int sdhci_msm_get_max_timeout_count(struct sdhci_host *host) -{ - return 0; +static unsigned int sdhci_msm_get_max_timeout_count(struct sdhci_host +*host) { + return 0; } #define MAX_PROP_SIZE 32 @@ -3564,6 +3564,7 @@ static const struct sdhci_ops sdhci_msm_ops = { .set_bus_width = sdhci_set_bus_width, .set_uhs_signaling = sdhci_msm_set_uhs_signaling, .get_max_timeout_count = sdhci_msm_get_max_timeout_count, + #if defined(CONFIG_SDC_QTI) .dump_vendor_regs = sdhci_msm_dump_vendor_regs, #endif From 445dbcd415007f799ac1fb03b13b1aa0d9f5a694 Mon Sep 17 00:00:00 2001 From: Yonghui Jia Date: Sun, 7 Feb 2021 21:27:39 -0600 Subject: [PATCH 314/698] Revert "(CR): enable zram writeback kconfig on SM4350" Reason: zram-writeback will make 3 side effects 1. Swapcached too large 2. May cause CTS fail 3. May cause panic This reverts commit db753c431b0b778e4f1824efe79718b5e3864839. Change-Id: I61c6d2eb0222d8bd4d749971bdf5ccaacee854ab Reviewed-on: https://gerrit.mot.com/1873703 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Zhizhong Ge Reviewed-by: Bingqian Yang Reviewed-by: Zhenxin Xi Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi.config | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi.config b/arch/arm64/configs/vendor/ext_config/moto-holi.config index 1e6ec5bf06d3..aef6a24d0481 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi.config @@ -30,4 +30,3 @@ CONFIG_SCHED_STACK_END_CHECK=y CONFIG_MEDIA_USB_SUPPORT=y CONFIG_USB_VIDEO_CLASS=y -CONFIG_ZRAM_WRITEBACK=y From 617a48518991848704fcace21d21a9c9e6d6138a Mon Sep 17 00:00:00 2001 From: wangyq13 Date: Sun, 7 Feb 2021 22:25:40 +0800 Subject: [PATCH 315/698] qcom-wled: disable cabc only when adjust to low brightness Disable cabc only when adjust to low brightnss. Don't disable cabc when screen off/on, this causes big voltage issue on pm6150l/7150l. Change-Id: I510ea8d1e3de1cee1a612fec6a08d50792b8b0af Signed-off-by: wangyq13 Reviewed-on: https://gerrit.mot.com/1873482 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Hua Tan Submit-Approved: Jira Key --- drivers/video/backlight/qcom-spmi-wled.c | 28 +++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/drivers/video/backlight/qcom-spmi-wled.c b/drivers/video/backlight/qcom-spmi-wled.c index 5ecbc9aeb10f..8489d1b2567a 100644 --- a/drivers/video/backlight/qcom-spmi-wled.c +++ b/drivers/video/backlight/qcom-spmi-wled.c @@ -300,6 +300,7 @@ struct wled { u32 leds_per_string; u32 exp_map[EXP_DIMMING_TABLE_SIZE]; bool low_bl_force_cabc_disable; + bool only_low_bl_force_cabc_disable; struct low_bl_config low_bl_cfg; bool bl_step_up_enable; struct bl_step_config bl_step_cfg; @@ -584,6 +585,23 @@ static int wled_update_status(struct backlight_device *bl) } } + if (wled->only_low_bl_force_cabc_disable && wled->brightness) { + if (brightness < wled->low_bl_cfg.low_bl_threshold) { + brightness = brightness * wled->low_bl_cfg.low_bl_remap_percent/100; + if (!wled->cabc_disabled) { + wled->cabc_config(wled, false); + wled->cabc_disabled = true; + pr_info("under low brightness(%d), will disable cabc\n", brightness); + } + + } + else if ((wled->brightness < wled->low_bl_cfg.low_bl_threshold) && (wled->cabc_disabled)){ + wled->cabc_disabled = false; + wled->cabc_config(wled, true); + pr_info("exit low brightness(%d), will enable cabc\n", brightness); + } + } + if (wled->bl_step_up_enable) { rc = wled_set_brightness_step(wled, brightness); if (rc < 0) { @@ -660,6 +678,11 @@ static int wled_update_status(struct backlight_device *bl) wled->cabc_disabled = true; pr_info("disable wled cabc\n"); } + if (wled->only_low_bl_force_cabc_disable && wled->cabc_disabled ) { + wled->cabc_disabled = false; + wled->cabc_config(wled, true); + pr_info("screen off, enable wled cabc\n"); + } rc = wled_module_enable(wled, brightness); if (rc < 0) { pr_err("wled disable failed rc:%d\n", rc); @@ -1317,8 +1340,10 @@ static int parse_low_bl_config(struct wled *wled) if (of_property_read_bool(dev->of_node, "mmi,low-bl-force-cabc-disable")) wled->low_bl_force_cabc_disable = true; + if (of_property_read_bool(dev->of_node, "mmi,only-low-bl-force-cabc-disable")) + wled->only_low_bl_force_cabc_disable = true; - if (wled->low_bl_force_cabc_disable) { + if (wled->low_bl_force_cabc_disable || wled->only_low_bl_force_cabc_disable) { of_property_read_u32(dev->of_node, "mmi,low-bl-threshold", &val); wled->low_bl_cfg.low_bl_threshold = val; @@ -1399,6 +1424,7 @@ static int wled5_setup(struct wled *wled) return rc; wled->low_bl_force_cabc_disable = false; + wled->only_low_bl_force_cabc_disable = false; if (wled->cfg.cabc_sel) parse_low_bl_config(wled); /* Enable one of the modulators A or B based on mod_sel */ From a9db7a28439310aab7e4940de719fdcd69e88034 Mon Sep 17 00:00:00 2001 From: wangyq13 Date: Thu, 28 Jan 2021 11:25:58 +0800 Subject: [PATCH 316/698] defconfig: holi: enable coresight configs for qdss defconfig/holi-debug: Enable coresight configs for qdss. Change-Id: I0d779a9fbd9c093d57c6f49862b41359912d321d Signed-off-by: wangyq13 Reviewed-on: https://gerrit.mot.com/1863643 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Hongshu Lou Reviewed-by: Yonghui Jia Reviewed-by: Zhenxin Xi Submit-Approved: Jira Key --- .../configs/vendor/ext_config/debug-holi.config | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arch/arm64/configs/vendor/ext_config/debug-holi.config b/arch/arm64/configs/vendor/ext_config/debug-holi.config index 26bda5b0d09d..7de99ef290b7 100644 --- a/arch/arm64/configs/vendor/ext_config/debug-holi.config +++ b/arch/arm64/configs/vendor/ext_config/debug-holi.config @@ -37,3 +37,15 @@ CONFIG_CPU_FREQ_STAT=y # CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_I2C is not set # CONFIG_STATIC_USERMODEHELPER is not set CONFIG_LOG_BUF_SHIFT=18 +CONFIG_CORESIGHT=y +CONFIG_CORESIGHT_LINK_AND_SINK_TMC=y +CONFIG_CORESIGHT_DYNAMIC_REPLICATOR=y +CONFIG_CORESIGHT_STM=y +CONFIG_CORESIGHT_CTI=y +CONFIG_CORESIGHT_CTI_SAVE_DISABLE=y +CONFIG_CORESIGHT_TPDA=y +CONFIG_CORESIGHT_TPDM=y +CONFIG_CORESIGHT_HWEVENT=y +CONFIG_CORESIGHT_DUMMY=y +CONFIG_CORESIGHT_REMOTE_ETM=y +CONFIG_CORESIGHT_TGU=y From f559241762d565cb758da2f2cf6bcee30e188fe3 Mon Sep 17 00:00:00 2001 From: zhucc2 Date: Tue, 2 Mar 2021 17:38:45 +0800 Subject: [PATCH 317/698] mmc: use max discard ignoring max_busy_timeout parameter. On kernel 4.14, no matter sd card type, all use max discard value. However, kernel 5.4 remove this logical, and will cause system watchdog, if user format 512GB/1TB class 10 card. Change-Id: Idc6b00187b8800465fca4af8f720aaf87db5700b Reviewed-on: https://gerrit.mot.com/1890338 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- drivers/mmc/core/core.c | 6 ++++++ drivers/mmc/host/sdhci-msm.c | 1 + include/linux/mmc/host.h | 2 ++ 3 files changed, 9 insertions(+) diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 8ca425538576..ff015f5ca282 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -2927,6 +2927,12 @@ unsigned int mmc_calc_max_discard(struct mmc_card *card) struct mmc_host *host = card->host; unsigned int max_discard, max_trim; + if (!host->max_busy_timeout || + (host->caps2 & MMC_CAP2_MAX_DISCARD_SIZE)) + { + pr_err("mmc_calc_max_discard UINT_MAX = %d \n",UINT_MAX); + return UINT_MAX; + } /* * Without erase_group_def set, MMC erase timeout depends on clock * frequence which can change. In that case, the best choice is diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c index b12c3dd8607e..6a88499d1c90 100644 --- a/drivers/mmc/host/sdhci-msm.c +++ b/drivers/mmc/host/sdhci-msm.c @@ -4549,6 +4549,7 @@ static int sdhci_msm_probe(struct platform_device *pdev) host->timeout_clk_div = 4; msm_host->mmc->caps2 |= MMC_CAP2_CLK_SCALE; #endif + msm_host->mmc->caps2 |= MMC_CAP2_MAX_DISCARD_SIZE; sdhci_msm_setup_pm(pdev, msm_host); host->mmc_host_ops.execute_tuning = sdhci_msm_execute_tuning; diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index 38cfd8faa2d2..162640f0bc88 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -483,6 +483,8 @@ struct mmc_host { #if defined(CONFIG_SDC_QTI) #define MMC_CAP2_CLK_SCALE (1 << 28) /* Allow dynamic clk scaling */ #endif +/* use max discard ignoring max_busy_timeout parameter */ +#define MMC_CAP2_MAX_DISCARD_SIZE (1 << 31) int fixed_drv_type; /* fixed driver type for non-removable media */ From 3dc89329ea055bdbbaacb790724791a8aea1f608 Mon Sep 17 00:00:00 2001 From: Nick Desaulniers Date: Fri, 3 Mar 2017 15:40:12 -0800 Subject: [PATCH 318/698] tracing: do not leak kernel addresses This l(CR) breaks tracing tools l(CR) trace-cmd. It logs in the same format but now addresses are all 0x0. Bug: 34277115 MOT-CRs-fixed: (CR) Change-Id: Ifb0d4d2a184bf0d95726de05b1acee0287a375d9 Reviewed-on: https://gerrit.mot.com/1887836 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Wang Wang Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key Reviewed-on: https://gerrit.mot.com/1892775 Reviewed-by: Huosheng Liao --- kernel/trace/trace_printk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/trace/trace_printk.c b/kernel/trace/trace_printk.c index d4e31e969206..b8014b361a1a 100644 --- a/kernel/trace/trace_printk.c +++ b/kernel/trace/trace_printk.c @@ -306,7 +306,7 @@ static int t_show(struct seq_file *m, void *v) if (!*fmt) return 0; - seq_printf(m, "0x%lx : \"", *(unsigned long *)fmt); + seq_printf(m, "0x%lx : \"", 0L); /* * Tabs and new lines need to be converted. From 07f8b5f50a299f8fddb45b105cb4563d3799f87f Mon Sep 17 00:00:00 2001 From: linyx10 Date: Thu, 4 Mar 2021 16:15:53 +0800 Subject: [PATCH 319/698] Add the ABI required by mcDrvModule.ko to qcom gki whitelist. These ABI are used in mcDrvModule.ko and they have been added to GKI whitelist, so add them to qcom whitelist: d_path get_task_exe_file get_task_mm ktime_get_raw_ts64 mmput release_pages Change-Id: If1d64546756b658e4e726ee8abef452d79a9aa5c Signed-off-by: linyx10 Reviewed-on: https://gerrit.mot.com/1892816 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Binsheng Que Reviewed-by: Zhenxin Xi Submit-Approved: Jira Key --- android/abi_gki_aarch64_qcom | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/android/abi_gki_aarch64_qcom b/android/abi_gki_aarch64_qcom index 0f570e744ca7..ef98aa4dca85 100644 --- a/android/abi_gki_aarch64_qcom +++ b/android/abi_gki_aarch64_qcom @@ -607,6 +607,7 @@ down down_read down_write + d_path dput drain_workqueue driver_find_device @@ -1030,6 +1031,8 @@ get_random_bytes get_random_u32 __get_task_comm + get_task_exe_file + get_task_mm get_task_pid __getblk_gfp get_tree_single @@ -1406,6 +1409,7 @@ ktime_add_safe ktime_get ktime_get_mono_fast_ns + ktime_get_raw_ts64 ktime_get_real_seconds ktime_get_real_ts64 ktime_get_ts64 @@ -1509,6 +1513,7 @@ mmc_cqe_request_done mmc_of_parse mmc_send_tuning + mmput mod_delayed_work_on mod_node_page_state mod_timer @@ -2063,6 +2068,7 @@ regulator_unregister_notifier regulatory_set_wiphy_regd release_firmware + release_pages __release_region release_sock remap_pfn_range From adc9d546d5aca12aec4eec5c12904080f441d418 Mon Sep 17 00:00:00 2001 From: linyx10 Date: Thu, 24 Dec 2020 10:30:15 +0800 Subject: [PATCH 320/698] Add new smc invoke interface for Trustonic TEE driver. In kernel 5.4, the old qcom interface scm_call2() has been abandoned, so add new function trustonic_smc_fastcall() for Trustonic TEE driver module, and it will send syscall to the secure world through new qcom scm interface. Change-Id: Ib76c00e9910be6796fc71bdcfaf4352fd8f2806c Signed-off-by: linyx10 Reviewed-on: https://gerrit.mot.com/1836283 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Zhenxin Xi Submit-Approved: Jira Key --- drivers/firmware/qcom_scm-smc.c | 67 +++++++++++++++++++++++++++++++++ drivers/firmware/qcom_scm.c | 6 +++ drivers/firmware/qcom_scm.h | 1 + include/linux/qcom_scm.h | 1 + 4 files changed, 75 insertions(+) diff --git a/drivers/firmware/qcom_scm-smc.c b/drivers/firmware/qcom_scm-smc.c index 66af8140ef2d..b14b6a626a3b 100644 --- a/drivers/firmware/qcom_scm-smc.c +++ b/drivers/firmware/qcom_scm-smc.c @@ -28,6 +28,10 @@ #define MAX_QCOM_SCM_ARGS 10 #define MAX_QCOM_SCM_RETS 3 +#define SCM_SVC_MOBICORE 250 +#define SCM_CMD_MOBICORE 1 +#define ARM_SMCCC_OWNER_MOBI_OS 51 + #define QCOM_SCM_ATOMIC BIT(0) #define QCOM_SCM_NORETRY BIT(1) @@ -2388,6 +2392,69 @@ int __qcom_scm_invoke_smc(struct device *dev, phys_addr_t in_buf, return ret; } +int __trustonic_smc_fastcall(void *fc_generic, size_t size) +{ + int ret; + struct qcom_scm_desc desc = { + .svc = SCM_SVC_MOBICORE, + .cmd = SCM_CMD_MOBICORE, + .owner = ARM_SMCCC_OWNER_MOBI_OS + }; + + void *scm_buf_va = NULL; + phys_addr_t scm_buf_pa; + struct qtee_shm scm_shm = {0}; + + if (qtee_shmbridge_is_enabled()) { + + ret = qtee_shmbridge_allocate_shm(PAGE_ALIGN(size), &scm_shm); + if (ret) + return ret; + } + else { + scm_shm.vaddr = kzalloc(PAGE_ALIGN(size), GFP_KERNEL); + if (!scm_shm.vaddr) + return -ENOMEM; + + scm_shm.paddr = dma_map_single(NULL, scm_shm.vaddr, size, DMA_TO_DEVICE); + if (dma_mapping_error(NULL, scm_shm.paddr)) { + kfree(scm_shm.vaddr); + return -ENOMEM; + } + } + + scm_buf_va = scm_shm.vaddr; + scm_buf_pa = scm_shm.paddr; + + if (!scm_buf_va) + return -ENOMEM; + + memset(scm_buf_va, 0, size); + memcpy(scm_buf_va, fc_generic, size); + qtee_shmbridge_flush_shm_buf(&scm_shm); + + desc.args[0] = scm_buf_pa; + desc.args[1] = (u32)size; + desc.args[2] = scm_buf_pa; + desc.args[3] = (u32)size; + desc.arginfo = QCOM_SCM_ARGS(4, QCOM_SCM_RW, QCOM_SCM_VAL, QCOM_SCM_RW, QCOM_SCM_VAL); + + ret = qcom_scm_call(NULL, &desc); + + qtee_shmbridge_flush_shm_buf(&scm_shm); + memcpy(fc_generic, scm_buf_va, size); + + if (qtee_shmbridge_is_enabled()) { + qtee_shmbridge_free_shm(&scm_shm); + } + else { + dma_unmap_single(NULL, scm_shm.paddr, size, DMA_TO_DEVICE); + kfree(scm_shm.vaddr); + } + + return ret; +} + int __qcom_scm_invoke_callback_response(struct device *dev, phys_addr_t out_buf, size_t out_buf_size, int32_t *result, u64 *response_type, unsigned int *data) diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c index 5b6543836b50..86fe5501cee5 100644 --- a/drivers/firmware/qcom_scm.c +++ b/drivers/firmware/qcom_scm.c @@ -1065,6 +1065,12 @@ int qcom_scm_invoke_smc(phys_addr_t in_buf, size_t in_buf_size, } EXPORT_SYMBOL(qcom_scm_invoke_smc); +int trustonic_smc_fastcall(void *fc_generic, size_t size) +{ + return __trustonic_smc_fastcall(fc_generic, size); +} +EXPORT_SYMBOL(trustonic_smc_fastcall); + int qcom_scm_invoke_callback_response(phys_addr_t out_buf, size_t out_buf_size, int32_t *result, u64 *response_type, unsigned int *data) diff --git a/drivers/firmware/qcom_scm.h b/drivers/firmware/qcom_scm.h index 445790592780..e784405794a5 100644 --- a/drivers/firmware/qcom_scm.h +++ b/drivers/firmware/qcom_scm.h @@ -297,6 +297,7 @@ extern int __qcom_scm_invoke_smc_legacy(struct device *dev, phys_addr_t in_buf, extern int __qcom_scm_invoke_smc(struct device *dev, phys_addr_t in_buf, size_t in_buf_size, phys_addr_t out_buf, size_t out_buf_size, int32_t *result, u64 *response_type, unsigned int *data); +extern int __trustonic_smc_fastcall(void *fc_generic, size_t size); extern int __qcom_scm_invoke_callback_response(struct device *dev, phys_addr_t out_buf, size_t out_buf_size, int32_t *result, u64 *response_type, unsigned int *data); diff --git a/include/linux/qcom_scm.h b/include/linux/qcom_scm.h index d4ce6f0c7989..f22c9c6a5ca6 100644 --- a/include/linux/qcom_scm.h +++ b/include/linux/qcom_scm.h @@ -208,6 +208,7 @@ extern int qcom_scm_invoke_smc_legacy(phys_addr_t in_buf, size_t in_buf_size, extern int qcom_scm_invoke_smc(phys_addr_t in_buf, size_t in_buf_size, phys_addr_t out_buf, size_t out_buf_size, int32_t *result, u64 *response_type, unsigned int *data); +extern int trustonic_smc_fastcall(void *fc_generic, size_t size); extern int qcom_scm_invoke_callback_response(phys_addr_t out_buf, size_t out_buf_size, int32_t *result, u64 *response_type, unsigned int *data); From aee7b39c18b7e17ddb60db7aff3f0f1ef830a6ab Mon Sep 17 00:00:00 2001 From: louhs1 Date: Thu, 11 Mar 2021 14:38:51 +0800 Subject: [PATCH 321/698] arm64/config: add ibiza cmcc extra config add the extra config for ibiza cmcc project please add the different config here for cmcc unique request. Change-Id: I98af3946c12ce4036072a691d11e82aa3c12750f Signed-off-by: louhs1 Reviewed-on: https://gerrit.mot.com/1898418 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Yiwen Liu Reviewed-by: Yonghui Jia Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- .../configs/vendor/ext_config/moto-holi-ibiza-cmcc-extra.config | 1 + 1 file changed, 1 insertion(+) create mode 100644 arch/arm64/configs/vendor/ext_config/moto-holi-ibiza-cmcc-extra.config diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza-cmcc-extra.config b/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza-cmcc-extra.config new file mode 100644 index 000000000000..b1fcb086bf73 --- /dev/null +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza-cmcc-extra.config @@ -0,0 +1 @@ +CONFIG_ZRAM_WRITEBACK=y From 731c495e28ecf53894d8b262e4af9e945dabd7f5 Mon Sep 17 00:00:00 2001 From: louhs1 Date: Thu, 11 Mar 2021 14:37:57 +0800 Subject: [PATCH 322/698] kernel/config: append extra config for project if a prject need extra config, please add to the extra config for example: moto-holi-ibiza-cmcc-extra.config match TARGET_PRODUCT_TYPE: cmcc factory retail ... Change-Id: I6157eee802bfe4cd11c5d6b76b518b04353c9c27 Signed-off-by: louhs1 Reviewed-on: https://gerrit.mot.com/1898417 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Yiwen Liu Reviewed-by: Yonghui Jia Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- scripts/gki/fragment_motoconfig.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/scripts/gki/fragment_motoconfig.sh b/scripts/gki/fragment_motoconfig.sh index 3143fce77372..f5087921b115 100755 --- a/scripts/gki/fragment_motoconfig.sh +++ b/scripts/gki/fragment_motoconfig.sh @@ -58,6 +58,11 @@ elif [ $TARGET_BUILD_VARIANT == "userdebug" ] && [ $REQUIRED_DEFCONFIG != ${LOCA fi fi +#merge moto product extra config +if [ -e $MOTO_CONFIG_DIR/moto-${LOCAL_PLATFORM_NAME}-${TARGET_PRODUCT_NAME}-$TARGET_PRODUCT_TYPE-extra.config ]; then + MOTO_REQUIRED_CONFIG+=" $MOTO_CONFIG_DIR/moto-${LOCAL_PLATFORM_NAME}-${TARGET_PRODUCT_NAME}-$TARGET_PRODUCT_TYPE-extra.config" +fi + #merge moto product config if [ -e $MOTO_CONFIG_DIR/moto-${LOCAL_PLATFORM_NAME}-${TARGET_PRODUCT_NAME}.config ]; then MOTO_REQUIRED_CONFIG+=" $MOTO_CONFIG_DIR/moto-${LOCAL_PLATFORM_NAME}-${TARGET_PRODUCT_NAME}.config" From e81049289e4c73e53c0ce876f46744ebd7edadef Mon Sep 17 00:00:00 2001 From: quebs2 Date: Fri, 12 Mar 2021 15:39:55 +0800 Subject: [PATCH 323/698] Fix instability issue during tbase load in Kernel 5.4 Tbase load was failing intermittently during fc_init() operation in __smc() with error: Trustonic TEE: ERROR -14 __smc: fc_init failed (4dee8000) The root cause has two components 1- qcom_scm_call() needs to be done atomically. Task reschedule was causing a failure. Thus changed to the atomic call qcom_scm_call_atomic(). 2- Qcom scm_call requires cache maintenance. API attests that any buffers that are expected to be accessed by the secure world must be flushed before invoking qcom_scm_call and invalidated in the cache immediately after qcom_scm_call returns. Cache invalidation was missing, hence add it. Change-Id: I83139fc5110eb3af536a30800c994c8e451df1fa Signed-off-by: quebs2 Reviewed-on: https://gerrit.mot.com/1899491 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Zhenxin Xi Submit-Approved: Jira Key --- drivers/firmware/qcom_scm-smc.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/firmware/qcom_scm-smc.c b/drivers/firmware/qcom_scm-smc.c index b14b6a626a3b..11257612c487 100644 --- a/drivers/firmware/qcom_scm-smc.c +++ b/drivers/firmware/qcom_scm-smc.c @@ -2394,7 +2394,8 @@ int __qcom_scm_invoke_smc(struct device *dev, phys_addr_t in_buf, int __trustonic_smc_fastcall(void *fc_generic, size_t size) { - int ret; + int ret = 0; + struct qcom_scm_desc desc = { .svc = SCM_SVC_MOBICORE, .cmd = SCM_CMD_MOBICORE, @@ -2402,7 +2403,7 @@ int __trustonic_smc_fastcall(void *fc_generic, size_t size) }; void *scm_buf_va = NULL; - phys_addr_t scm_buf_pa; + phys_addr_t scm_buf_pa = 0; struct qtee_shm scm_shm = {0}; if (qtee_shmbridge_is_enabled()) { @@ -2439,9 +2440,9 @@ int __trustonic_smc_fastcall(void *fc_generic, size_t size) desc.args[3] = (u32)size; desc.arginfo = QCOM_SCM_ARGS(4, QCOM_SCM_RW, QCOM_SCM_VAL, QCOM_SCM_RW, QCOM_SCM_VAL); - ret = qcom_scm_call(NULL, &desc); - - qtee_shmbridge_flush_shm_buf(&scm_shm); + ret = qcom_scm_call_atomic(NULL, &desc); + qtee_shmbridge_inv_shm_buf(&scm_shm); + memset(fc_generic, 0x00, size); memcpy(fc_generic, scm_buf_va, size); if (qtee_shmbridge_is_enabled()) { From 48cc6284d89af278fb47d5350f54d0e8a17a387c Mon Sep 17 00:00:00 2001 From: mahj8 Date: Mon, 15 Mar 2021 15:26:57 +0800 Subject: [PATCH 324/698] Revert "(CR): arch/config: disable CONFIG_STATIC_USERMODEHELPER" This change is not need. Because we have changed the code to reach the goal at https://gerrit.mot.com/#/c/1899604/ Mot-CRs-fixed:(CR) This reverts commit d80c7cd6d49b21e72e2b91e9e5c556dbeb5b5e85. Change-Id: I3a58e7d0153f0751f2e8714669683a980b1bf736 Reviewed-on: https://gerrit.mot.com/1900615 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/debug-holi.config | 1 - arch/arm64/configs/vendor/ext_config/factory-holi.config | 1 - 2 files changed, 2 deletions(-) diff --git a/arch/arm64/configs/vendor/ext_config/debug-holi.config b/arch/arm64/configs/vendor/ext_config/debug-holi.config index 7de99ef290b7..ff9ff6c35dd6 100644 --- a/arch/arm64/configs/vendor/ext_config/debug-holi.config +++ b/arch/arm64/configs/vendor/ext_config/debug-holi.config @@ -35,7 +35,6 @@ CONFIG_CPU_FREQ_STAT=y # CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_ZEROFLASH is not set # CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_DIAGNOSTICS is not set # CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_I2C is not set -# CONFIG_STATIC_USERMODEHELPER is not set CONFIG_LOG_BUF_SHIFT=18 CONFIG_CORESIGHT=y CONFIG_CORESIGHT_LINK_AND_SINK_TMC=y diff --git a/arch/arm64/configs/vendor/ext_config/factory-holi.config b/arch/arm64/configs/vendor/ext_config/factory-holi.config index 1ae7affe3eec..caf4e8c59e4e 100644 --- a/arch/arm64/configs/vendor/ext_config/factory-holi.config +++ b/arch/arm64/configs/vendor/ext_config/factory-holi.config @@ -17,4 +17,3 @@ CONFIG_SERIAL_MSM_GENI_CONSOLE=y CONFIG_QCOM_RTB=y CONFIG_QCOM_RTB_QGKI=y CONFIG_QCOM_RTB_SEPARATE_CPUS=y -# CONFIG_STATIC_USERMODEHELPER is not set From e6f4e4aa6f8dafd2aae8d2a214de8320490f1246 Mon Sep 17 00:00:00 2001 From: mahj8 Date: Fri, 12 Mar 2021 18:22:40 +0800 Subject: [PATCH 325/698] kernel: unit power off failed when removed charger unit power off failed when removed charger in factory mode. Because google android R define CONFIG_STATIC_USERMODEHELPER and CONFIG_STATIC_USERMODEHELPER_PATH = "", so sub_info->path is always empty. Change-Id: If06b3a52e657e083ce89f2f75f717c753a57d685 Signed-off-by: mahj8 Reviewed-on: https://gerrit.mot.com/1899604 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- kernel/umh.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/kernel/umh.c b/kernel/umh.c index b8c524dcc76f..f601857fa9b1 100644 --- a/kernel/umh.c +++ b/kernel/umh.c @@ -403,6 +403,10 @@ struct subprocess_info *call_usermodehelper_setup(const char *path, char **argv, #else sub_info->path = path; #endif + + if ((path != NULL) && !strcmp(path, "/system/bin/reboot")) + sub_info->path = path; + sub_info->argv = argv; sub_info->envp = envp; From 408ab273a2c423466e59653d948bf7a208f76ab6 Mon Sep 17 00:00:00 2001 From: houdz1 Date: Fri, 12 Mar 2021 18:11:12 +0800 Subject: [PATCH 326/698] wled: initial value of low_bl_delay_ms to 0 When "mmi,low-bl-delay-ms" is not defined, the value of low_bl_delay_ms is uncertain. Change-Id: I7c2c2d185a31d6a7db9e39960532ca65f49cf6a9 Signed-off-by: houdz1 Reviewed-on: https://gerrit.mot.com/1899598 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Yeqing Wang Reviewed-by: Shanshan Dai Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- drivers/video/backlight/qcom-spmi-wled.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/video/backlight/qcom-spmi-wled.c b/drivers/video/backlight/qcom-spmi-wled.c index 8489d1b2567a..86e1bc02be4f 100644 --- a/drivers/video/backlight/qcom-spmi-wled.c +++ b/drivers/video/backlight/qcom-spmi-wled.c @@ -1350,6 +1350,7 @@ static int parse_low_bl_config(struct wled *wled) of_property_read_u32(dev->of_node, "mmi,low-bl-remap-percent", &val); wled->low_bl_cfg.low_bl_remap_percent = val; + val = 0; of_property_read_u32(dev->of_node, "mmi,low-bl-delay-ms", &val); wled->low_bl_cfg.low_bl_delay_ms = val; From a428f55af0c3a1acd73c28ac11a0ef625d857adc Mon Sep 17 00:00:00 2001 From: houdz1 Date: Mon, 15 Mar 2021 15:34:51 +0800 Subject: [PATCH 327/698] wled: set the brightness to "low_bl_remap_percent" when disable cabc When enable"low-bl-disable-cabc" function,We must set the brightness to "low_bl_remap_percent" when under the low-bl. Change-Id: Ie4b17b0a46479726059af686c6cc5503141a6b49 Reviewed-on: https://gerrit.mot.com/1900712 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Yeqing Wang Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- drivers/video/backlight/qcom-spmi-wled.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/video/backlight/qcom-spmi-wled.c b/drivers/video/backlight/qcom-spmi-wled.c index 86e1bc02be4f..b58d2e4fc4a8 100644 --- a/drivers/video/backlight/qcom-spmi-wled.c +++ b/drivers/video/backlight/qcom-spmi-wled.c @@ -568,7 +568,7 @@ static int wled_update_status(struct backlight_device *bl) mutex_lock(&wled->lock); if (brightness) { - if (wled->low_bl_force_cabc_disable && wled->brightness) { + if (wled->low_bl_force_cabc_disable) { if (brightness <= wled->low_bl_cfg.low_bl_threshold) { brightness = brightness * wled->low_bl_cfg.low_bl_remap_percent/100; if (!wled->cabc_disabled) { @@ -578,14 +578,14 @@ static int wled_update_status(struct backlight_device *bl) } } - else if ((wled->brightness < wled->low_bl_cfg.low_bl_threshold) && (wled->cabc_disabled)) { + else if ((wled->brightness < wled->low_bl_cfg.low_bl_threshold) && (wled->cabc_disabled) && wled->brightness) { wled->cabc_disabled = false; wled->cabc_config(wled, true); pr_info("exit low brightness(%d), will enable cabc\n", brightness); } } - if (wled->only_low_bl_force_cabc_disable && wled->brightness) { + if (wled->only_low_bl_force_cabc_disable) { if (brightness < wled->low_bl_cfg.low_bl_threshold) { brightness = brightness * wled->low_bl_cfg.low_bl_remap_percent/100; if (!wled->cabc_disabled) { From 3d90262b5899cac4188c67252df7ae983c4df4d7 Mon Sep 17 00:00:00 2001 From: quebs2 Date: Tue, 16 Mar 2021 15:29:40 +0800 Subject: [PATCH 328/698] qcom_scm: Retry T-Base smc call when TZ is busy. We cannot guarantee the Trustonic nq kthread is always uninterruptable, atomic and SMP safe, so that we will send the command to the SCM and wait for the command to finish processing from secure world in case the QSEE might be busy at that point. This can be used in pre-emptible context when the Trustonic fast call is invoked to run whereby the scm handler happens to be owned by other threads. Change-Id: I0aac105684c7b8b7bed7ab2146b8ef62dab42837 Signed-off-by: quebs2 Reviewed-on: https://gerrit.mot.com/1902496 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Jefferson Rodrigo Capovilla Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- drivers/firmware/qcom_scm-smc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/firmware/qcom_scm-smc.c b/drivers/firmware/qcom_scm-smc.c index 11257612c487..46a64458e51b 100644 --- a/drivers/firmware/qcom_scm-smc.c +++ b/drivers/firmware/qcom_scm-smc.c @@ -2440,7 +2440,7 @@ int __trustonic_smc_fastcall(void *fc_generic, size_t size) desc.args[3] = (u32)size; desc.arginfo = QCOM_SCM_ARGS(4, QCOM_SCM_RW, QCOM_SCM_VAL, QCOM_SCM_RW, QCOM_SCM_VAL); - ret = qcom_scm_call_atomic(NULL, &desc); + ret = qcom_scm_call(NULL, &desc); qtee_shmbridge_inv_shm_buf(&scm_shm); memset(fc_generic, 0x00, size); memcpy(fc_generic, scm_buf_va, size); From 824502c8d18b2fb342c02d28890959a99e35d0a5 Mon Sep 17 00:00:00 2001 From: huangzq2 Date: Thu, 11 Mar 2021 09:49:55 +0800 Subject: [PATCH 329/698] mm: zram: fix swapcached issue on kernel 5.4 Afer Zram backing dev setuped, zram will be treated as a ASYNC IO swap device, no longer SYNC IO device, because WB pages do have IO operation on swap in, so the optimization on skiping swapcache for fast swap device will no longer be applyed on such case. Now we refactor this optimization, skip the swapcache by checking SYNC IO state on each swap page via ioctl. Reuse ioctl because we should not break the GKI. Change-Id: Ia1dc351eafc7c0b62126a3864a6da9136c2bfe6d Signed-off-by: huangzq2 Reviewed-on: https://gerrit.mot.com/1898090 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Yonghui Jia Reviewed-by: Zhizhong Ge Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- drivers/block/zram/zram_drv.c | 25 +++++++++++++++++++++++++ include/linux/swap.h | 1 + mm/memory.c | 17 +++++++++++++---- mm/page_io.c | 16 ++++++++++++++++ 4 files changed, 55 insertions(+), 4 deletions(-) diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c index cd242fd9db18..60650ecf9166 100644 --- a/drivers/block/zram/zram_drv.c +++ b/drivers/block/zram/zram_drv.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -1630,6 +1631,27 @@ static void zram_slot_free_notify(struct block_device *bdev, zram_slot_unlock(zram, index); } +/* Moto huangzq2: check sync_io state on swap entry, + * return 0 on wb page, else return 1. + */ +#ifdef CONFIG_ZRAM_WRITEBACK +static int zram_ioctl(struct block_device *bdev, fmode_t mode, + unsigned int cmd, unsigned long index) +{ + struct zram *zram; + int has_sync_io = 1; + + if (cmd != SWP_SYNCHRONOUS_IO) return -EINVAL; + + zram = bdev->bd_disk->private_data; + zram_slot_lock(zram, index); + has_sync_io = zram_test_flag(zram, index, ZRAM_WB) ? 0 : 1; + zram_slot_unlock(zram, index); + + return has_sync_io; +} +#endif + static int zram_rw_page(struct block_device *bdev, sector_t sector, struct page *page, unsigned int op) { @@ -1822,6 +1844,9 @@ static int zram_open(struct block_device *bdev, fmode_t mode) static const struct block_device_operations zram_devops = { .open = zram_open, .swap_slot_free_notify = zram_slot_free_notify, +#ifdef CONFIG_ZRAM_WRITEBACK + .ioctl = zram_ioctl, +#endif .rw_page = zram_rw_page, .owner = THIS_MODULE }; diff --git a/include/linux/swap.h b/include/linux/swap.h index b407d3963649..bb50a6d0eee4 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h @@ -397,6 +397,7 @@ extern void end_swap_bio_write(struct bio *bio); extern int __swap_writepage(struct page *page, struct writeback_control *wbc, bio_end_io_t end_write_func); extern int swap_set_page_dirty(struct page *page); +extern bool swap_slot_has_sync_io(swp_entry_t entry); int add_swap_extent(struct swap_info_struct *sis, unsigned long start_page, unsigned long nr_pages, sector_t start_block); diff --git a/mm/memory.c b/mm/memory.c index 47c12f886c0d..609e32cfbb0e 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -3089,9 +3089,18 @@ vm_fault_t do_swap_page(struct vm_fault *vmf) if (!page) { struct swap_info_struct *si = swp_swap_info(entry); + bool skip_swapcache = false; - if (si->flags & SWP_SYNCHRONOUS_IO && - __swap_count(entry) == 1) { + /* Moto huangzq2: check sync_io on each page if we enabled Zram wb. + * Zram writeback will remove SWP_SYNCHRONOUS_IO flag as it has disk + * IO operation on writeback page during swap in. + */ + if (si->flags & SWP_SYNCHRONOUS_IO && __swap_count(entry) == 1) + skip_swapcache = true; + else if (__swap_count(entry) == 1 && swap_slot_has_sync_io(entry)) + skip_swapcache = true; + + if (skip_swapcache) { /* skip swapcache */ page = alloc_page_vma(GFP_HIGHUSER_MOVABLE | __GFP_CMA | __GFP_OFFLINABLE, vma, @@ -3115,8 +3124,8 @@ vm_fault_t do_swap_page(struct vm_fault *vmf) ret = VM_FAULT_RETRY; goto out; } else { - page = swapin_readahead(entry, GFP_HIGHUSER_MOVABLE, - vmf); + page = swapin_readahead(entry, GFP_HIGHUSER_MOVABLE | __GFP_CMA + | __GFP_OFFLINABLE, vmf); swapcache = page; } diff --git a/mm/page_io.c b/mm/page_io.c index bc370c8e1667..e91f008af794 100644 --- a/mm/page_io.c +++ b/mm/page_io.c @@ -71,6 +71,22 @@ void end_swap_bio_write(struct bio *bio) bio_put(bio); } +/* Moto huangzq2: check sync_io state on swap entry */ +bool swap_slot_has_sync_io(swp_entry_t entry) +{ + struct swap_info_struct *sis; + struct gendisk *disk; + + sis = swp_swap_info(entry); + disk = sis->bdev->bd_disk; + if (disk->fops->ioctl) { + return disk->fops->ioctl(sis->bdev, 0, + SWP_SYNCHRONOUS_IO, swp_offset(entry)) == 1; + } + + return false; +} + static void swap_slot_free_notify(struct page *page) { struct swap_info_struct *sis; From 1c3fe4abfab71f29bcba556b62ea4c0ab3082308 Mon Sep 17 00:00:00 2001 From: huangzq2 Date: Sat, 13 Mar 2021 19:28:24 +0800 Subject: [PATCH 330/698] mm: zram: skip readahead for sync io pages Zram is a ram based swap, but Zram with writeback is ram + IO based swap, so we still need readhead for the pages on backing store, the page-cluster should be tuned on each chipset if we enabled zram wb, beside this, we made this patch to skip readahead on the page which has not been writebacked. Change-Id: Ia219baf888cfc6ef4865f7c4d682ab4384de893c Signed-off-by: huangzq2 Reviewed-on: https://gerrit.mot.com/1900257 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key Reviewed-on: https://gerrit.mot.com/1902452 Reviewed-by: Yonghui Jia Reviewed-by: Zhizhong Ge Reviewed-by: Huosheng Liao --- mm/swap_state.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/mm/swap_state.c b/mm/swap_state.c index 260ac6a822b9..16709312e949 100644 --- a/mm/swap_state.c +++ b/mm/swap_state.c @@ -738,6 +738,12 @@ static struct page *swap_vma_readahead(swp_entry_t fentry, gfp_t gfp_mask, bool page_allocated; struct vma_swap_readahead ra_info = {0,}; + /* Moto huangzq2: don't readahead sync io pages */ + if (swap_slot_has_sync_io(fentry)) { + ra_info.win = 1; + goto skip; + } + swap_ra_info(vmf, &ra_info); if (ra_info.win == 1) goto skip; @@ -753,6 +759,9 @@ static struct page *swap_vma_readahead(swp_entry_t fentry, gfp_t gfp_mask, entry = pte_to_swp_entry(pentry); if (unlikely(non_swap_entry(entry))) continue; + /* Moto huangzq2: don't readahead sync io pages */ + if (swap_slot_has_sync_io(entry)) + continue; page = __read_swap_cache_async(entry, gfp_mask, vma, vmf->address, &page_allocated); if (!page) From 0daa6e1781c408fa5d2a2d6dfe1d2a569efa2d62 Mon Sep 17 00:00:00 2001 From: huangzq2 Date: Sat, 13 Mar 2021 19:39:45 +0800 Subject: [PATCH 331/698] mm: zram: free the swap slot when swap in The zram pages on backing store can not be freed when swap in, becase they have swap cache. So before these pages become drity, they will be always read from swap cache or backing store. If these pages happens to be swap out again, the swap cahce will be deleted, then they can only be loaded from backing store, not zram. Change-Id: I59a4ef1f7b6fb4ce803a56a7eaae7693a69780d4 Signed-off-by: huangzq2 Reviewed-on: https://gerrit.mot.com/1900258 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key Reviewed-on: https://gerrit.mot.com/1902453 Reviewed-by: Yonghui Jia Reviewed-by: Zhizhong Ge Reviewed-by: Huosheng Liao --- mm/page_io.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/mm/page_io.c b/mm/page_io.c index e91f008af794..6a88629a5806 100644 --- a/mm/page_io.c +++ b/mm/page_io.c @@ -398,11 +398,12 @@ int swap_readpage(struct page *page, bool synchronous) ret = bdev_read_page(sis->bdev, swap_page_sector(page), page); if (!ret) { - if (trylock_page(page)) { - swap_slot_free_notify(page); - unlock_page(page); - } - + /* + * Moto huangzq2: We either remove the trylock_page or use lock_page + * here, becuase trylock will always return false due to page_endio + * in zram_rw_page. + */ + swap_slot_free_notify(page); count_vm_event(PSWPIN); goto out; } From d0402a631e3410bd18789fca92c2d9d416fd94b1 Mon Sep 17 00:00:00 2001 From: Mark Reed-MREED1 Date: Sun, 14 Mar 2021 14:36:04 -0500 Subject: [PATCH 332/698] - Disable reboot to EDL mode (blankflash) QCOM allows us to boot into EDL mode, however, there is no reason to do so outside the bootloader. Disabling is good security practice and required for tracfone security submission. Change-Id: Id859e88e1140f68521c0fd146444b2f7af34aaa5 Reviewed-on: https://gerrit.mot.com/1900249 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Joel Voss Submit-Approved: Jira Key --- drivers/power/reset/msm-poweroff.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/power/reset/msm-poweroff.c b/drivers/power/reset/msm-poweroff.c index 2ea1865d448b..002eb49200dc 100644 --- a/drivers/power/reset/msm-poweroff.c +++ b/drivers/power/reset/msm-poweroff.c @@ -166,6 +166,8 @@ static bool get_dload_mode(void) static void enable_emergency_dload_mode(void) { +#if 0 +// MOTO: Disabled for security hardening if (emergency_dload_mode_addr) { __raw_writel(EMERGENCY_DLOAD_MAGIC1, emergency_dload_mode_addr); @@ -185,6 +187,9 @@ static void enable_emergency_dload_mode(void) } qcom_scm_set_download_mode(SCM_EDLOAD_MODE, tcsr_boot_misc_detect ?: 0); +#else + pr_err("EDL mode disabled\n"); +#endif } static int dload_set(const char *val, const struct kernel_param *kp) From a067e6085f0aff6117996772a2e4e3317295c890 Mon Sep 17 00:00:00 2001 From: jiayh2 Date: Tue, 16 Mar 2021 16:00:08 +0800 Subject: [PATCH 333/698] Denver enable zram-writeback kernel config on main line set CONFIG_ZRAM_WRITEBACK to y This config will split zram-writeback features in zram driver Change-Id: I74013e18a1ec8d8245fab72f471456a4707a9f02 Reviewed-on: https://gerrit.mot.com/1902517 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Huosheng Liao Reviewed-by: Zhizhong Ge Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi-denver.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-denver.config b/arch/arm64/configs/vendor/ext_config/moto-holi-denver.config index bc02edbfb9ea..a843ecbe8583 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-denver.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-denver.config @@ -15,6 +15,7 @@ # CONFIG_DENVER_DTB=y CONFIG_FS_EPOLL_WAKEUP_DEBUG=y +CONFIG_ZRAM_WRITEBACK=y # CONFIG_THERMAL_STATISTICS is not set # CONFIG_TOUCHSCREEN_SYNAPTICS_TCM is not set # CONFIG_TOUCHSCREEN_SYNAPTICS_DSX is not set From c2ff69edcc599b537f8e1a2a915cd830e1ec36e1 Mon Sep 17 00:00:00 2001 From: jiayh2 Date: Tue, 16 Mar 2021 16:02:06 +0800 Subject: [PATCH 334/698] Ibiza enable zram-writeback kernel config on main line set CONFIG_ZRAM_WRITEBACK to y This config will split zram-writeback features in zram driver Change-Id: Id6bffe9a1f42909cd2154b68751ae6198a4040c6 Reviewed-on: https://gerrit.mot.com/1902519 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Zhizhong Ge Reviewed-by: Bin Liu Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config b/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config index 832db8c7008f..4ba81a1528f0 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config @@ -16,4 +16,5 @@ CONFIG_IBIZA_DTB=y # CONFIG_NFC_QTI_I2C is not set CONFIG_FS_EPOLL_WAKEUP_DEBUG=y +CONFIG_ZRAM_WRITEBACK=y # CONFIG_THERMAL_STATISTICS is not set From 946ecab4871b9b51732eea6d25bf3060957ec688 Mon Sep 17 00:00:00 2001 From: Yiwen Liu Date: Wed, 24 Mar 2021 14:38:31 +0800 Subject: [PATCH 335/698] defconfig: initial corfup defconfig Corfup: SM4350, initial configs cloned from Ibiza. Change-Id: I6dabff415665c81c03c74718ab5f3ae39ed5a5fe Signed-off-by: Yiwen Liu Reviewed-on: https://gerrit.mot.com/1908449 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Hongshu Lou Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- .../ext_config/debug-holi-corfup.config | 25 +++++++++++++++++++ .../ext_config/factory-holi-corfup.config | 16 ++++++++++++ .../vendor/ext_config/moto-holi-corfup.config | 20 +++++++++++++++ drivers/soc/qcom/Kconfig | 8 ++++++ 4 files changed, 69 insertions(+) create mode 100644 arch/arm64/configs/vendor/ext_config/debug-holi-corfup.config create mode 100644 arch/arm64/configs/vendor/ext_config/factory-holi-corfup.config create mode 100644 arch/arm64/configs/vendor/ext_config/moto-holi-corfup.config diff --git a/arch/arm64/configs/vendor/ext_config/debug-holi-corfup.config b/arch/arm64/configs/vendor/ext_config/debug-holi-corfup.config new file mode 100644 index 000000000000..13f71e03c466 --- /dev/null +++ b/arch/arm64/configs/vendor/ext_config/debug-holi-corfup.config @@ -0,0 +1,25 @@ +# +# Please avoid changing the Qualcomm defconfig files and use this file to +# add any Motorola-specific configuration changes that are applicable to +# userdebug, eng, and user builds. +# +# After building, a list of all of the config files that are used can be found +# at the top of: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/mapphone_defconfig +# +# The actual output of the kernel configuration system can be found at: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/.config +# +# You can check the .config file to verify that your configuration option is +# being set as expected. +# + +# CONFIG_CGROUP_DEBUG is not set +# CONFIG_CLEANCACHE is not set +# CONFIG_CMA_ALLOW_WRITE_DEBUGFS is not set +# CONFIG_CMA_DEBUG is not set +# CONFIG_PREEMPTIRQ_EVENTS is not set +# CONFIG_PREEMPT_TRACER is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_TEST_USER_COPY is not set diff --git a/arch/arm64/configs/vendor/ext_config/factory-holi-corfup.config b/arch/arm64/configs/vendor/ext_config/factory-holi-corfup.config new file mode 100644 index 000000000000..830e8a22f610 --- /dev/null +++ b/arch/arm64/configs/vendor/ext_config/factory-holi-corfup.config @@ -0,0 +1,16 @@ +# +# Please avoid changing the Qualcomm defconfig files and use this file to +# add any Motorola-specific configuration changes that are applicable to +# userdebug, eng, and user builds. +# +# After building, a list of all of the config files that are used can be found +# at the top of: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/mapphone_defconfig +# +# The actual output of the kernel configuration system can be found at: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/.config +# +# You can check the .config file to verify that your configuration option is +# being set as expected. +# + diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-corfup.config b/arch/arm64/configs/vendor/ext_config/moto-holi-corfup.config new file mode 100644 index 000000000000..4b9f14dfcb0d --- /dev/null +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-corfup.config @@ -0,0 +1,20 @@ +# +# Please avoid changing the Qualcomm defconfig files and use this file to +# add any Motorola-specific configuration changes that are applicable to +# userdebug, eng, and user builds. +# +# After building, a list of all of the config files that are used can be found +# at the top of: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/mapphone_defconfig +# +# The actual output of the kernel configuration system can be found at: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/.config +# +# You can check the .config file to verify that your configuration option is +# being set as expected. +# +CONFIG_CORFUP_DTB=y +# CONFIG_NFC_QTI_I2C is not set +CONFIG_FS_EPOLL_WAKEUP_DEBUG=y +CONFIG_ZRAM_WRITEBACK=y +# CONFIG_THERMAL_STATISTICS is not set diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index b81685e71f3a..eea8e02fabae 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -28,6 +28,14 @@ config IBIZA_DTB Only include IBIZA specific DTBs to limit the number that get built during kernel compilation. +config CORFUP_DTB + depends on ARCH_QCOM + default n + bool "CORFUP DTBs" + help + Only include CORFUP specific DTBs to limit the number that + get built during kernel compilation. + config QCOM_AOSS_QMP tristate "Qualcomm AOSS Driver" depends on ARCH_QCOM || COMPILE_TEST From 26b7fe96b7714fbd869f2412ce9b77f033a0bc5f Mon Sep 17 00:00:00 2001 From: Mike SU Date: Sat, 3 Apr 2021 17:55:49 +0800 Subject: [PATCH 336/698] MOTODESK-3077 Change the NCM default interface name to ncm0 The NCM default interface name "usb0" is confused. Use "ncm0" better. Change-Id: I361074b9a3b04968f477d78e7c5a4fd6fe418fdc Reviewed-on: https://gerrit.mot.com/1916424 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Yuecai Liu Reviewed-by: Huosheng Liao Reviewed-by: Xuejin Wang Submit-Approved: Jira Key --- drivers/usb/gadget/function/f_ncm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/usb/gadget/function/f_ncm.c b/drivers/usb/gadget/function/f_ncm.c index d6f50ecbad03..e379cac90ed7 100644 --- a/drivers/usb/gadget/function/f_ncm.c +++ b/drivers/usb/gadget/function/f_ncm.c @@ -1462,7 +1462,8 @@ static int ncm_bind(struct usb_configuration *c, struct usb_function *f) */ if (!ncm_opts->bound) { mutex_lock(&ncm_opts->lock); - ncm_opts->net = gether_setup_default(); + /* MOTODESK-3077 Use ncm interface name. suzh1 2021-04-03 */ + ncm_opts->net = gether_setup_name_default("ncm"); if (IS_ERR(ncm_opts->net)) { status = PTR_ERR(ncm_opts->net); mutex_unlock(&ncm_opts->lock); From 7bbd9267e31078f7b69b979e3b95cbf66d50b3d3 Mon Sep 17 00:00:00 2001 From: weimh1 Date: Sun, 25 Apr 2021 17:08:16 +0800 Subject: [PATCH 337/698] kernel/config: adjust factory defconfig 1.factory support only userdebug build,so it will include many debug configs which lead to boot slowly. 2.remove qcom debug files as perf when factory build. Change-Id: I7be5d0ba2379d61051b2e3c9d9b2cab4b5c36445 Signed-off-by: weimh1 Reviewed-on: https://gerrit.mot.com/1932024 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Yiwen Liu Reviewed-by: Shicheng Gong Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- scripts/gki/generate_defconfig.sh | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/scripts/gki/generate_defconfig.sh b/scripts/gki/generate_defconfig.sh index a6e3d6eaea58..6a3d5a5f28dc 100755 --- a/scripts/gki/generate_defconfig.sh +++ b/scripts/gki/generate_defconfig.sh @@ -57,13 +57,18 @@ FINAL_DEFCONFIG_BLEND="" source ${SCRIPTS_ROOT}/fragment_motoconfig.sh ${PLATFORM_NAME} ${REQUIRED_DEFCONFIG} FINAL_DEFCONFIG_BLEND+=${MOTO_REQUIRED_CONFIG} +TARGET_PRODUCT_TYPE=${TARGET_PRODUCT#*_} case "$REQUIRED_DEFCONFIG" in ${PLATFORM_NAME}-qgki-debug_defconfig ) - FINAL_DEFCONFIG_BLEND+=" $QCOM_DEBUG_FRAG" + if [ $TARGET_PRODUCT_TYPE != "factory" ]; then + FINAL_DEFCONFIG_BLEND+=" $QCOM_DEBUG_FRAG" + fi ;& # Intentional fallthrough ${PLATFORM_NAME}-qgki-consolidate_defconfig ) - FINAL_DEFCONFIG_BLEND+=" $QCOM_CONSOLIDATE_FRAG" + if [ $TARGET_PRODUCT_TYPE != "factory" ]; then + FINAL_DEFCONFIG_BLEND+=" $QCOM_CONSOLIDATE_FRAG" + fi ;& # Intentional fallthrough ${PLATFORM_NAME}-qgki_defconfig ) # DEBUG_FS fragment. @@ -77,7 +82,9 @@ case "$REQUIRED_DEFCONFIG" in FINAL_DEFCONFIG_BLEND+=" $QCOM_GKI_FRAG " ;; ${PLATFORM_NAME}-debug_defconfig ) - FINAL_DEFCONFIG_BLEND+=" $QCOM_GENERIC_DEBUG_FRAG " + if [ $TARGET_PRODUCT_TYPE != "factory" ]; then + FINAL_DEFCONFIG_BLEND+=" $QCOM_GENERIC_DEBUG_FRAG " + fi ;& ${PLATFORM_NAME}_defconfig ) FINAL_DEFCONFIG_BLEND+=" $QCOM_GENERIC_PERF_FRAG " From 0ad3cfe7d00e1e1c447442eaaaec6362538febdb Mon Sep 17 00:00:00 2001 From: Yonghui Jia Date: Fri, 23 Apr 2021 03:42:52 -0500 Subject: [PATCH 338/698] Revert "kernel5.4: mm zram:free the swap slot when swap in" Reason, the changes may cause panic problem Fix, revert the change This reverts commit 147db8784085f8456da0c2870e626da4c25f1778. Change-Id: Ia4cfda84125c5d06af363e6a2d685d0c94c26c5f Reviewed-on: https://gerrit.mot.com/1930858 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Zhizhong Ge Reviewed-by: Zhangqing Huang Reviewed-by: Huosheng Liao Reviewed-by: Zhongsheng Xia Submit-Approved: Jira Key --- mm/page_io.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/mm/page_io.c b/mm/page_io.c index 6a88629a5806..e91f008af794 100644 --- a/mm/page_io.c +++ b/mm/page_io.c @@ -398,12 +398,11 @@ int swap_readpage(struct page *page, bool synchronous) ret = bdev_read_page(sis->bdev, swap_page_sector(page), page); if (!ret) { - /* - * Moto huangzq2: We either remove the trylock_page or use lock_page - * here, becuase trylock will always return false due to page_endio - * in zram_rw_page. - */ - swap_slot_free_notify(page); + if (trylock_page(page)) { + swap_slot_free_notify(page); + unlock_page(page); + } + count_vm_event(PSWPIN); goto out; } From 2378f761eff4abcaa9a380ce1b47e826c3e6d20f Mon Sep 17 00:00:00 2001 From: jixj Date: Tue, 27 Apr 2021 14:37:34 +0800 Subject: [PATCH 339/698] defconfig: initial cyprus defconfig Cyprus 5G: SM4350, initial configs cloned from corfup. Change-Id: I4bcfe484944cc42f0bca56639c9dcd910af652ee Reviewed-on: https://gerrit.mot.com/1933497 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- .../ext_config/debug-holi-cyprus.config | 25 +++++++++++++++++++ .../ext_config/factory-holi-cyprus.config | 16 ++++++++++++ .../vendor/ext_config/moto-holi-cyprus.config | 20 +++++++++++++++ drivers/soc/qcom/Kconfig | 8 ++++++ 4 files changed, 69 insertions(+) create mode 100644 arch/arm64/configs/vendor/ext_config/debug-holi-cyprus.config create mode 100644 arch/arm64/configs/vendor/ext_config/factory-holi-cyprus.config create mode 100644 arch/arm64/configs/vendor/ext_config/moto-holi-cyprus.config diff --git a/arch/arm64/configs/vendor/ext_config/debug-holi-cyprus.config b/arch/arm64/configs/vendor/ext_config/debug-holi-cyprus.config new file mode 100644 index 000000000000..13f71e03c466 --- /dev/null +++ b/arch/arm64/configs/vendor/ext_config/debug-holi-cyprus.config @@ -0,0 +1,25 @@ +# +# Please avoid changing the Qualcomm defconfig files and use this file to +# add any Motorola-specific configuration changes that are applicable to +# userdebug, eng, and user builds. +# +# After building, a list of all of the config files that are used can be found +# at the top of: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/mapphone_defconfig +# +# The actual output of the kernel configuration system can be found at: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/.config +# +# You can check the .config file to verify that your configuration option is +# being set as expected. +# + +# CONFIG_CGROUP_DEBUG is not set +# CONFIG_CLEANCACHE is not set +# CONFIG_CMA_ALLOW_WRITE_DEBUGFS is not set +# CONFIG_CMA_DEBUG is not set +# CONFIG_PREEMPTIRQ_EVENTS is not set +# CONFIG_PREEMPT_TRACER is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_TEST_USER_COPY is not set diff --git a/arch/arm64/configs/vendor/ext_config/factory-holi-cyprus.config b/arch/arm64/configs/vendor/ext_config/factory-holi-cyprus.config new file mode 100644 index 000000000000..830e8a22f610 --- /dev/null +++ b/arch/arm64/configs/vendor/ext_config/factory-holi-cyprus.config @@ -0,0 +1,16 @@ +# +# Please avoid changing the Qualcomm defconfig files and use this file to +# add any Motorola-specific configuration changes that are applicable to +# userdebug, eng, and user builds. +# +# After building, a list of all of the config files that are used can be found +# at the top of: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/mapphone_defconfig +# +# The actual output of the kernel configuration system can be found at: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/.config +# +# You can check the .config file to verify that your configuration option is +# being set as expected. +# + diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-cyprus.config b/arch/arm64/configs/vendor/ext_config/moto-holi-cyprus.config new file mode 100644 index 000000000000..7fb00ded132e --- /dev/null +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-cyprus.config @@ -0,0 +1,20 @@ +# +# Please avoid changing the Qualcomm defconfig files and use this file to +# add any Motorola-specific configuration changes that are applicable to +# userdebug, eng, and user builds. +# +# After building, a list of all of the config files that are used can be found +# at the top of: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/mapphone_defconfig +# +# The actual output of the kernel configuration system can be found at: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/.config +# +# You can check the .config file to verify that your configuration option is +# being set as expected. +# +CONFIG_CYPRUS_DTB=y +# CONFIG_NFC_QTI_I2C is not set +CONFIG_FS_EPOLL_WAKEUP_DEBUG=y +CONFIG_ZRAM_WRITEBACK=y +# CONFIG_THERMAL_STATISTICS is not set diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index eea8e02fabae..1301457d637f 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -36,6 +36,14 @@ config CORFUP_DTB Only include CORFUP specific DTBs to limit the number that get built during kernel compilation. +config CYPRUS_DTB + depends on ARCH_QCOM + default n + bool "CYPRUS DTBs" + help + Only include CYPRUS specific DTBs to limit the number that + get built during kernel compilation. + config QCOM_AOSS_QMP tristate "Qualcomm AOSS Driver" depends on ARCH_QCOM || COMPILE_TEST From baa5f17656c7a149fb97e37b083a3290f2f9593c Mon Sep 17 00:00:00 2001 From: jixj Date: Thu, 6 May 2021 14:59:31 +0800 Subject: [PATCH 340/698] Change device name from cyprus to cypfg for Cyprus 5G device name "cyprus" was already used by ODM1 project. So need change device name from cyprus to cypfg for Cyprus 5G project. Change-Id: I7b4ce66495d3232b928e0b6fdcfaa44d0e16e7f7 Reviewed-on: https://gerrit.mot.com/1940602 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiaojun Ji Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- .../{debug-holi-cyprus.config => debug-holi-cypfg.config} | 0 ...factory-holi-cyprus.config => factory-holi-cypfg.config} | 0 .../{moto-holi-cyprus.config => moto-holi-cypfg.config} | 2 +- drivers/soc/qcom/Kconfig | 6 +++--- 4 files changed, 4 insertions(+), 4 deletions(-) rename arch/arm64/configs/vendor/ext_config/{debug-holi-cyprus.config => debug-holi-cypfg.config} (100%) rename arch/arm64/configs/vendor/ext_config/{factory-holi-cyprus.config => factory-holi-cypfg.config} (100%) rename arch/arm64/configs/vendor/ext_config/{moto-holi-cyprus.config => moto-holi-cypfg.config} (97%) diff --git a/arch/arm64/configs/vendor/ext_config/debug-holi-cyprus.config b/arch/arm64/configs/vendor/ext_config/debug-holi-cypfg.config similarity index 100% rename from arch/arm64/configs/vendor/ext_config/debug-holi-cyprus.config rename to arch/arm64/configs/vendor/ext_config/debug-holi-cypfg.config diff --git a/arch/arm64/configs/vendor/ext_config/factory-holi-cyprus.config b/arch/arm64/configs/vendor/ext_config/factory-holi-cypfg.config similarity index 100% rename from arch/arm64/configs/vendor/ext_config/factory-holi-cyprus.config rename to arch/arm64/configs/vendor/ext_config/factory-holi-cypfg.config diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-cyprus.config b/arch/arm64/configs/vendor/ext_config/moto-holi-cypfg.config similarity index 97% rename from arch/arm64/configs/vendor/ext_config/moto-holi-cyprus.config rename to arch/arm64/configs/vendor/ext_config/moto-holi-cypfg.config index 7fb00ded132e..e805d169eea8 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-cyprus.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-cypfg.config @@ -13,7 +13,7 @@ # You can check the .config file to verify that your configuration option is # being set as expected. # -CONFIG_CYPRUS_DTB=y +CONFIG_CYPFG_DTB=y # CONFIG_NFC_QTI_I2C is not set CONFIG_FS_EPOLL_WAKEUP_DEBUG=y CONFIG_ZRAM_WRITEBACK=y diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index 1301457d637f..4ba2e7c11011 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -36,12 +36,12 @@ config CORFUP_DTB Only include CORFUP specific DTBs to limit the number that get built during kernel compilation. -config CYPRUS_DTB +config CYPFG_DTB depends on ARCH_QCOM default n - bool "CYPRUS DTBs" + bool "CYPFG DTBs" help - Only include CYPRUS specific DTBs to limit the number that + Only include CYPFG specific DTBs to limit the number that get built during kernel compilation. config QCOM_AOSS_QMP From ffaa6c5aad658bac115524bf152fe744a3832426 Mon Sep 17 00:00:00 2001 From: zhangly19 Date: Tue, 11 May 2021 10:25:22 +0800 Subject: [PATCH 341/698] fix r1.0_00026 rebase error ++++++++++ ld.lld: error: undefined symbol: smblib_get_prop_usb_voltage_max >>> referenced by qpnp-smb5.c:939 ++++++++++ move "#ifdef QCOM_BASE" to correct location Change-Id: I099e7f607e190d3ec3ce17a7a1ede8a7bd1c0005 Reviewed-on: https://gerrit.mot.com/1945042 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Submit-Approved: Jira Key Tested-by: Jira Key Reviewed-by: Haijian Ma Reviewed-by: Lianlu Chen --- drivers/power/supply/qcom/smb5-lib.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/power/supply/qcom/smb5-lib.c b/drivers/power/supply/qcom/smb5-lib.c index b17f5b356c74..38cb13bb4cb6 100644 --- a/drivers/power/supply/qcom/smb5-lib.c +++ b/drivers/power/supply/qcom/smb5-lib.c @@ -3491,7 +3491,7 @@ int smblib_get_prop_usb_voltage_max_design(struct smb_charger *chg, { switch (chg->real_charger_type) { case QTI_POWER_SUPPLY_TYPE_USB_HVDCP: -#ifdef QCOM_BASE + if (chg->qc2_unsupported_voltage == QC2_NON_COMPLIANT_9V) { val->intval = MICRO_5V; break; @@ -3522,6 +3522,7 @@ int smblib_get_prop_usb_voltage_max(struct smb_charger *chg, { switch (chg->real_charger_type) { case QTI_POWER_SUPPLY_TYPE_USB_HVDCP: +#ifdef QCOM_BASE if (chg->qc2_unsupported_voltage == QC2_NON_COMPLIANT_9V) { val->intval = MICRO_5V; break; From 632683b8f167cccfed6e42fae0b097354cebb830 Mon Sep 17 00:00:00 2001 From: huangzq2 Date: Tue, 27 Apr 2021 18:08:04 +0800 Subject: [PATCH 342/698] mm: zram: use rw_page for zram page but submit_bio for zram wb page Since reading zram wb page is an async operation, we can not immediately free the slot here. So we need to read the page via submit_bio and free the slot in end_swap_bio_read. (bio chain will be used to handle bio here and bio in zram driver for wb page). Change-Id: I71b88c4a2388c086bd7e0cd63b8c632b93217a95 Signed-off-by: huangzq2 Reviewed-on: https://gerrit.mot.com/1933720 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key Reviewed-on: https://gerrit.mot.com/1952123 Reviewed-by: Yonghui Jia Reviewed-by: Huosheng Liao --- mm/page_io.c | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/mm/page_io.c b/mm/page_io.c index e91f008af794..2c6201e9f645 100644 --- a/mm/page_io.c +++ b/mm/page_io.c @@ -84,7 +84,7 @@ bool swap_slot_has_sync_io(swp_entry_t entry) SWP_SYNCHRONOUS_IO, swp_offset(entry)) == 1; } - return false; + return (sis->flags & SWP_SYNCHRONOUS_IO) == SWP_SYNCHRONOUS_IO; } static void swap_slot_free_notify(struct page *page) @@ -368,6 +368,7 @@ int swap_readpage(struct page *page, bool synchronous) blk_qc_t qc; struct gendisk *disk; unsigned long pflags; + swp_entry_t entry; VM_BUG_ON_PAGE(!PageSwapCache(page) && !synchronous, page); VM_BUG_ON_PAGE(!PageLocked(page), page); @@ -396,15 +397,24 @@ int swap_readpage(struct page *page, bool synchronous) goto out; } - ret = bdev_read_page(sis->bdev, swap_page_sector(page), page); - if (!ret) { - if (trylock_page(page)) { - swap_slot_free_notify(page); - unlock_page(page); - } + /* Moto huangzq2: Use rw_page for zram page but submit_bio for zram wb page. + * Since reading zram wb page is an async operation, we can not immediately + * free the slot here. So we need to read the page via submit_bio and free + * the slot in end_swap_bio_read. (bio chain will be used to handle bio here + * and bio in zram driver for wb page). + */ + entry.val = page_private(page); + if (swap_slot_has_sync_io(entry)) { + ret = bdev_read_page(sis->bdev, swap_page_sector(page), page); + if (!ret) { + if (trylock_page(page)) { + swap_slot_free_notify(page); + unlock_page(page); + } - count_vm_event(PSWPIN); - goto out; + count_vm_event(PSWPIN); + goto out; + } } ret = 0; From b2c751350a2beec83698419007eac689c0045833 Mon Sep 17 00:00:00 2001 From: wangyq13 Date: Wed, 19 May 2021 23:27:44 +0800 Subject: [PATCH 343/698] deconfig: corfup: disable fts touch configs, move to ko defconfig/corfup: Disable fts touch configs, move fts driver to ko. Change-Id: I267acf79228137fa91f5eff593cd3ed5d5c9bf07 Signed-off-by: wangyq13 Reviewed-on: https://gerrit.mot.com/1954462 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Jun Weng Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi-corfup.config | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-corfup.config b/arch/arm64/configs/vendor/ext_config/moto-holi-corfup.config index 4b9f14dfcb0d..b5bf64fc77d5 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-corfup.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-corfup.config @@ -18,3 +18,5 @@ CONFIG_CORFUP_DTB=y CONFIG_FS_EPOLL_WAKEUP_DEBUG=y CONFIG_ZRAM_WRITEBACK=y # CONFIG_THERMAL_STATISTICS is not set +# CONFIG_TOUCHSCREEN_FTS is not set +# CONFIG_TOUCHSCREEN_FTS_DIRECTORY is not set From d4bbff0602c4bf0a5e6a428a38e769cb0fc5638b Mon Sep 17 00:00:00 2001 From: fuxm1 Date: Wed, 24 Feb 2021 16:27:03 +0800 Subject: [PATCH 344/698] scsi/ufs: porting Samsung TW + HPB feature Remark: proting samsung hpb + tw driver to msm-5.4 br-4350 branch Change-Id: Ie964195e3b9bc1ef7d5ba585e839239b4aa1c761 Signed-off-by: fuxm1 Reviewed-on: https://gerrit.mot.com/1885583 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- drivers/scsi/ufs/Kconfig | 58 + drivers/scsi/ufs/Makefile | 4 + drivers/scsi/ufs/ufs-qcom.c | 8 + drivers/scsi/ufs/ufs.h | 67 +- drivers/scsi/ufs/ufsfeature.c | 703 ++++++ drivers/scsi/ufs/ufsfeature.h | 192 ++ drivers/scsi/ufs/ufshcd.c | 227 +- drivers/scsi/ufs/ufshcd.h | 46 + drivers/scsi/ufs/ufshpb.c | 4099 +++++++++++++++++++++++++++++++++ drivers/scsi/ufs/ufshpb.h | 346 +++ drivers/scsi/ufs/ufshpb_skh.c | 3275 ++++++++++++++++++++++++++ drivers/scsi/ufs/ufshpb_skh.h | 518 +++++ drivers/scsi/ufs/ufstw.c | 900 ++++++++ drivers/scsi/ufs/ufstw.h | 126 + include/scsi/scsi_cmnd.h | 3 + 15 files changed, 10562 insertions(+), 10 deletions(-) create mode 100755 drivers/scsi/ufs/ufsfeature.c create mode 100755 drivers/scsi/ufs/ufsfeature.h create mode 100755 drivers/scsi/ufs/ufshpb.c create mode 100755 drivers/scsi/ufs/ufshpb.h create mode 100644 drivers/scsi/ufs/ufshpb_skh.c create mode 100644 drivers/scsi/ufs/ufshpb_skh.h create mode 100755 drivers/scsi/ufs/ufstw.c create mode 100755 drivers/scsi/ufs/ufstw.h diff --git a/drivers/scsi/ufs/Kconfig b/drivers/scsi/ufs/Kconfig index f25d1491a4d4..1c3484c72b6b 100644 --- a/drivers/scsi/ufs/Kconfig +++ b/drivers/scsi/ufs/Kconfig @@ -196,3 +196,61 @@ config SCSI_UFS_CRYPTO_QTI Enable Vendor Crypto Engine Support in UFS Enabling this allows kernel to use UFS crypto operations defined and implemented by QTI. + +config UFSFEATURE + bool "UFS feature activate" + depends on SCSI_UFSHCD + ---help--- + UFS feature activate such as hpb, tw and etc. + +config UFSHPB + bool "UFS Host Performance Booster support" + depends on SCSI_UFSHCD && UFSFEATURE + ---help--- + UFS HPB Feature Enable + +config HPB_DEBUG + bool "HPB Debug Log Enable" + depends on SCSI_UFSHCD && UFSFEATURE && UFSHPB + default n + ---help--- + UFS HPB Debug Enable (dmesg log[=if set debug sysfs] & BLK_TRACE msg) + +config HPB_ERR_INJECTION + bool "HPB ERROR INJECTION" + depends on SCSI_UFSHCD && UFSFEATURE && UFSHPB + ---help--- + error injection for checking HPB entry integrity + +config UFSTW + bool "UFS Turbo Write support" + depends on SCSI_UFSHCD && UFSFEATURE + ---help--- + UFS TW Feature Enable + +config UFSTW_IGNORE_GUARANTEE_BIT + bool "Ignore UFS Turbo Write Life Time Guarantee bit for POC" + default n + depends on SCSI_UFSHCD && UFSFEATURE && UFSTW + ---help--- + ignore the guarantee bit[31] of dTurboWriteBufferLifeTimeEst for PoC + +config UFSTW_BOOT_ENABLED + bool "Turbo Write enabled at boot time" + default y + depends on SCSI_UFSHCD && UFSFEATURE && UFSTW + ---help--- + fTurboWriteEn and fTurboWriteBufferFlushDuringHibnerEnter flags + are enabled at boot time. + +config SCSI_SKHPB + bool "Activate HPB Host-aware Performance Booster" + depends on (SCSI_UFSHCD || SCSI_UFSHCD_QTI) + help + Activate or deactive SKHPB driver + +config MICRON_HPB + bool "Activate micron HPB Host-aware Performance Booster" + depends on SCSI_UFSHCD && UFSFEATURE && UFSHPB + help + Activate or deactive micron HPB driver diff --git a/drivers/scsi/ufs/Makefile b/drivers/scsi/ufs/Makefile index 8a0421a1b569..f0d24fac1ee8 100644 --- a/drivers/scsi/ufs/Makefile +++ b/drivers/scsi/ufs/Makefile @@ -5,8 +5,12 @@ obj-$(CONFIG_SCSI_UFS_DWC_TC_PLATFORM) += tc-dwc-g210-pltfrm.o ufshcd-dwc.o tc-d obj-$(CONFIG_SCSI_UFS_CDNS_PLATFORM) += cdns-pltfrm.o obj-$(CONFIG_SCSI_UFS_QCOM) += ufs-qcom.o obj-$(CONFIG_SCSI_UFSHCD) += ufshcd-core.o +obj-$(CONFIG_UFSFEATURE) += ufsfeature.o +obj-$(CONFIG_UFSHPB) += ufshpb.o +obj-$(CONFIG_UFSTW) += ufstw.o ufshcd-core-y += ufshcd.o ufs-sysfs.o ufshcd-core-$(CONFIG_SCSI_UFS_BSG) += ufs_bsg.o +obj-$(CONFIG_SCSI_SKHPB) += ufshpb_skh.o obj-$(CONFIG_SCSI_UFSHCD_PCI) += ufshcd-pci.o obj-$(CONFIG_SCSI_UFSHCD_PLATFORM) += ufshcd-pltfrm.o obj-$(CONFIG_SCSI_UFS_HISI) += ufs-hisi.o diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c index 562ac279de39..8d976bc3e3e0 100644 --- a/drivers/scsi/ufs/ufs-qcom.c +++ b/drivers/scsi/ufs/ufs-qcom.c @@ -2257,6 +2257,14 @@ ufs_qcom_query_ioctl(struct ufs_hba *hba, u8 lun, void __user *buffer) goto out_release_mem; } +#if defined(CONFIG_UFSFEATURE) + if (ufsf_check_query(ioctl_data->opcode)) { + err = ufsf_query_ioctl(hba, lun, buffer, ioctl_data, + UFSFEATURE_SELECTOR); + goto out_release_mem; + } +#endif + /* verify legal parameters & send query */ switch (ioctl_data->opcode) { case UPIU_QUERY_OPCODE_READ_DESC: diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h index 22f03719b419..39a2b164c661 100644 --- a/drivers/scsi/ufs/ufs.h +++ b/drivers/scsi/ufs/ufs.h @@ -152,6 +152,14 @@ enum flag_idn { QUERY_FLAG_IDN_WB_EN = 0x0E, QUERY_FLAG_IDN_WB_BUFF_FLUSH_EN = 0x0F, QUERY_FLAG_IDN_WB_BUFF_FLUSH_DURING_HIBERN8 = 0x10, +#if defined(CONFIG_UFSHPB) || defined(CONFIG_SCSI_SKHPB) + QUERY_FLAG_IDN_HPB_RESET = 0x11, +#endif +#if defined(CONFIG_UFSTW) + QUERY_FLAG_IDN_TW_EN = 0x0E, + QUERY_FLAG_IDN_TW_BUF_FLUSH_EN = 0x0F, + QUERY_FLAG_IDN_TW_FLUSH_DURING_HIBERN = 0x10, +#endif }; /* Attribute idn for Query requests */ @@ -184,8 +192,19 @@ enum attr_idn { QUERY_ATTR_IDN_AVAIL_WB_BUFF_SIZE = 0x1D, QUERY_ATTR_IDN_WB_BUFF_LIFE_TIME_EST = 0x1E, QUERY_ATTR_IDN_CURR_WB_BUFF_SIZE = 0x1F, +#if defined(CONFIG_UFSTW) + QUERY_ATTR_IDN_TW_FLUSH_STATUS = 0x1C, + QUERY_ATTR_IDN_TW_AVAIL_BUF_SIZE = 0x1D, + QUERY_ATTR_IDN_TW_BUF_LIFETIME_EST = 0x1E, + QUERY_ATTR_IDN_TW_CURR_BUF_SIZE = 0x1F, +#endif +#if defined(CONFIG_UFSFEATURE) + QUERY_ATTR_IDN_SUP_VENDOR_OPTIONS = 0xFF, +#endif }; +#define QUERY_ATTR_IDN_BOOT_LU_EN_MAX 0x02 + /* Descriptor idn for Query requests */ enum desc_idn { QUERY_DESC_IDN_DEVICE = 0x0, @@ -207,11 +226,11 @@ enum desc_header_offset { }; enum ufs_desc_def_size { - QUERY_DESC_DEVICE_DEF_SIZE = 0x59, - QUERY_DESC_CONFIGURATION_DEF_SIZE = 0x90, + QUERY_DESC_DEVICE_DEF_SIZE = 0x5F, + QUERY_DESC_CONFIGURATION_DEF_SIZE = 0xE6, QUERY_DESC_UNIT_DEF_SIZE = 0x2D, QUERY_DESC_INTERCONNECT_DEF_SIZE = 0x06, - QUERY_DESC_GEOMETRY_DEF_SIZE = 0x48, + QUERY_DESC_GEOMETRY_DEF_SIZE = 0x59, QUERY_DESC_POWER_DEF_SIZE = 0x62, QUERY_DESC_HEALTH_DEF_SIZE = 0x25, }; @@ -236,6 +255,15 @@ enum unit_desc_param { UNIT_DESC_PARAM_CTX_CAPABILITIES = 0x20, UNIT_DESC_PARAM_LARGE_UNIT_SIZE_M1 = 0x22, UNIT_DESC_PARAM_WB_BUF_ALLOC_UNITS = 0x29, +#if defined(CONFIG_UFSHPB) || defined(CONFIG_SCSI_SKHPB) + UNIT_DESC_HPB_LU_MAX_ACTIVE_REGIONS = 0x23, + UNIT_DESC_HPB_LU_PIN_REGION_START_OFFSET = 0x25, + UNIT_DESC_HPB_LU_NUM_PIN_REGIONS = 0x27, +#endif +#if defined(CONFIG_UFSTW) + UNIT_DESC_TW_LU_WRITE_BUFFER_ALLOC_UNIT = 0x29, + +#endif }; /* Device descriptor parameters offsets in bytes*/ @@ -279,6 +307,19 @@ enum device_desc_param { DEVICE_DESC_PARAM_WB_PRESRV_USRSPC_EN = 0x53, DEVICE_DESC_PARAM_WB_TYPE = 0x54, DEVICE_DESC_PARAM_WB_SHARED_ALLOC_UNITS = 0x55, +#if defined(CONFIG_UFSHPB) || defined(CONFIG_SCSI_SKHPB) + DEVICE_DESC_PARAM_HPB_VER = 0x40, + DEVICE_DESC_PARAM_HPB_CONTROL = 0x42, +#endif +#if defined(CONFIG_UFSFEATURE) + DEVICE_DESC_PARAM_EX_FEAT_SUP = 0x4F, +#endif +#if defined(CONFIG_UFSTW) + DEVICE_DESC_PARAM_TW_VER = 0x4D, + DEVICE_DESC_PARAM_TW_RETURN_TO_USER = 0x53, + DEVICE_DESC_PARAM_TW_BUF_TYPE = 0x54, + DEVICE_DESC_PARAM_TW_SHARED_BUF_ALLOC_UNITS = 0x55, +#endif }; /* Interconnect descriptor parameters offsets in bytes*/ @@ -328,6 +369,20 @@ enum geometry_desc_param { GEOMETRY_DESC_PARAM_WB_BUFF_CAP_ADJ = 0x54, GEOMETRY_DESC_PARAM_WB_SUP_RED_TYPE = 0x55, GEOMETRY_DESC_PARAM_WB_SUP_WB_TYPE = 0x56, +#if defined(CONFIG_UFSHPB) || defined(CONFIG_SCSI_SKHPB) + GEOMETRY_DESC_HPB_REGION_SIZE = 0x48, + GEOMETRY_DESC_HPB_NUMBER_LU = 0x49, + GEOMETRY_DESC_HPB_SUBREGION_SIZE = 0x4A, + GEOMETRY_DESC_HPB_DEVICE_MAX_ACTIVE_REGIONS = 0x4B, +#endif +#if defined(CONFIG_UFSTW) + GEOMETRY_DESC_TW_GROUP_NUM_CAP = 0x4E, + GEOMETRY_DESC_TW_MAX_SIZE = 0x4F, + GEOMETRY_DESC_TW_NUMBER_LU = 0x53, + GEOMETRY_DESC_TW_CAP_ADJ_FAC = 0x54, + GEOMETRY_DESC_TW_SUPPORT_USER_REDUCTION_TYPES = 0x55, + GEOMETRY_DESC_TW_SUPPORT_BUF_TYPE = 0x56, +#endif }; /* Health descriptor parameters offsets in bytes*/ @@ -391,6 +446,9 @@ enum power_desc_param_offset { enum { MASK_EE_STATUS = 0xFFFF, MASK_EE_URGENT_BKOPS = (1 << 2), +#if defined(CONFIG_UFSTW) + MASK_EE_TW = (1 << 5), +#endif }; /* Background operation status */ @@ -469,6 +527,9 @@ enum { MASK_RSP_EXCEPTION_EVENT = 0x10000, MASK_TM_SERVICE_RESP = 0xFF, MASK_TM_FUNC = 0xFF, +#if defined(CONFIG_SCSI_SKHPB) + MASK_RSP_UPIU_HPB_UPDATE_ALERT = 0x20000, +#endif }; /* Task management service response */ diff --git a/drivers/scsi/ufs/ufsfeature.c b/drivers/scsi/ufs/ufsfeature.c new file mode 100755 index 000000000000..7f65f74efb04 --- /dev/null +++ b/drivers/scsi/ufs/ufsfeature.c @@ -0,0 +1,703 @@ +/* + * Universal Flash Storage Feature Support + * + * Copyright (C) 2017-2018 Samsung Electronics Co., Ltd. + * + * Authors: + * Yongmyung Lee + * Jinyoung Choi + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * See the COPYING file in the top-level directory or visit + * + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * This program is provided "AS IS" and "WITH ALL FAULTS" and + * without warranty of any kind. You are solely responsible for + * determining the appropriateness of using and distributing + * the program and assume all risks associated with your exercise + * of rights with respect to the program, including but not limited + * to infringement of third party rights, the risks and costs of + * program errors, damage to or loss of data, programs or equipment, + * and unavailability or interruption of operations. Under no + * circumstances will the contributor of this Program be liable for + * any damages of any kind arising from your use or distribution of + * this program. + * + * The Linux Foundation chooses to take subject only to the GPLv2 + * license terms, and distributes only under these terms. + */ + +#include "ufsfeature.h" +#include "ufshcd.h" +#include "ufs-qcom.h" + +#define QUERY_REQ_TIMEOUT 1500 /* msec */ + +static inline void ufsf_init_query(struct ufs_hba *hba, + struct ufs_query_req **request, + struct ufs_query_res **response, + enum query_opcode opcode, u8 idn, + u8 index, u8 selector) +{ + *request = &hba->dev_cmd.query.request; + *response = &hba->dev_cmd.query.response; + memset(*request, 0, sizeof(struct ufs_query_req)); + memset(*response, 0, sizeof(struct ufs_query_res)); + (*request)->upiu_req.opcode = opcode; + (*request)->upiu_req.idn = idn; + (*request)->upiu_req.index = index; + (*request)->upiu_req.selector = selector; +} + +/* + * ufs feature common functions. + */ +static int ufsf_query_flag(struct ufs_hba *hba, enum query_opcode opcode, + enum flag_idn idn, u8 index, bool *flag_res) +{ + struct ufs_query_req *request = NULL; + struct ufs_query_res *response = NULL; + int err; + + BUG_ON(!hba); + + ufshcd_hold(hba, false); + mutex_lock(&hba->dev_cmd.lock); + + /* + * Init the query response and request parameters + */ + ufsf_init_query(hba, &request, &response, opcode, idn, index, + UFSFEATURE_SELECTOR); + + switch (opcode) { + case UPIU_QUERY_OPCODE_SET_FLAG: + case UPIU_QUERY_OPCODE_CLEAR_FLAG: + case UPIU_QUERY_OPCODE_TOGGLE_FLAG: + request->query_func = UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST; + break; + case UPIU_QUERY_OPCODE_READ_FLAG: + request->query_func = UPIU_QUERY_FUNC_STANDARD_READ_REQUEST; + if (!flag_res) { + /* No dummy reads */ + dev_err(hba->dev, "%s: Invalid argument for read request\n", + __func__); + err = -EINVAL; + goto out_unlock; + } + break; + default: + dev_err(hba->dev, + "%s: Expected query flag opcode but got = %d\n", + __func__, opcode); + err = -EINVAL; + goto out_unlock; + } + + /* Send query request */ + err = ufshcd_exec_dev_cmd(hba, DEV_CMD_TYPE_QUERY, QUERY_REQ_TIMEOUT); + if (err) { + dev_err(hba->dev, + "%s: Sending flag query for idn %d failed, err = %d\n", + __func__, idn, err); + goto out_unlock; + } + + if (flag_res) + *flag_res = (be32_to_cpu(response->upiu_res.value) & + MASK_QUERY_UPIU_FLAG_LOC) & 0x1; + +out_unlock: + mutex_unlock(&hba->dev_cmd.lock); + ufshcd_release(hba); + return err; +} + +int ufsf_query_flag_retry(struct ufs_hba *hba, enum query_opcode opcode, + enum flag_idn idn, u8 idx, bool *flag_res) +{ + int ret; + int retries; + + BUG_ON(idx > 7); + + for (retries = 0; retries < UFSF_QUERY_REQ_RETRIES; retries++) { + ret = ufsf_query_flag(hba, opcode, idn, idx, flag_res); + if (ret) + dev_dbg(hba->dev, + "%s: failed with error %d, retries %d\n", + __func__, ret, retries); + else + break; + } + if (ret) + dev_err(hba->dev, + "%s: query flag, opcode %d, idn %d, failed with error %d after %d retires\n", + __func__, opcode, idn, ret, retries); + return ret; +} + +int ufsf_query_attr_retry(struct ufs_hba *hba, enum query_opcode opcode, + enum attr_idn idn, u8 idx, u32 *attr_val) +{ + int ret; + int retries; + + for (retries = 0; retries < UFSF_QUERY_REQ_RETRIES; retries++) { + ret = ufshcd_query_attr(hba, opcode, idn, idx, + UFSFEATURE_SELECTOR, attr_val); + if (ret) + dev_dbg(hba->dev, + "%s: failed with error %d, retries %d\n", + __func__, ret, retries); + else + break; + } + if (ret) + dev_err(hba->dev, + "%s: query attr, opcode %d, idn %d, failed with error %d after %d retires\n", + __func__, opcode, idn, ret, retries); + return ret; +} + +static int ufsf_read_desc(struct ufs_hba *hba, u8 desc_id, u8 desc_index, + u8 selector, u8 *desc_buf, u32 size) +{ + int err = 0; + + pm_runtime_get_sync(hba->dev); + + err = ufshcd_query_descriptor_retry(hba, UPIU_QUERY_OPCODE_READ_DESC, + desc_id, desc_index, + selector, + desc_buf, &size); + if (err) + ERR_MSG("reading Device Desc failed. err = %d", err); + + pm_runtime_put_sync(hba->dev); + + return err; +} + +static int ufsf_read_dev_desc(struct ufsf_feature *ufsf, u8 selector) +{ + u8 desc_buf[UFSF_QUERY_DESC_DEVICE_MAX_SIZE]; + int ret; + + ret = ufsf_read_desc(ufsf->hba, QUERY_DESC_IDN_DEVICE, 0, selector, + desc_buf, UFSF_QUERY_DESC_DEVICE_MAX_SIZE); + if (ret) + return ret; + + ufsf->num_lu = desc_buf[DEVICE_DESC_PARAM_NUM_LU]; + INFO_MSG("device lu count %d", ufsf->num_lu); + + INFO_MSG("sel=%u length=%u(0x%x) bSupport=0x%.2x, extend=0x%.2x_%.2x", + selector, desc_buf[DEVICE_DESC_PARAM_LEN], + desc_buf[DEVICE_DESC_PARAM_LEN], + desc_buf[DEVICE_DESC_PARAM_UFS_FEAT], + desc_buf[DEVICE_DESC_PARAM_EX_FEAT_SUP+2], + desc_buf[DEVICE_DESC_PARAM_EX_FEAT_SUP+3]); + + INFO_MSG("Driver Feature Version : (%.6X%s)", UFSFEATURE_DD_VER, + UFSFEATURE_DD_VER_POST); + + +#if defined(CONFIG_UFSHPB) + ufshpb_get_dev_info(ufsf, desc_buf); +#endif +#if defined(CONFIG_UFSTW) + ufstw_get_dev_info(ufsf, desc_buf); +#endif + return 0; +} + +static int ufsf_read_geo_desc(struct ufsf_feature *ufsf, u8 selector) +{ + u8 geo_buf[UFSF_QUERY_DESC_GEOMETRY_MAX_SIZE]; + int ret; + + ret = ufsf_read_desc(ufsf->hba, QUERY_DESC_IDN_GEOMETRY, 0, selector, + geo_buf, UFSF_QUERY_DESC_GEOMETRY_MAX_SIZE); + if (ret) + return ret; + +#if defined(CONFIG_UFSHPB) + if (ufshpb_get_state(ufsf) == HPB_NEED_INIT) + ufshpb_get_geo_info(ufsf, geo_buf); +#endif + +#if defined(CONFIG_UFSTW) + if (ufstw_get_state(ufsf) == TW_NEED_INIT) + ufstw_get_geo_info(ufsf, geo_buf); +#endif + return 0; +} + +static void ufsf_read_unit_desc(struct ufsf_feature *ufsf, int lun, u8 selector) +{ + u8 unit_buf[UFSF_QUERY_DESC_UNIT_MAX_SIZE]; + int lu_enable, ret = 0; + + ret = ufsf_read_desc(ufsf->hba, QUERY_DESC_IDN_UNIT, lun, selector, + unit_buf, UFSF_QUERY_DESC_UNIT_MAX_SIZE); + if (ret) { + ERR_MSG("read unit desc failed. ret (%d)", ret); + goto out; + } + + lu_enable = unit_buf[UNIT_DESC_PARAM_LU_ENABLE]; + if (!lu_enable) + return; + +#if defined(CONFIG_UFSHPB) + if (ufshpb_get_state(ufsf) == HPB_NEED_INIT) + ufshpb_get_lu_info(ufsf, lun, unit_buf); +#endif + +#if defined(CONFIG_UFSTW) + if (ufstw_get_state(ufsf) == TW_NEED_INIT) + ufstw_alloc_lu(ufsf, lun, unit_buf); +#endif +out: + return; +} + +void ufsf_device_check(struct ufs_hba *hba) +{ + struct ufsf_feature *ufsf = &hba->ufsf; + int ret, lun; + u32 status; + + ufsf->hba = hba; + + ufshcd_query_attr(ufsf->hba, UPIU_QUERY_OPCODE_READ_ATTR, + QUERY_ATTR_IDN_SUP_VENDOR_OPTIONS, 0, 0, &status); + INFO_MSG("UFS FEATURE SELECTOR Dev %d - D/D %d", status, + UFSFEATURE_SELECTOR); + + ret = ufsf_read_dev_desc(ufsf, UFSFEATURE_SELECTOR); + if (ret) + return; + + ret = ufsf_read_geo_desc(ufsf, UFSFEATURE_SELECTOR); + if (ret) + return; + + seq_scan_lu(lun) + ufsf_read_unit_desc(ufsf, lun, UFSFEATURE_SELECTOR); +} + +static int ufsf_execute_dev_ctx_req(struct ufsf_feature *ufsf, + int lun, unsigned char *cdb, + void *buf, int len) +{ + struct scsi_sense_hdr sshdr; + struct scsi_device *sdev; + int ret = 0; + + sdev = ufsf->sdev_ufs_lu[lun]; + if (!sdev) { + WARN_MSG("cannot find scsi_device"); + return -ENODEV; + } + + ufsf->issue_ioctl = true; + ret = scsi_execute(sdev, cdb, DMA_FROM_DEVICE, buf, len, NULL, &sshdr, + msecs_to_jiffies(30000), 3, 0, 0, NULL); + ufsf->issue_ioctl = false; + + return ret; +} + +static inline void ufsf_set_read_dev_ctx(unsigned char *cdb, int lba, int len) +{ + cdb[0] = READ_10; + cdb[1] = 0x02; + cdb[2] = GET_BYTE_3(lba); + cdb[3] = GET_BYTE_2(lba); + cdb[4] = GET_BYTE_1(lba); + cdb[5] = GET_BYTE_0(lba); + cdb[6] = GET_BYTE_2(len); + cdb[7] = GET_BYTE_1(len); + cdb[8] = GET_BYTE_0(len); +} + +int ufsf_issue_req_dev_ctx(struct ufsf_feature *ufsf, int lun, + unsigned char *buf, int buf_len) +{ + unsigned char cdb[10] = { 0 }; + int cmd_len = buf_len >> OS_PAGE_SHIFT; + int ret = 0; + + ufsf_set_read_dev_ctx(cdb, READ10_DEBUG_LBA, cmd_len); + + ret = ufsf_execute_dev_ctx_req(ufsf, lun, cdb, buf, buf_len); + + if (ret < 0) + ERR_MSG("failed with err %d", ret); + + return ret; +} + +static void ufsf_print_query_buf(unsigned char *field, int size) +{ + unsigned char buf[255]; + int count = 0; + int i; + + count += snprintf(buf, 8, "(0x00):"); + + for (i = 0; i < size; i++) { + count += snprintf(buf + count, 4, " %.2X", field[i]); + + if ((i + 1) % 16 == 0) { + buf[count] = '\n'; + buf[count + 1] = '\0'; + printk(buf); + count = 0; + count += snprintf(buf, 8, "(0x%.2X):", i + 1); + } else if ((i + 1) % 4 == 0) + count += snprintf(buf + count, 3, " :"); + } + buf[count] = '\n'; + buf[count + 1] = '\0'; + printk(buf); +} + +inline int ufsf_check_query(__u32 opcode) +{ + return (opcode & 0xffff0000) >> 16 == UFSFEATURE_QUERY_OPCODE; +} + +static inline void ufsf_set_read10_debug_cmd(unsigned char *cdb, int lba, + int len) +{ + cdb[0] = READ_10; + cdb[1] = 0x02; + cdb[2] = GET_BYTE_3(lba); + cdb[3] = GET_BYTE_2(lba); + cdb[4] = GET_BYTE_1(lba); + cdb[5] = GET_BYTE_0(lba); + cdb[6] = GET_BYTE_2(len); + cdb[7] = GET_BYTE_1(len); + cdb[8] = GET_BYTE_0(len); +} + +int ufsf_query_ioctl(struct ufs_hba *hba, int lun, void __user *buffer, + struct ufs_ioctl_query_data *ioctl_data, u8 selector) +{ + unsigned char *kernel_buf; + int opcode; + int err = 0; + int index = 0; + int length = 0; + int buf_len = 0; + + opcode = ioctl_data->opcode & 0xffff; + + INFO_MSG("op %u idn %u sel %u size %u(0x%X)", opcode, ioctl_data->idn, + selector, ioctl_data->buf_size, ioctl_data->buf_size); + + buf_len = (ioctl_data->idn == QUERY_DESC_IDN_STRING) ? + IOCTL_DEV_CTX_MAX_SIZE : QUERY_DESC_MAX_SIZE; + + kernel_buf = kzalloc(buf_len, GFP_KERNEL); + if (!kernel_buf) { + err = -ENOMEM; + goto out; + } + + switch (opcode) { + case UPIU_QUERY_OPCODE_WRITE_DESC: + err = copy_from_user(kernel_buf, buffer + + sizeof(struct ufs_ioctl_query_data), + ioctl_data->buf_size); + INFO_MSG("buf size %d", ioctl_data->buf_size); + ufsf_print_query_buf(kernel_buf, ioctl_data->buf_size); + if (err) + goto out_release_mem; + break; + + case UPIU_QUERY_OPCODE_READ_DESC: + switch (ioctl_data->idn) { + case QUERY_DESC_IDN_UNIT: + if (!ufs_is_valid_unit_desc_lun(lun)) { + ERR_MSG("No unit descriptor for lun 0x%x", lun); + err = -EINVAL; + goto out_release_mem; + } + index = lun; + INFO_MSG("read lu desc lun: %d", index); + break; +#if 0 + case QUERY_DESC_IDN_STRING: + if (!ufs_is_valid_unit_desc_lun(lun)) { + ERR_MSG("No unit descriptor for lun 0x%x", lun); + err = -EINVAL; + goto out_release_mem; + } + err = ufsf_issue_req_dev_ctx(ufsf, lun, kernel_buf, + ioctl_data->buf_size); + if (err < 0) + goto out_release_mem; + + goto copy_buffer; +#endif + case QUERY_DESC_IDN_DEVICE: + case QUERY_DESC_IDN_GEOMETRY: + case QUERY_DESC_IDN_CONFIGURATION: + break; + + default: + ERR_MSG("invalid idn %d", ioctl_data->idn); + err = -EINVAL; + goto out_release_mem; + } + break; + default: + ERR_MSG("invalid opcode %d", opcode); + err = -EINVAL; + goto out_release_mem; + } + + length = ioctl_data->buf_size; + + err = ufshcd_query_descriptor_retry(hba, opcode, ioctl_data->idn, + index, selector, kernel_buf, + &length); + if (err) + goto out_release_mem; +#if 0 +copy_buffer: +#endif + + if (opcode == UPIU_QUERY_OPCODE_READ_DESC) { + err = copy_to_user(buffer, ioctl_data, + sizeof(struct ufs_ioctl_query_data)); + if (err) + ERR_MSG("Failed copying back to user."); + + err = copy_to_user(buffer + sizeof(struct ufs_ioctl_query_data), + kernel_buf, ioctl_data->buf_size); + if (err) + ERR_MSG("Fail: copy rsp_buffer to user space."); + } +out_release_mem: + kfree(kernel_buf); +out: + return err; +} + +inline int ufsf_get_scsi_device(struct ufs_hba *hba, struct scsi_device *sdev) +{ + unsigned long flags; + int ret; + + spin_lock_irqsave(hba->host->host_lock, flags); + ret = scsi_device_get(sdev); + if (!ret && !scsi_device_online(sdev)) { + spin_unlock_irqrestore(hba->host->host_lock, flags); + scsi_device_put(sdev); + ERR_MSG("scsi_device_get failed.(%d)", ret); + return -ENODEV; + } + spin_unlock_irqrestore(hba->host->host_lock, flags); + + return ret; +} + +inline bool ufsf_is_valid_lun(int lun) +{ + return lun < UFS_UPIU_MAX_GENERAL_LUN; +} + +inline void ufsf_slave_configure(struct ufsf_feature *ufsf, + struct scsi_device *sdev) +{ + if (ufsf_is_valid_lun(sdev->lun)) { + ufsf->sdev_ufs_lu[sdev->lun] = sdev; + ufsf->slave_conf_cnt++; + INFO_MSG("lun[%d] sdev(%p) q(%p) slave_conf_cnt(%d/%d)", + (int)sdev->lun, sdev, sdev->request_queue, + ufsf->slave_conf_cnt, ufsf->num_lu); + +#if defined(CONFIG_UFSHPB) + if (ufsf->num_lu == ufsf->slave_conf_cnt) { + if (ufshpb_get_state(ufsf) == HPB_NEED_INIT) { + INFO_MSG("wakeup ufshpb_init_handler"); + wake_up(&ufsf->hpb_wait); + } + } +#endif + } +} + +inline void ufsf_prep_fn(struct ufsf_feature *ufsf, + struct ufshcd_lrb *lrbp) +{ +#if defined(CONFIG_UFSHPB) + if (ufshpb_get_state(ufsf) == HPB_PRESENT && + ufsf->issue_ioctl == false) + ufshpb_prep_fn(ufsf, lrbp); +#endif + +#if defined(CONFIG_UFSTW) + if (ufstw_get_state(ufsf) == TW_PRESENT) + ufstw_prep_fn(ufsf, lrbp); +#endif +} + +inline void ufsf_reset_lu(struct ufsf_feature *ufsf) +{ +#if defined(CONFIG_UFSTW) + INFO_MSG("run reset_lu.. tw_state(%d) -> TW_RESET", + ufstw_get_state(ufsf)); + ufstw_set_state(ufsf, TW_RESET); + ufstw_reset(ufsf, false); +#endif +} + +inline void ufsf_reset_host(struct ufsf_feature *ufsf) +{ +#if defined(CONFIG_UFSHPB) + INFO_MSG("run reset_host.. hpb_state(%d) -> HPB_RESET", + ufshpb_get_state(ufsf)); + if (ufshpb_get_state(ufsf) == HPB_PRESENT) + ufshpb_reset_host(ufsf); +#endif + +#if defined(CONFIG_UFSTW) + INFO_MSG("run reset_host.. tw_state(%d) -> TW_RESET", + ufstw_get_state(ufsf)); + if (ufstw_get_state(ufsf) == TW_PRESENT) + ufstw_reset_host(ufsf); +#endif +} + +inline void ufsf_init(struct ufsf_feature *ufsf) +{ +#if defined(CONFIG_UFSHPB) + if (ufshpb_get_state(ufsf) == HPB_NEED_INIT) { + INFO_MSG("init start.. hpb_state (%d)", HPB_NEED_INIT); + schedule_work(&ufsf->hpb_init_work); + } +#endif + +#if defined(CONFIG_UFSTW) + if (ufstw_get_state(ufsf) == TW_NEED_INIT) + ufstw_init(ufsf); +#endif +} + +inline void ufsf_reset(struct ufsf_feature *ufsf) +{ +#if defined(CONFIG_UFSHPB) + if (ufshpb_get_state(ufsf) == HPB_RESET) { + INFO_MSG("reset start.. hpb_state %d", HPB_RESET); + ufshpb_reset(ufsf); + } +#endif + +#if defined(CONFIG_UFSTW) + if (ufstw_get_state(ufsf) == TW_RESET && + !ufsf->hba->pm_op_in_progress) { + INFO_MSG("reset start.. tw_state %d", + ufstw_get_state(ufsf)); + ufstw_reset(ufsf, false); + } +#endif +} + +inline void ufsf_remove(struct ufsf_feature *ufsf) +{ +#if defined(CONFIG_UFSHPB) + if (ufshpb_get_state(ufsf) == HPB_PRESENT) + ufshpb_remove(ufsf, HPB_NEED_INIT); +#endif + +#if defined(CONFIG_UFSTW) + if (ufstw_get_state(ufsf) == TW_PRESENT) + ufstw_remove(ufsf); +#endif +} + +inline void ufsf_set_init_state(struct ufsf_feature *ufsf) +{ + ufsf->slave_conf_cnt = 0; + ufsf->issue_ioctl = false; +#if defined(CONFIG_UFSHPB) + ufshpb_set_state(ufsf, HPB_NEED_INIT); + INIT_WORK(&ufsf->hpb_init_work, ufshpb_init_handler); + init_waitqueue_head(&ufsf->hpb_wait); +#endif +#if defined(CONFIG_UFSTW) + ufstw_set_state(ufsf, TW_NEED_INIT); +#endif +} + +inline void ufsf_suspend(struct ufsf_feature *ufsf) +{ +#if defined(CONFIG_UFSHPB) + /* + * if suspend failed, pm could call the suspend function again, + * in this case, ufshpb state already had been changed to SUSPEND state. + * so, we will not call ufshpb_suspend. + */ + if (ufshpb_get_state(ufsf) == HPB_PRESENT) + ufshpb_suspend(ufsf); +#endif +} + +inline void ufsf_resume(struct ufsf_feature *ufsf) +{ +#if defined(CONFIG_UFSHPB) + if (ufshpb_get_state(ufsf) == HPB_SUSPEND || + ufshpb_get_state(ufsf) == HPB_PRESENT) { + if (ufshpb_get_state(ufsf) == HPB_PRESENT) + WARN_MSG("warning.. hpb state PRESENT in resuming"); + ufshpb_resume(ufsf); + } +#endif + +#if defined(CONFIG_UFSTW) + if (ufstw_get_state(ufsf) == TW_RESET) + ufstw_reset(ufsf, true); +#endif +} + + +inline void ufsf_change_lun(struct ufsf_feature *ufsf, + struct ufshcd_lrb *lrbp) +{ + int ctx_lba = LI_EN_32(lrbp->cmd->cmnd + 2); + + if (unlikely(ufsf->issue_ioctl == true && + ctx_lba == READ10_DEBUG_LBA)) { + lrbp->lun = READ10_DEBUG_LUN; + INFO_MSG("lun 0x%X lba 0x%X", lrbp->lun, ctx_lba); + } +} + +/* + * Wrapper functions for ufshpb. + */ +#if defined(CONFIG_UFSHPB) +inline void ufsf_hpb_noti_rb(struct ufsf_feature *ufsf, struct ufshcd_lrb *lrbp) +{ + if (ufshpb_get_state(ufsf) == HPB_PRESENT) + ufshpb_rsp_upiu(ufsf, lrbp); +} + +#else +inline void ufsf_hpb_noti_rb(struct ufsf_feature *ufsf, + struct ufshcd_lrb *lrbp) {} +#endif diff --git a/drivers/scsi/ufs/ufsfeature.h b/drivers/scsi/ufs/ufsfeature.h new file mode 100755 index 000000000000..4b5b7b56adb2 --- /dev/null +++ b/drivers/scsi/ufs/ufsfeature.h @@ -0,0 +1,192 @@ +/* + * Universal Flash Storage Feature Support + * + * Copyright (C) 2017-2018 Samsung Electronics Co., Ltd. + * + * Authors: + * Yongmyung Lee + * Jinyoung Choi + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * See the COPYING file in the top-level directory or visit + * + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * This program is provided "AS IS" and "WITH ALL FAULTS" and + * without warranty of any kind. You are solely responsible for + * determining the appropriateness of using and distributing + * the program and assume all risks associated with your exercise + * of rights with respect to the program, including but not limited + * to infringement of third party rights, the risks and costs of + * program errors, damage to or loss of data, programs or equipment, + * and unavailability or interruption of operations. Under no + * circumstances will the contributor of this Program be liable for + * any damages of any kind arising from your use or distribution of + * this program. + * + * The Linux Foundation chooses to take subject only to the GPLv2 + * license terms, and distributes only under these terms. + */ + +#ifndef _UFSFEATURE_H_ +#define _UFSFEATURE_H_ + +#include + +#include "ufs.h" + +#include "ufshpb.h" +#include "ufstw.h" + +/* Version info */ +#define UFSFEATURE_DD_VER 0x010100 +#define UFSFEATURE_DD_VER_POST "" + +#define UFSFEATURE_QUERY_OPCODE 0x5500 + +/* For read10 debug */ +#define READ10_DEBUG_LUN 0x7F +#define READ10_DEBUG_LBA 0x48504230 + +/* Constant value*/ +#define SECTOR 512 +#define BLOCK 4096 +#define SECTORS_PER_BLOCK (BLOCK / SECTOR) +#define BITS_PER_DWORD 32 +#define sects_per_blk_shift 3 +#define bits_per_dword_shift 5 +#define bits_per_dword_mask 0x1F +#define bits_per_byte_shift 3 + +#define IOCTL_DEV_CTX_MAX_SIZE OS_PAGE_SIZE +#define OS_PAGE_SIZE 4096 +#define OS_PAGE_SHIFT 12 + +#define UFSF_QUERY_REQ_RETRIES 1 + +/* Description */ +#define UFSF_QUERY_DESC_DEVICE_MAX_SIZE 0x5F +#define UFSF_QUERY_DESC_CONFIGURAION_MAX_SIZE 0xE6 +#define UFSF_QUERY_DESC_UNIT_MAX_SIZE 0x2D +#define UFSF_QUERY_DESC_GEOMETRY_MAX_SIZE 0x59 + +#define UFSFEATURE_SELECTOR 0x01 + +/* query_flag */ +#define MASK_QUERY_UPIU_FLAG_LOC 0xFF + +/* For read10 debug */ +#define READ10_DEBUG_LUN 0x7F +#define READ10_DEBUG_LBA 0x48504230 + +/* BIG -> LI */ +#define LI_EN_16(x) be16_to_cpu(*(__be16 *)(x)) +#define LI_EN_32(x) be32_to_cpu(*(__be32 *)(x)) +#define LI_EN_64(x) be64_to_cpu(*(__be64 *)(x)) + +/* LI -> BIG */ +#define GET_BYTE_0(num) (((num) >> 0) & 0xff) +#define GET_BYTE_1(num) (((num) >> 8) & 0xff) +#define GET_BYTE_2(num) (((num) >> 16) & 0xff) +#define GET_BYTE_3(num) (((num) >> 24) & 0xff) +#define GET_BYTE_4(num) (((num) >> 32) & 0xff) +#define GET_BYTE_5(num) (((num) >> 40) & 0xff) +#define GET_BYTE_6(num) (((num) >> 48) & 0xff) +#define GET_BYTE_7(num) (((num) >> 56) & 0xff) + +#define INFO_MSG(msg, args...) pr_info("%s:%d info: " msg "\n", \ + __func__, __LINE__, ##args) +#define ERR_MSG(msg, args...) pr_err("%s:%d err: " msg "\n", \ + __func__, __LINE__, ##args) +#define WARN_MSG(msg, args...) pr_warn("%s:%d warn: " msg "\n", \ + __func__, __LINE__, ##args) + +#define seq_scan_lu(lun) for (lun = 0; lun < UFS_UPIU_MAX_GENERAL_LUN; lun++) + +#define TMSG(ufsf, lun, msg, args...) \ + do { if (ufsf->sdev_ufs_lu[lun] && \ + ufsf->sdev_ufs_lu[lun]->request_queue) \ + blk_add_trace_msg( \ + ufsf->sdev_ufs_lu[lun]->request_queue, \ + msg, ##args); \ + } while (0) \ + +struct ufsf_lu_desc { + /* Common info */ + int lu_enable; /* 03h bLUEnable */ + int lu_queue_depth; /* 06h lu queue depth info*/ + int lu_logblk_size; /* 0Ah bLogicalBlockSize. default 0x0C = 4KB */ + u64 lu_logblk_cnt; /* 0Bh qLogicalBlockCount. */ + +#if defined(CONFIG_UFSHPB) + u16 lu_max_active_hpb_rgns; /* 23h:24h wLUMaxActiveHPBRegions */ + u16 lu_hpb_pinned_rgn_startidx; /* 25h:26h wHPBPinnedRegionStartIdx */ + u16 lu_num_hpb_pinned_rgns; /* 27h:28h wNumHPBPinnedRegions */ + int lu_hpb_pinned_end_offset; +#endif +#if defined(CONFIG_UFSTW) + unsigned int tw_lu_buf_size; +#endif +}; + +struct ufsf_feature { + struct ufs_hba *hba; + int num_lu; + int slave_conf_cnt; + struct scsi_device *sdev_ufs_lu[UFS_UPIU_MAX_GENERAL_LUN]; + bool issue_ioctl; + +#if defined(CONFIG_UFSHPB) + struct ufshpb_dev_info hpb_dev_info; + struct ufshpb_lu *hpb_lup[UFS_UPIU_MAX_GENERAL_LUN]; + struct work_struct hpb_init_work; + struct work_struct hpb_eh_work; + wait_queue_head_t hpb_wait; + atomic_t hpb_state; + struct kref hpb_kref; +#endif +#if defined(CONFIG_UFSTW) + struct ufstw_dev_info tw_dev_info; + struct ufstw_lu *tw_lup[UFS_UPIU_MAX_GENERAL_LUN]; + atomic_t tw_state; +#endif +}; + +struct ufs_hba; +struct ufshcd_lrb; +struct ufs_ioctl_query_data; + +void ufsf_device_check(struct ufs_hba *hba); +int ufsf_check_query(__u32 opcode); +int ufsf_query_ioctl(struct ufs_hba *hba, int lun, void __user *buffer, + struct ufs_ioctl_query_data *ioctl_data, + u8 selector); +int ufsf_query_flag_retry(struct ufs_hba *hba, enum query_opcode opcode, + enum flag_idn idn, u8 idx, bool *flag_res); +int ufsf_query_attr_retry(struct ufs_hba *hba, enum query_opcode opcode, + enum attr_idn idn, u8 idx, u32 *attr_val); +int ufsf_get_scsi_device(struct ufs_hba *hba, struct scsi_device *sdev); +bool ufsf_is_valid_lun(int lun); +void ufsf_slave_configure(struct ufsf_feature *ufsf, struct scsi_device *sdev); +void ufsf_change_lun(struct ufsf_feature *ufsf, struct ufshcd_lrb *lrbp); + +void ufsf_prep_fn(struct ufsf_feature *ufsf, struct ufshcd_lrb *lrbp); +void ufsf_reset_lu(struct ufsf_feature *ufsf); +void ufsf_reset_host(struct ufsf_feature *ufsf); +void ufsf_init(struct ufsf_feature *ufsf); +void ufsf_reset(struct ufsf_feature *ufsf); +void ufsf_remove(struct ufsf_feature *ufsf); +void ufsf_set_init_state(struct ufsf_feature *ufsf); +void ufsf_suspend(struct ufsf_feature *ufsf); +void ufsf_resume(struct ufsf_feature *ufsf); + +/* for hpb */ +void ufsf_hpb_noti_rb(struct ufsf_feature *ufsf, struct ufshcd_lrb *lrbp); +#endif /* End of Header */ diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 569d2efbf783..c66f206410bd 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -66,6 +66,7 @@ #define UIC_CMD_TIMEOUT 500 #endif +unsigned int storage_mfrid; /* NOP OUT retries waiting for NOP IN response */ #define NOP_OUT_RETRIES 10 /* Timeout after 30 msecs if NOP OUT hangs without response */ @@ -200,7 +201,21 @@ struct ufs_pm_lvl_states ufs_pm_lvl_states[] = { {UFS_POWERDOWN_PWR_MODE, UIC_LINK_HIBERN8_STATE}, {UFS_POWERDOWN_PWR_MODE, UIC_LINK_OFF_STATE}, }; - +#if defined(CONFIG_SCSI_SKHPB) +static inline int is_support_hpb_100_device(unsigned int mfrid){ + return IS_SKHYNIX_DEVICE(mfrid); +} +#endif +#if defined(CONFIG_UFSFEATURE) +static inline int is_support_hpb_200_device(unsigned int mfrid){ +#if defined(CONFIG_MICRON_HPB) + return (IS_SAMSUNG_DEVICE(mfrid) || IS_MICRON_DEVICE(mfrid)); +#else + return IS_SAMSUNG_DEVICE(mfrid); +#endif + return 0; +} +#endif static inline enum ufs_dev_pwr_mode ufs_get_pm_lvl_to_dev_pwr_mode(enum ufs_pm_level lvl) { @@ -255,7 +270,36 @@ static struct ufs_dev_fix ufs_fixups[] = { UFS_FIX(UFS_VENDOR_SAMSUNG, "KLUDG4UHDB-B2D1", UFS_DEVICE_QUIRK_PA_HIBER8TIME), #endif +#if defined(CONFIG_SCSI_SKHPB) + UFS_FIX(UFS_VENDOR_SKHYNIX, "H28S", + SKHPB_QUIRK_PURGE_HINT_INFO_WHEN_SLEEP), + UFS_FIX(UFS_VENDOR_SKHYNIX, "H9HQ15ACPMA", + SKHPB_QUIRK_PURGE_HINT_INFO_WHEN_SLEEP), + UFS_FIX(UFS_VENDOR_SKHYNIX, "H9HQ15AECMA", + SKHPB_QUIRK_PURGE_HINT_INFO_WHEN_SLEEP), + UFS_FIX(UFS_VENDOR_SKHYNIX, "H9HQ15AECMM", + SKHPB_QUIRK_PURGE_HINT_INFO_WHEN_SLEEP), + UFS_FIX(UFS_VENDOR_SKHYNIX, "H9HQ15AFAMA", + SKHPB_QUIRK_PURGE_HINT_INFO_WHEN_SLEEP), + UFS_FIX(UFS_VENDOR_SKHYNIX, "H9HQ15AFAMM", + SKHPB_QUIRK_PURGE_HINT_INFO_WHEN_SLEEP), + UFS_FIX(UFS_VENDOR_SKHYNIX, "H9HQ15AJAMM", + SKHPB_QUIRK_PURGE_HINT_INFO_WHEN_SLEEP), + + UFS_FIX(UFS_VENDOR_SKHYNIX, "H9HQ21AECMM", + SKHPB_QUIRK_PURGE_HINT_INFO_WHEN_SLEEP), + UFS_FIX(UFS_VENDOR_SKHYNIX, "H9HQ21AECMZ", + SKHPB_QUIRK_PURGE_HINT_INFO_WHEN_SLEEP), + UFS_FIX(UFS_VENDOR_SKHYNIX, "H9HQ21AFAMM", + SKHPB_QUIRK_PURGE_HINT_INFO_WHEN_SLEEP), + UFS_FIX(UFS_VENDOR_SKHYNIX, "H9HQ21AFAMZ", + SKHPB_QUIRK_PURGE_HINT_INFO_WHEN_SLEEP), + UFS_FIX(UFS_VENDOR_SKHYNIX, "H9HQ21AJAMM", + SKHPB_QUIRK_PURGE_HINT_INFO_WHEN_SLEEP), + UFS_FIX(UFS_VENDOR_SKHYNIX, "H9HQ21AHDMM", + SKHPB_QUIRK_PURGE_HINT_INFO_WHEN_SLEEP), +#endif END_FIX }; @@ -2563,9 +2607,23 @@ static int ufshcd_comp_scsi_upiu(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) lrbp->command_type = UTP_CMD_TYPE_UFS_STORAGE; if (likely(lrbp->cmd)) { +#if defined(CONFIG_UFSFEATURE) + if (is_support_hpb_200_device(storage_mfrid)){ + ufsf_change_lun(&hba->ufsf, lrbp); + ufsf_prep_fn(&hba->ufsf, lrbp); + } +#endif ufshcd_prepare_req_desc_hdr(lrbp, &upiu_flags, lrbp->cmd->sc_data_direction); ufshcd_prepare_utp_scsi_cmd_upiu(lrbp, upiu_flags); +#if defined(CONFIG_SCSI_SKHPB) + if (is_support_hpb_100_device(storage_mfrid)){ + if (hba->skhpb_state == SKHPB_PRESENT && + hba->issue_ioctl == false) { + skhpb_prep_fn(hba, lrbp); + } + } +#endif } else { ret = -EINVAL; } @@ -2655,6 +2713,22 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) lrbp->req_abort_skip = false; ufshcd_comp_scsi_upiu(hba, lrbp); +#if defined(CONFIG_UFSFEATURE) && defined(CONFIG_UFSHPB) + if (is_support_hpb_200_device(storage_mfrid)){ + if (cmd->cmnd[0] != 0x28) + BUG_ON(cmd->requeue_cnt); + + if (cmd->requeue_cnt) + err = -EAGAIN; + + if (err) { + ufshcd_release(hba); + lrbp->cmd = NULL; + clear_bit_unlock(tag, &hba->lrb_in_use); + goto out; + } + } +#endif err = ufshcd_map_sg(hba, lrbp); if (err) { @@ -2897,8 +2971,13 @@ static inline void ufshcd_put_dev_cmd_tag(struct ufs_hba *hba, int tag) * NOTE: Since there is only one available tag for device management commands, * it is expected you hold the hba->dev_cmd.lock mutex. */ +#if defined(CONFIG_UFSFEATURE) +int ufshcd_exec_dev_cmd(struct ufs_hba *hba, + enum dev_cmd_type cmd_type, int timeout) +#else static int ufshcd_exec_dev_cmd(struct ufs_hba *hba, enum dev_cmd_type cmd_type, int timeout) +#endif { struct ufshcd_lrb *lrbp; int err; @@ -2967,8 +3046,13 @@ static inline void ufshcd_init_query(struct ufs_hba *hba, (*request)->upiu_req.selector = selector; } +#if defined(CONFIG_SCSI_SKHPB) +int ufshcd_query_flag_retry(struct ufs_hba *hba, + enum query_opcode opcode, enum flag_idn idn, u8 index, bool *flag_res) +#else static int ufshcd_query_flag_retry(struct ufs_hba *hba, enum query_opcode opcode, enum flag_idn idn, u8 index, bool *flag_res) +#endif { int ret; int retries; @@ -4952,13 +5036,23 @@ static int ufshcd_slave_configure(struct scsi_device *sdev) struct request_queue *q = sdev->request_queue; struct ufs_hba *hba = shost_priv(sdev->host); +#if defined(CONFIG_UFSFEATURE) + if (is_support_hpb_200_device(storage_mfrid)){ + ufsf_slave_configure(&hba->ufsf, sdev); + } +#endif blk_queue_update_dma_pad(q, PRDT_DATA_BYTE_COUNT_PAD - 1); ufshcd_crypto_setup_rq_keyslot_manager(hba, q); if (ufshcd_is_rpm_autosuspend_allowed(hba)) sdev->rpm_autosuspend = 1; - +#if defined(CONFIG_SCSI_SKHPB) + if (is_support_hpb_100_device(storage_mfrid)){ + if (sdev->lun < UFS_UPIU_MAX_GENERAL_LUN) + hba->sdev_ufs_lu[sdev->lun] = sdev; + } +#endif return 0; } @@ -5087,6 +5181,20 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) if (schedule_work(&hba->eeh_work)) pm_runtime_get_noresume(hba->dev); } + +#if defined(CONFIG_UFSFEATURE) + if (is_support_hpb_200_device(storage_mfrid)){ + if (scsi_status == SAM_STAT_GOOD) + ufsf_hpb_noti_rb(&hba->ufsf, lrbp); + } +#endif +#if defined(CONFIG_SCSI_SKHPB) + if (is_support_hpb_100_device(storage_mfrid)){ + if (hba->skhpb_state == SKHPB_PRESENT && + scsi_status == SAM_STAT_GOOD) + skhpb_rsp_upiu(hba, lrbp); + } +#endif break; case UPIU_TRANSACTION_REJECT_UPIU: /* TODO: handle Reject UPIU Response */ @@ -5188,6 +5296,13 @@ static void __ufshcd_transfer_req_compl(struct ufs_hba *hba, cmd = lrbp->cmd; ufshcd_vops_compl_xfer_req(hba, index, (cmd) ? true : false); if (cmd) { +#if defined(CONFIG_UFSFEATURE) && defined(CONFIG_UFSHPB) && defined(CONFIG_HPB_DEBUG) + if (is_support_hpb_200_device(storage_mfrid)) + trace_printk("%llu + %u cmd 0x%X comp tag[%d] out %lX\n", + (unsigned long long) blk_rq_pos(cmd->request), + (unsigned int) blk_rq_sectors(cmd->request), + cmd->cmnd[0], index, hba->outstanding_reqs); +#endif ufshcd_add_command_trace(hba, index, "complete"); result = ufshcd_transfer_rsp_status(hba, lrbp); scsi_dma_unmap(cmd); @@ -6732,6 +6847,18 @@ out: hba->req_abort_count = 0; ufshcd_update_reg_hist(&hba->ufs_stats.dev_reset, (u32)err); if (!err) { +#if defined(CONFIG_UFSFEATURE) + if (is_support_hpb_200_device(storage_mfrid)) + ufsf_reset_lu(&hba->ufsf); +#endif +#if defined(CONFIG_SCSI_SKHPB) + if (is_support_hpb_100_device(storage_mfrid)){ + if (hba->skhpb_state == SKHPB_PRESENT) + hba->skhpb_state = SKHPB_RESET; + schedule_delayed_work(&hba->skhpb_init_work, + msecs_to_jiffies(10)); + } +#endif err = SUCCESS; } else { dev_err(hba->dev, "%s: failed with err %d\n", __func__, err); @@ -6942,6 +7069,12 @@ static int ufshcd_host_reset_and_restore(struct ufs_hba *hba) int err; unsigned long flags; +#if defined(CONFIG_UFSFEATURE) + if (is_support_hpb_200_device(storage_mfrid)){ + ufsf_reset_host(&hba->ufsf); + } +#endif + /* * Stop the host controller and complete the requests * cleared by h/w @@ -7300,18 +7433,25 @@ static void ufshcd_wb_probe(struct ufs_hba *hba, u8 *desc_buf) */ if (!(dev_info->wspecversion >= 0x310 || dev_info->wspecversion == 0x220 || - (hba->dev_quirks & UFS_DEVICE_QUIRK_SUPPORT_EXTENDED_FEATURES))) + (hba->dev_quirks & UFS_DEVICE_QUIRK_SUPPORT_EXTENDED_FEATURES))) { + dev_err(hba->dev, "%s: vendor quirks don't support wb, wb_disable\n",__func__); goto wb_disabled; + } - if (hba->desc_size.dev_desc < DEVICE_DESC_PARAM_EXT_UFS_FEATURE_SUP + 4) + if (hba->desc_size.dev_desc < DEVICE_DESC_PARAM_EXT_UFS_FEATURE_SUP + 4) { + dev_err(hba->dev, "%s: ufs device don't support ext ufs feature, wb_disable\n", + __func__); goto wb_disabled; + } dev_info->d_ext_ufs_feature_sup = get_unaligned_be32(desc_buf + DEVICE_DESC_PARAM_EXT_UFS_FEATURE_SUP); - if (!(dev_info->d_ext_ufs_feature_sup & UFS_DEV_WRITE_BOOSTER_SUP)) + if (!(dev_info->d_ext_ufs_feature_sup & UFS_DEV_WRITE_BOOSTER_SUP)) { + dev_err(hba->dev, "%s: ufs device don't support write booster feature, wb_disable\n",__func__); goto wb_disabled; + } /* * WB may be supported but not configured while provisioning. @@ -7329,8 +7469,10 @@ static void ufshcd_wb_probe(struct ufs_hba *hba, u8 *desc_buf) dev_info->d_wb_alloc_units = get_unaligned_be32(desc_buf + DEVICE_DESC_PARAM_WB_SHARED_ALLOC_UNITS); - if (!dev_info->d_wb_alloc_units) + if (!dev_info->d_wb_alloc_units) { + dev_err(hba->dev, "%s: read wb_share_alloc_units is 0 , wb_disable\n",__func__); goto wb_disabled; + } } else { for (lun = 0; lun < UFS_UPIU_MAX_WB_LUN_ID; lun++) { d_lu_wb_buf_alloc = 0; @@ -7345,8 +7487,10 @@ static void ufshcd_wb_probe(struct ufs_hba *hba, u8 *desc_buf) } } - if (!d_lu_wb_buf_alloc) + if (!d_lu_wb_buf_alloc) { + dev_err(hba->dev, "%s: read wb_share_alloc_units is 0 , wb_disable\n",__func__); goto wb_disabled; + } } return; @@ -7799,6 +7943,13 @@ static int ufshcd_add_lus(struct ufs_hba *hba) ufs_bsg_probe(hba); scsi_scan_host(hba->host); +#if defined(CONFIG_UFSFEATURE) + if (is_support_hpb_200_device(storage_mfrid)){ + ufsf_device_check(hba); + ufsf_init(&hba->ufsf); + } +#endif + out: return ret; } @@ -7918,10 +8069,20 @@ reinit: ufshcd_set_active_icc_lvl(hba); ufshcd_wb_config(hba); + +#if defined(CONFIG_SCSI_SKHPB) + if (is_support_hpb_100_device(storage_mfrid)) + schedule_delayed_work(&hba->skhpb_init_work, 0); +#endif /* Enable Auto-Hibernate if configured */ ufshcd_auto_hibern8_enable(hba); out: +#if defined(CONFIG_UFSFEATURE) + if (is_support_hpb_200_device(storage_mfrid)) + ufsf_reset(&hba->ufsf); +#endif + spin_lock_irqsave(hba->host->host_lock, flags); if (ret) hba->ufshcd_state = UFSHCD_STATE_ERROR; @@ -8783,6 +8944,11 @@ static int ufshcd_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op) req_link_state = UIC_LINK_OFF_STATE; } +#if defined(CONFIG_UFSFEATURE) + if (is_support_hpb_200_device(storage_mfrid)) + ufsf_suspend(&hba->ufsf); +#endif + ret = ufshcd_crypto_suspend(hba, pm_op); if (ret) goto out; @@ -8793,6 +8959,10 @@ static int ufshcd_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op) */ ufshcd_hold(hba, false); hba->clk_gating.is_suspended = true; +#if defined(CONFIG_SCSI_SKHPB) + if(is_support_hpb_100_device(storage_mfrid)) + skhpb_suspend(hba); +#endif if (hba->clk_scaling.is_allowed) { cancel_work_sync(&hba->clk_scaling.suspend_work); @@ -8917,6 +9087,11 @@ enable_gating: hba->dev_info.b_rpm_dev_flush_capable = false; ufshcd_release(hba); ufshcd_crypto_resume(hba, pm_op); +#if defined(CONFIG_UFSFEATURE) + if (is_support_hpb_200_device(storage_mfrid)){ + ufsf_resume(&hba->ufsf); + } +#endif out: if (hba->dev_info.b_rpm_dev_flush_capable) { schedule_delayed_work(&hba->rpm_dev_flush_recheck_work, @@ -9059,6 +9234,15 @@ static int ufshcd_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op) cancel_delayed_work(&hba->rpm_dev_flush_recheck_work); } +#if defined(CONFIG_UFSFEATURE) + if (is_support_hpb_200_device(storage_mfrid)) + ufsf_resume(&hba->ufsf); +#endif +#if defined(CONFIG_SCSI_SKHPB) + if (is_support_hpb_100_device(storage_mfrid)) + skhpb_resume(hba); +#endif + /* Schedule clock gating in case of no access to UFS device yet */ ufshcd_release(hba); @@ -9313,8 +9497,20 @@ EXPORT_SYMBOL(ufshcd_shutdown); */ void ufshcd_remove(struct ufs_hba *hba) { +#if defined(CONFIG_UFSFEATURE) + if (is_support_hpb_200_device(storage_mfrid)){ + ufsf_remove(&hba->ufsf); + } +#endif ufs_bsg_remove(hba); ufs_sysfs_remove_nodes(hba->dev); + +#if defined(CONFIG_SCSI_SKHPB) + if (is_support_hpb_100_device(storage_mfrid)){ + skhpb_release(hba, SKHPB_NEED_INIT); + } +#endif + scsi_remove_host(hba->host); destroy_workqueue(hba->eh_wq); /* disable interrupts */ @@ -9586,6 +9782,17 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq) */ ufshcd_set_ufs_dev_active(hba); +#if defined(CONFIG_UFSFEATURE) + if (is_support_hpb_200_device(storage_mfrid)){ + ufsf_set_init_state(&hba->ufsf); + } +#endif +#if defined(CONFIG_SCSI_SKHPB) + if (is_support_hpb_100_device(storage_mfrid)){ + /* initialize hpb structures */ + ufshcd_init_hpb(hba); + } +#endif async_schedule(ufshcd_async_scan, hba); ufs_sysfs_add_nodes(hba->dev); @@ -9603,6 +9810,12 @@ out_disable: out_error: return err; } +static int __init storage_mfrid_setup(char *str) +{ + storage_mfrid = simple_strtol(str, NULL, 16); + return 1; +} +__setup("storage_mfrid=",storage_mfrid_setup); EXPORT_SYMBOL_GPL(ufshcd_init); MODULE_AUTHOR("Santosh Yaragnavi "); diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index d9003a0b12a4..ce44b1db6e5b 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -73,10 +73,22 @@ #include "ufs_quirks.h" #include "ufshci.h" +#if defined(CONFIG_UFSFEATURE) +#include "ufsfeature.h" +#endif + +#if defined(CONFIG_SCSI_SKHPB) +#include "ufshpb_skh.h" +#endif + #define UFSHCD "ufshcd" #define UFSHCD_DRIVER_VERSION "0.2" #define UFSHCD_QUIRK_BROKEN_AUTO_HIBERN8 0x40000 +extern unsigned int storage_mfrid; +#define IS_SAMSUNG_DEVICE(mfrid) (UFS_VENDOR_SAMSUNG == (mfrid)) +#define IS_SKHYNIX_DEVICE(mfrid) (UFS_VENDOR_SKHYNIX == (mfrid)) +#define IS_MICRON_DEVICE(mfrid) (UFS_VENDOR_MICRON == (mfrid)) struct ufs_hba; @@ -1016,6 +1028,24 @@ struct ufs_hba { struct device bsg_dev; struct request_queue *bsg_queue; +#if defined(CONFIG_SCSI_SKHPB) + /* HPB support */ + u32 skhpb_feat; + int skhpb_state; + int skhpb_max_regions; + struct delayed_work skhpb_init_work; + bool issue_ioctl; + struct skhpb_lu *skhpb_lup[UFS_UPIU_MAX_GENERAL_LUN]; + struct work_struct skhpb_eh_work; + u32 skhpb_quirk; + u8 hpb_control_mode; +#define SKHPB_U8_MAX 0xFF + u8 skhpb_quicklist_lu_enable[UFS_UPIU_MAX_GENERAL_LUN]; +#endif + +#if defined(CONFIG_SCSI_SKHPB) + struct scsi_device *sdev_ufs_lu[UFS_UPIU_MAX_GENERAL_LUN]; +#endif #ifdef CONFIG_SCSI_UFS_CRYPTO /* crypto */ union ufs_crypto_capabilities crypto_capabilities; @@ -1028,6 +1058,10 @@ struct ufs_hba { bool wb_buf_flush_enabled; bool wb_enabled; struct delayed_work rpm_dev_flush_recheck_work; + +#if defined(CONFIG_UFSFEATURE) + struct ufsf_feature ufsf; +#endif ANDROID_KABI_RESERVE(1); ANDROID_KABI_RESERVE(2); ANDROID_KABI_RESERVE(3); @@ -1123,7 +1157,11 @@ static inline bool ufshcd_is_auto_hibern8_enabled(struct ufs_hba *hba) static inline bool ufshcd_is_wb_allowed(struct ufs_hba *hba) { +#if defined(CONFIG_UFSTW) + return false; +#else return hba->caps & UFSHCD_CAP_WB_EN; +#endif } #define ufshcd_writel(hba, val, reg) \ @@ -1297,6 +1335,10 @@ void ufshcd_fixup_dev_quirks(struct ufs_hba *hba, struct ufs_dev_fix *fixups); #define SD_ASCII_STD true #define SD_RAW false +#if defined(CONFIG_UFSFEATURE) +int ufshcd_exec_dev_cmd(struct ufs_hba *hba, + enum dev_cmd_type cmd_type, int timeout); +#endif int ufshcd_hold(struct ufs_hba *hba, bool async); void ufshcd_release(struct ufs_hba *hba); @@ -1500,6 +1542,10 @@ static inline u8 ufshcd_scsi_to_upiu_lun(unsigned int scsi_lun) return scsi_lun & UFS_UPIU_MAX_UNIT_NUM_ID; } +#if defined(CONFIG_SCSI_SKHPB) +int ufshcd_query_flag_retry(struct ufs_hba *hba, + enum query_opcode opcode, enum flag_idn idn, u8 index, bool *flag_res); +#endif int ufshcd_dump_regs(struct ufs_hba *hba, size_t offset, size_t len, const char *prefix); diff --git a/drivers/scsi/ufs/ufshpb.c b/drivers/scsi/ufs/ufshpb.c new file mode 100755 index 000000000000..1659a648a846 --- /dev/null +++ b/drivers/scsi/ufs/ufshpb.c @@ -0,0 +1,4099 @@ +/* + * Universal Flash Storage Host Performance Booster + * + * Copyright (C) 2017-2018 Samsung Electronics Co., Ltd. + * + * Authors: + * Yongmyung Lee + * Jinyoung Choi + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * See the COPYING file in the top-level directory or visit + * + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * This program is provided "AS IS" and "WITH ALL FAULTS" and + * without warranty of any kind. You are solely responsible for + * determining the appropriateness of using and distributing + * the program and assume all risks associated with your exercise + * of rights with respect to the program, including but not limited + * to infringement of third party rights, the risks and costs of + * program errors, damage to or loss of data, programs or equipment, + * and unavailability or interruption of operations. Under no + * circumstances will the contributor of this Program be liable for + * any damages of any kind arising from your use or distribution of + * this program. + * + * The Linux Foundation chooses to take subject only to the GPLv2 + * license terms, and distributes only under these terms. + */ + +#include "ufshcd.h" +#include "ufshpb.h" + +#define UFSHCD_REQ_SENSE_SIZE 18 + +static int ufshpb_create_sysfs(struct ufsf_feature *ufsf, + struct ufshpb_lu *hpb); +static void ufshpb_remove_sysfs(struct ufshpb_lu *hpb); + + +static inline void +ufshpb_get_pos_from_lpn(struct ufshpb_lu *hpb, unsigned long lpn, int *rgn_idx, + int *srgn_idx, int *offset) +{ + int rgn_offset; + + *rgn_idx = lpn >> hpb->entries_per_rgn_shift; + rgn_offset = lpn & hpb->entries_per_rgn_mask; + *srgn_idx = rgn_offset >> hpb->entries_per_srgn_shift; + *offset = rgn_offset & hpb->entries_per_srgn_mask; +} + +inline int ufshpb_valid_srgn(struct ufshpb_region *rgn, + struct ufshpb_subregion *srgn) +{ + return rgn->rgn_state != HPB_RGN_INACTIVE && + srgn->srgn_state == HPB_SRGN_CLEAN; +} + +/* Must be held hpb_lock */ +static bool ufshpb_ppn_dirty_check(struct ufshpb_lu *hpb, unsigned long lpn, + int transfer_len) +{ + struct ufshpb_region *rgn; + struct ufshpb_subregion *srgn; + unsigned long cur_lpn = lpn; + int rgn_idx, srgn_idx, srgn_offset, find_size; + int scan_cnt = transfer_len; + + do { + ufshpb_get_pos_from_lpn(hpb, cur_lpn, &rgn_idx, &srgn_idx, + &srgn_offset); + rgn = hpb->rgn_tbl + rgn_idx; + srgn = rgn->srgn_tbl + srgn_idx; + + if (!ufshpb_valid_srgn(rgn, srgn)) + return true; + + if (unlikely(!srgn->mctx || !srgn->mctx->ppn_dirty)) + return true; + + if (hpb->entries_per_srgn < srgn_offset + scan_cnt) { + int cnt = hpb->entries_per_srgn - srgn_offset; + + find_size = hpb->entries_per_srgn; + scan_cnt -= cnt; + cur_lpn += cnt; + } else { + find_size = srgn_offset + scan_cnt; + scan_cnt = 0; + } + + srgn_offset = + find_next_bit((unsigned long *)srgn->mctx->ppn_dirty, + hpb->entries_per_srgn, srgn_offset); + + if (srgn_offset < hpb->entries_per_srgn) + return srgn_offset < find_size; + + } while (scan_cnt); + + return false; +} + +static void ufshpb_set_read16_cmd(struct ufshpb_lu *hpb, struct scsi_cmnd *cmd, + u64 ppn, unsigned int transfer_len, + int hpb_ctx_id) +{ + unsigned char *cdb = cmd->cmnd; + + cdb[0] = READ_16; + cdb[2] = cmd->cmnd[2]; + cdb[3] = cmd->cmnd[3]; + cdb[4] = cmd->cmnd[4]; + cdb[5] = cmd->cmnd[5]; + cdb[6] = GET_BYTE_7(ppn); + cdb[7] = GET_BYTE_6(ppn); + cdb[8] = GET_BYTE_5(ppn); + cdb[9] = GET_BYTE_4(ppn); + cdb[10] = GET_BYTE_3(ppn); + cdb[11] = GET_BYTE_2(ppn); + cdb[12] = GET_BYTE_1(ppn); + cdb[13] = GET_BYTE_0(ppn); + + if (hpb_ctx_id < MAX_HPB_CONTEXT_ID) + cdb[14] = (1 << 7) | hpb_ctx_id; + else + cdb[14] = UFSHPB_GROUP_NUMBER; + + cdb[15] = transfer_len; + + cmd->cmd_len = UFS_CDB_SIZE; +} + +/* called with hpb_lock (irq) */ +static inline void +ufshpb_set_dirty_bits(struct ufshpb_lu *hpb, struct ufshpb_region *rgn, + struct ufshpb_subregion *srgn, int dword, int offset, + unsigned int cnt) +{ + const unsigned long mask = ((1UL << cnt) - 1) & 0xffffffff; + + if (rgn->rgn_state == HPB_RGN_INACTIVE) + return; + + BUG_ON(!srgn->mctx); + srgn->mctx->ppn_dirty[dword] |= (mask << offset); +} + +static inline void ufshpb_get_bit_offset(struct ufshpb_lu *hpb, int srgn_offset, + int *dword, int *offset) +{ + *dword = srgn_offset >> bits_per_dword_shift; + *offset = srgn_offset & bits_per_dword_mask; +} + +static void ufshpb_set_dirty(struct ufshpb_lu *hpb, struct ufshcd_lrb *lrbp, + int rgn_idx, int srgn_idx, int srgn_offset) +{ + struct ufshpb_region *rgn; + struct ufshpb_subregion *srgn; + int cnt, bit_cnt, bit_dword, bit_offset; + + cnt = blk_rq_sectors(lrbp->cmd->request) >> sects_per_blk_shift; + ufshpb_get_bit_offset(hpb, srgn_offset, &bit_dword, &bit_offset); + + do { + bit_cnt = min(cnt, BITS_PER_DWORD - bit_offset); + + rgn = hpb->rgn_tbl + rgn_idx; + srgn = rgn->srgn_tbl + srgn_idx; + + ufshpb_set_dirty_bits(hpb, rgn, srgn, bit_dword, bit_offset, + bit_cnt); + + bit_offset = 0; + bit_dword++; + + if (bit_dword == hpb->dwords_per_srgn) { + bit_dword = 0; + srgn_idx++; + + if (srgn_idx == hpb->srgns_per_rgn) { + srgn_idx = 0; + rgn_idx++; + } + } + cnt -= bit_cnt; + } while (cnt); + + BUG_ON(cnt < 0); +} + +static inline bool ufshpb_is_read_cmd(struct scsi_cmnd *cmd) +{ + return (cmd->cmnd[0] == READ_10 || cmd->cmnd[0] == READ_16); +} + +static inline bool ufshpb_is_write_cmd(struct scsi_cmnd *cmd) +{ + return (cmd->cmnd[0] == WRITE_10 || cmd->cmnd[0] == WRITE_16); +} + +static inline bool ufshpb_is_discard_cmd(struct scsi_cmnd *cmd) +{ + return cmd->cmnd[0] == UNMAP; +} + +static u64 ufshpb_get_ppn(struct ufshpb_map_ctx *mctx, int pos, int *error) +{ + u64 *ppn_table; + struct page *page = NULL; + int index, offset; + + index = pos / HPB_ENTREIS_PER_OS_PAGE; + offset = pos % HPB_ENTREIS_PER_OS_PAGE; + + page = mctx->m_page[index]; + if (unlikely(!page)) { + *error = -ENOMEM; + ERR_MSG("mctx %p cannot get m_page", mctx); + return 0; + } + + ppn_table = page_address(page); + if (unlikely(!ppn_table)) { + *error = -ENOMEM; + ERR_MSG("mctx %p cannot get ppn_table vm", mctx); + return 0; + } + + return ppn_table[offset]; +} + +#if defined(CONFIG_HPB_ERR_INJECTION) +static u64 ufshpb_get_bitflip_ppn(struct ufshpb_lu *hpb, u64 ppn) +{ + return (ppn ^ hpb->err_injection_bitflip); +} + +static u64 ufshpb_get_offset_ppn(struct ufshpb_lu *hpb, u64 ppn) +{ + return (ppn + hpb->err_injection_offset); +} + +static u64 ufshpb_get_random_ppn(struct ufshpb_lu *hpb, u64 ppn) +{ + u64 random_ppn = 0; + + if (!hpb->err_injection_random) + return ppn; + + get_random_bytes(&random_ppn, sizeof(random_ppn)); + + return random_ppn; +} + +static u64 ufshpb_get_err_injection_ppn(struct ufshpb_lu *hpb, u64 ppn) +{ + u64 new_ppn = 0; + + if (hpb->err_injection_select == HPB_ERR_INJECTION_BITFLIP) + new_ppn = ufshpb_get_bitflip_ppn(hpb, ppn); + else if (hpb->err_injection_select == HPB_ERR_INJECTION_OFFSET) + new_ppn = ufshpb_get_offset_ppn(hpb, ppn); + else if (hpb->err_injection_select == HPB_ERR_INJECTION_RANDOM) + new_ppn = ufshpb_get_random_ppn(hpb, ppn); + + return new_ppn; +} +#endif + +inline int ufshpb_get_state(struct ufsf_feature *ufsf) +{ + return atomic_read(&ufsf->hpb_state); +} + +inline void ufshpb_set_state(struct ufsf_feature *ufsf, int state) +{ + atomic_set(&ufsf->hpb_state, state); +} + +static inline int ufshpb_lu_get(struct ufshpb_lu *hpb) +{ + if (!hpb) + return -ENODEV; + + if (ufshpb_get_state(hpb->ufsf) != HPB_PRESENT) + return -EBUSY; + + kref_get(&hpb->ufsf->hpb_kref); + return 0; +} + +static inline void ufshpb_schedule_error_handler(struct kref *kref) +{ + struct ufsf_feature *ufsf; + + ufsf = container_of(kref, struct ufsf_feature, hpb_kref); + schedule_work(&ufsf->hpb_eh_work); +} + +static inline void ufshpb_lu_put(struct ufshpb_lu *hpb) +{ + kref_put(&hpb->ufsf->hpb_kref, ufshpb_schedule_error_handler); +} + +static void ufshpb_failed(struct ufshpb_lu *hpb, const char *f) +{ + ERR_MSG("ufshpb_driver failed. function (%s)", f); + ufshpb_set_state(hpb->ufsf, HPB_FAILED); + ufshpb_lu_put(hpb); +} + +/* + * end_io() is called with held the queue lock. + * so, blk_put_request is not available directly. + */ +static void ufshpb_put_blk_request(struct request *req) +{ + struct request_queue *q = req->q; + + if (q->mq_ops) { + blk_mq_free_request(req); + } else { + lockdep_assert_held(&q->queue_lock); + blk_put_request(req); + } +} + +static inline void ufshpb_put_pre_req(struct ufshpb_lu *hpb, + struct ufshpb_req *pre_req) +{ + pre_req->req = NULL; + pre_req->bio = NULL; + list_add_tail(&pre_req->list_req, &hpb->lh_pre_req_free); + hpb->num_inflight_pre_req--; +} + +static struct ufshpb_req *ufshpb_get_pre_req(struct ufshpb_lu *hpb) +{ + struct ufshpb_req *pre_req; + + if (hpb->num_inflight_pre_req >= hpb->throttle_pre_req) { + HPB_FTRACE(hpb, "inflight %d throttle %d", + hpb->num_inflight_pre_req, hpb->throttle_pre_req); + return NULL; + } + + pre_req = list_first_entry_or_null(&hpb->lh_pre_req_free, + struct ufshpb_req, list_req); + if (unlikely(!pre_req)) { + HPB_DEBUG(hpb, "no pre_req"); + return NULL; + } + + list_del_init(&pre_req->list_req); + hpb->num_inflight_pre_req++; + + return pre_req; +} + +static void ufshpb_pre_req_compl_fn(struct request *req, blk_status_t error) +{ + struct ufshpb_req *pre_req = (struct ufshpb_req *)req->end_io_data; + struct ufshpb_lu *hpb = pre_req->hpb; + unsigned long flags; + struct scsi_sense_hdr sshdr; + + if (error) { + ERR_MSG("block status (%d)", error); + scsi_normalize_sense(pre_req->sense, SCSI_SENSE_BUFFERSIZE, + &sshdr); + ERR_MSG("code %x sense_key %x asc %x ascq %x", + sshdr.response_code, + sshdr.sense_key, sshdr.asc, sshdr.ascq); + ERR_MSG("byte4 %x byte5 %x byte6 %x additional_len %x", + sshdr.byte4, sshdr.byte5, + sshdr.byte6, sshdr.additional_length); + } + + bio_put(pre_req->bio); + ufshpb_put_blk_request(pre_req->req); + spin_lock_irqsave(&hpb->hpb_lock, flags); + ufshpb_put_pre_req(pre_req->hpb, pre_req); + spin_unlock_irqrestore(&hpb->hpb_lock, flags); + + ufshpb_lu_put(pre_req->hpb); +} + +static int ufshpb_prep_entry(struct ufshpb_req *pre_req, struct page *page) +{ + struct ufshpb_lu *hpb = pre_req->hpb; + struct ufshpb_region *rgn; + struct ufshpb_subregion *srgn; + u64 *addr; + u64 entry_ppn = 0; + unsigned long lpn = pre_req->wb.lpn; + int rgn_idx, srgn_idx, srgn_offset; + int i, error = 0; + unsigned long flags; + + addr = page_address(page); + + spin_lock_irqsave(&hpb->hpb_lock, flags); + for (i = 0; i < pre_req->wb.len; i++, lpn++) { + ufshpb_get_pos_from_lpn(hpb, lpn, &rgn_idx, &srgn_idx, + &srgn_offset); + + rgn = hpb->rgn_tbl + rgn_idx; + srgn = rgn->srgn_tbl + srgn_idx; + + if (!ufshpb_valid_srgn(rgn, srgn)) + goto mctx_error; + + BUG_ON(!srgn->mctx); + + entry_ppn = ufshpb_get_ppn(srgn->mctx, srgn_offset, &error); + if (error) + goto mctx_error; + +#if defined(CONFIG_HPB_ERR_INJECTION) + if (hpb->err_injection_select != HPB_ERR_INJECTION_DISABLE) + entry_ppn = + ufshpb_get_err_injection_ppn(hpb, entry_ppn); +#endif + + addr[i] = entry_ppn; + } + spin_unlock_irqrestore(&hpb->hpb_lock, flags); + return 0; +mctx_error: + spin_unlock_irqrestore(&hpb->hpb_lock, flags); + return -ENOMEM; +} + +static int ufshpb_pre_req_add_bio_page(struct request_queue *q, + struct ufshpb_req *pre_req) +{ + struct page *page = pre_req->wb.m_page; + struct bio *bio = pre_req->bio; + int entries_bytes, ret; + + BUG_ON(!page); + + ret = ufshpb_prep_entry(pre_req, page); + if (ret) + return ret; + + entries_bytes = pre_req->wb.len * sizeof(u64); + + ret = bio_add_pc_page(q, bio, page, entries_bytes, 0); + if (ret != entries_bytes) { + ERR_MSG("bio_add_pc_page fail (%d)", ret); + return -ENOMEM; + } + + return 0; +} + +static inline unsigned long ufshpb_get_lpn(struct request *rq) +{ + return blk_rq_pos(rq) / SECTORS_PER_BLOCK; +} + +static inline unsigned int ufshpb_get_len(struct request *rq) +{ + return blk_rq_sectors(rq) / SECTORS_PER_BLOCK; +} + +static inline unsigned int ufshpb_is_unaligned(struct request *rq) +{ + return blk_rq_sectors(rq) % SECTORS_PER_BLOCK; +} + +static inline int ufshpb_issue_ctx_id_ticket(struct ufshpb_lu *hpb) +{ + int hpb_ctx_id; + + hpb->ctx_id_ticket++; + if (hpb->ctx_id_ticket >= MAX_HPB_CONTEXT_ID) + hpb->ctx_id_ticket = 0; + hpb_ctx_id = hpb->ctx_id_ticket; + + return hpb_ctx_id; +} + +static inline void ufshpb_set_prefetch_cmd(unsigned char *cdb, + unsigned long lpn, unsigned int len, + int hpb_ctx_id) +{ + int len_byte = len * HPB_ENTRY_SIZE; + + cdb[0] = UFSHPB_WRITE_BUFFER; + cdb[1] = UFSHPB_WB_ID_PREFETCH; + cdb[2] = GET_BYTE_3(lpn); + cdb[3] = GET_BYTE_2(lpn); + cdb[4] = GET_BYTE_1(lpn); + cdb[5] = GET_BYTE_0(lpn); + cdb[6] = (1 << 7) | hpb_ctx_id; + cdb[7] = GET_BYTE_1(len_byte); + cdb[8] = GET_BYTE_0(len_byte); + cdb[9] = 0x00; /* Control = 0x00 */ +} + +static void ufshpb_hctx_unlock_mimic(struct blk_mq_hw_ctx *hctx, int srcu_idx) +__releases(hctx->srcu) +{ + if (!(hctx->flags & BLK_MQ_F_BLOCKING)) + rcu_read_unlock(); + else + srcu_read_unlock(hctx->srcu, srcu_idx); +} + +static void ufshpb_hctx_lock_mimic(struct blk_mq_hw_ctx *hctx, int *srcu_idx) +__acquires(hctx->srcu) +{ + if (!(hctx->flags & BLK_MQ_F_BLOCKING)) { + /* shut up gcc false positive */ + *srcu_idx = 0; + rcu_read_lock(); + } else + *srcu_idx = srcu_read_lock(hctx->srcu); +} + +static int ufshpb_blk_mq_dispatch_rq_list_mimic(struct blk_mq_hw_ctx *hctx, + struct request *rq) +{ + struct request_queue *q = rq->q; + struct blk_mq_queue_data bd; + blk_status_t ret = 0; + + if (!blk_mq_get_dispatch_budget(hctx)) + return -EAGAIN; + + if (!blk_mq_get_driver_tag(rq)) { + blk_mq_put_dispatch_budget(hctx); + return -EAGAIN; + } + + bd.rq = rq; + + ret = q->mq_ops->queue_rq(hctx, &bd); + if (ret == BLK_STS_RESOURCE || ret == BLK_STS_DEV_RESOURCE) { + /* + * If an I/O scheduler has been configured and we got a + * driver tag for the next request already, free it + * again. + */ + return -EIO; + } + + if (unlikely(ret != BLK_STS_OK)) + return -EIO; + + return (int)ret; +} + +static int ufshpb_blk_mq_sched_dispatch_requests(struct blk_mq_hw_ctx *hctx, + struct request *rq) +{ + int ret; + + /* RCU or SRCU read lock is needed before checking quiesced flag */ + if (unlikely(blk_mq_hctx_stopped(hctx) || blk_queue_quiesced(rq->q))) + return -EPERM; + + hctx->run++; + + ret = ufshpb_blk_mq_dispatch_rq_list_mimic(hctx, rq); + + return ret; +} + +static int ufshpb_blk_mq_run_hw_queue_mimic(struct blk_mq_hw_ctx *hctx, + struct request *rq) +{ + int srcu_idx; + int ret = 0; + + /* + * We should be running this queue from one of the CPUs that + * are mapped to it. + * + * There are at least two related races now between setting + * hctx->next_cpu from blk_mq_hctx_next_cpu() and running + * __blk_mq_run_hw_queue(): + * + * - hctx->next_cpu is found offline in blk_mq_hctx_next_cpu(), + * but later it becomes online, then this warning is harmless + * at all + * + * - hctx->next_cpu is found online in blk_mq_hctx_next_cpu(), + * but later it becomes offline, then the warning can't be + * triggered, and we depend on blk-mq timeout handler to + * handle dispatched requests to this hctx + */ + if (!cpumask_test_cpu(raw_smp_processor_id(), hctx->cpumask) && + cpu_online(hctx->next_cpu)) { + printk(KERN_WARNING "run queue from wrong CPU %d, hctx %s\n", + raw_smp_processor_id(), + cpumask_empty(hctx->cpumask) ? "inactive" : "active"); + dump_stack(); + } + + /* + * We can't run the queue inline with ints disabled. Ensure that + * we catch bad users of this early. + */ + WARN_ON_ONCE(in_interrupt()); + + if (hctx->flags & BLK_MQ_F_BLOCKING) + return -EPERM; + + ufshpb_hctx_lock_mimic(hctx, &srcu_idx); + ret = ufshpb_blk_mq_sched_dispatch_requests(hctx, rq); + ufshpb_hctx_unlock_mimic(hctx, srcu_idx); + + return ret; +} + +static int ufshpb_insert_pre_req_directly(struct request *rq) +{ + struct blk_mq_hw_ctx *hctx = rq->mq_hctx; + int cpu = get_cpu(); + int ret = 0; + + if (likely(cpumask_test_cpu(cpu, hctx->cpumask))) { + ret = ufshpb_blk_mq_run_hw_queue_mimic(hctx, rq); + put_cpu(); + return ret; + } + put_cpu(); + return -EPERM; +} + +static int ufshpb_blk_execute_rq_nowait_mimic(struct request_queue *q, + struct request *rq, + rq_end_io_fn *done) +{ + int ret = 0; + + WARN_ON(irqs_disabled()); + WARN_ON(!blk_rq_is_passthrough(rq)); + + rq->rq_disk = NULL; + rq->end_io = done; + + ret = ufshpb_insert_pre_req_directly(rq); + return ret; +} + +static int ufshpb_execute_pre_req(struct ufshpb_lu *hpb, struct scsi_cmnd *cmd, + struct ufshpb_req *pre_req, int hpb_ctx_id) +{ + struct scsi_device *sdev = cmd->device; + struct request_queue *q = sdev->request_queue; + struct request *req; + struct scsi_request *rq; + struct bio *bio = pre_req->bio; + int ret = 0; + + pre_req->hpb = hpb; + pre_req->wb.lpn = ufshpb_get_lpn(cmd->request); + pre_req->wb.len = ufshpb_get_len(cmd->request); + ret = ufshpb_pre_req_add_bio_page(q, pre_req); + if (ret) + return ret; + + req = pre_req->req; + + /* 1. request setup */ + blk_rq_append_bio(req, &bio); + req->rq_flags |= RQF_QUIET; + req->timeout = 30 * HZ; + req->end_io_data = (void *)pre_req; + + /* 2. scsi_request setup */ + rq = scsi_req(req); + rq->retries = 1; + ufshpb_set_prefetch_cmd(rq->cmd, pre_req->wb.lpn, pre_req->wb.len, + hpb_ctx_id); + rq->cmd_len = scsi_command_size(rq->cmd); + + ret = ufshpb_blk_execute_rq_nowait_mimic(q, req, + ufshpb_pre_req_compl_fn); + + if (!ret) + atomic64_inc(&hpb->pre_req_cnt); + + return ret; +} + +static int ufshpb_issue_pre_req(struct ufshpb_lu *hpb, struct scsi_cmnd *cmd, + int *hpb_ctx_id) +{ + struct ufshpb_req *pre_req; + struct request *req = NULL; + struct bio *bio = NULL; + unsigned long flags; + int ctx_id; + int ret = 0; + + req = blk_get_request(cmd->device->request_queue, + REQ_OP_SCSI_OUT | REQ_SYNC, + BLK_MQ_REQ_PREEMPT | BLK_MQ_REQ_NOWAIT); + if (IS_ERR(req)) + return -EAGAIN; + + bio = bio_alloc(GFP_ATOMIC, 1); + if (!bio) { + blk_put_request(req); + return -EAGAIN; + } + + spin_lock_irqsave(&hpb->hpb_lock, flags); + pre_req = ufshpb_get_pre_req(hpb); + if (!pre_req) { + ret = -EAGAIN; + goto unlock_out; + } + ctx_id = ufshpb_issue_ctx_id_ticket(hpb); + spin_unlock_irqrestore(&hpb->hpb_lock, flags); + + pre_req->req = req; + pre_req->bio = bio; + +#if defined(CONFIG_HPB_DEBUG) + { + unsigned int start_lpn, end_lpn; + int s_rgn_idx, s_srgn_idx, s_offset; + int e_rgn_idx, e_srgn_idx, e_offset; + + start_lpn = ufshpb_get_lpn(cmd->request); + end_lpn = start_lpn + ufshpb_get_len(cmd->request) - 1; + + ufshpb_get_pos_from_lpn(hpb, start_lpn, &s_rgn_idx, &s_srgn_idx, + &s_offset); + ufshpb_get_pos_from_lpn(hpb, end_lpn, &e_rgn_idx, &e_srgn_idx, + &e_offset); + HPB_FTRACE(hpb, "R[%05d](%d) - R[%05d](%d)", + s_rgn_idx, hpb->rgn_tbl[s_rgn_idx].rgn_state, + e_rgn_idx, hpb->rgn_tbl[e_rgn_idx].rgn_state); + } +#endif + + ret = ufshpb_lu_get(hpb); + if (unlikely(ret)) { + if (ret == -ENODEV) + ERR_MSG("lu_get failed (%d)", ret); + HPB_DEBUG(hpb, "lu_get failed (%d)", ret); + goto free_pre_req; + } + + ret = ufshpb_execute_pre_req(hpb, cmd, pre_req, ctx_id); + if (ret) { + ufshpb_lu_put(hpb); + goto free_pre_req; + } + + *hpb_ctx_id = ctx_id; + + return ret; +free_pre_req: + spin_lock_irqsave(&hpb->hpb_lock, flags); + ufshpb_put_pre_req(hpb, pre_req); +unlock_out: + spin_unlock_irqrestore(&hpb->hpb_lock, flags); + bio_put(bio); + blk_put_request(req); + return ret; +} + +static inline bool ufshpb_is_support_chunk(int transfer_len) +{ + return transfer_len <= HPB_MULTI_CHUNK_HIGH; +} + +static int ufshpb_fill_passthrough_rq(struct scsi_cmnd *cmd) +{ + struct request *rq = cmd->request; + struct scsi_device *sdp = cmd->device; + struct bio *bio = rq->bio; + sector_t sector = 0; + unsigned int data_len = 0; + u8 *p = NULL; + + /* + * UFS is 4K block device. + */ + if (unlikely(sdp->sector_size != BLOCK)) { + ERR_MSG("this device is not 4K block device"); + return -EACCES; + } + + switch (cmd->cmnd[0]) { + case UNMAP: + /* + * UNMAP command has just a block descriptor(=a phys_segment). + */ + if (unlikely(!bio) || + unlikely(bio->bi_vcnt != 1)) { + ERR_MSG("UNMAP bio info is incorrect"); + return -EINVAL; + } + + p = page_address(bio->bi_io_vec->bv_page); + if (unlikely(!p)) { + ERR_MSG("can't get bio page address"); + return -ENOMEM; + } + + sector = LI_EN_64(p + 8); + data_len = LI_EN_32(p + 16); + break; + case READ_10: + case WRITE_10: + sector = LI_EN_32(cmd->cmnd + 2); + data_len = LI_EN_16(cmd->cmnd + 7); + break; + case READ_16: + case WRITE_16: + sector = LI_EN_64(cmd->cmnd + 2); + data_len = LI_EN_32(cmd->cmnd + 10); + break; + default: + return 0; + }; + + rq->__sector = sector << sects_per_blk_shift; + rq->__data_len = data_len << sects_per_blk_shift << SECTOR_SHIFT; + + return 0; +} + +/* routine : READ10 -> HPB_READ */ +void ufshpb_prep_fn(struct ufsf_feature *ufsf, struct ufshcd_lrb *lrbp) +{ + struct ufshpb_lu *hpb; + struct ufshpb_region *rgn; + struct ufshpb_subregion *srgn; + struct request *rq; + struct scsi_cmnd *cmd = lrbp->cmd; + u64 ppn = 0; + unsigned long lpn, flags; + int hpb_ctx_id = MAX_HPB_CONTEXT_ID; + int transfer_len = TRANSFER_LEN; + int rgn_idx, srgn_idx, srgn_offset, ret, error = 0; + + /* WKLU could not be HPB-LU */ + if (!lrbp || !ufsf_is_valid_lun(lrbp->lun)) { + cmd->requeue_cnt = 0; + return; + } + + cmd = lrbp->cmd; + + if (!ufshpb_is_read_cmd(cmd)) + cmd->requeue_cnt = 0; + + if (!ufshpb_is_read_cmd(cmd) && !ufshpb_is_write_cmd(cmd) && + !ufshpb_is_discard_cmd(cmd)) + return; + + rq = cmd->request; + if (unlikely(blk_rq_is_passthrough(rq) && + rq->__sector == (sector_t)-1)) { + ret = ufshpb_fill_passthrough_rq(cmd); + if (ret) + return; + } + + hpb = ufsf->hpb_lup[lrbp->lun]; + ret = ufshpb_lu_get(hpb); + if (unlikely(ret)) { + HPB_DEBUG(hpb, "lu_get failed (%d)", ret); + cmd->requeue_cnt = 0; + return; + } + + if (hpb->force_disable) { + if (ufshpb_is_read_cmd(cmd)) + HPB_FTRACE(hpb, "%llu + %u READ_10 (force_disable)", + (unsigned long long) blk_rq_pos(rq), + (unsigned int) blk_rq_sectors(rq)); + + goto put_hpb; + } + + lpn = ufshpb_get_lpn(rq); + ufshpb_get_pos_from_lpn(hpb, lpn, &rgn_idx, &srgn_idx, &srgn_offset); + rgn = hpb->rgn_tbl + rgn_idx; + srgn = rgn->srgn_tbl + srgn_idx; + + /* + * If cmd type is WRITE, bitmap set to dirty. + */ + if (ufshpb_is_write_cmd(cmd) || ufshpb_is_discard_cmd(cmd)) { + spin_lock_irqsave(&hpb->hpb_lock, flags); + if (rgn->rgn_state != HPB_RGN_INACTIVE) { + ufshpb_set_dirty(hpb, lrbp, rgn_idx, srgn_idx, + srgn_offset); + } + spin_unlock_irqrestore(&hpb->hpb_lock, flags); + } + + if (!ufshpb_is_read_cmd(cmd)) + goto put_hpb; + + if (unlikely(ufshpb_is_unaligned(rq))) { + HPB_FTRACE(hpb, "%llu + %u READ_10 R[%05d](%d) (not aligned)", + (unsigned long long) blk_rq_pos(rq), + (unsigned int) blk_rq_sectors(rq), + rgn_idx, rgn->rgn_state); + + goto put_hpb; + } + + transfer_len = ufshpb_get_len(rq); + if (unlikely(!transfer_len)) + goto put_hpb; + + if (!ufshpb_is_support_chunk(transfer_len)) { + HPB_FTRACE(hpb, "%llu + %u READ_10 R[%05d](%d) (not support chunk)", + (unsigned long long) blk_rq_pos(rq), + (unsigned int) blk_rq_sectors(rq), + rgn_idx, rgn->rgn_state); + + goto put_hpb; + } +#if defined(CONFIG_MICRON_HPB) + if (IS_MICRON_DEVICE(storage_mfrid) && transfer_len >= hpb->pre_req_min_tr_len && + transfer_len <= hpb->pre_req_max_tr_len) { + goto put_hpb; + } +#endif + spin_lock_irqsave(&hpb->hpb_lock, flags); + if (ufshpb_ppn_dirty_check(hpb, lpn, transfer_len)) { + atomic64_inc(&hpb->miss); + spin_unlock_irqrestore(&hpb->hpb_lock, flags); + HPB_FTRACE(hpb, "%llu + %u READ_10 R[%05d](%d) (hpb map invalid)", + (unsigned long long) blk_rq_pos(rq), + (unsigned int) blk_rq_sectors(rq), + rgn_idx, rgn->rgn_state); + + goto put_hpb; + } + + ppn = ufshpb_get_ppn(srgn->mctx, srgn_offset, &error); +#if defined(CONFIG_HPB_ERR_INJECTION) + if (hpb->err_injection_select != HPB_ERR_INJECTION_DISABLE) + ppn = ufshpb_get_err_injection_ppn(hpb, ppn); +#endif + spin_unlock_irqrestore(&hpb->hpb_lock, flags); + if (unlikely(error)) { + ERR_MSG("ppn failed (%d) R[%05d](%d) S[%d](%d)", + error, rgn_idx, rgn->rgn_state, + srgn_idx, srgn->srgn_state); + ufshpb_lu_put(hpb); + goto wakeup_ee_worker; + } + + /* + * WRITE_BUFFER CMD support 36K (len=9) ~ 512K (len=128) default. + * it is possible to change range of transfer_len through sysfs. + */ + if (transfer_len >= hpb->pre_req_min_tr_len && + transfer_len <= hpb->pre_req_max_tr_len) { + ret = ufshpb_issue_pre_req(hpb, cmd, &hpb_ctx_id); + if (ret) { + if (ret == -EAGAIN) { + if (cmd->requeue_cnt < + hpb->pre_req_requeue_cnt) { + cmd->requeue_cnt++; + goto requeue; + } + } + atomic64_inc(&hpb->miss); + goto put_hpb; + } + } + + ufshpb_set_read16_cmd(hpb, cmd, ppn, transfer_len, hpb_ctx_id); + HPB_FTRACE(hpb, "%llu + %u READ_HPB R[%05d](%d) - context_id %d", + (unsigned long long) blk_rq_pos(rq), + (unsigned int) blk_rq_sectors(rq), + rgn_idx, rgn->rgn_state, hpb_ctx_id); + + atomic64_inc(&hpb->hit); +put_hpb: + cmd->requeue_cnt = 0; +requeue: + ufshpb_lu_put(hpb); + return; +wakeup_ee_worker: + ufshpb_failed(hpb, __func__); +} + +static inline void ufshpb_put_map_req(struct ufshpb_lu *hpb, + struct ufshpb_req *map_req) +{ + map_req->req = NULL; + map_req->bio = NULL; + list_add_tail(&map_req->list_req, &hpb->lh_map_req_free); + hpb->num_inflight_map_req--; +} + +static struct ufshpb_req *ufshpb_get_map_req(struct ufshpb_lu *hpb) +{ + struct ufshpb_req *map_req; + + if (hpb->num_inflight_map_req >= hpb->throttle_map_req) { + HPB_FTRACE(hpb, "inflight %d throttle %d", + hpb->num_inflight_map_req, hpb->throttle_map_req); + return NULL; + } + + map_req = list_first_entry_or_null(&hpb->lh_map_req_free, + struct ufshpb_req, list_req); + if (!map_req) { + HPB_DEBUG(hpb, "no map_req"); + return NULL; + } + + list_del_init(&map_req->list_req); + hpb->num_inflight_map_req++; + + return map_req; +} + +static int ufshpb_clean_dirty_bitmap(struct ufshpb_lu *hpb, + struct ufshpb_subregion *srgn) +{ + struct ufshpb_region *rgn; + + BUG_ON(!srgn->mctx); + + rgn = hpb->rgn_tbl + srgn->rgn_idx; + + if (rgn->rgn_state == HPB_RGN_INACTIVE) { + HPB_DEBUG(hpb, "evicted R[%05d](%d) S[%d](%d)", + srgn->rgn_idx, rgn->rgn_state, + srgn->srgn_idx, srgn->srgn_state); + return -EINVAL; + } + + memset(srgn->mctx->ppn_dirty, 0x00, + hpb->entries_per_srgn >> bits_per_byte_shift); + + return 0; +} + +static void ufshpb_clean_active_subregion(struct ufshpb_lu *hpb, + struct ufshpb_subregion *srgn) +{ + struct ufshpb_region *rgn; + + BUG_ON(!srgn->mctx); + + rgn = hpb->rgn_tbl + srgn->rgn_idx; + + if (rgn->rgn_state == HPB_RGN_INACTIVE) { + HPB_DEBUG(hpb, "evicted R[%05d](%d) S[%d](%d)", + srgn->rgn_idx, rgn->rgn_state, + srgn->srgn_idx, srgn->srgn_state); + return; + } + srgn->srgn_state = HPB_SRGN_CLEAN; +} + +static void ufshpb_error_active_subregion(struct ufshpb_lu *hpb, + struct ufshpb_subregion *srgn) +{ + struct ufshpb_region *rgn; + + BUG_ON(!srgn->mctx); + + rgn = hpb->rgn_tbl + srgn->rgn_idx; + + if (rgn->rgn_state == HPB_RGN_INACTIVE) { + ERR_MSG("evicted R[%05d](%d) S[%d](%d)", + srgn->rgn_idx, rgn->rgn_state, + srgn->srgn_idx, srgn->srgn_state); + return; + } + srgn->srgn_state = HPB_SRGN_DIRTY; +} + +#if defined(CONFIG_HPB_DEBUG) +static void ufshpb_check_ppn(struct ufshpb_lu *hpb, int rgn_idx, int srgn_idx, + struct ufshpb_map_ctx *mctx, const char *str) +{ + int error = 0; + u64 val[2]; + + BUG_ON(!mctx); + + val[0] = ufshpb_get_ppn(mctx, 0, &error); + if (!error) + val[1] = ufshpb_get_ppn(mctx, hpb->entries_per_srgn - 1, + &error); + if (error) + val[0] = val[1] = 0; + + HPB_DEBUG(hpb, "%s RB R[%05d](%d) S[%d](%d) (%llx ~ %llx)", + str, rgn_idx, hpb->rgn_tbl[rgn_idx].rgn_state, + srgn_idx, hpb->rgn_tbl[rgn_idx].srgn_tbl[srgn_idx].srgn_state, + val[0], val[1]); +} +#endif + +static void ufshpb_map_compl_process(struct ufshpb_req *map_req) +{ + struct ufshpb_lu *hpb = map_req->hpb; + struct ufshpb_region *rgn = hpb->rgn_tbl + map_req->rb.rgn_idx; + struct ufshpb_subregion *srgn = rgn->srgn_tbl + map_req->rb.srgn_idx; + unsigned long flags; + + atomic64_inc(&hpb->map_compl_cnt); + +#if defined(CONFIG_HPB_DEBUG) + if (hpb->debug) + ufshpb_check_ppn(hpb, srgn->rgn_idx, srgn->srgn_idx, srgn->mctx, + "COMPL"); +#endif + HPB_FTRACE(hpb, "R[%05d](%d)", + map_req->rb.rgn_idx, rgn->rgn_state); + + spin_lock_irqsave(&hpb->hpb_lock, flags); + ufshpb_clean_active_subregion(hpb, srgn); + spin_unlock_irqrestore(&hpb->hpb_lock, flags); +} + +static inline void ufshpb_act_rsp_list_add(struct ufshpb_lu *hpb, + struct ufshpb_subregion *srgn) +{ + atomic64_inc(&hpb->act_rsp_list_cnt); + list_add_tail(&srgn->list_act_srgn, &hpb->lh_act_srgn); + HPB_FTRACE(hpb, "R[%05d](%d) S[%d](%d)", + srgn->rgn_idx, hpb->rgn_tbl[srgn->rgn_idx].rgn_state, + srgn->srgn_idx, srgn->srgn_state); +} + +static inline void ufshpb_act_rsp_list_del(struct ufshpb_lu *hpb, + struct ufshpb_subregion *srgn) +{ + atomic64_dec(&hpb->act_rsp_list_cnt); + list_del_init(&srgn->list_act_srgn); + HPB_FTRACE(hpb, "R[%05d](%d) S[%d](%d)", + srgn->rgn_idx, hpb->rgn_tbl[srgn->rgn_idx].rgn_state, + srgn->srgn_idx, srgn->srgn_state); +} + +static inline void ufshpb_inact_rsp_list_add(struct ufshpb_lu *hpb, + struct ufshpb_region *rgn) +{ + atomic64_inc(&hpb->inact_rsp_list_cnt); + list_add_tail(&rgn->list_inact_rgn, &hpb->lh_inact_rgn); + HPB_FTRACE(hpb, "R[%05d](%d)", + rgn->rgn_idx, hpb->rgn_tbl[rgn->rgn_idx].rgn_state); +} + +static inline void ufshpb_inact_rsp_list_del(struct ufshpb_lu *hpb, + struct ufshpb_region *rgn) +{ + atomic64_dec(&hpb->inact_rsp_list_cnt); + list_del_init(&rgn->list_inact_rgn); + HPB_FTRACE(hpb, "R[%05d](%d)", + rgn->rgn_idx, hpb->rgn_tbl[rgn->rgn_idx].rgn_state); +} + +static void ufshpb_update_active_info(struct ufshpb_lu *hpb, int rgn_idx, + int srgn_idx) +{ + struct ufshpb_region *rgn; + struct ufshpb_subregion *srgn; + + rgn = hpb->rgn_tbl + rgn_idx; + srgn = rgn->srgn_tbl + srgn_idx; + + if (!list_empty(&rgn->list_inact_rgn)) + ufshpb_inact_rsp_list_del(hpb, rgn); + + if (list_empty(&srgn->list_act_srgn)) + ufshpb_act_rsp_list_add(hpb, srgn); +} + +static void ufshpb_update_inactive_info(struct ufshpb_lu *hpb, int rgn_idx) +{ + struct ufshpb_region *rgn; + struct ufshpb_subregion *srgn; + int srgn_idx; + + rgn = hpb->rgn_tbl + rgn_idx; + + for (srgn_idx = 0; srgn_idx < rgn->srgn_cnt; srgn_idx++) { + srgn = rgn->srgn_tbl + srgn_idx; + + if (!list_empty(&srgn->list_act_srgn)) + ufshpb_act_rsp_list_del(hpb, srgn); + } + + if (list_empty(&rgn->list_inact_rgn)) + ufshpb_inact_rsp_list_add(hpb, rgn); +} + +static int ufshpb_map_req_error(struct ufshpb_req *map_req) +{ + struct ufshpb_lu *hpb = map_req->hpb; + struct ufshpb_region *rgn; + struct ufshpb_subregion *srgn; + struct scsi_sense_hdr sshdr; + unsigned long flags; + + rgn = hpb->rgn_tbl + map_req->rb.rgn_idx; + srgn = rgn->srgn_tbl + map_req->rb.srgn_idx; + + scsi_normalize_sense(map_req->sense, SCSI_SENSE_BUFFERSIZE, &sshdr); + + ERR_MSG("code %x sense_key %x asc %x ascq %x", + sshdr.response_code, sshdr.sense_key, sshdr.asc, sshdr.ascq); + ERR_MSG("byte4 %x byte5 %x byte6 %x additional_len %x", + sshdr.byte4, sshdr.byte5, sshdr.byte6, sshdr.additional_length); + + if (sshdr.sense_key != ILLEGAL_REQUEST) + return 0; + + spin_lock_irqsave(&hpb->hpb_lock, flags); + if (rgn->rgn_state == HPB_RGN_PINNED) { + if (sshdr.asc == 0x06 && sshdr.ascq == 0x01) { + HPB_DEBUG(hpb, "retry R[%05d] S[%d]", + map_req->rb.rgn_idx, map_req->rb.srgn_idx); + spin_unlock_irqrestore(&hpb->hpb_lock, flags); + spin_lock(&hpb->retry_list_lock); + list_add_tail(&map_req->list_req, + &hpb->lh_map_req_retry); + spin_unlock(&hpb->retry_list_lock); + + spin_lock_irqsave(&hpb->hpb_lock, flags); + ufshpb_error_active_subregion(hpb, srgn); + spin_unlock_irqrestore(&hpb->hpb_lock, flags); + + schedule_delayed_work(&hpb->retry_work, + msecs_to_jiffies(RETRY_DELAY_MS)); + return -EAGAIN; + } + HPB_DEBUG(hpb, "dirty R[%05d] S[%d]", + map_req->rb.rgn_idx, map_req->rb.srgn_idx); + ufshpb_error_active_subregion(hpb, srgn); + spin_unlock_irqrestore(&hpb->hpb_lock, flags); + } else { + ufshpb_error_active_subregion(hpb, srgn); + + spin_unlock_irqrestore(&hpb->hpb_lock, flags); + + spin_lock_irqsave(&hpb->rsp_list_lock, flags); + ufshpb_update_inactive_info(hpb, map_req->rb.rgn_idx); + spin_unlock_irqrestore(&hpb->rsp_list_lock, flags); + HPB_DEBUG(hpb, "inact R[%05d]", map_req->rb.rgn_idx); + schedule_work(&hpb->task_work); + } + + return 0; +} + +/* routine : map_req compl */ +static void ufshpb_map_req_compl_fn(struct request *req, blk_status_t error) +{ + struct ufshpb_req *map_req = (struct ufshpb_req *) req->end_io_data; + struct ufshpb_lu *hpb = map_req->hpb; + unsigned long flags; + int ret; + + if (ufshpb_get_state(hpb->ufsf) == HPB_FAILED) + goto free_map_req; + + if (error) { + ERR_MSG("ERR %d R[%05d](%d) S[%d](%d)", error, + map_req->rb.rgn_idx, + hpb->rgn_tbl[map_req->rb.rgn_idx].rgn_state, + map_req->rb.srgn_idx, + hpb->rgn_tbl[map_req->rb.rgn_idx].srgn_tbl[map_req->rb.srgn_idx].srgn_state); + ret = ufshpb_map_req_error(map_req); + if (ret) + goto retry_map_req; + } else + ufshpb_map_compl_process(map_req); + +free_map_req: + bio_put(map_req->bio); + ufshpb_put_blk_request(map_req->req); + spin_lock_irqsave(&hpb->hpb_lock, flags); + ufshpb_put_map_req(map_req->hpb, map_req); + spin_unlock_irqrestore(&hpb->hpb_lock, flags); +retry_map_req: + scsi_device_put(hpb->ufsf->sdev_ufs_lu[hpb->lun]); + ufshpb_lu_put(hpb); +} + +static inline void ufshpb_set_read_buf_cmd(unsigned char *cdb, int rgn_idx, + int srgn_idx, int srgn_mem_size) +{ + cdb[0] = UFSHPB_READ_BUFFER; + cdb[1] = UFSHPB_RB_ID_READ; + cdb[2] = GET_BYTE_1(rgn_idx); + cdb[3] = GET_BYTE_0(rgn_idx); + cdb[4] = GET_BYTE_1(srgn_idx); + cdb[5] = GET_BYTE_0(srgn_idx); + cdb[6] = GET_BYTE_2(srgn_mem_size); + cdb[7] = GET_BYTE_1(srgn_mem_size); + cdb[8] = GET_BYTE_0(srgn_mem_size); + cdb[9] = 0x00; +} + +static int ufshpb_map_req_add_bio_page(struct ufshpb_lu *hpb, + struct request_queue *q, struct bio *bio, + struct ufshpb_map_ctx *mctx) +{ + struct page *page = NULL; + int i, ret = 0; + + bio_reset(bio); + + for (i = 0; i < hpb->mpages_per_srgn; i++) { + /* virt_to_page(p + (OS_PAGE_SIZE * i)); */ + page = mctx->m_page[i]; + if (!page) + return -ENOMEM; + + ret = bio_add_pc_page(q, bio, page, hpb->mpage_bytes, 0); + + if (ret != hpb->mpage_bytes) { + ERR_MSG("bio_add_pc_page fail (%d)", ret); + return -ENOMEM; + } + } + + return 0; +} + +static int ufshpb_execute_map_req(struct ufshpb_lu *hpb, + struct ufshpb_req *map_req) +{ + struct scsi_device *sdev; + struct request_queue *q; + struct request *req; + struct bio *bio = map_req->bio; + struct scsi_request *rq; + int ret = 0; + + sdev = hpb->ufsf->sdev_ufs_lu[hpb->lun]; + if (!sdev) { + ERR_MSG("cannot find scsi_device"); + return -ENODEV; + } + + ret = ufsf_get_scsi_device(hpb->ufsf->hba, sdev); + if (ret) + return ret; + + q = sdev->request_queue; + + ret = ufshpb_map_req_add_bio_page(hpb, q, bio, map_req->rb.mctx); + if (ret) { + scsi_device_put(sdev); + return ret; + } + + req = map_req->req; + + /* 1. request setup */ + blk_rq_append_bio(req, &bio); /* req->__data_len is setted */ + req->rq_flags |= RQF_QUIET; + req->timeout = 30 * HZ; + req->end_io_data = (void *)map_req; + + /* 2. scsi_request setup */ + rq = scsi_req(req); + rq->retries = 3; + + ufshpb_set_read_buf_cmd(rq->cmd, map_req->rb.rgn_idx, + map_req->rb.srgn_idx, hpb->srgn_mem_size); + rq->cmd_len = scsi_command_size(rq->cmd); + +#if defined(CONFIG_HPB_DEBUG) + if (hpb->debug) + ufshpb_check_ppn(hpb, map_req->rb.rgn_idx, map_req->rb.srgn_idx, + map_req->rb.mctx, "ISSUE"); +#endif + ret = ufshpb_blk_execute_rq_nowait_mimic(q, req, ufshpb_map_req_compl_fn); + if (ret) { + scsi_device_put(sdev); + return ret; + } + + atomic64_inc(&hpb->map_req_cnt); + HPB_FTRACE(hpb, "issue R[%05d](%d) S[%d](%d)", + map_req->rb.rgn_idx, + hpb->rgn_tbl[map_req->rb.rgn_idx].rgn_state, + map_req->rb.srgn_idx, + hpb->rgn_tbl[map_req->rb.rgn_idx].srgn_tbl[map_req->rb.srgn_idx].srgn_state); + + return 0; +} + +static struct ufshpb_map_ctx *ufshpb_get_map_ctx(struct ufshpb_lu *hpb, + int *err) +{ + struct ufshpb_map_ctx *mctx; + + mctx = list_first_entry_or_null(&hpb->lh_map_ctx_free, + struct ufshpb_map_ctx, list_table); + if (mctx) { + list_del_init(&mctx->list_table); + hpb->debug_free_table--; + return mctx; + } + *err = -ENOMEM; + return NULL; +} + +static inline void ufshpb_add_lru_info(struct victim_select_info *lru_info, + struct ufshpb_region *rgn) +{ + rgn->rgn_state = HPB_RGN_ACTIVE; + list_add_tail(&rgn->list_lru_rgn, &lru_info->lh_lru_rgn); + atomic64_inc(&lru_info->active_cnt); +} + +static inline int ufshpb_add_region(struct ufshpb_lu *hpb, + struct ufshpb_region *rgn) +{ + struct victim_select_info *lru_info; + int srgn_idx; + int err = 0; + + lru_info = &hpb->lru_info; + + for (srgn_idx = 0; srgn_idx < rgn->srgn_cnt; srgn_idx++) { + struct ufshpb_subregion *srgn; + + srgn = rgn->srgn_tbl + srgn_idx; + + srgn->mctx = ufshpb_get_map_ctx(hpb, &err); + if (!srgn->mctx) { + ERR_MSG("mctx ERR %d R[%05d](%d) S[%d](%d) free_table %d", + err, srgn->rgn_idx, rgn->rgn_state, + srgn_idx, srgn->srgn_state, + hpb->debug_free_table); + goto out; + } + + srgn->srgn_state = HPB_SRGN_DIRTY; + } + + HPB_FTRACE(hpb, "add R[%05d](%d)", + rgn->rgn_idx, rgn->rgn_state); + + ufshpb_add_lru_info(lru_info, rgn); +out: + return err; +} + +static inline void ufshpb_put_map_ctx(struct ufshpb_lu *hpb, + struct ufshpb_map_ctx *mctx) +{ + list_add(&mctx->list_table, &hpb->lh_map_ctx_free); + hpb->debug_free_table++; +} + +static inline void ufshpb_purge_active_subregion(struct ufshpb_lu *hpb, + struct ufshpb_subregion *srgn, + int state) +{ + if (unlikely(state == HPB_SRGN_UNUSED)) { + ufshpb_put_map_ctx(hpb, srgn->mctx); + srgn->mctx = NULL; + } + + srgn->srgn_state = state; +} + +static inline void ufshpb_cleanup_lru_info(struct victim_select_info *lru_info, + struct ufshpb_region *rgn) +{ + list_del_init(&rgn->list_lru_rgn); + rgn->rgn_state = HPB_RGN_INACTIVE; + atomic64_dec(&lru_info->active_cnt); +} + +static void __ufshpb_evict_region(struct ufshpb_lu *hpb, + struct ufshpb_region *rgn) +{ + struct victim_select_info *lru_info; + struct ufshpb_subregion *srgn; + int srgn_idx; + + lru_info = &hpb->lru_info; + + HPB_FTRACE(hpb, "evict R[%05d](%d)", + rgn->rgn_idx, rgn->rgn_state); + + ufshpb_cleanup_lru_info(lru_info, rgn); + + for (srgn_idx = 0; srgn_idx < rgn->srgn_cnt; srgn_idx++) { + srgn = rgn->srgn_tbl + srgn_idx; + + ufshpb_purge_active_subregion(hpb, srgn, HPB_SRGN_UNUSED); + } +} + +static void ufshpb_hit_lru_info(struct victim_select_info *lru_info, + struct ufshpb_region *rgn) +{ + switch (lru_info->selection_type) { + case LRU: + list_move_tail(&rgn->list_lru_rgn, &lru_info->lh_lru_rgn); + break; + default: + break; + } +} + +/* + * Must be held hpb_lock before call this func. + */ +static int ufshpb_check_issue_state_srgns(struct ufshpb_lu *hpb, + struct ufshpb_region *rgn) +{ + struct ufshpb_subregion *srgn; + int srgn_idx; + + for (srgn_idx = 0; srgn_idx < rgn->srgn_cnt; srgn_idx++) { + srgn = rgn->srgn_tbl + srgn_idx; + + if (srgn->srgn_state == HPB_SRGN_ISSUED) { + HPB_FTRACE(hpb, "R[%05d](%d)", + rgn->rgn_idx, rgn->rgn_state); + + return -EPERM; + } + } + return 0; +} + +static struct ufshpb_region *ufshpb_victim_lru_info(struct ufshpb_lu *hpb) +{ + struct victim_select_info *lru_info = &hpb->lru_info; + struct ufshpb_region *rgn; + struct ufshpb_region *victim_rgn = NULL; + + switch (lru_info->selection_type) { + case LRU: + list_for_each_entry(rgn, &lru_info->lh_lru_rgn, list_lru_rgn) { + if (!rgn) + break; + + if (ufshpb_check_issue_state_srgns(hpb, rgn)) + continue; + + victim_rgn = rgn; + break; + } + break; + default: + break; + } + + return victim_rgn; +} + +static int ufshpb_evict_region(struct ufshpb_lu *hpb, struct ufshpb_region *rgn) +{ + unsigned long flags; + + spin_lock_irqsave(&hpb->hpb_lock, flags); + if (rgn->rgn_state == HPB_RGN_PINNED) { + /* Pinned region should not drop-out.*/ + ERR_MSG("drop-out ERR R[%05d](%d)", + rgn->rgn_idx, rgn->rgn_state); + goto out; + } + + if (!list_empty(&rgn->list_lru_rgn)) { + if (ufshpb_check_issue_state_srgns(hpb, rgn)) + goto evict_fail; + + __ufshpb_evict_region(hpb, rgn); + } +out: + spin_unlock_irqrestore(&hpb->hpb_lock, flags); + return 0; +evict_fail: + spin_unlock_irqrestore(&hpb->hpb_lock, flags); + return -EPERM; +} + +static inline struct +ufshpb_rsp_field *ufshpb_get_hpb_rsp(struct ufshcd_lrb *lrbp) +{ + return (struct ufshpb_rsp_field *)&lrbp->ucd_rsp_ptr->sr.sense_data_len; +} + +static int ufshpb_issue_map_req(struct ufshpb_lu *hpb, + struct ufshpb_subregion *srgn) +{ + struct scsi_device *sdev = hpb->ufsf->sdev_ufs_lu[hpb->lun]; + struct request *req = NULL; + struct bio *bio = NULL; + struct ufshpb_req *map_req = NULL; + unsigned long flags; + int ret = 0; + + req = blk_get_request(sdev->request_queue, REQ_OP_SCSI_IN, + BLK_MQ_REQ_PREEMPT); + if (IS_ERR(req)) + return -EAGAIN; + + bio = bio_alloc(GFP_KERNEL, hpb->mpages_per_srgn); + if (!bio) { + blk_put_request(req); + return -EAGAIN; + } + + spin_lock_irqsave(&hpb->hpb_lock, flags); + + if (srgn->srgn_state == HPB_SRGN_ISSUED) { + ret = -EAGAIN; + goto unlock_out; + } + + ret = ufshpb_clean_dirty_bitmap(hpb, srgn); + if (ret) { + ret = -EAGAIN; + goto unlock_out; + } + + map_req = ufshpb_get_map_req(hpb); + if (!map_req) { + ret = -ENOMEM; + goto unlock_out; + } + + srgn->srgn_state = HPB_SRGN_ISSUED; + + spin_unlock_irqrestore(&hpb->hpb_lock, flags); + + map_req->req = req; + map_req->bio = bio; + map_req->hpb = hpb; + map_req->rb.rgn_idx = srgn->rgn_idx; + map_req->rb.srgn_idx = srgn->srgn_idx; + map_req->rb.mctx = srgn->mctx; + map_req->rb.lun = hpb->lun; + + ret = ufshpb_lu_get(hpb); + if (unlikely(ret)) { + if (ret == -ENODEV) + ERR_MSG("lu_get failed (%d)", ret); + HPB_DEBUG(hpb, "lu_get failed (%d)", ret); + + goto free_map_req; + } + + ret = ufshpb_execute_map_req(hpb, map_req); + if (ret) + goto map_req_failed; + + return ret; +map_req_failed: + ufshpb_lu_put(hpb); +free_map_req: + spin_lock_irqsave(&hpb->hpb_lock, flags); + srgn->srgn_state = HPB_SRGN_DIRTY; + ufshpb_put_map_req(hpb, map_req); +unlock_out: + spin_unlock_irqrestore(&hpb->hpb_lock, flags); + bio_put(bio); + blk_put_request(req); + return ret; +} + +static int ufshpb_load_region(struct ufshpb_lu *hpb, struct ufshpb_region *rgn) +{ + struct ufshpb_region *victim_rgn; + struct victim_select_info *lru_info = &hpb->lru_info; + unsigned long flags; + int ret = 0; + + /* + * if already region is added to lru_list, + * just initiate the information of lru. + * because the region already has the map ctx. + * (!list_empty(&rgn->list_region) == region->state=active...) + */ + spin_lock_irqsave(&hpb->hpb_lock, flags); + if (!list_empty(&rgn->list_lru_rgn)) { + ufshpb_hit_lru_info(lru_info, rgn); + goto out; + } + + if (rgn->rgn_state == HPB_RGN_INACTIVE) { + if (atomic64_read(&lru_info->active_cnt) + == lru_info->max_lru_active_cnt) { + victim_rgn = ufshpb_victim_lru_info(hpb); + if (!victim_rgn) { + HPB_DEBUG(hpb, "victim_rgn is NULL"); + ret = -ENOMEM; + goto out; + } + HPB_FTRACE(hpb, "lru_max %lld R[%05d](%d)", + atomic64_read(&lru_info->active_cnt), + victim_rgn->rgn_idx, victim_rgn->rgn_state); + + __ufshpb_evict_region(hpb, victim_rgn); + } + + ret = ufshpb_add_region(hpb, rgn); + if (ret) { + ERR_MSG("add_region failed (%d)", ret); + spin_unlock_irqrestore(&hpb->hpb_lock, flags); + goto wakeup_ee_worker; + } + } +out: + spin_unlock_irqrestore(&hpb->hpb_lock, flags); + return ret; +wakeup_ee_worker: + ufshpb_failed(hpb, __func__); + return ret; +} + +static void ufshpb_rsp_req_region_update(struct ufshpb_lu *hpb, + struct ufshpb_rsp_field *rsp_field) +{ + struct ufshpb_region *rgn; + struct ufshpb_subregion *srgn; + int num, rgn_idx, srgn_idx; + + HPB_FTRACE(hpb, "ACT %d INACT %d", + rsp_field->active_rgn_cnt, rsp_field->inactive_rgn_cnt); + + /* + * If active rgn = inactive rgn, choose inactive rgn. + * So, active process -> inactive process + */ + for (num = 0; num < rsp_field->active_rgn_cnt; num++) { + rgn_idx = be16_to_cpu(rsp_field->hpb_active_field[num].active_rgn); + srgn_idx = be16_to_cpu(rsp_field->hpb_active_field[num].active_srgn); + + if (unlikely(rgn_idx >= hpb->rgns_per_lu)) { + ERR_MSG("R[%05d] is wrong. (Max %d)", + rgn_idx, hpb->rgns_per_lu); + continue; + } + + rgn = hpb->rgn_tbl + rgn_idx; + + if (unlikely(srgn_idx >= rgn->srgn_cnt)) { + ERR_MSG("R[%05d] S[%d] is wrong. (Max %d)", + rgn_idx, srgn_idx, rgn->srgn_cnt); + continue; + } + + srgn = rgn->srgn_tbl + srgn_idx; + + HPB_FTRACE(hpb, "ACT %d R[%05d](%d) S[%d](%d)", + num + 1, rgn_idx, rgn->rgn_state, + srgn_idx, srgn->srgn_idx); + spin_lock(&hpb->rsp_list_lock); + ufshpb_update_active_info(hpb, rgn_idx, srgn_idx); + spin_unlock(&hpb->rsp_list_lock); + + /* It is just blocking HPB_READ */ + spin_lock(&hpb->hpb_lock); + if (srgn->srgn_state == HPB_SRGN_CLEAN) + srgn->srgn_state = HPB_SRGN_DIRTY; + spin_unlock(&hpb->hpb_lock); + atomic64_inc(&hpb->rb_active_cnt); + } + + for (num = 0; num < rsp_field->inactive_rgn_cnt; num++) { + rgn_idx = be16_to_cpu(rsp_field->hpb_inactive_field[num]); + + if (unlikely(rgn_idx >= hpb->rgns_per_lu)) { + ERR_MSG("R[%05d] is wrong. (Max %d)", + rgn_idx, hpb->rgns_per_lu); + continue; + } + + rgn = hpb->rgn_tbl + rgn_idx; + + HPB_FTRACE(hpb, "INACT %d R[%05d](%d)", + num + 1, rgn_idx, rgn->rgn_state); + spin_lock(&hpb->rsp_list_lock); + ufshpb_update_inactive_info(hpb, rgn_idx); + spin_unlock(&hpb->rsp_list_lock); + + /* + * to block HPB_READ + */ + spin_lock(&hpb->hpb_lock); + if (rgn->rgn_state != HPB_RGN_INACTIVE) { + for (srgn_idx = 0; srgn_idx < rgn->srgn_cnt; srgn_idx++) { + srgn = rgn->srgn_tbl + srgn_idx; + if (srgn->srgn_state == HPB_SRGN_CLEAN) + srgn->srgn_state = HPB_SRGN_DIRTY; + } + } + spin_unlock(&hpb->hpb_lock); + + atomic64_inc(&hpb->rb_inactive_cnt); + } + + schedule_work(&hpb->task_work); +} + +static inline int ufshpb_may_field_valid(struct ufshcd_lrb *lrbp, + struct ufshpb_rsp_field *rsp_field) +{ + if (be16_to_cpu(rsp_field->sense_data_len) != DEV_SENSE_SEG_LEN || + rsp_field->desc_type != DEV_DES_TYPE || + rsp_field->additional_len != DEV_ADDITIONAL_LEN || + rsp_field->hpb_type == HPB_RSP_NONE || + rsp_field->active_rgn_cnt > MAX_ACTIVE_NUM || + rsp_field->inactive_rgn_cnt > MAX_INACTIVE_NUM || + (!rsp_field->active_rgn_cnt && !rsp_field->inactive_rgn_cnt)) + return -EINVAL; + + if (!ufsf_is_valid_lun(lrbp->lun)) { + ERR_MSG("LU(%d) is not supported", lrbp->lun); + return -EINVAL; + } + + return 0; +} + +static bool ufshpb_is_empty_rsp_lists(struct ufshpb_lu *hpb) +{ + bool ret = true; + unsigned long flags; + + spin_lock_irqsave(&hpb->rsp_list_lock, flags); + if (!list_empty(&hpb->lh_inact_rgn) || !list_empty(&hpb->lh_act_srgn)) + ret = false; + spin_unlock_irqrestore(&hpb->rsp_list_lock, flags); + + return ret; +} + +/* routine : isr (ufs) */ +void ufshpb_rsp_upiu(struct ufsf_feature *ufsf, struct ufshcd_lrb *lrbp) +{ + struct ufshpb_lu *hpb; + struct ufshpb_rsp_field *rsp_field; + int data_seg_len, ret; + + data_seg_len = be32_to_cpu(lrbp->ucd_rsp_ptr->header.dword_2) + & MASK_RSP_UPIU_DATA_SEG_LEN; + + if (!data_seg_len) { + bool do_task_work = false; + + if (!ufsf_is_valid_lun(lrbp->lun)) + return; + + hpb = ufsf->hpb_lup[lrbp->lun]; + ret = ufshpb_lu_get(hpb); + if (unlikely(ret)) { + HPB_DEBUG(hpb, "lu_get failed (%d)", ret); + return; + } + + do_task_work = !ufshpb_is_empty_rsp_lists(hpb); + if (do_task_work) + schedule_work(&hpb->task_work); + + goto put_hpb; + } + + rsp_field = ufshpb_get_hpb_rsp(lrbp); + + if (ufshpb_may_field_valid(lrbp, rsp_field)) { + WARN_ON(rsp_field->additional_len != DEV_ADDITIONAL_LEN); + return; + } + + hpb = ufsf->hpb_lup[lrbp->lun]; + ret = ufshpb_lu_get(hpb); + if (unlikely(ret)) { + HPB_DEBUG(hpb, "lu_get failed (%d)", ret); + return; + } + + if (hpb->force_map_req_disable) + goto put_hpb; + + atomic64_inc(&hpb->rb_noti_cnt); + + switch (rsp_field->hpb_type) { + case HPB_RSP_REQ_REGION_UPDATE: + WARN_ON(data_seg_len != DEV_DATA_SEG_LEN); + ufshpb_rsp_req_region_update(hpb, rsp_field); + goto put_hpb; + default: + HPB_DEBUG(hpb, "HPB_TYPE %d is not available", + rsp_field->hpb_type); + goto put_hpb; + } + +put_hpb: + ufshpb_lu_put(hpb); +} + +static int ufshpb_execute_map_req_wait(struct ufshpb_lu *hpb, + unsigned char *cmd, + struct ufshpb_subregion *srgn) +{ + struct ufsf_feature *ufsf = hpb->ufsf; + struct scsi_device *sdev; + struct request_queue *q; + struct request *req; + struct scsi_request *rq; + struct bio *bio; + struct scsi_sense_hdr sshdr; + unsigned long flags; + int ret = 0; + + sdev = ufsf->sdev_ufs_lu[hpb->lun]; + if (!sdev) { + ERR_MSG("cannot find scsi_device"); + return -ENODEV; + } + + q = sdev->request_queue; + + ret = ufsf_get_scsi_device(ufsf->hba, sdev); + if (ret) + return ret; + + req = blk_get_request(q, REQ_OP_SCSI_IN, BLK_MQ_REQ_PREEMPT); + if (IS_ERR(req)) { + ERR_MSG("cannot get request"); + ret = -EIO; + goto sdev_put_out; + } + + bio = bio_alloc(GFP_KERNEL, hpb->mpages_per_srgn); + if (!bio) { + ret = -ENOMEM; + goto req_put_out; + } + + ret = ufshpb_map_req_add_bio_page(hpb, q, bio, srgn->mctx); + if (ret) + goto mem_free_out; + + /* 1. request setup*/ + blk_rq_append_bio(req, &bio); /* req->__data_len */ + req->rq_flags |= RQF_QUIET; + req->timeout = 30 * HZ; + + /* 2. scsi_request setup */ + rq = scsi_req(req); + rq->retries = 3; + rq->cmd_len = scsi_command_size(cmd); + memcpy(rq->cmd, cmd, rq->cmd_len); + + blk_execute_rq(q, NULL, req, 1); + if (rq->result) { + ret = -EIO; + scsi_normalize_sense(rq->sense, SCSI_SENSE_BUFFERSIZE, &sshdr); + ERR_MSG("code %x sense_key %x asc %x ascq %x", + sshdr.response_code, sshdr.sense_key, sshdr.asc, + sshdr.ascq); + ERR_MSG("byte4 %x byte5 %x byte6 %x additional_len %x", + sshdr.byte4, sshdr.byte5, sshdr.byte6, + sshdr.additional_length); + spin_lock_irqsave(&hpb->hpb_lock, flags); + ufshpb_error_active_subregion(hpb, srgn); + spin_unlock_irqrestore(&hpb->hpb_lock, flags); + } +mem_free_out: + bio_put(bio); +req_put_out: + blk_put_request(req); +sdev_put_out: + scsi_device_put(sdev); + return ret; +} + +static void ufshpb_issue_map_req_from_list(struct ufshpb_lu *hpb) +{ + struct ufshpb_subregion *srgn; + unsigned long flags; + int ret; + + spin_lock_irqsave(&hpb->rsp_list_lock, flags); + + while ((srgn = list_first_entry_or_null(&hpb->lh_pinned_srgn, + struct ufshpb_subregion, + list_act_srgn))) { + unsigned char cmd[10] = { 0 }; + + list_del_init(&srgn->list_act_srgn); + spin_unlock_irqrestore(&hpb->rsp_list_lock, flags); + + ufshpb_set_read_buf_cmd(cmd, srgn->rgn_idx, srgn->srgn_idx, + hpb->srgn_mem_size); + +#if defined(CONFIG_HPB_DEBUG) + if (hpb->debug) + ufshpb_check_ppn(hpb, srgn->rgn_idx, srgn->srgn_idx, + srgn->mctx, "ISSUE"); +#endif + HPB_FTRACE(hpb, "issue R[%05d](%d)", + srgn->rgn_idx, hpb->rgn_tbl[srgn->rgn_idx].rgn_state); + + ret = ufshpb_execute_map_req_wait(hpb, cmd, srgn); + if (ret < 0) { + ERR_MSG("issue ERR %d R[%05d](%d) S%0d(%d)", + ret, + srgn->rgn_idx, hpb->rgn_tbl[srgn->rgn_idx].rgn_state, + srgn->srgn_idx, srgn->srgn_state); + spin_lock_irqsave(&hpb->rsp_list_lock, flags); + if (list_empty(&srgn->list_act_srgn)) + list_add(&srgn->list_act_srgn, + &hpb->lh_pinned_srgn); + continue; + } + +#if defined(CONFIG_HPB_DEBUG) + if (hpb->debug) + ufshpb_check_ppn(hpb, srgn->rgn_idx, srgn->srgn_idx, + srgn->mctx, "COMPL"); +#endif + HPB_FTRACE(hpb, "compl R[%05d](%d)", + srgn->rgn_idx, hpb->rgn_tbl[srgn->rgn_idx].rgn_state); + + spin_lock_irqsave(&hpb->hpb_lock, flags); + ufshpb_clean_active_subregion(hpb, srgn); + spin_unlock_irqrestore(&hpb->hpb_lock, flags); + + spin_lock_irqsave(&hpb->rsp_list_lock, flags); + } + + spin_unlock_irqrestore(&hpb->rsp_list_lock, flags); +} + +static void ufshpb_pinned_work_handler(struct work_struct *work) +{ + struct ufshpb_lu *hpb; + int ret; + + hpb = container_of(work, struct ufshpb_lu, pinned_work); + HPB_DEBUG(hpb, "worker start"); + + pm_runtime_get_sync(hpb->ufsf->hba->dev); + ret = ufshpb_lu_get(hpb); + if (unlikely(ret)) { + if (ret == -ENODEV) + ERR_MSG("lu_get failed (%d)", ret); + HPB_DEBUG(hpb, "lu_get failed (%d)", ret); + return; + } + + if (!list_empty(&hpb->lh_pinned_srgn)) + ufshpb_issue_map_req_from_list(hpb); + /* + * if its function failed at init time, + * ufshpb-device will request map-req, + * so it is not critical-error, and just finish work-handler + */ + + ufshpb_lu_put(hpb); + pm_runtime_put_sync(hpb->ufsf->hba->dev); + HPB_DEBUG(hpb, "worker end"); +} + +static int ufshpb_check_pm(struct ufshpb_lu *hpb) +{ + struct ufs_hba *hba = hpb->ufsf->hba; + + if (hba->pm_op_in_progress || + hba->curr_dev_pwr_mode != UFS_ACTIVE_PWR_MODE) { + INFO_MSG("hba current power state %d pm_progress %d", + hba->curr_dev_pwr_mode, + hba->pm_op_in_progress); + return -ENODEV; + } + return 0; +} + +static void ufshpb_retry_work_handler(struct work_struct *work) +{ + struct ufshpb_lu *hpb; + struct delayed_work *dwork = to_delayed_work(work); + struct ufshpb_req *map_req, *next; + struct ufshpb_region *rgn; + struct ufshpb_subregion *srgn; + unsigned long flags; + bool do_retry = false; + int ret = 0; + + LIST_HEAD(retry_list); + + hpb = container_of(dwork, struct ufshpb_lu, retry_work); + + if (ufshpb_check_pm(hpb)) + return; + + ret = ufshpb_lu_get(hpb); + if (unlikely(ret)) { + if (ret == -ENODEV) + ERR_MSG("lu_get failed (%d)", ret); + HPB_DEBUG(hpb, "lu_get failed (%d)", ret); + return; + } + + HPB_DEBUG(hpb, "worker start"); + + spin_lock_bh(&hpb->retry_list_lock); + list_splice_init(&hpb->lh_map_req_retry, &retry_list); + spin_unlock_bh(&hpb->retry_list_lock); + + list_for_each_entry_safe(map_req, next, &retry_list, list_req) { + if (ufshpb_get_state(hpb->ufsf) == HPB_SUSPEND) { + INFO_MSG("suspend state. Issue READ_BUFFER in the next turn"); + spin_lock_bh(&hpb->retry_list_lock); + list_splice_init(&retry_list, &hpb->lh_map_req_retry); + spin_unlock_bh(&hpb->retry_list_lock); + do_retry = true; + break; + } + + list_del_init(&map_req->list_req); + + rgn = hpb->rgn_tbl + map_req->rb.rgn_idx; + srgn = rgn->srgn_tbl + map_req->rb.srgn_idx; + + bio_put(map_req->bio); + blk_put_request(map_req->req); + spin_lock_irqsave(&hpb->hpb_lock, flags); + ufshpb_put_map_req(hpb, map_req); + spin_unlock_irqrestore(&hpb->hpb_lock, flags); + + ret = ufshpb_lu_get(hpb); + if (unlikely(ret)) { + if (ret == -ENODEV) + ERR_MSG("lu_get failed (%d)", ret); + HPB_DEBUG(hpb, "lu_get failed (%d)", ret); + continue; + } + + ret = ufshpb_issue_map_req(hpb, srgn); + if (ret) { + ERR_MSG("issue ERR %d R[%05d](%d) S%0d(%d)", + ret, rgn->rgn_idx, rgn->rgn_state, + srgn->srgn_idx, srgn->srgn_state); + spin_lock_bh(&hpb->retry_list_lock); + list_splice_init(&retry_list, &hpb->lh_map_req_retry); + spin_unlock_bh(&hpb->retry_list_lock); + do_retry = true; + break; + } + } + HPB_DEBUG(hpb, "worker end"); + ufshpb_lu_put(hpb); + + if (do_retry) + schedule_delayed_work(&hpb->retry_work, + msecs_to_jiffies(RETRY_DELAY_MS)); +} + +static void ufshpb_add_starved_list(struct ufshpb_lu *hpb, + struct ufshpb_region *rgn, + struct list_head *starved_list) +{ + struct ufshpb_subregion *srgn; + int srgn_idx; + + if (!list_empty(&rgn->list_inact_rgn)) + return; + + for (srgn_idx = 0; srgn_idx < rgn->srgn_cnt; srgn_idx++) { + srgn = rgn->srgn_tbl + srgn_idx; + + if (!list_empty(&srgn->list_act_srgn)) + return; + } + /* It will be added to hpb->lh_inact_rgn */ + atomic64_inc(&hpb->inact_rsp_list_cnt); + list_add_tail(&rgn->list_inact_rgn, starved_list); + + HPB_FTRACE(hpb, "R[%05d](%d)", + rgn->rgn_idx, rgn->rgn_state); + +} + +static void ufshpb_run_inactive_region_list(struct ufshpb_lu *hpb) +{ + struct ufshpb_region *rgn; + unsigned long flags; + int ret; + LIST_HEAD(starved_list); + + spin_lock_irqsave(&hpb->rsp_list_lock, flags); + while ((rgn = list_first_entry_or_null(&hpb->lh_inact_rgn, + struct ufshpb_region, + list_inact_rgn))) { + if (ufshpb_get_state(hpb->ufsf) == HPB_SUSPEND) { + INFO_MSG("suspend state. Inactivate rgn the next turn"); + break; + } + + HPB_FTRACE(hpb, "inact R[%05d](%d)", + rgn->rgn_idx, rgn->rgn_state); + + ufshpb_inact_rsp_list_del(hpb, rgn); + spin_unlock_irqrestore(&hpb->rsp_list_lock, flags); + + ret = ufshpb_evict_region(hpb, rgn); + if (ret) { + spin_lock_irqsave(&hpb->rsp_list_lock, flags); + ufshpb_add_starved_list(hpb, rgn, &starved_list); + spin_unlock_irqrestore(&hpb->rsp_list_lock, flags); + } + + spin_lock_irqsave(&hpb->rsp_list_lock, flags); + } + + list_splice(&starved_list, &hpb->lh_inact_rgn); + spin_unlock_irqrestore(&hpb->rsp_list_lock, flags); +} + +static void ufshpb_add_active_list(struct ufshpb_lu *hpb, + struct ufshpb_region *rgn, + struct ufshpb_subregion *srgn) +{ + if (!list_empty(&rgn->list_inact_rgn)) + return; + + if (!list_empty(&srgn->list_act_srgn)) { + list_move(&srgn->list_act_srgn, &hpb->lh_act_srgn); + return; + } + + HPB_FTRACE(hpb, "R[%05d](%d)", + rgn->rgn_idx, rgn->rgn_state); + + ufshpb_act_rsp_list_add(hpb, srgn); +} + +static void ufshpb_run_active_subregion_list(struct ufshpb_lu *hpb) +{ + struct ufshpb_region *rgn; + struct ufshpb_subregion *srgn; + unsigned long flags; + int ret = 0; + + spin_lock_irqsave(&hpb->rsp_list_lock, flags); + while ((srgn = list_first_entry_or_null(&hpb->lh_act_srgn, + struct ufshpb_subregion, + list_act_srgn))) { + if (ufshpb_get_state(hpb->ufsf) == HPB_SUSPEND) { + INFO_MSG("suspend state. Issuing READ_BUFFER the next turn"); + break; + } + + ufshpb_act_rsp_list_del(hpb, srgn); + + if (hpb->force_map_req_disable) { + HPB_DEBUG(hpb, "map_req disabled"); + continue; + } + + spin_unlock_irqrestore(&hpb->rsp_list_lock, flags); + + rgn = hpb->rgn_tbl + srgn->rgn_idx; + + HPB_FTRACE(hpb, "R[%05d](%d)", + rgn->rgn_idx, rgn->rgn_state); + + ret = ufshpb_load_region(hpb, rgn); + if (ret) + break; + + ret = ufshpb_issue_map_req(hpb, srgn); + if (ret) + break; + + spin_lock_irqsave(&hpb->rsp_list_lock, flags); + } + + if (ret) { + spin_lock_irqsave(&hpb->rsp_list_lock, flags); + ufshpb_add_active_list(hpb, rgn, srgn); + } + spin_unlock_irqrestore(&hpb->rsp_list_lock, flags); +} + +static void ufshpb_task_work_handler(struct work_struct *work) +{ + struct ufshpb_lu *hpb; + int ret; + + hpb = container_of(work, struct ufshpb_lu, task_work); + ret = ufshpb_lu_get(hpb); + if (unlikely(ret)) { + if (ret == -ENODEV) + ERR_MSG("lu_get failed (%d)", ret); + HPB_DEBUG(hpb, "lu_get failed (%d)", ret); + return; + } + + ufshpb_run_inactive_region_list(hpb); + ufshpb_run_active_subregion_list(hpb); + + ufshpb_lu_put(hpb); +} + +static inline void ufshpb_map_req_mempool_remove(struct ufshpb_lu *hpb) +{ + struct ufshpb_req *map_req; + int i; + + for (i = 0; i < hpb->qd; i++) { + map_req = hpb->map_req + i; + if (map_req->req) + blk_put_request(map_req->req); + if (map_req->bio) + bio_put(map_req->bio); + } + + kfree(hpb->map_req); +} + +static inline void ufshpb_pre_req_mempool_remove(struct ufshpb_lu *hpb) +{ + struct ufshpb_req *pre_req; + int i; + + for (i = 0; i < hpb->qd; i++) { + pre_req = hpb->pre_req + i; + if (pre_req->req) + blk_put_request(pre_req->req); + if (pre_req->bio) + bio_put(pre_req->bio); + __free_page(pre_req->wb.m_page); + } + + kfree(hpb->pre_req); +} + +static void ufshpb_table_mempool_remove(struct ufshpb_lu *hpb) +{ + struct ufshpb_map_ctx *mctx, *next; + int i; + + /* + * the mctx in the lh_map_ctx_free has been allocated completely. + */ + list_for_each_entry_safe(mctx, next, &hpb->lh_map_ctx_free, + list_table) { + for (i = 0; i < hpb->mpages_per_srgn; i++) + __free_page(mctx->m_page[i]); + + vfree(mctx->ppn_dirty); + kfree(mctx->m_page); + kfree(mctx); + hpb->alloc_mctx--; + } +} + +/* + * this function doesn't need to hold lock due to be called in init. + * (hpb_lock, rsp_list_lock, etc..) + */ +static int ufshpb_init_pinned_active_region(struct ufshpb_lu *hpb, + struct ufshpb_region *rgn) +{ + struct ufshpb_subregion *srgn; + int srgn_idx, j; + int err = 0; + + for (srgn_idx = 0; srgn_idx < rgn->srgn_cnt; srgn_idx++) { + srgn = rgn->srgn_tbl + srgn_idx; + + srgn->mctx = ufshpb_get_map_ctx(hpb, &err); + if (err) { + ERR_MSG("mctx ERR %d R[%05d](%d) S[%d](%d) free_table %d", + err, srgn->rgn_idx, rgn->rgn_state, + srgn_idx, srgn->srgn_state, + hpb->debug_free_table); + goto release; + } + + srgn->srgn_state = HPB_SRGN_ISSUED; + /* + * no need to clean ppn_dirty bitmap + * because it is vzalloc-ed @ufshpb_table_mempool_init() + */ + list_add_tail(&srgn->list_act_srgn, &hpb->lh_pinned_srgn); + } + + rgn->rgn_state = HPB_RGN_PINNED; + + return 0; + +release: + for (j = 0; j < srgn_idx; j++) { + srgn = rgn->srgn_tbl + j; + ufshpb_put_map_ctx(hpb, srgn->mctx); + } + + return err; +} + +static inline bool ufshpb_is_pinned_region(struct ufshpb_lu *hpb, int rgn_idx) +{ + if (hpb->lu_pinned_end_offset != PINNED_NOT_SET && + rgn_idx >= hpb->lu_pinned_rgn_startidx && + rgn_idx <= hpb->lu_pinned_end_offset) + return true; + + return false; +} + +static inline void ufshpb_init_jobs(struct ufshpb_lu *hpb) +{ + INIT_WORK(&hpb->pinned_work, ufshpb_pinned_work_handler); + INIT_DELAYED_WORK(&hpb->retry_work, ufshpb_retry_work_handler); + INIT_WORK(&hpb->task_work, ufshpb_task_work_handler); +} + +static inline void ufshpb_cancel_jobs(struct ufshpb_lu *hpb) +{ + cancel_work_sync(&hpb->pinned_work); + cancel_delayed_work_sync(&hpb->retry_work); + cancel_work_sync(&hpb->task_work); +} + +static void ufshpb_init_subregion_tbl(struct ufshpb_lu *hpb, + struct ufshpb_region *rgn) +{ + int srgn_idx; + + for (srgn_idx = 0; srgn_idx < rgn->srgn_cnt; srgn_idx++) { + struct ufshpb_subregion *srgn = rgn->srgn_tbl + srgn_idx; + + INIT_LIST_HEAD(&srgn->list_act_srgn); + + srgn->rgn_idx = rgn->rgn_idx; + srgn->srgn_idx = srgn_idx; + srgn->srgn_state = HPB_SRGN_UNUSED; + } +} + +static inline int ufshpb_alloc_subregion_tbl(struct ufshpb_lu *hpb, + struct ufshpb_region *rgn, + int srgn_cnt) +{ + rgn->srgn_tbl = + kzalloc(sizeof(struct ufshpb_subregion) * srgn_cnt, GFP_KERNEL); + if (!rgn->srgn_tbl) + return -ENOMEM; + + rgn->srgn_cnt = srgn_cnt; + return 0; +} + +static int ufshpb_table_mempool_init(struct ufshpb_lu *hpb) +{ + struct ufshpb_map_ctx *mctx = NULL; + int i, j, k; + + INIT_LIST_HEAD(&hpb->lh_map_ctx_free); + + hpb->alloc_mctx = hpb->lu_max_active_rgns * hpb->srgns_per_rgn; + + for (i = 0; i < hpb->alloc_mctx; i++) { + mctx = kmalloc(sizeof(struct ufshpb_map_ctx), GFP_KERNEL); + if (!mctx) + goto release_mem; + + mctx->m_page = + kzalloc(sizeof(struct page *) * hpb->mpages_per_srgn, + GFP_KERNEL); + if (!mctx->m_page) + goto release_mem; + + mctx->ppn_dirty = vzalloc(hpb->entries_per_srgn >> + bits_per_byte_shift); + if (!mctx->ppn_dirty) + goto release_mem; + + for (j = 0; j < hpb->mpages_per_srgn; j++) { + mctx->m_page[j] = alloc_page(GFP_KERNEL | __GFP_ZERO); + if (!mctx->m_page[j]) { + for (k = 0; k < j; k++) + __free_page(mctx->m_page[k]); + goto release_mem; + } + } + + INIT_LIST_HEAD(&mctx->list_table); + list_add(&mctx->list_table, &hpb->lh_map_ctx_free); + + hpb->debug_free_table++; + } + + INFO_MSG("The number of mctx = (%d). debug_free_table (%d)", + hpb->alloc_mctx, hpb->debug_free_table); + return 0; +release_mem: + /* + * mctxs already added in lh_map_ctx_free will be removed + * in the caller function. + */ + if (mctx) { + kfree(mctx->m_page); + vfree(mctx->ppn_dirty); + kfree(mctx); + } + return -ENOMEM; +} + +static int ufshpb_map_req_mempool_init(struct ufshpb_lu *hpb) +{ + struct scsi_device *sdev; + struct request_queue *q; + struct ufshpb_req *map_req = NULL; + int qd = hpb->qd; + int i; + + sdev = hpb->ufsf->sdev_ufs_lu[hpb->lun]; + q = sdev->request_queue; + + INIT_LIST_HEAD(&hpb->lh_map_req_free); + INIT_LIST_HEAD(&hpb->lh_map_req_retry); + + hpb->map_req = kzalloc(sizeof(struct ufshpb_req) * qd, GFP_KERNEL); + if (!hpb->map_req) + goto release_mem; + + for (i = 0; i < qd; i++) { + map_req = hpb->map_req + i; + INIT_LIST_HEAD(&map_req->list_req); + map_req->req = NULL; + map_req->bio = NULL; + + list_add_tail(&map_req->list_req, &hpb->lh_map_req_free); + } + + return 0; +release_mem: + kfree(hpb->map_req); + return -ENOMEM; +} + +static int ufshpb_pre_req_mempool_init(struct ufshpb_lu *hpb) +{ + struct scsi_device *sdev; + struct request_queue *q; + struct ufshpb_req *pre_req = NULL; + int qd = hpb->qd; + int i, j; + + INIT_LIST_HEAD(&hpb->lh_pre_req_free); + + sdev = hpb->ufsf->sdev_ufs_lu[hpb->lun]; + q = sdev->request_queue; + + hpb->pre_req = kzalloc(sizeof(struct ufshpb_req) * qd, GFP_KERNEL); + if (!hpb->pre_req) + goto release_mem; + + for (i = 0; i < qd; i++) { + pre_req = hpb->pre_req + i; + INIT_LIST_HEAD(&pre_req->list_req); + pre_req->req = NULL; + pre_req->bio = NULL; + + pre_req->wb.m_page = alloc_page(GFP_KERNEL | __GFP_ZERO); + if (!pre_req->wb.m_page) { + for (j = 0; j < i; j++) + __free_page(hpb->pre_req[j].wb.m_page); + + goto release_mem; + } + list_add_tail(&pre_req->list_req, &hpb->lh_pre_req_free); + } + + return 0; +release_mem: + kfree(hpb->pre_req); + return -ENOMEM; +} + +static void ufshpb_find_lu_qd(struct ufshpb_lu *hpb) +{ + struct scsi_device *sdev; + struct ufs_hba *hba; + + sdev = hpb->ufsf->sdev_ufs_lu[hpb->lun]; + hba = hpb->ufsf->hba; + + /* + * ufshcd_slave_alloc(sdev) -> ufshcd_set_queue_depth(sdev) + * a lu-queue-depth compared with lu_info and hba->nutrs + * is selected in ufshcd_set_queue_depth() + */ + hpb->qd = sdev->queue_depth; + INFO_MSG("lu (%d) queue_depth (%d)", hpb->lun, hpb->qd); + if (!hpb->qd) { + hpb->qd = hba->nutrs; + INFO_MSG("lu_queue_depth is 0. we use device's queue info."); + INFO_MSG("hba->nutrs = (%d)", hba->nutrs); + } + + hpb->throttle_map_req = hpb->qd; + hpb->throttle_pre_req = hpb->qd; + hpb->num_inflight_map_req = 0; + hpb->num_inflight_pre_req = 0; +} + +static void ufshpb_init_lu_constant(struct ufshpb_dev_info *hpb_dev_info, + struct ufshpb_lu *hpb) +{ + unsigned long long rgn_unit_size, rgn_mem_size; + int entries_per_rgn; + + hpb->debug = false; + + ufshpb_find_lu_qd(hpb); + + /* for pre_req */ + hpb->pre_req_min_tr_len = HPB_MULTI_CHUNK_LOW; + hpb->pre_req_max_tr_len = HPB_MULTI_CHUNK_HIGH; + hpb->ctx_id_ticket = 0; + hpb->pre_req_requeue_cnt = DEFAULT_WB_REQUEUE_CNT; + + /* From descriptors */ + rgn_unit_size = (unsigned long long) + SECTOR * (0x01 << hpb_dev_info->rgn_size); + rgn_mem_size = rgn_unit_size / BLOCK * HPB_ENTRY_SIZE; + + hpb->srgn_unit_size = (unsigned long long) + SECTOR * (0x01 << hpb_dev_info->srgn_size); + hpb->srgn_mem_size = hpb->srgn_unit_size / BLOCK * HPB_ENTRY_SIZE; + + /* relation : lu <-> region <-> sub region <-> entry */ + entries_per_rgn = rgn_mem_size / HPB_ENTRY_SIZE; + hpb->entries_per_srgn = hpb->srgn_mem_size / HPB_ENTRY_SIZE; + hpb->srgns_per_rgn = rgn_mem_size / hpb->srgn_mem_size; + + /* + * regions_per_lu = (lu_num_blocks * 4096) / region_unit_size + * = (lu_num_blocks * HPB_ENTRY_SIZE) / region_mem_size + */ + hpb->rgns_per_lu = + ((unsigned long long)hpb->lu_num_blocks + + (rgn_mem_size / HPB_ENTRY_SIZE) - 1) + / (rgn_mem_size / HPB_ENTRY_SIZE); + hpb->srgns_per_lu = + ((unsigned long long)hpb->lu_num_blocks + + (hpb->srgn_mem_size / HPB_ENTRY_SIZE) - 1) + / (hpb->srgn_mem_size / HPB_ENTRY_SIZE); + + /* mempool info */ + hpb->mpage_bytes = OS_PAGE_SIZE; + hpb->mpages_per_srgn = hpb->srgn_mem_size / hpb->mpage_bytes; + + /* Bitmask Info. */ + hpb->dwords_per_srgn = hpb->entries_per_srgn / BITS_PER_DWORD; + hpb->entries_per_rgn_shift = ffs(entries_per_rgn) - 1; + hpb->entries_per_rgn_mask = entries_per_rgn - 1; + hpb->entries_per_srgn_shift = ffs(hpb->entries_per_srgn) - 1; + hpb->entries_per_srgn_mask = hpb->entries_per_srgn - 1; + + INFO_MSG("===== From Device Descriptor! ====="); + INFO_MSG("hpb_region_size = (%d), hpb_subregion_size = (%d)", + hpb_dev_info->rgn_size, hpb_dev_info->srgn_size); + INFO_MSG("===== Constant Values(LU) ====="); + INFO_MSG("region_unit_size = (%lld), region_mem_size (%lld)", + rgn_unit_size, rgn_mem_size); + INFO_MSG("subregion_unit_size = (%lld), subregion_mem_size (%d)", + hpb->srgn_unit_size, hpb->srgn_mem_size); + + INFO_MSG("lu_num_blocks = (%d)", hpb->lu_num_blocks); + INFO_MSG("regions_per_lu = (%d), subregions_per_lu = (%d)", + hpb->rgns_per_lu, hpb->srgns_per_lu); + + INFO_MSG("subregions_per_region = %d", hpb->srgns_per_rgn); + INFO_MSG("entries_per_region (%u) shift (%u) mask (0x%X)", + entries_per_rgn, hpb->entries_per_rgn_shift, + hpb->entries_per_rgn_mask); + INFO_MSG("entries_per_subregion (%u) shift (%u) mask (0x%X)", + hpb->entries_per_srgn, hpb->entries_per_srgn_shift, + hpb->entries_per_srgn_mask); + INFO_MSG("mpages_per_subregion : (%d)", hpb->mpages_per_srgn); + INFO_MSG("==================================="); +} + +static int ufshpb_lu_hpb_init(struct ufsf_feature *ufsf, int lun) +{ + struct ufshpb_lu *hpb = ufsf->hpb_lup[lun]; + struct ufshpb_region *rgn_table, *rgn; + struct ufshpb_subregion *srgn; + int rgn_idx, srgn_idx, total_srgn_cnt, srgn_cnt, i, ret = 0; + + ufshpb_init_lu_constant(&ufsf->hpb_dev_info, hpb); + + rgn_table = kzalloc(sizeof(struct ufshpb_region) * hpb->rgns_per_lu, + GFP_KERNEL); + if (!rgn_table) { + ret = -ENOMEM; + goto out; + } + + INFO_MSG("active_region_table bytes: (%lu)", + (sizeof(struct ufshpb_region) * hpb->rgns_per_lu)); + + hpb->rgn_tbl = rgn_table; + + spin_lock_init(&hpb->hpb_lock); + spin_lock_init(&hpb->retry_list_lock); + spin_lock_init(&hpb->rsp_list_lock); + + /* init lru information */ + INIT_LIST_HEAD(&hpb->lru_info.lh_lru_rgn); + hpb->lru_info.selection_type = LRU; + + INIT_LIST_HEAD(&hpb->lh_pinned_srgn); + INIT_LIST_HEAD(&hpb->lh_act_srgn); + INIT_LIST_HEAD(&hpb->lh_inact_rgn); + + INIT_LIST_HEAD(&hpb->lh_map_ctx_free); + + ufshpb_init_jobs(hpb); + + ret = ufshpb_map_req_mempool_init(hpb); + if (ret) { + ERR_MSG("map_req_mempool init fail!"); + goto release_rgn_table; + } + + ret = ufshpb_pre_req_mempool_init(hpb); + if (ret) { + ERR_MSG("pre_req_mempool init fail!"); + goto release_map_req_mempool; + } + + ret = ufshpb_table_mempool_init(hpb); + if (ret) { + ERR_MSG("ppn table mempool init fail!"); + ufshpb_table_mempool_remove(hpb); + goto release_pre_req_mempool; + } + + total_srgn_cnt = hpb->srgns_per_lu; + INFO_MSG("total_subregion_count: (%d)", total_srgn_cnt); + for (rgn_idx = 0, srgn_cnt = 0; rgn_idx < hpb->rgns_per_lu; + rgn_idx++, total_srgn_cnt -= srgn_cnt) { + rgn = rgn_table + rgn_idx; + rgn->rgn_idx = rgn_idx; + + INIT_LIST_HEAD(&rgn->list_inact_rgn); + + /* init lru region information*/ + INIT_LIST_HEAD(&rgn->list_lru_rgn); + + srgn_cnt = min(total_srgn_cnt, hpb->srgns_per_rgn); + + ret = ufshpb_alloc_subregion_tbl(hpb, rgn, srgn_cnt); + if (ret) + goto release_srgns; + ufshpb_init_subregion_tbl(hpb, rgn); + + if (ufshpb_is_pinned_region(hpb, rgn_idx)) { + ret = ufshpb_init_pinned_active_region(hpb, rgn); + if (ret) + goto release_srgns; + } else { + rgn->rgn_state = HPB_RGN_INACTIVE; + } + } + + if (total_srgn_cnt != 0) { + ERR_MSG("error total_subregion_count: %d", + total_srgn_cnt); + goto release_srgns; + } + + atomic64_set(&hpb->lru_info.active_cnt, 0); + /* + * even if creating sysfs failed, ufshpb could run normally. + * so we don't deal with error handling + */ + ufshpb_create_sysfs(ufsf, hpb); + + return 0; +release_srgns: + for (i = 0; i < rgn_idx; i++) { + rgn = rgn_table + i; + if (rgn->srgn_tbl) { + for (srgn_idx = 0; srgn_idx < rgn->srgn_cnt; + srgn_idx++) { + srgn = rgn->srgn_tbl + srgn_idx; + if (srgn->mctx) + ufshpb_put_map_ctx(hpb, srgn->mctx); + } + kfree(rgn->srgn_tbl); + } + } + + ufshpb_table_mempool_remove(hpb); +release_pre_req_mempool: + ufshpb_pre_req_mempool_remove(hpb); +release_map_req_mempool: + ufshpb_map_req_mempool_remove(hpb); +release_rgn_table: + kfree(rgn_table); +out: + return ret; +} + +static inline int ufshpb_version_check(struct ufshpb_dev_info *hpb_dev_info, int oem_id) +{ + INFO_MSG("Support HPB Spec : Driver = (%.4X) Device = (%.4X) Vendor = (%.2x)", + UFSHPB_VER, hpb_dev_info->version,oem_id); + + INFO_MSG("HPB Driver Version : (%.6X%s)", + UFSHPB_DD_VER, UFSHPB_DD_VER_POST); + + if (hpb_dev_info->version != UFSHPB_VER && oem_id == 0x1ce) { + ERR_MSG("ERROR: HPB Spec Version mismatch. So HPB disabled."); + return -ENODEV; + } + if (hpb_dev_info->version != 0x200 && oem_id == 0x12c){ + ERR_MSG("ERROR: micron devices HPB Spec Version mismatch. So HPB disabled."); + return -ENODEV; + + } + return 0; +} + +void ufshpb_get_dev_info(struct ufsf_feature *ufsf, u8 *desc_buf) +{ + struct ufshpb_dev_info *hpb_dev_info = &ufsf->hpb_dev_info; + int ret; + int manufacturer = 0; + + if (desc_buf[DEVICE_DESC_PARAM_UFS_FEAT] & UFS_FEATURE_SUPPORT_HPB_BIT) + INFO_MSG("bUFSFeaturesSupport: HPB is set"); + else { + INFO_MSG("bUFSFeaturesSupport: HPB not support"); + ufshpb_set_state(ufsf, HPB_FAILED); + return; + } + + hpb_dev_info->version = LI_EN_16(desc_buf + DEVICE_DESC_PARAM_HPB_VER); + + manufacturer = LI_EN_16(desc_buf + DEVICE_DESC_PARAM_OEM_ID); + + ret = ufshpb_version_check(hpb_dev_info,manufacturer); + if (ret) + ufshpb_set_state(ufsf, HPB_FAILED); +} + +void ufshpb_get_geo_info(struct ufsf_feature *ufsf, u8 *geo_buf) +{ + struct ufshpb_dev_info *hpb_dev_info = &ufsf->hpb_dev_info; + int hpb_device_max_active_rgns = 0; + + hpb_dev_info->num_lu = geo_buf[GEOMETRY_DESC_HPB_NUMBER_LU]; + if (hpb_dev_info->num_lu == 0) { + ERR_MSG("Don't have a lu for hpb."); + ufshpb_set_state(ufsf, HPB_FAILED); + return; + } + + hpb_dev_info->rgn_size = geo_buf[GEOMETRY_DESC_HPB_REGION_SIZE]; + hpb_dev_info->srgn_size = geo_buf[GEOMETRY_DESC_HPB_SUBREGION_SIZE]; + hpb_device_max_active_rgns = + LI_EN_16(geo_buf + GEOMETRY_DESC_HPB_DEVICE_MAX_ACTIVE_REGIONS); + + INFO_MSG("[48] bHPBRegionSize (%u)", hpb_dev_info->rgn_size); + INFO_MSG("[49] bHPBNumberLU (%u)", hpb_dev_info->num_lu); + INFO_MSG("[4A] bHPBSubRegionSize (%u)", hpb_dev_info->srgn_size); + INFO_MSG("[4B:4C] wDeviceMaxActiveHPBRegions (%u)", + hpb_device_max_active_rgns); + + if (hpb_dev_info->rgn_size == 0 || hpb_dev_info->srgn_size == 0 || + hpb_device_max_active_rgns == 0) { + ERR_MSG("HPB NOT normally supported by device"); + ufshpb_set_state(ufsf, HPB_FAILED); + } +} + +void ufshpb_get_lu_info(struct ufsf_feature *ufsf, int lun, u8 *unit_buf) +{ + struct ufsf_lu_desc lu_desc; + struct ufshpb_lu *hpb; + + lu_desc.lu_enable = unit_buf[UNIT_DESC_PARAM_LU_ENABLE]; + lu_desc.lu_queue_depth = unit_buf[UNIT_DESC_PARAM_LU_Q_DEPTH]; + lu_desc.lu_logblk_size = unit_buf[UNIT_DESC_PARAM_LOGICAL_BLK_SIZE]; + lu_desc.lu_logblk_cnt = + LI_EN_64(unit_buf + UNIT_DESC_PARAM_LOGICAL_BLK_COUNT); + lu_desc.lu_max_active_hpb_rgns = + LI_EN_16(unit_buf + UNIT_DESC_HPB_LU_MAX_ACTIVE_REGIONS); + lu_desc.lu_hpb_pinned_rgn_startidx = + LI_EN_16(unit_buf + UNIT_DESC_HPB_LU_PIN_REGION_START_OFFSET); + lu_desc.lu_num_hpb_pinned_rgns = + LI_EN_16(unit_buf + UNIT_DESC_HPB_LU_NUM_PIN_REGIONS); + + if (lu_desc.lu_num_hpb_pinned_rgns > 0) { + lu_desc.lu_hpb_pinned_end_offset = + lu_desc.lu_hpb_pinned_rgn_startidx + + lu_desc.lu_num_hpb_pinned_rgns - 1; + } else + lu_desc.lu_hpb_pinned_end_offset = PINNED_NOT_SET; + + INFO_MSG("LUN(%d) [0A] bLogicalBlockSize (%d)", + lun, lu_desc.lu_logblk_size); + INFO_MSG("LUN(%d) [0B] qLogicalBlockCount (%llu)", + lun, lu_desc.lu_logblk_cnt); + INFO_MSG("LUN(%d) [03] bLuEnable (%d)", lun, lu_desc.lu_enable); + INFO_MSG("LUN(%d) [06] bLuQueueDepth (%d)", lun, + lu_desc.lu_queue_depth); + INFO_MSG("LUN(%d) [23:24] wLUMaxActiveHPBRegions (%d)", + lun, lu_desc.lu_max_active_hpb_rgns); + INFO_MSG("LUN(%d) [25:26] wHPBPinnedRegionStartIdx (%d)", + lun, lu_desc.lu_hpb_pinned_rgn_startidx); + INFO_MSG("LUN(%d) [27:28] wNumHPBPinnedRegions (%d)", + lun, lu_desc.lu_num_hpb_pinned_rgns); + INFO_MSG("LUN(%d) PINNED Start (%d) End (%d)", + lun, lu_desc.lu_hpb_pinned_rgn_startidx, + lu_desc.lu_hpb_pinned_end_offset); + + ufsf->hpb_lup[lun] = NULL; + + if (lu_desc.lu_enable == 0x02 && lu_desc.lu_max_active_hpb_rgns) { + ufsf->hpb_lup[lun] = kzalloc(sizeof(struct ufshpb_lu), + GFP_KERNEL); + if (!ufsf->hpb_lup[lun]) { + ERR_MSG("hpb_lup[%d] alloc failed", lun); + return; + } + + hpb = ufsf->hpb_lup[lun]; + hpb->ufsf = ufsf; + hpb->lun = lun; + hpb->lu_num_blocks = lu_desc.lu_logblk_cnt; + hpb->lu_max_active_rgns = lu_desc.lu_max_active_hpb_rgns; + hpb->lru_info.max_lru_active_cnt = + lu_desc.lu_max_active_hpb_rgns - + lu_desc.lu_num_hpb_pinned_rgns; + hpb->lu_pinned_rgn_startidx = + lu_desc.lu_hpb_pinned_rgn_startidx; + hpb->lu_pinned_end_offset = lu_desc.lu_hpb_pinned_end_offset; + } else { + INFO_MSG("===== LU (%d) is hpb-disabled.", lun); + } +} + +static void ufshpb_error_handler(struct work_struct *work) +{ + struct ufsf_feature *ufsf; + + ufsf = container_of(work, struct ufsf_feature, hpb_eh_work); + + WARN_MSG("driver has failed. but UFSHCD can run without UFSHPB"); + WARN_MSG("UFSHPB will be removed from the kernel"); + + ufshpb_remove(ufsf, HPB_FAILED); +} + +static int ufshpb_init(struct ufsf_feature *ufsf) +{ + int lun, ret; + struct ufshpb_lu *hpb; + int hpb_enabled_lun = 0; + + seq_scan_lu(lun) { + if (!ufsf->hpb_lup[lun]) + continue; + + /* + * HPB need info about request queue in order to issue + * RB-CMD for pinned region. + */ + if (!ufsf->sdev_ufs_lu[lun]) { + WARN_MSG("lun (%d) don't have scsi_device", lun); + continue; + } + + ret = ufshpb_lu_hpb_init(ufsf, lun); + if (ret) { + kfree(ufsf->hpb_lup[lun]); + continue; + } + hpb_enabled_lun++; + } + + if (hpb_enabled_lun == 0) { + ERR_MSG("No UFSHPB LU to init"); + ret = -ENODEV; + goto hpb_failed; + } + + INIT_WORK(&ufsf->hpb_eh_work, ufshpb_error_handler); + + kref_init(&ufsf->hpb_kref); + ufshpb_set_state(ufsf, HPB_PRESENT); + + seq_scan_lu(lun) + if (ufsf->hpb_lup[lun]) { + hpb = ufsf->hpb_lup[lun]; + + INFO_MSG("UFSHPB LU %d working", lun); + if (hpb->lu_pinned_end_offset != PINNED_NOT_SET) + schedule_work(&hpb->pinned_work); + } + + return 0; +hpb_failed: + ufshpb_set_state(ufsf, HPB_FAILED); + return ret; +} + +static void ufshpb_drop_retry_list(struct ufshpb_lu *hpb) +{ + struct ufshpb_req *map_req, *next; + struct request *req; + unsigned long flags; + LIST_HEAD(lh_reqs); + + if (list_empty(&hpb->lh_map_req_retry)) + return; + + spin_lock_irqsave(&hpb->hpb_lock, flags); + list_for_each_entry_safe(map_req, next, &hpb->lh_map_req_retry, + list_req) { + INFO_MSG("drop map_req %p ( %d - %d )", map_req, + map_req->rb.rgn_idx, map_req->rb.srgn_idx); + + list_del_init(&map_req->list_req); + + /* + * blk_put_request() will grap the queue_lock. + * so requests add to a list. + * lock seq : queue_lock -> hpb_lock. + */ + list_add_tail(&map_req->req->queuelist, &lh_reqs); + + bio_put(map_req->bio); + + ufshpb_put_map_req(hpb, map_req); + } + spin_unlock_irqrestore(&hpb->hpb_lock, flags); + + list_for_each_entry(req, &lh_reqs, queuelist) + blk_put_request(req); +} + +static void ufshpb_drop_rsp_lists(struct ufshpb_lu *hpb) +{ + struct ufshpb_region *rgn, *next_rgn; + struct ufshpb_subregion *srgn, *next_srgn; + unsigned long flags; + + spin_lock_irqsave(&hpb->rsp_list_lock, flags); + list_for_each_entry_safe(rgn, next_rgn, &hpb->lh_inact_rgn, + list_inact_rgn) { + list_del_init(&rgn->list_inact_rgn); + } + + list_for_each_entry_safe(srgn, next_srgn, &hpb->lh_act_srgn, + list_act_srgn) { + list_del_init(&srgn->list_act_srgn); + } + spin_unlock_irqrestore(&hpb->rsp_list_lock, flags); +} + +static void ufshpb_destroy_subregion_tbl(struct ufshpb_lu *hpb, + struct ufshpb_region *rgn) +{ + int srgn_idx; + + for (srgn_idx = 0; srgn_idx < rgn->srgn_cnt; srgn_idx++) { + struct ufshpb_subregion *srgn; + + srgn = rgn->srgn_tbl + srgn_idx; + srgn->srgn_state = HPB_SRGN_UNUSED; + + ufshpb_put_map_ctx(hpb, srgn->mctx); + } +} + +static void ufshpb_destroy_region_tbl(struct ufshpb_lu *hpb) +{ + int rgn_idx; + + INFO_MSG("Start"); + + for (rgn_idx = 0; rgn_idx < hpb->rgns_per_lu; rgn_idx++) { + struct ufshpb_region *rgn; + + rgn = hpb->rgn_tbl + rgn_idx; + if (rgn->rgn_state != HPB_RGN_INACTIVE) { + rgn->rgn_state = HPB_RGN_INACTIVE; + + ufshpb_destroy_subregion_tbl(hpb, rgn); + } + + kfree(rgn->srgn_tbl); + } + + ufshpb_table_mempool_remove(hpb); + kfree(hpb->rgn_tbl); + + INFO_MSG("End"); +} + +void ufshpb_remove(struct ufsf_feature *ufsf, int state) +{ + struct ufshpb_lu *hpb; + int lun; + + INFO_MSG("start release"); + ufshpb_set_state(ufsf, HPB_FAILED); + + INFO_MSG("kref count (%d)", + atomic_read(&ufsf->hpb_kref.refcount.refs)); + + seq_scan_lu(lun) { + hpb = ufsf->hpb_lup[lun]; + + INFO_MSG("lun (%d) (%p)", lun, hpb); + + ufsf->hpb_lup[lun] = NULL; + + if (!hpb) + continue; + + ufshpb_cancel_jobs(hpb); + + ufshpb_destroy_region_tbl(hpb); + if (hpb->alloc_mctx != 0) + WARN_MSG("warning: alloc_mctx (%d)", hpb->alloc_mctx); + + ufshpb_map_req_mempool_remove(hpb); + + ufshpb_pre_req_mempool_remove(hpb); + + ufshpb_remove_sysfs(hpb); + + kfree(hpb); + } + + ufshpb_set_state(ufsf, state); + + INFO_MSG("end release"); +} + +void ufshpb_reset(struct ufsf_feature *ufsf) +{ + ufshpb_set_state(ufsf, HPB_PRESENT); +} + +void ufshpb_reset_host(struct ufsf_feature *ufsf) +{ + struct ufshpb_lu *hpb; + int lun; + + ufshpb_set_state(ufsf, HPB_RESET); + seq_scan_lu(lun) { + hpb = ufsf->hpb_lup[lun]; + if (hpb) { + INFO_MSG("UFSHPB lun %d reset", lun); + ufshpb_cancel_jobs(hpb); + ufshpb_drop_retry_list(hpb); + ufshpb_drop_rsp_lists(hpb); + } + } +} + +static inline int ufshpb_probe_lun_done(struct ufsf_feature *ufsf) +{ + return (ufsf->num_lu == ufsf->slave_conf_cnt); +} + +void ufshpb_init_handler(struct work_struct *work) +{ + struct ufsf_feature *ufsf; + int ret = 0; + + ufsf = container_of(work, struct ufsf_feature, hpb_init_work); + + INFO_MSG("probe_done(%d)", ufshpb_probe_lun_done(ufsf)); + + ret = wait_event_timeout(ufsf->hpb_wait, + ufshpb_probe_lun_done(ufsf), + msecs_to_jiffies(10000)); + if (ret == 0) + ERR_MSG("Probing LU is not fully complete."); + + INFO_MSG("probe_done(%d) ret(%d)", ufshpb_probe_lun_done(ufsf), ret); + INFO_MSG("HPB_INIT_START"); + + ret = ufshpb_init(ufsf); + if (ret) + ERR_MSG("UFSHPB driver init failed. (%d)", ret); +} + +void ufshpb_suspend(struct ufsf_feature *ufsf) +{ + struct ufshpb_lu *hpb; + int lun; + + seq_scan_lu(lun) { + hpb = ufsf->hpb_lup[lun]; + if (hpb) { + INFO_MSG("ufshpb_lu %d goto suspend", lun); + INFO_MSG("ufshpb_lu %d changes suspend state", lun); + ufshpb_set_state(ufsf, HPB_SUSPEND); + ufshpb_cancel_jobs(hpb); + } + } +} + +void ufshpb_resume(struct ufsf_feature *ufsf) +{ + struct ufshpb_lu *hpb; + int lun; + + seq_scan_lu(lun) { + hpb = ufsf->hpb_lup[lun]; + if (hpb) { + bool do_task_work = false; + bool do_retry_work = false; + + ufshpb_set_state(ufsf, HPB_PRESENT); + + do_task_work = !ufshpb_is_empty_rsp_lists(hpb); + do_retry_work = + !list_empty_careful(&hpb->lh_map_req_retry); + + INFO_MSG("ufshpb_lu %d resume. do_task_work %d retry %d", + lun, do_task_work, do_retry_work); + + if (do_task_work) + schedule_work(&hpb->task_work); + if (do_retry_work) + schedule_delayed_work(&hpb->retry_work, + msecs_to_jiffies(100)); + } + } +} + +static void ufshpb_stat_reset(struct ufshpb_lu *hpb) +{ + atomic64_set(&hpb->hit, 0); + atomic64_set(&hpb->miss, 0); + atomic64_set(&hpb->rb_noti_cnt, 0); + atomic64_set(&hpb->rb_active_cnt, 0); + atomic64_set(&hpb->rb_inactive_cnt, 0); + atomic64_set(&hpb->map_req_cnt, 0); + atomic64_set(&hpb->map_compl_cnt, 0); + atomic64_set(&hpb->pre_req_cnt, 0); +} + +/* SYSFS functions */ +static ssize_t ufshpb_sysfs_prep_disable_show(struct ufshpb_lu *hpb, char *buf) +{ + int ret; + + ret = snprintf(buf, PAGE_SIZE, "force_hpb_read_disable %d\n", + hpb->force_disable); + + INFO_MSG("force_hpb_read_disable %d", hpb->force_disable); + return ret; +} + +static ssize_t ufshpb_sysfs_prep_disable_store(struct ufshpb_lu *hpb, + const char *buf, size_t cnt) +{ + unsigned long value; + + if (kstrtoul(buf, 0, &value)) + return -EINVAL; + + if (value > 1) + return -EINVAL; + + if (value == 1) + hpb->force_disable = true; + else if (value == 0) + hpb->force_disable = false; + + INFO_MSG("force_hpb_read_disable %d", hpb->force_disable); + + return cnt; +} + +static ssize_t ufshpb_sysfs_map_disable_show(struct ufshpb_lu *hpb, char *buf) +{ + int ret; + + ret = snprintf(buf, PAGE_SIZE, "force_map_req_disable %d\n", + hpb->force_map_req_disable); + + INFO_MSG("force_map_req_disable %d", hpb->force_map_req_disable); + + return ret; +} + +static ssize_t ufshpb_sysfs_map_disable_store(struct ufshpb_lu *hpb, + const char *buf, size_t cnt) +{ + unsigned long value; + + if (kstrtoul(buf, 0, &value)) + return -EINVAL; + + if (value > 1) + return -EINVAL; + + if (value == 1) + hpb->force_map_req_disable = true; + else if (value == 0) + hpb->force_map_req_disable = false; + + INFO_MSG("force_map_req_disable %d", hpb->force_map_req_disable); + + return cnt; +} + +static ssize_t ufshpb_sysfs_throttle_map_req_show(struct ufshpb_lu *hpb, + char *buf) +{ + int ret; + +#if defined(CONFIG_HPB_DEBUG) + ret = snprintf(buf, PAGE_SIZE, "throttle_map_req %d (inflight: %d)\n", + hpb->throttle_map_req, hpb->num_inflight_map_req); +#else + ret = snprintf(buf, PAGE_SIZE, "throttle_map_req %d\n", + hpb->throttle_map_req); +#endif + + INFO_MSG("throttle_map_req %d", hpb->throttle_map_req); + + return ret; +} + +static ssize_t ufshpb_sysfs_throttle_map_req_store(struct ufshpb_lu *hpb, + const char *buf, size_t cnt) +{ + unsigned long throttle_map_req; + + if (kstrtoul(buf, 0, &throttle_map_req)) + return -EINVAL; + + if (throttle_map_req > hpb->qd) + return -EINVAL; + + if ((int)throttle_map_req < 0 || (int)throttle_map_req > hpb->qd) + return -EINVAL; + + hpb->throttle_map_req = (int)throttle_map_req; + + INFO_MSG("throttle_map_req %d", hpb->throttle_map_req); + + return cnt; +} + +static ssize_t ufshpb_sysfs_throttle_pre_req_show(struct ufshpb_lu *hpb, + char *buf) +{ + int ret; + +#if defined(CONFIG_HPB_DEBUG) + ret = snprintf(buf, PAGE_SIZE, "throttle_pre_req %d (inflight: %d)\n", + hpb->throttle_pre_req, hpb->num_inflight_pre_req); +#else + ret = snprintf(buf, PAGE_SIZE, "throttle_pre_req %d\n", + hpb->throttle_pre_req); +#endif + + INFO_MSG("throttle_pre_req %d", hpb->throttle_pre_req); + + return ret; +} + +static ssize_t ufshpb_sysfs_throttle_pre_req_store(struct ufshpb_lu *hpb, + const char *buf, size_t cnt) +{ + unsigned long throttle_pre_req; + + if (kstrtoul(buf, 0, &throttle_pre_req)) + return -EINVAL; + + if (throttle_pre_req > hpb->qd) + return -EINVAL; + + if ((int)throttle_pre_req < 0 || (int)throttle_pre_req > hpb->qd) + return -EINVAL; + + hpb->throttle_pre_req = (int)throttle_pre_req; + + INFO_MSG("throttle_pre_req %d", hpb->throttle_pre_req); + + return cnt; +} + +static ssize_t ufshpb_sysfs_pre_req_min_tr_len_show(struct ufshpb_lu *hpb, + char *buf) +{ + int ret; + + ret = snprintf(buf, PAGE_SIZE, "%d", hpb->pre_req_min_tr_len); + INFO_MSG("pre_req min transfer len %d", hpb->pre_req_min_tr_len); + + return ret; +} + +static ssize_t ufshpb_sysfs_pre_req_min_tr_len_store(struct ufshpb_lu *hpb, + const char *buf, + size_t count) +{ + unsigned long val; + + if (kstrtoul(buf, 0, &val)) + return -EINVAL; + + if (val < 0) + val = 0; + + if (hpb->pre_req_max_tr_len < val || val < HPB_MULTI_CHUNK_LOW) + INFO_MSG("value is wrong. pre_req transfer len %d ~ %d", + HPB_MULTI_CHUNK_LOW, hpb->pre_req_max_tr_len); + else + hpb->pre_req_min_tr_len = val; + + INFO_MSG("pre_req min transfer len %d", hpb->pre_req_min_tr_len); + + return count; +} + +static ssize_t ufshpb_sysfs_pre_req_max_tr_len_show(struct ufshpb_lu *hpb, + char *buf) +{ + int ret; + + ret = snprintf(buf, PAGE_SIZE, "%d", hpb->pre_req_max_tr_len); + INFO_MSG("pre_req max transfer len %d", hpb->pre_req_max_tr_len); + + return ret; +} + +static ssize_t ufshpb_sysfs_pre_req_max_tr_len_store(struct ufshpb_lu *hpb, + const char *buf, + size_t count) +{ + unsigned long val; + + if (kstrtoul(buf, 0, &val)) + return -EINVAL; + + if (hpb->pre_req_min_tr_len > val || val > HPB_MULTI_CHUNK_HIGH) { + INFO_MSG("value is wrong. pre_req transfer len %d ~ %d", + hpb->pre_req_min_tr_len, HPB_MULTI_CHUNK_HIGH); + return -EINVAL; + } + + hpb->pre_req_max_tr_len = val; + + INFO_MSG("pre_req max transfer len %d", hpb->pre_req_max_tr_len); + + return count; +} + +static ssize_t ufshpb_sysfs_pre_req_requeue_cnt_show(struct ufshpb_lu *hpb, + char *buf) +{ + int ret; + + ret = snprintf(buf, PAGE_SIZE, "%d", hpb->pre_req_requeue_cnt); + INFO_MSG("pre_req requeue cnt %d", hpb->pre_req_requeue_cnt); + + return ret; +} + +static ssize_t ufshpb_sysfs_pre_req_requeue_cnt_store(struct ufshpb_lu *hpb, + const char *buf, + size_t count) +{ + unsigned long val; + + if (kstrtoul(buf, 0, &val)) + return -EINVAL; + + if (val < 0) + val = 0; + + hpb->pre_req_requeue_cnt = val; + + INFO_MSG("pre_req requeue cnt %d", hpb->pre_req_requeue_cnt); + + return count; +} + +#if defined(CONFIG_HPB_DEBUG) +static ssize_t ufshpb_sysfs_debug_show(struct ufshpb_lu *hpb, char *buf) +{ + int ret; + + ret = snprintf(buf, PAGE_SIZE, "debug %d\n", hpb->debug); + + INFO_MSG("debug %d", hpb->debug); + + return ret; +} + +static ssize_t ufshpb_sysfs_debug_store(struct ufshpb_lu *hpb, + const char *buf, size_t cnt) +{ + unsigned long debug; + + if (kstrtoul(buf, 0, &debug)) + return -EINVAL; + + if (debug > 1) + return -EINVAL; + + if (debug == 1) + hpb->debug = 1; + else + hpb->debug = 0; + + INFO_MSG("debug %d", hpb->debug); + + return cnt; +} +#endif + +static ssize_t ufshpb_sysfs_rsp_list_cnt_show(struct ufshpb_lu *hpb, char *buf) +{ + long long act_cnt, inact_cnt; + int ret; + + act_cnt = atomic64_read(&hpb->act_rsp_list_cnt); + inact_cnt = atomic64_read(&hpb->inact_rsp_list_cnt); + + ret = snprintf(buf, PAGE_SIZE, + "act_rsp_list_cnt %lld inact_rsp_list_cnt %lld\n", + act_cnt, inact_cnt); + + INFO_MSG("%s", buf); + + return ret; +} + +#if defined(CONFIG_HPB_ERR_INJECTION) +static ssize_t ufshpb_sysfs_err_injection_select_show(struct ufshpb_lu *hpb, + char *buf) +{ + char error_injection[8]; + int ret; + + if (hpb->err_injection_select == HPB_ERR_INJECTION_DISABLE) + strlcpy(error_injection, "disable", 8); + else if (hpb->err_injection_select == HPB_ERR_INJECTION_BITFLIP) + strlcpy(error_injection, "bitflip", 8); + else if (hpb->err_injection_select == HPB_ERR_INJECTION_OFFSET) + strlcpy(error_injection, "offset", 7); + else if (hpb->err_injection_select == HPB_ERR_INJECTION_RANDOM) + strlcpy(error_injection, "random", 7); + + ret = snprintf(buf, PAGE_SIZE, "err_injection_select %s", + error_injection); + + INFO_MSG("err_injection_select %s", error_injection); + + return ret; +} + +static ssize_t ufshpb_sysfs_err_injection_select_store(struct ufshpb_lu *hpb, + const char *buf, + size_t cnt) +{ + char error_injection[8]; + int ret; + + error_injection[7] = '\0'; + + ret = sscanf(buf, "%7s", error_injection); + if (!ret) { + INFO_MSG("input failed..."); + return cnt; + } + + if (!strncmp(error_injection, "disable", 7)) + hpb->err_injection_select = HPB_ERR_INJECTION_DISABLE; + else if (!strncmp(error_injection, "bitflip", 7)) + hpb->err_injection_select = HPB_ERR_INJECTION_BITFLIP; + else if (!strncmp(error_injection, "offset", 6)) + hpb->err_injection_select = HPB_ERR_INJECTION_OFFSET; + else if (!strncmp(error_injection, "random", 6)) + hpb->err_injection_select = HPB_ERR_INJECTION_RANDOM; + else { + hpb->err_injection_select = HPB_ERR_INJECTION_DISABLE; + strlcpy(error_injection, "disable", 8); + } + + INFO_MSG("err_injection_select %s", error_injection); + + return cnt; +} + +static ssize_t ufshpb_sysfs_err_injection_bitflip_show(struct ufshpb_lu *hpb, + char *buf) +{ + int ret; + + ret = snprintf(buf, PAGE_SIZE, "err_injection_bitflip %llx", + hpb->err_injection_bitflip); + + return ret; +} + +static ssize_t ufshpb_sysfs_err_injection_bitflip_store(struct ufshpb_lu *hpb, + const char *buf, + size_t cnt) +{ + unsigned long long err_injection_bitflip; + + if (kstrtoull(buf, 0, &err_injection_bitflip)) + return -EINVAL; + + hpb->err_injection_bitflip = err_injection_bitflip; + + INFO_MSG("err_injection_bitflip %llx", hpb->err_injection_bitflip); + + return cnt; +} + +static ssize_t ufshpb_sysfs_err_injection_offset_show(struct ufshpb_lu *hpb, + char *buf) +{ + int ret; + + ret = snprintf(buf, PAGE_SIZE, "err_injection_offset %lld\n", + hpb->err_injection_offset); + + INFO_MSG("err_injection_offset %lld", hpb->err_injection_offset); + + return ret; +} + +static ssize_t ufshpb_sysfs_err_injection_offset_store(struct ufshpb_lu *hpb, + const char *buf, + size_t cnt) +{ + unsigned long long err_injection_offset; + + if (kstrtoull(buf, 0, &err_injection_offset)) + return -EINVAL; + + hpb->err_injection_offset = err_injection_offset; + + INFO_MSG("err_injection_offset %lld", hpb->err_injection_offset); + + return cnt; +} + +static ssize_t ufshpb_sysfs_err_injection_random_show(struct ufshpb_lu *hpb, + char *buf) +{ + int ret; + + ret = snprintf(buf, PAGE_SIZE, "err_injection_random %d\n", + hpb->err_injection_random); + + INFO_MSG("err_injection_random %d", hpb->err_injection_random); + + return ret; +} + +static ssize_t ufshpb_sysfs_err_injection_random_store(struct ufshpb_lu *hpb, + const char *buf, + size_t cnt) +{ + unsigned long err_injection_random; + + if (kstrtoul(buf, 0, &err_injection_random)) + return -EINVAL; + + if (err_injection_random > 1) + return -EINVAL; + + hpb->err_injection_random = err_injection_random; + + INFO_MSG("err_injection_random %d", hpb->err_injection_random); + + return cnt; +} +#endif + +static ssize_t ufshpb_sysfs_version_show(struct ufshpb_lu *hpb, char *buf) +{ + int ret; + + ret = snprintf(buf, PAGE_SIZE, "HPB version %.4X D/D version %.6X%s\n", + hpb->ufsf->hpb_dev_info.version, + UFSHPB_DD_VER, UFSHPB_DD_VER_POST); + + INFO_MSG("HPB version %.4X D/D version %.6X%s", + hpb->ufsf->hpb_dev_info.version, + UFSHPB_DD_VER, UFSHPB_DD_VER_POST); + + return ret; +} + +static ssize_t ufshpb_sysfs_hit_show(struct ufshpb_lu *hpb, char *buf) +{ + long long hit_cnt; + int ret; + + hit_cnt = atomic64_read(&hpb->hit); + + ret = snprintf(buf, PAGE_SIZE, "hit_count %lld\n", hit_cnt); + + INFO_MSG("hit_count %lld", hit_cnt); + + return ret; +} + +static ssize_t ufshpb_sysfs_miss_show(struct ufshpb_lu *hpb, char *buf) +{ + long long miss_cnt; + int ret; + + miss_cnt = atomic64_read(&hpb->miss); + + ret = snprintf(buf, PAGE_SIZE, "miss_count %lld\n", miss_cnt); + + INFO_MSG("miss_count %lld", miss_cnt); + + return ret; +} + +static ssize_t ufshpb_sysfs_map_req_show(struct ufshpb_lu *hpb, char *buf) +{ + long long rb_noti_cnt, rb_active_cnt, rb_inactive_cnt; + long long map_req_cnt, map_compl_cnt; + int ret; + + rb_noti_cnt = atomic64_read(&hpb->rb_noti_cnt); + rb_active_cnt = atomic64_read(&hpb->rb_active_cnt); + rb_inactive_cnt = atomic64_read(&hpb->rb_inactive_cnt); + map_req_cnt = atomic64_read(&hpb->map_req_cnt); + map_compl_cnt = atomic64_read(&hpb->map_compl_cnt); + + ret = snprintf(buf, PAGE_SIZE, + "rb_noti %lld ACT %lld INACT %lld map_req_count %lld map_compl_count %lld\n", + rb_noti_cnt, rb_active_cnt, rb_inactive_cnt, + map_req_cnt, map_compl_cnt); + + INFO_MSG("rb_noti %lld ACT %lld INACT %lld map_req_count %lld map_compl_count %lld", + rb_noti_cnt, rb_active_cnt, rb_inactive_cnt, + map_req_cnt, map_compl_cnt); + + return ret; +} + +static ssize_t ufshpb_sysfs_pre_req_show(struct ufshpb_lu *hpb, char *buf) +{ + long long pre_req_cnt; + int ret; + + pre_req_cnt = atomic64_read(&hpb->pre_req_cnt); + + ret = snprintf(buf, PAGE_SIZE, "pre_req_count %lld\n", pre_req_cnt); + + INFO_MSG("pre_req_count %lld", pre_req_cnt); + + return ret; +} + +static ssize_t ufshpb_sysfs_region_stat_show(struct ufshpb_lu *hpb, char *buf) +{ + int ret, pin_cnt = 0, act_cnt = 0, inact_cnt = 0, rgn_idx; + enum HPB_RGN_STATE state; + + for (rgn_idx = 0; rgn_idx < hpb->rgns_per_lu; rgn_idx++) { + state = hpb->rgn_tbl[rgn_idx].rgn_state; + if (state == HPB_RGN_PINNED) + pin_cnt++; + else if (state == HPB_RGN_ACTIVE) + act_cnt++; + else if (state == HPB_RGN_INACTIVE) + inact_cnt++; + } + + ret = snprintf(buf, PAGE_SIZE, + "Total %d pinned %d active %d inactive %d\n", + hpb->rgns_per_lu, pin_cnt, act_cnt, inact_cnt); + + INFO_MSG("Total %d pinned %d active %d inactive %d", + hpb->rgns_per_lu, pin_cnt, act_cnt, inact_cnt); + + return ret; +} + +static ssize_t ufshpb_sysfs_count_reset_store(struct ufshpb_lu *hpb, + const char *buf, size_t cnt) +{ + unsigned long debug; + + if (kstrtoul(buf, 0, &debug)) + return -EINVAL; + + if (debug != 1) + return -EINVAL; + + INFO_MSG("Stat Init"); + + ufshpb_stat_reset(hpb); + + return cnt; +} + +static ssize_t ufshpb_sysfs_info_lba_store(struct ufshpb_lu *hpb, + const char *buf, size_t cnt) +{ + struct ufshpb_region *rgn; + struct ufshpb_subregion *srgn; + u64 ppn = 0; + unsigned long value, lpn, flags; + int rgn_idx, srgn_idx, srgn_offset, error = 0; + + if (kstrtoul(buf, 0, &value)) { + ERR_MSG("kstrtoul error"); + return -EINVAL; + } + + if (value >= hpb->lu_num_blocks * SECTORS_PER_BLOCK) { + ERR_MSG("value %lu >= lu_num_blocks %d error", + value, hpb->lu_num_blocks * SECTORS_PER_BLOCK); + return -EINVAL; + } + + lpn = value / SECTORS_PER_BLOCK; + + ufshpb_get_pos_from_lpn(hpb, lpn, &rgn_idx, &srgn_idx, &srgn_offset); + + rgn = hpb->rgn_tbl + rgn_idx; + srgn = rgn->srgn_tbl + srgn_idx; + + spin_lock_irqsave(&hpb->hpb_lock, flags); + INFO_MSG("lba %lu lpn %lu region %d state %d subregion %d state %d", + value, lpn, rgn_idx, rgn->rgn_state, srgn_idx, + srgn->srgn_state); + + if (!ufshpb_valid_srgn(rgn, srgn)) { + INFO_MSG("[region %d subregion %d] has not valid hpb info.", + rgn_idx, srgn_idx); + goto out; + } + + if (!srgn->mctx) { + INFO_MSG("mctx is NULL"); + goto out; + } + + ppn = ufshpb_get_ppn(srgn->mctx, srgn_offset, &error); + if (error) { + INFO_MSG("getting ppn is fail from a page."); + goto out; + } + + INFO_MSG("ppn %llx is_dirty %d", ppn, + ufshpb_ppn_dirty_check(hpb, lpn, 1)); +out: + spin_unlock_irqrestore(&hpb->hpb_lock, flags); + return cnt; +} + +static ssize_t ufshpb_sysfs_info_region_store(struct ufshpb_lu *hpb, + const char *buf, size_t cnt) +{ + unsigned long rgn_idx; + int srgn_idx; + + if (kstrtoul(buf, 0, &rgn_idx)) + return -EINVAL; + + if (rgn_idx >= hpb->rgns_per_lu) { + ERR_MSG("error region %ld max %d", rgn_idx, hpb->rgns_per_lu); + return -EINVAL; + } + + INFO_MSG("(region state : PINNED=%d ACTIVE=%d INACTIVE=%d)", + HPB_RGN_PINNED, HPB_RGN_ACTIVE, HPB_RGN_INACTIVE); + + INFO_MSG("region %ld state %d", rgn_idx, + hpb->rgn_tbl[rgn_idx].rgn_state); + + for (srgn_idx = 0; srgn_idx < hpb->rgn_tbl[rgn_idx].srgn_cnt; + srgn_idx++) { + INFO_MSG("--- subregion %d state %d", srgn_idx, + hpb->rgn_tbl[rgn_idx].srgn_tbl[srgn_idx].srgn_state); + } + + return cnt; +} + +static ssize_t ufshpb_sysfs_ufshpb_release_store(struct ufshpb_lu *hpb, + const char *buf, size_t cnt) +{ + unsigned long value; + + INFO_MSG("start release function"); + + if (kstrtoul(buf, 0, &value)) { + ERR_MSG("kstrtoul error"); + return -EINVAL; + } + + if (value == 0xab) { + INFO_MSG("magic number %lu release start", value); + goto err_out; + } else { + INFO_MSG("wrong magic number %lu", value); + return -EINVAL; + } + + return cnt; +err_out: + INFO_MSG("ref_cnt %d", + atomic_read(&hpb->ufsf->hpb_kref.refcount.refs)); + ufshpb_failed(hpb, __func__); + + return cnt; +} + +static struct ufshpb_sysfs_entry ufshpb_sysfs_entries[] = { + __ATTR(hpb_read_disable, 0644, + ufshpb_sysfs_prep_disable_show, ufshpb_sysfs_prep_disable_store), + __ATTR(map_cmd_disable, 0644, + ufshpb_sysfs_map_disable_show, ufshpb_sysfs_map_disable_store), + __ATTR(throttle_map_req, 0644, + ufshpb_sysfs_throttle_map_req_show, + ufshpb_sysfs_throttle_map_req_store), + __ATTR(throttle_pre_req, 0644, + ufshpb_sysfs_throttle_pre_req_show, + ufshpb_sysfs_throttle_pre_req_store), + __ATTR(pre_req_min_tr_len, 0644, + ufshpb_sysfs_pre_req_min_tr_len_show, + ufshpb_sysfs_pre_req_min_tr_len_store), + __ATTR(pre_req_max_tr_len, 0644, + ufshpb_sysfs_pre_req_max_tr_len_show, + ufshpb_sysfs_pre_req_max_tr_len_store), + __ATTR(pre_req_requeue_cnt, 0644, + ufshpb_sysfs_pre_req_requeue_cnt_show, + ufshpb_sysfs_pre_req_requeue_cnt_store), +#if defined(CONFIG_HPB_DEBUG) + __ATTR(debug, 0644, + ufshpb_sysfs_debug_show, ufshpb_sysfs_debug_store), +#endif + __ATTR(rsp_list_count, 0444, ufshpb_sysfs_rsp_list_cnt_show, NULL), +#if defined(CONFIG_HPB_ERR_INJECTION) + __ATTR(err_injection_select, 0644, + ufshpb_sysfs_err_injection_select_show, + ufshpb_sysfs_err_injection_select_store), + __ATTR(err_injection_bitflip, 0644, + ufshpb_sysfs_err_injection_bitflip_show, + ufshpb_sysfs_err_injection_bitflip_store), + __ATTR(err_injection_offset, 0644, + ufshpb_sysfs_err_injection_offset_show, + ufshpb_sysfs_err_injection_offset_store), + __ATTR(err_injection_random, 0644, + ufshpb_sysfs_err_injection_random_show, + ufshpb_sysfs_err_injection_random_store), +#endif + __ATTR(hpb_version, 0444, ufshpb_sysfs_version_show, NULL), + __ATTR(hit_count, 0444, ufshpb_sysfs_hit_show, NULL), + __ATTR(miss_count, 0444, ufshpb_sysfs_miss_show, NULL), + __ATTR(map_req_count, 0444, ufshpb_sysfs_map_req_show, NULL), + __ATTR(pre_req_count, 0444, ufshpb_sysfs_pre_req_show, NULL), + __ATTR(region_stat_count, 0444, ufshpb_sysfs_region_stat_show, NULL), + __ATTR(count_reset, 0200, NULL, ufshpb_sysfs_count_reset_store), + __ATTR(get_info_from_lba, 0200, NULL, ufshpb_sysfs_info_lba_store), + __ATTR(get_info_from_region, 0200, NULL, + ufshpb_sysfs_info_region_store), + __ATTR(release, 0200, NULL, ufshpb_sysfs_ufshpb_release_store), + __ATTR_NULL +}; + +static ssize_t ufshpb_attr_show(struct kobject *kobj, struct attribute *attr, + char *page) +{ + struct ufshpb_sysfs_entry *entry; + struct ufshpb_lu *hpb; + ssize_t error; + + entry = container_of(attr, struct ufshpb_sysfs_entry, attr); + hpb = container_of(kobj, struct ufshpb_lu, kobj); + + if (!entry->show) + return -EIO; + + mutex_lock(&hpb->sysfs_lock); + error = entry->show(hpb, page); + mutex_unlock(&hpb->sysfs_lock); + return error; +} + +static ssize_t ufshpb_attr_store(struct kobject *kobj, struct attribute *attr, + const char *page, size_t len) +{ + struct ufshpb_sysfs_entry *entry; + struct ufshpb_lu *hpb; + ssize_t error; + + entry = container_of(attr, struct ufshpb_sysfs_entry, attr); + hpb = container_of(kobj, struct ufshpb_lu, kobj); + + if (!entry->store) + return -EIO; + + mutex_lock(&hpb->sysfs_lock); + error = entry->store(hpb, page, len); + mutex_unlock(&hpb->sysfs_lock); + return error; +} + +static const struct sysfs_ops ufshpb_sysfs_ops = { + .show = ufshpb_attr_show, + .store = ufshpb_attr_store, +}; + +static struct kobj_type ufshpb_ktype = { + .sysfs_ops = &ufshpb_sysfs_ops, + .release = NULL, +}; + +static int ufshpb_create_sysfs(struct ufsf_feature *ufsf, struct ufshpb_lu *hpb) +{ + struct device *dev = ufsf->hba->dev; + struct ufshpb_sysfs_entry *entry; + int err; + + hpb->sysfs_entries = ufshpb_sysfs_entries; + + ufshpb_stat_reset(hpb); + atomic64_set(&hpb->act_rsp_list_cnt, 0); + atomic64_set(&hpb->inact_rsp_list_cnt, 0); + + kobject_init(&hpb->kobj, &ufshpb_ktype); + mutex_init(&hpb->sysfs_lock); + + INFO_MSG("ufshpb creates sysfs lu %d %p dev->kobj %p", hpb->lun, + &hpb->kobj, &dev->kobj); + + err = kobject_add(&hpb->kobj, kobject_get(&dev->kobj), + "ufshpb_lu%d", hpb->lun); + if (!err) { + for (entry = hpb->sysfs_entries; entry->attr.name != NULL; + entry++) { + INFO_MSG("ufshpb_lu%d sysfs attr creates: %s", + hpb->lun, entry->attr.name); + if (sysfs_create_file(&hpb->kobj, &entry->attr)) + break; + } + INFO_MSG("ufshpb_lu%d sysfs adds uevent", hpb->lun); + kobject_uevent(&hpb->kobj, KOBJ_ADD); + } + + return err; +} + +static inline void ufshpb_remove_sysfs(struct ufshpb_lu *hpb) +{ + kobject_uevent(&hpb->kobj, KOBJ_REMOVE); + INFO_MSG("ufshpb removes sysfs lu %d %p ", hpb->lun, &hpb->kobj); + kobject_del(&hpb->kobj); +} diff --git a/drivers/scsi/ufs/ufshpb.h b/drivers/scsi/ufs/ufshpb.h new file mode 100755 index 000000000000..47271fa6ba33 --- /dev/null +++ b/drivers/scsi/ufs/ufshpb.h @@ -0,0 +1,346 @@ +/* + * Universal Flash Storage Host Performance Booster + * + * Copyright (C) 2017-2018 Samsung Electronics Co., Ltd. + * + * Authors: + * Yongmyung Lee + * Jinyoung Choi + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * See the COPYING file in the top-level directory or visit + * + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * This program is provided "AS IS" and "WITH ALL FAULTS" and + * without warranty of any kind. You are solely responsible for + * determining the appropriateness of using and distributing + * the program and assume all risks associated with your exercise + * of rights with respect to the program, including but not limited + * to infringement of third party rights, the risks and costs of + * program errors, damage to or loss of data, programs or equipment, + * and unavailability or interruption of operations. Under no + * circumstances will the contributor of this Program be liable for + * any damages of any kind arising from your use or distribution of + * this program. + * + * The Linux Foundation chooses to take subject only to the GPLv2 + * license terms, and distributes only under these terms. + */ + +#ifndef _UFSHPB_H_ +#define _UFSHPB_H_ + +#include +#include +#include +#include +#include +#include + +#if defined(CONFIG_HPB_ERR_INJECTION) +#include +#endif + +#include "../../../block/blk.h" +#include "../../../block/blk-mq.h" +#include "../../../block/blk-mq-sched.h" +#include "../scsi_priv.h" + +/* Version info*/ +#define UFSHPB_VER 0x0201 +#define UFSHPB_DD_VER 0x020800 +#define UFSHPB_DD_VER_POST UFSFEATURE_DD_VER_POST + +/* Constant value*/ +#define MAX_ACTIVE_NUM 2 +#define MAX_INACTIVE_NUM 2 + +#define HPB_ENTRY_SIZE 0x08 +#define HPB_ENTREIS_PER_OS_PAGE (OS_PAGE_SIZE / HPB_ENTRY_SIZE) + +#define RETRY_DELAY_MS 5000 + +/* HPB Support Chunk Size */ +#define HPB_MULTI_CHUNK_LOW 9 +#define HPB_MULTI_CHUNK_HIGH 128 +#define MAX_HPB_CONTEXT_ID 0x7f + +/* Description */ +#define UFS_FEATURE_SUPPORT_HPB_BIT 0x80 + +/* Response UPIU types */ +#define HPB_RSP_NONE 0x00 +#define HPB_RSP_REQ_REGION_UPDATE 0x01 + +/* Vender defined OPCODE */ +#define UFSHPB_READ_BUFFER 0xF9 +#define UFSHPB_WRITE_BUFFER 0xFA + +#define UFSHPB_GROUP_NUMBER 0x11 +#define UFSHPB_RB_ID_READ 0x01 +#define UFSHPB_WB_ID_PREFETCH 0x02 +#define TRANSFER_LEN 0x01 + +#define DEV_DATA_SEG_LEN 0x14 +#define DEV_SENSE_SEG_LEN 0x12 +#define DEV_DES_TYPE 0x80 +#define DEV_ADDITIONAL_LEN 0x10 + +#define PINNED_NOT_SET (-1) +#define DEFAULT_WB_REQUEUE_CNT 3 + +/* + * UFSHPB DEBUG + */ + +#if defined(CONFIG_HPB_DEBUG) +#define HPB_DEBUG(hpb, msg, args...) \ + do { if (hpb && hpb->debug) \ + printk(KERN_ERR "%s:%d " msg "\n", \ + __func__, __LINE__, ##args); \ + } while (0) + +#define HPB_FTRACE(hpb, msg, args...) \ + do { if (hpb && hpb->debug) \ + trace_printk("%04d\t " msg "\n", \ + __LINE__, ##args); \ + } while (0) +#else +#define HPB_DEBUG(hpb, msg, args...) do { } while (0) +#define HPB_FTRACE(hpb, msg, args...) do { } while (0) +#endif + +enum UFSHPB_STATE { + HPB_PRESENT = 1, + HPB_SUSPEND = 2, + HPB_FAILED = -2, + HPB_NEED_INIT = 0, + HPB_RESET = -3, +}; + +enum HPB_RGN_STATE { + HPB_RGN_INACTIVE, + HPB_RGN_ACTIVE, + HPB_RGN_PINNED, +}; + +enum HPB_SRGN_STATE { + HPB_SRGN_UNUSED, + HPB_SRGN_DIRTY, + HPB_SRGN_CLEAN, + HPB_SRGN_ISSUED, +}; + +#if defined(CONFIG_HPB_ERR_INJECTION) +enum HPB_ERR_INJECTION_SELECT { + HPB_ERR_INJECTION_DISABLE, + HPB_ERR_INJECTION_BITFLIP, + HPB_ERR_INJECTION_OFFSET, + HPB_ERR_INJECTION_RANDOM, +}; +#endif + +struct ufshpb_dev_info { + int num_lu; + int version; + int rgn_size; + int srgn_size; +}; + +struct ufshpb_active_field { + __be16 active_rgn; + __be16 active_srgn; +} __packed; + +struct ufshpb_rsp_field { + __be16 sense_data_len; + u8 desc_type; + u8 additional_len; + u8 hpb_type; + u8 reserved; + u8 active_rgn_cnt; + u8 inactive_rgn_cnt; + struct ufshpb_active_field hpb_active_field[2]; + __be16 hpb_inactive_field[2]; +} __packed; + +struct ufshpb_map_ctx { + struct page **m_page; + unsigned int *ppn_dirty; + + struct list_head list_table; +}; + +struct ufshpb_subregion { + struct ufshpb_map_ctx *mctx; + enum HPB_SRGN_STATE srgn_state; + int rgn_idx; + int srgn_idx; + + /* below information is used by rsp_list */ + struct list_head list_act_srgn; +}; + +struct ufshpb_region { + struct ufshpb_subregion *srgn_tbl; + enum HPB_RGN_STATE rgn_state; + int rgn_idx; + int srgn_cnt; + + /* below information is used by rsp_list */ + struct list_head list_inact_rgn; + + /* below information is used by lru */ + struct list_head list_lru_rgn; +}; + +struct ufshpb_req { + struct request *req; + struct bio *bio; + struct ufshpb_lu *hpb; + struct list_head list_req; + void (*end_io)(struct request *rq, int err); + void *end_io_data; + char sense[SCSI_SENSE_BUFFERSIZE]; + + union { + struct { + struct ufshpb_map_ctx *mctx; + unsigned int rgn_idx; + unsigned int srgn_idx; + unsigned int lun; + } rb; + struct { + struct page *m_page; + unsigned int len; + unsigned long lpn; + } wb; + }; +}; + +enum selection_type { + LRU = 1, +}; + +struct victim_select_info { + int selection_type; + struct list_head lh_lru_rgn; + int max_lru_active_cnt; /* supported hpb #region - pinned #region */ + atomic64_t active_cnt; +}; + +struct ufshpb_lu { + struct ufsf_feature *ufsf; + int lun; + int qd; + struct ufshpb_region *rgn_tbl; + + spinlock_t hpb_lock; + + spinlock_t retry_list_lock; + struct ufshpb_req *map_req; + int num_inflight_map_req; + int throttle_map_req; + struct list_head lh_map_req_free; + struct list_head lh_map_req_retry; + struct list_head lh_map_ctx_free; + + spinlock_t rsp_list_lock; + struct list_head lh_pinned_srgn; + struct list_head lh_act_srgn; + struct list_head lh_inact_rgn; + + struct kobject kobj; + struct mutex sysfs_lock; + struct ufshpb_sysfs_entry *sysfs_entries; + + struct ufshpb_req *pre_req; + int num_inflight_pre_req; + int throttle_pre_req; + struct list_head lh_pre_req_free; + int ctx_id_ticket; + int pre_req_min_tr_len; + int pre_req_max_tr_len; + int pre_req_requeue_cnt; + + struct work_struct pinned_work; + struct delayed_work retry_work; + struct work_struct task_work; + + /* for selecting victim */ + struct victim_select_info lru_info; + + int lu_max_active_rgns; + int lu_pinned_rgn_startidx; + int lu_pinned_end_offset; + int srgns_per_lu; + int rgns_per_lu; + int srgns_per_rgn; + int srgn_mem_size; + int entries_per_rgn_shift; + int entries_per_rgn_mask; + int entries_per_srgn; + int entries_per_srgn_shift; + int entries_per_srgn_mask; + int dwords_per_srgn; + unsigned long long srgn_unit_size; + int mpage_bytes; + int mpages_per_srgn; + int lu_num_blocks; + + /* for debug */ + int alloc_mctx; + int debug_free_table; + bool force_disable; + bool force_map_req_disable; + bool debug; + atomic64_t hit; + atomic64_t miss; + atomic64_t rb_noti_cnt; + atomic64_t rb_active_cnt; + atomic64_t rb_inactive_cnt; + atomic64_t map_req_cnt; + atomic64_t map_compl_cnt; + atomic64_t pre_req_cnt; + + atomic64_t act_rsp_list_cnt; + atomic64_t inact_rsp_list_cnt; +#if defined(CONFIG_HPB_ERR_INJECTION) + enum HPB_ERR_INJECTION_SELECT err_injection_select; + u64 err_injection_bitflip; + u64 err_injection_offset; + int err_injection_random; +#endif +}; + +struct ufshpb_sysfs_entry { + struct attribute attr; + ssize_t (*show)(struct ufshpb_lu *hpb, char *buf); + ssize_t (*store)(struct ufshpb_lu *hpb, const char *buf, size_t count); +}; + +struct ufs_hba; +struct ufshcd_lrb; + +int ufshpb_get_state(struct ufsf_feature *ufsf); +void ufshpb_set_state(struct ufsf_feature *ufsf, int state); +void ufshpb_get_dev_info(struct ufsf_feature *ufsf, u8 *desc_buf); +void ufshpb_get_geo_info(struct ufsf_feature *ufsf, u8 *geo_buf); +void ufshpb_get_lu_info(struct ufsf_feature *ufsf, int lun, u8 *unit_buf); +void ufshpb_init_handler(struct work_struct *work); +void ufshpb_rsp_upiu(struct ufsf_feature *ufsf, struct ufshcd_lrb *lrbp); +void ufshpb_resume(struct ufsf_feature *ufsf); +void ufshpb_suspend(struct ufsf_feature *ufsf); +void ufshpb_reset_host(struct ufsf_feature *ufsf); +void ufshpb_reset(struct ufsf_feature *ufsf); +void ufshpb_prep_fn(struct ufsf_feature *ufsf, struct ufshcd_lrb *lrbp); +void ufshpb_remove(struct ufsf_feature *ufsf, int state); +#endif /* End of Header */ diff --git a/drivers/scsi/ufs/ufshpb_skh.c b/drivers/scsi/ufs/ufshpb_skh.c new file mode 100644 index 000000000000..afa7cb0fb866 --- /dev/null +++ b/drivers/scsi/ufs/ufshpb_skh.c @@ -0,0 +1,3275 @@ +/* + * Universal Flash Storage Host Performance Booster + * + * Original work Copyright (C) 2017-2018 Samsung Electronics Co., Ltd. + * Modified work Copyright (C) 2018, Google, Inc. + * Modified work Copyright (C) 2019 SK hynix + * + * Original work Authors: + * Yongmyung Lee + * Jinyoung Choi + * Modifier + * Kihyun Cho + * Sengman Shin + * Jinsu Lee + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * See the COPYING file in the top-level directory or visit + * + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * This program is provided "AS IS" and "WITH ALL FAULTS" and + * without warranty of any kind. You are solely responsible for + * determining the appropriateness of using and distributing + * the program and assume all risks associated with your exercise + * of rights with respect to the program, including but not limited + * to infringement of third party rights, the risks and costs of + * program errors, damage to or loss of data, programs or equipment, + * and unavailability or interruption of operations. Under no + * circumstances will the contributor of this Program be liable for + * any damages of any kind arising from your use or distribution of + * this program. + * + * The Linux Foundation chooses to take subject only to the GPLv2 + * license terms, and distributes only under these terms. + */ + +#include +#include +#include +#include +#include + +#include "../../../block/blk.h" + +#include "ufs.h" +#include "ufshcd.h" +#include "ufshpb_skh.h" +#include + +u32 skhpb_debug_mask = SKHPB_LOG_ERR | SKHPB_LOG_INFO; +//u32 skhpb_debug_mask = SKHPB_LOG_ERR | SKHPB_LOG_INFO | SKHPB_LOG_DEBUG | SKHPB_LOG_HEX; +int debug_map_req = SKHPB_MAP_RSP_DISABLE; + +/* + * debug variables + */ +static int skhpb_alloc_mctx; + +/* + * define global constants + */ +static int skhpb_sects_per_blk_shift; +static int skhpb_bits_per_dword_shift; +static int skhpb_bits_per_dword_mask; + +static int skhpb_create_sysfs(struct ufs_hba *hba, struct skhpb_lu *hpb); +static int skhpb_check_lru_evict(struct skhpb_lu *hpb, struct skhpb_region *cb); +static void skhpb_error_handler(struct work_struct *work); +static void skhpb_evict_region(struct skhpb_lu *hpb, + struct skhpb_region *cb); +static void skhpb_purge_active_block(struct skhpb_lu *hpb); +static int skhpb_set_map_req(struct skhpb_lu *hpb, + int region, int subregion, struct skhpb_map_ctx *mctx, + struct skhpb_rsp_info *rsp_info, + enum SKHPB_BUFFER_MODE flag); +static void skhpb_rsp_map_cmd_req(struct skhpb_lu *hpb, + struct skhpb_rsp_info *rsp_info); +static void skhpb_map_loading_trigger(struct skhpb_lu *hpb, + bool only_pinned, bool do_work_handler); + +static inline void skhpb_purge_active_page(struct skhpb_lu *hpb, + struct skhpb_subregion *cp, int state); + +static void skhpb_hit_lru_info(struct skhpb_victim_select_info *lru_info, + struct skhpb_region *cb); + +static inline void skhpb_get_bit_offset( + struct skhpb_lu *hpb, int subregion_offset, + int *dword, int *offset) +{ + *dword = subregion_offset >> skhpb_bits_per_dword_shift; + *offset = subregion_offset & skhpb_bits_per_dword_mask; +} + +/* called with hpb_lock (irq) */ +static bool skhpb_ppn_dirty_check(struct skhpb_lu *hpb, + struct skhpb_subregion *cp, int subregion_offset) +{ + bool is_dirty = false; + unsigned int bit_dword, bit_offset; + + if (!cp->mctx->ppn_dirty) + return true; + + skhpb_get_bit_offset(hpb, subregion_offset, + &bit_dword, &bit_offset); + is_dirty = cp->mctx->ppn_dirty[bit_dword] & (1 << bit_offset) ? true : false; + + return is_dirty; +} + +static void skhpb_ppn_prep(struct skhpb_lu *hpb, + struct ufshcd_lrb *lrbp, skhpb_t ppn, + unsigned int sector_len) +{ + unsigned char cmd[16] = { 0 }; + + if (hpb->hba->skhpb_quirk & SKHPB_QUIRK_USE_READ_16_FOR_ENCRYPTION) + cmd[0] = READ_16; + else + cmd[0] = SKHPB_READ; + cmd[2] = lrbp->cmd->cmnd[2]; + cmd[3] = lrbp->cmd->cmnd[3]; + cmd[4] = lrbp->cmd->cmnd[4]; + cmd[5] = lrbp->cmd->cmnd[5]; + put_unaligned(ppn, (u64 *)&cmd[6]); + cmd[14] = (u8)(sector_len >> skhpb_sects_per_blk_shift); //Transfer length + if (hpb->hba->skhpb_quirk & SKHPB_QUIRK_USE_READ_16_FOR_ENCRYPTION) + cmd[15] = 0x01; //Control + else + cmd[15] = 0x00; //Control + + memcpy(lrbp->cmd->cmnd, cmd, MAX_CDB_SIZE); + memcpy(lrbp->ucd_req_ptr->sc.cdb, cmd, MAX_CDB_SIZE); + + //To verify the values within READ command + /* SKHPB_DRIVER_HEXDUMP("[HPB] HPB READ ", 16, 1, cmd, sizeof(cmd), 1); */ +} + +static inline void skhpb_set_dirty_bits(struct skhpb_lu *hpb, + struct skhpb_region *cb, struct skhpb_subregion *cp, + int dword, int offset, unsigned int count) +{ + const unsigned long mask = ((1UL << count) - 1) & 0xffffffff; + + if (cb->region_state == SKHPB_REGION_INACTIVE) + return; + + BUG_ON(!cp->mctx); + cp->mctx->ppn_dirty[dword] |= (mask << offset); +} + +/* called with hpb_lock (irq) */ +static void skhpb_set_dirty(struct skhpb_lu *hpb, + struct ufshcd_lrb *lrbp, int region, + int subregion, int subregion_offset) +{ + struct skhpb_region *cb; + struct skhpb_subregion *cp; + int count; + int bit_count, bit_dword, bit_offset; + + count = blk_rq_sectors(lrbp->cmd->request) >> skhpb_sects_per_blk_shift; + skhpb_get_bit_offset(hpb, subregion_offset, + &bit_dword, &bit_offset); + + do { + bit_count = min(count, SKHPB_BITS_PER_DWORD - bit_offset); + + cb = hpb->region_tbl + region; + cp = cb->subregion_tbl + subregion; + + skhpb_set_dirty_bits(hpb, cb, cp, + bit_dword, bit_offset, bit_count); + + bit_offset = 0; + bit_dword++; + + if (bit_dword == hpb->dwords_per_subregion) { + bit_dword = 0; + subregion++; + + if (subregion == hpb->subregions_per_region) { + subregion = 0; + region++; + } + } + + count -= bit_count; + } while (count); +} + +static inline bool skhpb_is_encrypted_lrbp(struct ufshcd_lrb *lrbp) +{ + /* To do + * UTRD_CRYPTO_ENABLE is not define at SM8350 + */ + //return (lrbp->utr_descriptor_ptr->header.dword_0 & UTRD_CRYPTO_ENABLE); + return true; +} + +static inline enum SKHPB_CMD skhpb_get_cmd(struct ufshcd_lrb *lrbp) +{ + unsigned char cmd = lrbp->cmd->cmnd[0]; + + if (cmd == READ_10 || cmd == READ_16) + return SKHPB_CMD_READ; + if (cmd == WRITE_10 || cmd == WRITE_16) + return SKHPB_CMD_WRITE; + if (cmd == UNMAP) + return SKHPB_CMD_DISCARD; + return SKHPB_CMD_OTHERS; +} + +static inline void skhpb_get_pos_from_lpn(struct skhpb_lu *hpb, + unsigned int lpn, int *region, int *subregion, int *offset) +{ + int region_offset; + + *region = lpn >> hpb->entries_per_region_shift; + region_offset = lpn & hpb->entries_per_region_mask; + *subregion = region_offset >> hpb->entries_per_subregion_shift; + *offset = region_offset & hpb->entries_per_subregion_mask; +} + +static inline bool skhpb_check_region_subregion_validity(struct skhpb_lu *hpb, + int region, int subregion) +{ + struct skhpb_region *cb; + + if (region >= hpb->regions_per_lu){ + SKHPB_DRIVER_E("[HCM] Out of REGION range - region[%d]:MAX[%d]\n", + region, hpb->regions_per_lu); + return false; + } + cb = hpb->region_tbl + region; + if (subregion >= cb->subregion_count){ + SKHPB_DRIVER_E("[HCM] Out of SUBREGION range - subregion[i]:MAX[%d]\n", + subregion, cb->subregion_count); + return false; + } + return true; +} + + +static inline skhpb_t skhpb_get_ppn(struct skhpb_map_ctx *mctx, int pos) +{ + skhpb_t *ppn_table; + int index, offset; + + index = pos / SKHPB_ENTREIS_PER_OS_PAGE; + offset = pos % SKHPB_ENTREIS_PER_OS_PAGE; + + ppn_table = page_address(mctx->m_page[index]); + return ppn_table[offset]; +} + + +#if defined(SKHPB_READ_LARGE_CHUNK_SUPPORT) +static bool skhpb_subregion_dirty_check(struct skhpb_lu *hpb, struct skhpb_subregion *cp, + int subregion_offset, int reqBlkCnt) +{ + unsigned int bit_dword, bit_offset; + unsigned int tmp; + int checkCnt; + + if (!cp->mctx) + return true; + + if (!cp->mctx->ppn_dirty) + return true; + + skhpb_get_bit_offset(hpb, subregion_offset, + &bit_dword, &bit_offset); + + while (true) { + checkCnt = SKHPB_BITS_PER_DWORD - bit_offset; + if (cp->mctx->ppn_dirty[bit_dword]) { + tmp = cp->mctx->ppn_dirty[bit_dword] << bit_offset; + if (SKHPB_BITS_PER_DWORD - reqBlkCnt > 0) + tmp = tmp >> (SKHPB_BITS_PER_DWORD - reqBlkCnt); + if (tmp) + return true; + } + reqBlkCnt -= checkCnt; + if (reqBlkCnt <= 0) + break; + bit_dword++; + if (bit_dword >= hpb->ppn_dirties_per_subregion) + break; + bit_offset = 0; + } + return false; +} + +static bool skhpb_lc_dirty_check(struct skhpb_lu *hpb, unsigned int lpn, unsigned int rq_sectors) +{ + int reg; + int subReg; + struct skhpb_region *cb; + struct skhpb_subregion *cp; + unsigned long cur_lpn = lpn; + int subRegOffset; + int reqBlkCnt = rq_sectors >> skhpb_sects_per_blk_shift; + + do { + skhpb_get_pos_from_lpn(hpb, cur_lpn, ®, &subReg, &subRegOffset); + if (!skhpb_check_region_subregion_validity(hpb, reg, subReg)) + return true; + cb = hpb->region_tbl + reg; + cp = cb->subregion_tbl + subReg; + + if (cb->region_state == SKHPB_REGION_INACTIVE || + cp->subregion_state != SKHPB_SUBREGION_CLEAN) { + atomic64_inc(&hpb->lc_reg_subreg_miss); + return true; + } + + if (skhpb_subregion_dirty_check(hpb, cp, subRegOffset, reqBlkCnt)) { + //SKHPB_DRIVER_D("[NORMAL READ] DIRTY: Region(%d), SubRegion(%d) \n", reg, subReg); + atomic64_inc(&hpb->lc_entry_dirty_miss); + return true; + } + + if (hpb->entries_per_subregion < subRegOffset + reqBlkCnt) { + reqBlkCnt -= (hpb->entries_per_subregion - subRegOffset); + } else { + reqBlkCnt = 0; + } + + cur_lpn += reqBlkCnt; + } while(reqBlkCnt); + + return false; +} +#endif + +void skhpb_prep_fn(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) +{ + struct skhpb_lu *hpb; + struct skhpb_region *cb; + struct skhpb_subregion *cp; + unsigned int lpn; + skhpb_t ppn = 0; + int region, subregion, subregion_offset; + const struct request *rq; + unsigned long long rq_pos; + unsigned int rq_sectors; + unsigned char cmd; + unsigned long flags; + + /* WKLU could not be HPB-LU */ + if (lrbp->lun >= UFS_UPIU_MAX_GENERAL_LUN) + return; + + hpb = hba->skhpb_lup[lrbp->lun]; + if (!hpb || !hpb->lu_hpb_enable) + return; + + if (hpb->force_hpb_read_disable) + return; + + cmd = skhpb_get_cmd(lrbp); + if (cmd == SKHPB_CMD_OTHERS) + return; + /* + * TODO: check if ICE is not supported or not. + * + * if (cmd==SKHPB_CMD_READ && skhpb_is_encrypted_lrbp(lrbp)) + * return; + */ + rq = lrbp->cmd->request; + rq_pos = blk_rq_pos(rq); + rq_sectors = blk_rq_sectors(rq); + + lpn = rq_pos / SKHPB_SECTORS_PER_BLOCK; + skhpb_get_pos_from_lpn( + hpb, lpn, ®ion, &subregion, &subregion_offset); + if (!skhpb_check_region_subregion_validity(hpb, region, subregion)) + return; + cb = hpb->region_tbl + region; + cp = cb->subregion_tbl + subregion; + + if (cmd == SKHPB_CMD_WRITE || + cmd == SKHPB_CMD_DISCARD) { + if (cb->region_state == SKHPB_REGION_INACTIVE) { + return; + } + spin_lock_irqsave(&hpb->hpb_lock, flags); + skhpb_set_dirty(hpb, lrbp, region, subregion, + subregion_offset); + spin_unlock_irqrestore(&hpb->hpb_lock, flags); + return; + } + +#if defined(SKHPB_READ_LARGE_CHUNK_SUPPORT) + if (((rq_sectors & (SKHPB_SECTORS_PER_BLOCK - 1)) != 0) || + rq_sectors > + (SKHPB_READ_LARGE_CHUNK_MAX_BLOCK_COUNT << skhpb_sects_per_blk_shift)) { +#else + if (rq_sectors != SKHPB_SECTORS_PER_BLOCK) { +#endif + atomic64_inc(&hpb->size_miss); + return; + } + + spin_lock_irqsave(&hpb->hpb_lock, flags); + if (cb->region_state == SKHPB_REGION_INACTIVE) { + atomic64_inc(&hpb->region_miss); + spin_unlock_irqrestore(&hpb->hpb_lock, flags); + return; + } else if (cp->subregion_state != SKHPB_SUBREGION_CLEAN){ + atomic64_inc(&hpb->subregion_miss); + spin_unlock_irqrestore(&hpb->hpb_lock, flags); + return; + } + if (rq_sectors <= SKHPB_SECTORS_PER_BLOCK) { + if (skhpb_ppn_dirty_check(hpb, cp, subregion_offset)) { + atomic64_inc(&hpb->entry_dirty_miss); + spin_unlock_irqrestore(&hpb->hpb_lock, flags); + return; + } + } +#if defined(SKHPB_READ_LARGE_CHUNK_SUPPORT) + else { + if (skhpb_lc_dirty_check(hpb, lpn, rq_sectors)) { + spin_unlock_irqrestore(&hpb->hpb_lock, flags); + return; + } + atomic64_inc(&hpb->lc_hit); + } +#endif + ppn = skhpb_get_ppn(cp->mctx, subregion_offset); + spin_unlock_irqrestore(&hpb->hpb_lock, flags); + + //SKHPB_DRIVER_D("XXX ufs ppn %016llx, lba %u\n", (unsigned long long)ppn, lpn); + skhpb_ppn_prep(hpb, lrbp, ppn, rq_sectors); + atomic64_inc(&hpb->hit); + return; +} + +static int skhpb_clean_dirty_bitmap( + struct skhpb_lu *hpb, struct skhpb_subregion *cp) +{ + struct skhpb_region *cb; + + cb = hpb->region_tbl + cp->region; + + /* if mctx is null, active block had been evicted out */ + if (cb->region_state == SKHPB_REGION_INACTIVE || !cp->mctx) { + SKHPB_DRIVER_D("%d - %d error already evicted\n", + cp->region, cp->subregion); + return -EINVAL; + } + + memset(cp->mctx->ppn_dirty, 0x00, + hpb->entries_per_subregion / BITS_PER_BYTE); + return 0; +} + +static void skhpb_clean_active_subregion( + struct skhpb_lu *hpb, struct skhpb_subregion *cp) +{ + struct skhpb_region *cb; + + cb = hpb->region_tbl + cp->region; + + /* if mctx is null, active block had been evicted out */ + if (cb->region_state == SKHPB_REGION_INACTIVE || !cp->mctx) { + SKHPB_DRIVER_D("%d - %d clean already evicted\n", + cp->region, cp->subregion); + return; + } + cp->subregion_state = SKHPB_SUBREGION_CLEAN; +} + +static void skhpb_error_active_subregion( + struct skhpb_lu *hpb, struct skhpb_subregion *cp) +{ + struct skhpb_region *cb; + + cb = hpb->region_tbl + cp->region; + + /* if mctx is null, active block had been evicted out */ + if (cb->region_state == SKHPB_REGION_INACTIVE || !cp->mctx) { + SKHPB_DRIVER_E("%d - %d evicted\n", cp->region, cp->subregion); + return; + } + cp->subregion_state = SKHPB_SUBREGION_DIRTY; +} + +static void skhpb_map_compl_process(struct skhpb_lu *hpb, + struct skhpb_map_req *map_req) +{ + unsigned long flags; + + SKHPB_MAP_REQ_TIME(map_req, map_req->RSP_end, 1); + SKHPB_DRIVER_D("SKHPB RB COMPL BUFFER %d - %d\n", map_req->region, map_req->subregion); + + spin_lock_irqsave(&hpb->hpb_lock, flags); + skhpb_clean_active_subregion(hpb, + hpb->region_tbl[map_req->region].subregion_tbl + + map_req->subregion); + spin_unlock_irqrestore(&hpb->hpb_lock, flags); +} + +static void skhpb_map_inactive_compl_process(struct skhpb_lu *hpb, + struct skhpb_map_req *map_req) +{ + SKHPB_DRIVER_D("SKHPB WB COMPL BUFFER %d\n", map_req->region); + SKHPB_MAP_REQ_TIME(map_req, map_req->RSP_end, 1); +} + +/* + * Must held rsp_list_lock before enter this function + */ +static struct skhpb_rsp_info *skhpb_get_req_info(struct skhpb_lu *hpb) +{ + struct skhpb_rsp_info *rsp_info = + list_first_entry_or_null(&hpb->lh_rsp_info_free, + struct skhpb_rsp_info, + list_rsp_info); + if (!rsp_info) { + SKHPB_DRIVER_E("there is no rsp_info"); + return NULL; + } + list_del(&rsp_info->list_rsp_info); + memset(rsp_info, 0x00, sizeof(struct skhpb_rsp_info)); + + INIT_LIST_HEAD(&rsp_info->list_rsp_info); + + return rsp_info; +} + +static void skhpb_map_req_compl_fn(struct request *req, blk_status_t error) +{ + struct skhpb_map_req *map_req = req->end_io_data; + struct ufs_hba *hba; + struct skhpb_lu *hpb; + struct scsi_sense_hdr sshdr; + struct skhpb_region *cb; + struct scsi_request *scsireq = scsi_req(req); + unsigned long flags; + + /* shut up "bio leak" warning */ + memcpy(map_req->sense, scsireq->sense, SCSI_SENSE_BUFFERSIZE); + req->bio = NULL; + blk_put_request(req); + + hpb = map_req->hpb; + hba = hpb->hba; + cb = hpb->region_tbl + map_req->region; + + if (hba->skhpb_state != SKHPB_PRESENT) + goto free_map_req; + + if (!error) { + skhpb_map_compl_process(hpb, map_req); + goto free_map_req; + } + + SKHPB_DRIVER_E("error number %d ( %d - %d )\n", + error, map_req->region, map_req->subregion); + scsi_normalize_sense(map_req->sense, + SCSI_SENSE_BUFFERSIZE, &sshdr); + SKHPB_DRIVER_E("code %x sense_key %x asc %x ascq %x\n", + sshdr.response_code, + sshdr.sense_key, sshdr.asc, sshdr.ascq); + SKHPB_DRIVER_E("byte4 %x byte5 %x byte6 %x additional_len %x\n", + sshdr.byte4, sshdr.byte5, + sshdr.byte6, sshdr.additional_length); + atomic64_inc(&hpb->rb_fail); + + if (sshdr.sense_key == ILLEGAL_REQUEST) { + if (sshdr.asc == 0x00 && sshdr.ascq == 0x16) { + /* OPERATION IN PROGRESS */ + SKHPB_DRIVER_E("retry rb %d - %d", + map_req->region, map_req->subregion); + + spin_lock(&hpb->map_list_lock); + INIT_LIST_HEAD(&map_req->list_map_req); + list_add_tail(&map_req->list_map_req, &hpb->lh_map_req_retry); + spin_unlock(&hpb->map_list_lock); + + schedule_delayed_work(&hpb->skhpb_map_req_retry_work, + msecs_to_jiffies(5000)); + return; + } + } + // Only change subregion status at here. + // Do not put map_ctx, it will re-use when it is activated again. + spin_lock_irqsave(&hpb->hpb_lock, flags); + skhpb_error_active_subregion(hpb, cb->subregion_tbl + map_req->subregion); + spin_unlock_irqrestore(&hpb->hpb_lock, flags); +free_map_req: + spin_lock(&hpb->map_list_lock); + INIT_LIST_HEAD(&map_req->list_map_req); + list_add_tail(&map_req->list_map_req, &hpb->lh_map_req_free); + spin_unlock(&hpb->map_list_lock); + atomic64_dec(&hpb->alloc_map_req_cnt); +} + +static void skhpb_map_inactive_req_compl_fn( + struct request *req, blk_status_t error) +{ + struct skhpb_map_req *map_req = req->end_io_data; + struct ufs_hba *hba; + struct skhpb_lu *hpb; + struct scsi_sense_hdr sshdr; + struct skhpb_region *cb; + struct scsi_request *scsireq = scsi_req(req); + unsigned long flags; + + /* shut up "bio leak" warning */ + memcpy(map_req->sense, scsireq->sense, SCSI_SENSE_BUFFERSIZE); + req->bio = NULL; + blk_put_request(req); + + hpb = map_req->hpb; + hba = hpb->hba; + cb = hpb->region_tbl + map_req->region; + + if (hba->skhpb_state != SKHPB_PRESENT) + goto free_map_req; + + if (!error) { + skhpb_map_inactive_compl_process(hpb, map_req); + goto free_map_req; + } + + SKHPB_DRIVER_E("error number %d ( %d - %d )", + error, map_req->region, map_req->subregion); + scsi_normalize_sense(map_req->sense, SCSI_SENSE_BUFFERSIZE, + &sshdr); + SKHPB_DRIVER_E("code %x sense_key %x asc %x ascq %x", + sshdr.response_code, + sshdr.sense_key, sshdr.asc, sshdr.ascq); + SKHPB_DRIVER_E("byte4 %x byte5 %x byte6 %x additional_len %x", + sshdr.byte4, sshdr.byte5, + sshdr.byte6, sshdr.additional_length); + atomic64_inc(&hpb->rb_fail); + + if (sshdr.sense_key == ILLEGAL_REQUEST) { + if (cb->is_pinned) { + SKHPB_DRIVER_E("WRITE_BUFFER is not allowed on pinned area: region#%d", + cb->region); + } else { + if (sshdr.asc == 0x00 && sshdr.ascq == 0x16) { + /* OPERATION IN PROGRESS */ + SKHPB_DRIVER_E("retry wb %d", map_req->region); + + spin_lock(&hpb->map_list_lock); + INIT_LIST_HEAD(&map_req->list_map_req); + list_add_tail(&map_req->list_map_req, &hpb->lh_map_req_retry); + spin_unlock(&hpb->map_list_lock); + + schedule_delayed_work(&hpb->skhpb_map_req_retry_work, + msecs_to_jiffies(5000)); + return; + } + } + } + // Only change subregion status at here. + // Do not put map_ctx, it will re-use when it is activated again. + spin_lock_irqsave(&hpb->hpb_lock, flags); + skhpb_error_active_subregion(hpb, cb->subregion_tbl + map_req->subregion); + spin_unlock_irqrestore(&hpb->hpb_lock, flags); +free_map_req: + spin_lock(&hpb->map_list_lock); + INIT_LIST_HEAD(&map_req->list_map_req); + list_add_tail(&map_req->list_map_req, &hpb->lh_map_req_free); + spin_unlock(&hpb->map_list_lock); + atomic64_dec(&hpb->alloc_map_req_cnt); +} + +static int skhpb_execute_req_dev_ctx(struct skhpb_lu *hpb, + unsigned char *cmd, void *buf, int length) +{ + unsigned long flags; + struct scsi_sense_hdr sshdr; + struct scsi_device *sdp; + struct ufs_hba *hba = hpb->hba; + int ret = 0; + + spin_lock_irqsave(hba->host->host_lock, flags); + sdp = hba->sdev_ufs_lu[hpb->lun]; + if (sdp) { + ret = scsi_device_get(sdp); + if (!ret && !scsi_device_online(sdp)) { + ret = -ENODEV; + scsi_device_put(sdp); + } else if (!ret) { + hba->issue_ioctl = true; + } + } else { + ret = -ENODEV; + } + spin_unlock_irqrestore(hba->host->host_lock, flags); + if (ret) + return ret; + + ret = scsi_execute_req(sdp, cmd, DMA_FROM_DEVICE, + buf, length, &sshdr, + msecs_to_jiffies(30000), 3, NULL); + spin_lock_irqsave(hba->host->host_lock, flags); + hba->issue_ioctl = false; + spin_unlock_irqrestore(hba->host->host_lock, flags); + scsi_device_put(sdp); + return ret; +} + +static inline void skhpb_set_read_dev_ctx_cmd(unsigned char *cmd, int lba, + int length) +{ + cmd[0] = READ_10; + cmd[1] = 0x02; + cmd[2] = SKHPB_GET_BYTE_3(lba); + cmd[3] = SKHPB_GET_BYTE_2(lba); + cmd[4] = SKHPB_GET_BYTE_1(lba); + cmd[5] = SKHPB_GET_BYTE_0(lba); + cmd[6] = SKHPB_GET_BYTE_2(length); + cmd[7] = SKHPB_GET_BYTE_1(length); + cmd[8] = SKHPB_GET_BYTE_0(length); +} + +int skhpb_issue_req_dev_ctx(struct skhpb_lu *hpb, unsigned char *buf, + int buf_length) +{ + unsigned char cmd[10] = { 0 }; + int cmd_len = buf_length >> PAGE_SHIFT; + int ret = 0; + + skhpb_set_read_dev_ctx_cmd(cmd, 0x48504230, cmd_len); + + ret = skhpb_execute_req_dev_ctx(hpb, cmd, buf, buf_length); + if (ret < 0) + SKHPB_DRIVER_E("failed with err %d\n", ret); + return ret; +} + +static inline void skhpb_set_write_buf_cmd(unsigned char *cmd, int region) +{ + cmd[0] = SKHPB_WRITE_BUFFER; + cmd[1] = 0x01; + cmd[2] = SKHPB_GET_BYTE_1(region); + cmd[3] = SKHPB_GET_BYTE_0(region); + cmd[4] = 0x00; + cmd[5] = 0x00; + cmd[6] = 0x00; + cmd[7] = 0x00; + cmd[8] = 0x00; + cmd[9] = 0x00; + + //To verify the values within WRITE_BUFFER command + SKHPB_DRIVER_HEXDUMP("[HPB] WRITE BUFFER ", 16, 1, cmd, 10, 1); +} + +static inline void skhpb_set_read_buf_cmd(unsigned char *cmd, + int region, int subregion, int subregion_mem_size) +{ + cmd[0] = SKHPB_READ_BUFFER; + cmd[1] = 0x01; + cmd[2] = SKHPB_GET_BYTE_1(region); + cmd[3] = SKHPB_GET_BYTE_0(region); + cmd[4] = SKHPB_GET_BYTE_1(subregion); + cmd[5] = SKHPB_GET_BYTE_0(subregion); + cmd[6] = SKHPB_GET_BYTE_2(subregion_mem_size); + cmd[7] = SKHPB_GET_BYTE_1(subregion_mem_size); + cmd[8] = SKHPB_GET_BYTE_0(subregion_mem_size); + cmd[9] = 0x00; + + //To verify the values within READ_BUFFER command + SKHPB_DRIVER_HEXDUMP("[HPB] READ BUFFER ", 16, 1, cmd, 10, 1); +} + +static int skhpb_add_bio_page(struct skhpb_lu *hpb, + struct request_queue *q, struct bio *bio, struct bio_vec *bvec, + struct skhpb_map_ctx *mctx) +{ + struct page *page = NULL; + int i, ret; + + bio_init(bio, bvec, hpb->mpages_per_subregion); + + for (i = 0; i < hpb->mpages_per_subregion; i++) { + page = mctx->m_page[i]; + if (!page) + return -ENOMEM; + + ret = bio_add_pc_page(q, bio, page, hpb->mpage_bytes, 0); + if (ret != hpb->mpage_bytes) { + SKHPB_DRIVER_E("error ret %d\n", ret); + return -EINVAL; + } + } + return 0; +} + +static int skhpb_map_req_issue( + struct skhpb_lu *hpb, struct skhpb_map_req *map_req) +{ + struct request_queue *q = hpb->hba->sdev_ufs_lu[hpb->lun]->request_queue; + struct request *req; + struct scsi_request *scsireq; + unsigned char cmd[10] = { 0 }; + int ret; + + if (map_req->rwbuffer_flag == W_BUFFER) + skhpb_set_write_buf_cmd(cmd, map_req->region); + else + skhpb_set_read_buf_cmd(cmd, map_req->region, map_req->subregion, + map_req->subregion_mem_size); + if (map_req->rwbuffer_flag == W_BUFFER) + req = blk_get_request(q, REQ_OP_SCSI_OUT, BLK_MQ_REQ_PREEMPT); + else + req = blk_get_request(q, REQ_OP_SCSI_IN, BLK_MQ_REQ_PREEMPT); + if (IS_ERR(req)) { + int rv = PTR_ERR(req); + + if (map_req->rwbuffer_flag == W_BUFFER) + SKHPB_DRIVER_E("blk_get_request errno %d, \ + retry #%d, WRITE BUFFER %d\n", + rv, map_req->retry_cnt, map_req->region); + else + SKHPB_DRIVER_E("blk_get_request errno %d, \ + retry #%d, READ BUFFER %d:%d\n", + rv, map_req->retry_cnt, + map_req->region, map_req->subregion); + + if (map_req->retry_cnt == 10) { + /* give up */ + return rv; + } + + spin_lock_bh(&hpb->map_list_lock); + list_add_tail(&map_req->list_map_req, &hpb->lh_map_req_retry); + spin_unlock_bh(&hpb->map_list_lock); + + schedule_delayed_work(&hpb->skhpb_map_req_retry_work, msecs_to_jiffies(10)); + + return 0; + } + scsireq = scsi_req(req); + + scsireq->cmd_len = COMMAND_SIZE(cmd[0]); + BUG_ON(scsireq->cmd_len > sizeof(scsireq->__cmd)); + scsireq->cmd = scsireq->__cmd; + memcpy(scsireq->cmd, cmd, scsireq->cmd_len); + + req->rq_flags |= RQF_QUIET | RQF_PREEMPT; + req->timeout = msecs_to_jiffies(30000); + req->end_io_data = map_req; + + if (map_req->rwbuffer_flag == R_BUFFER) { + ret = skhpb_add_bio_page( + hpb, q, &map_req->bio, map_req->bvec, map_req->mctx); + if (ret) { + SKHPB_DRIVER_E("skhpb_add_bio_page_error %d\n", ret); + goto out_put_request; + } + map_req->pbio = &map_req->bio; + blk_rq_append_bio(req, &map_req->pbio); + } + SKHPB_DRIVER_D("issue map_request: %d - %d\n", + map_req->region, map_req->subregion); + + SKHPB_MAP_REQ_TIME(map_req, map_req->RSP_issue, 0); + if( hpb->hpb_control_mode == HOST_CTRL_MODE) { + if (map_req->rwbuffer_flag == W_BUFFER) + blk_execute_rq_nowait( + q, NULL, req, 0, skhpb_map_inactive_req_compl_fn); + else + blk_execute_rq_nowait(q, NULL, req, 0, skhpb_map_req_compl_fn); + } else + blk_execute_rq_nowait(q, NULL, req, 1, skhpb_map_req_compl_fn); + + if (map_req->rwbuffer_flag == W_BUFFER) + atomic64_inc(&hpb->w_map_req_cnt); + else + atomic64_inc(&hpb->map_req_cnt); + + return 0; + +out_put_request: + blk_put_request(req); + return ret; +} + +static int skhpb_set_map_req(struct skhpb_lu *hpb, + int region, int subregion, struct skhpb_map_ctx *mctx, + struct skhpb_rsp_info *rsp_info, + enum SKHPB_BUFFER_MODE flag) +{ + bool last = hpb->region_tbl[region].subregion_tbl[subregion].last; + struct skhpb_map_req *map_req; + + spin_lock_bh(&hpb->map_list_lock); + map_req = list_first_entry_or_null(&hpb->lh_map_req_free, + struct skhpb_map_req, + list_map_req); + if (!map_req) { + SKHPB_DRIVER_E("There is no map_req\n"); + spin_unlock_bh(&hpb->map_list_lock); + return -ENOMEM; + } + list_del(&map_req->list_map_req); + spin_unlock_bh(&hpb->map_list_lock); + atomic64_inc(&hpb->alloc_map_req_cnt); + + memset(map_req, 0x00, sizeof(struct skhpb_map_req)); + + map_req->hpb = hpb; + map_req->region = region; + map_req->subregion = subregion; + map_req->subregion_mem_size = + last ? hpb->last_subregion_mem_size : hpb->subregion_mem_size; + map_req->mctx = mctx; + map_req->lun = hpb->lun; + map_req->RSP_start = rsp_info->RSP_start; + if (flag == W_BUFFER) { + map_req->rwbuffer_flag = W_BUFFER; + } else + map_req->rwbuffer_flag = R_BUFFER; + + if(skhpb_map_req_issue(hpb, map_req)) { + SKHPB_DRIVER_E("issue Failed!!!\n"); + return -ENOMEM; + } + + return 0; +} + +static struct skhpb_map_ctx *skhpb_get_map_ctx(struct skhpb_lu *hpb) +{ + struct skhpb_map_ctx *mctx; + + mctx = list_first_entry_or_null(&hpb->lh_map_ctx, + struct skhpb_map_ctx, list_table); + if (mctx) { + list_del_init(&mctx->list_table); + hpb->debug_free_table--; + return mctx; + } + return ERR_PTR(-ENOMEM); +} + +static inline void skhpb_add_lru_info(struct skhpb_victim_select_info *lru_info, + struct skhpb_region *cb) +{ + cb->region_state = SKHPB_REGION_ACTIVE; + list_add_tail(&cb->list_region, &lru_info->lru); + atomic64_inc(&lru_info->active_count); +} + +static inline int skhpb_add_region(struct skhpb_lu *hpb, + struct skhpb_region *cb) +{ + struct skhpb_victim_select_info *lru_info; + int subregion; + int err = 0; + + lru_info = &hpb->lru_info; + + //SKHPB_DRIVER_D("E->active region: %d", cb->region); + + for (subregion = 0; subregion < cb->subregion_count; subregion++) { + struct skhpb_subregion *cp; + + cp = cb->subregion_tbl + subregion; + cp->mctx = skhpb_get_map_ctx(hpb); + if (IS_ERR(cp->mctx)) { + err = PTR_ERR(cp->mctx); + goto out; + } + cp->subregion_state = SKHPB_SUBREGION_DIRTY; + } + if (!cb->is_pinned) + skhpb_add_lru_info(lru_info, cb); + + atomic64_inc(&hpb->region_add); +out: + if (err) + SKHPB_DRIVER_E("get mctx failed. err %d subregion %d free_table %d\n", + err, subregion, hpb->debug_free_table); + return err; +} + +static inline void skhpb_put_map_ctx( + struct skhpb_lu *hpb, struct skhpb_map_ctx *mctx) +{ + list_add(&mctx->list_table, &hpb->lh_map_ctx); + hpb->debug_free_table++; +} + +static inline void skhpb_purge_active_page(struct skhpb_lu *hpb, + struct skhpb_subregion *cp, int state) +{ + if (state == SKHPB_SUBREGION_UNUSED) { + skhpb_put_map_ctx(hpb, cp->mctx); + cp->mctx = NULL; + } + cp->subregion_state = state; +} + +static inline void skhpb_cleanup_lru_info( + struct skhpb_victim_select_info *lru_info, + struct skhpb_region *cb) +{ + list_del_init(&cb->list_region); + cb->region_state = SKHPB_REGION_INACTIVE; + cb->hit_count = 0; + atomic64_dec(&lru_info->active_count); +} + +static inline void skhpb_evict_region(struct skhpb_lu *hpb, + struct skhpb_region *cb) +{ + struct skhpb_victim_select_info *lru_info; + struct skhpb_subregion *cp; + int subregion; + + // If the maximum value is exceeded at the time of region addition, + // it may have already been processed. + if (cb->region_state == SKHPB_REGION_INACTIVE) { + SKHPB_DRIVER_D("Region:%d was already inactivated.\n", + cb->region); + return; + } + lru_info = &hpb->lru_info; + + //SKHPB_DRIVER_D("C->EVICT region: %d\n", cb->region); + + skhpb_cleanup_lru_info(lru_info, cb); + atomic64_inc(&hpb->region_evict); + for (subregion = 0; subregion < cb->subregion_count; subregion++) { + cp = cb->subregion_tbl + subregion; + + skhpb_purge_active_page(hpb, cp, SKHPB_SUBREGION_UNUSED); + } +} + +static void skhpb_hit_lru_info(struct skhpb_victim_select_info *lru_info, + struct skhpb_region *cb) +{ + switch (lru_info->selection_type) { + case TYPE_LRU: + list_move_tail(&cb->list_region, &lru_info->lru); + break; + case TYPE_LFU: + if (cb->hit_count != 0xffffffff) + cb->hit_count++; + + list_move_tail(&cb->list_region, &lru_info->lru); + break; + default: + break; + } +} + +static struct skhpb_region *skhpb_victim_lru_info( + struct skhpb_victim_select_info *lru_info) +{ + struct skhpb_region *cb; + struct skhpb_region *victim_cb = NULL; + u32 hit_count = 0xffffffff; + + switch (lru_info->selection_type) { + case TYPE_LRU: + victim_cb = list_first_entry(&lru_info->lru, + struct skhpb_region, list_region); + break; + case TYPE_LFU: + list_for_each_entry(cb, &lru_info->lru, list_region) { + if (hit_count > cb->hit_count) { + hit_count = cb->hit_count; + victim_cb = cb; + } + } + break; + default: + break; + } + return victim_cb; +} + +static int skhpb_check_lru_evict(struct skhpb_lu *hpb, struct skhpb_region *cb) +{ + struct skhpb_victim_select_info *lru_info = &hpb->lru_info; + struct skhpb_region *victim_cb; + unsigned long flags; + if (cb->is_pinned) + return 0; + + spin_lock_irqsave(&hpb->hpb_lock, flags); + if (!list_empty(&cb->list_region)) { + skhpb_hit_lru_info(lru_info, cb); + goto out; + } + + if (cb->region_state != SKHPB_REGION_INACTIVE) + goto out; + + if (atomic64_read(&lru_info->active_count) == lru_info->max_lru_active_count) { + + victim_cb = skhpb_victim_lru_info(lru_info); + + if (!victim_cb) { + SKHPB_DRIVER_E("SKHPB victim_cb is NULL\n"); + goto unlock_error; + } + SKHPB_DRIVER_D("max lru case. victim : %d\n", victim_cb->region); + skhpb_evict_region(hpb, victim_cb); + } + if (skhpb_add_region(hpb, cb)) { + SKHPB_DRIVER_E("SKHPB memory allocation failed\n"); + goto unlock_error; + } + + +out: + spin_unlock_irqrestore(&hpb->hpb_lock, flags); + return 0; +unlock_error: + spin_unlock_irqrestore(&hpb->hpb_lock, flags); + return -ENOMEM; +} + +static int skhpb_evict_load_region(struct skhpb_lu *hpb, + struct skhpb_rsp_info *rsp_info) +{ + struct skhpb_region *cb; + int region, iter; + unsigned long flags; + + for (iter = 0; iter < rsp_info->inactive_cnt; iter++) { + region = rsp_info->inactive_list.region[iter]; + cb = hpb->region_tbl + region; + + if (cb->is_pinned) { + /* + * Pinned active-block should not drop-out. + * But if so, it would treat error as critical, + * and it will run skhpb_eh_work + */ + SKHPB_DRIVER_E("SKHPB pinned active-block drop-out error\n"); + return -ENOMEM; + } + if (list_empty(&cb->list_region)) + continue; + + spin_lock_irqsave(&hpb->hpb_lock, flags); + skhpb_evict_region(hpb, cb); + spin_unlock_irqrestore(&hpb->hpb_lock, flags); + } + + for (iter = 0; iter < rsp_info->active_cnt; iter++) { + region = rsp_info->active_list.region[iter]; + cb = hpb->region_tbl + region; + if(skhpb_check_lru_evict(hpb, cb)) + return -ENOMEM; + } + return 0; +} + +static inline struct skhpb_rsp_field *skhpb_get_hpb_rsp( + struct ufshcd_lrb *lrbp) +{ + return (struct skhpb_rsp_field *)&lrbp->ucd_rsp_ptr->sr.sense_data_len; +} + +static void skhpb_rsp_map_cmd_req(struct skhpb_lu *hpb, + struct skhpb_rsp_info *rsp_info) +{ + struct skhpb_region *cb; + struct skhpb_subregion *cp; + int region, subregion; + int iter; + int ret; + unsigned long flags; + + /* + * Before Issue read buffer CMD for active active block, + * prepare the memory from memory pool. + */ + ret = skhpb_evict_load_region(hpb, rsp_info); + if (ret) { + SKHPB_DRIVER_E("region evict/load failed. ret %d\n", ret); + goto wakeup_ee_worker; + } + for (iter = 0; iter < rsp_info->active_cnt; iter++) { + region = rsp_info->active_list.region[iter]; + subregion = rsp_info->active_list.subregion[iter]; + cb = hpb->region_tbl + region; + + if (region >= hpb->regions_per_lu || + subregion >= cb->subregion_count) { + SKHPB_DRIVER_E("skhpb issue-map %d - %d range error\n", + region, subregion); + goto wakeup_ee_worker; + } + + cp = cb->subregion_tbl + subregion; + + /* + * if subregion_state set SKHPB_SUBREGION_ISSUED, + * active_page has already been added to list, + * so it just ends function. + */ + spin_lock_irqsave(&hpb->hpb_lock, flags); + if (cp->subregion_state == SKHPB_SUBREGION_ISSUED) { + spin_unlock_irqrestore(&hpb->hpb_lock, flags); + continue; + } + + cp->subregion_state = SKHPB_SUBREGION_ISSUED; + + ret = skhpb_clean_dirty_bitmap(hpb, cp); + + spin_unlock_irqrestore(&hpb->hpb_lock, flags); + + if (ret) + continue; + + if (!hpb->hba->sdev_ufs_lu[hpb->lun] || + !hpb->hba->sdev_ufs_lu[hpb->lun]->request_queue) + return; + ret = skhpb_set_map_req(hpb, region, subregion, + cp->mctx, rsp_info, R_BUFFER); + SKHPB_DRIVER_D("SEND READ_BUFFER - Region:%d, SubRegion:%d\n", + region, subregion); + if (ret) { + SKHPB_DRIVER_E("skhpb_set_map_req error %d\n", ret); + goto wakeup_ee_worker; + } + } + return; + +wakeup_ee_worker: + hpb->hba->skhpb_state = SKHPB_FAILED; + schedule_work(&hpb->hba->skhpb_eh_work); +} + +/* routine : isr (ufs) */ +void skhpb_rsp_upiu(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) +{ + struct skhpb_lu *hpb; + struct skhpb_rsp_field *rsp_field; + struct skhpb_rsp_info *rsp_info; + int data_seg_len, num, blk_idx, update_alert; + + update_alert = be32_to_cpu(lrbp->ucd_rsp_ptr->header.dword_2) + & MASK_RSP_UPIU_HPB_UPDATE_ALERT; + data_seg_len = be32_to_cpu(lrbp->ucd_rsp_ptr->header.dword_2) + & MASK_RSP_UPIU_DATA_SEG_LEN; + if (!update_alert || !data_seg_len) { + bool do_tasklet = false; + + if (lrbp->lun >= UFS_UPIU_MAX_GENERAL_LUN) + return; + + hpb = hba->skhpb_lup[lrbp->lun]; + if (!hpb) + return; + + spin_lock(&hpb->rsp_list_lock); + do_tasklet = !list_empty(&hpb->lh_rsp_info); + spin_unlock(&hpb->rsp_list_lock); + + if (do_tasklet) + schedule_work(&hpb->skhpb_rsp_work); + return; + } + rsp_field = skhpb_get_hpb_rsp(lrbp); + if ((get_unaligned_be16(rsp_field->sense_data_len + 0) + != SKHPB_DEV_SENSE_SEG_LEN) || + rsp_field->desc_type != SKHPB_DEV_DES_TYPE || + rsp_field->additional_len != SKHPB_DEV_ADDITIONAL_LEN || + rsp_field->hpb_type == SKHPB_RSP_NONE || + rsp_field->active_region_cnt > SKHPB_MAX_ACTIVE_NUM || + rsp_field->inactive_region_cnt > SKHPB_MAX_INACTIVE_NUM) + return; + + if (rsp_field->lun >= UFS_UPIU_MAX_GENERAL_LUN) { + SKHPB_DRIVER_E("lun is not general = %d", rsp_field->lun); + return; + } + hpb = hba->skhpb_lup[rsp_field->lun]; + if (!hpb) { + SKHPB_DRIVER_E("UFS-LU%d is not SKHPB LU\n", rsp_field->lun); + return; + } + if (hpb->force_map_req_disable) + return; + SKHPB_DRIVER_D("HPB-Info Noti: %d LUN: %d Seg-Len %d, Req_type = %d\n", + rsp_field->hpb_type, rsp_field->lun, + data_seg_len, rsp_field->hpb_type); + if (!hpb->lu_hpb_enable) { + SKHPB_DRIVER_E("LU(%d) not HPB-LU\n", rsp_field->lun); + return; + } + //To verify the values within RESPONSE UPIU. + SKHPB_DRIVER_HEXDUMP("[HPB] RESP UPIU ", 16, 1, + lrbp->ucd_rsp_ptr, sizeof(struct utp_upiu_rsp), 1); + //If wLUMaxActiveHPBRegions == wNumHPBPinnedRegions + if (hpb->lru_info.max_lru_active_count == 0){ + SKHPB_DRIVER_D("max_lru_active_count is 0"); + return; + } + + switch (rsp_field->hpb_type) { + case SKHPB_RSP_REQ_REGION_UPDATE: + atomic64_inc(&hpb->rb_noti_cnt); + WARN_ON(data_seg_len != SKHPB_DEV_DATA_SEG_LEN); + + spin_lock(&hpb->rsp_list_lock); + rsp_info = skhpb_get_req_info(hpb); + spin_unlock(&hpb->rsp_list_lock); + if (!rsp_info) + return; + rsp_info->type = SKHPB_RSP_REQ_REGION_UPDATE; + + for (num = 0; num < rsp_field->active_region_cnt; num++) { + blk_idx = num * SKHPB_PER_ACTIVE_INFO_BYTES; + rsp_info->active_list.region[num] = + get_unaligned_be16(rsp_field->hpb_active_field + blk_idx); + rsp_info->active_list.subregion[num] = + get_unaligned_be16(rsp_field->hpb_active_field + + blk_idx + 2); + SKHPB_DRIVER_D("active num: %d, #block: %d, page#: %d\n", + num + 1, + rsp_info->active_list.region[num], + rsp_info->active_list.subregion[num]); + } + rsp_info->active_cnt = num; + + for (num = 0; num < rsp_field->inactive_region_cnt; num++) { + blk_idx = num * SKHPB_PER_INACTIVE_INFO_BYTES; + rsp_info->inactive_list.region[num] = + get_unaligned_be16(rsp_field->hpb_inactive_field + blk_idx); + SKHPB_DRIVER_D("inactive num: %d, #block: %d\n", + num + 1, rsp_info->inactive_list.region[num]); + } + rsp_info->inactive_cnt = num; + + SKHPB_DRIVER_D("active cnt: %d, inactive cnt: %d\n", + rsp_info->active_cnt, rsp_info->inactive_cnt); + SKHPB_DRIVER_D("add_list %p -> %p\n", + rsp_info, &hpb->lh_rsp_info); + + spin_lock(&hpb->rsp_list_lock); + list_add_tail(&rsp_info->list_rsp_info, &hpb->lh_rsp_info); + spin_unlock(&hpb->rsp_list_lock); + + schedule_work(&hpb->skhpb_rsp_work); + break; + + case SKHPB_RSP_HPB_RESET: + for (num = 0 ; num < UFS_UPIU_MAX_GENERAL_LUN ; num++) + { + hpb = hba->skhpb_lup[num]; + if (!hpb || !hpb->lu_hpb_enable) + continue; + atomic64_inc(&hpb->reset_noti_cnt); + + spin_lock(&hpb->rsp_list_lock); + rsp_info = skhpb_get_req_info(hpb); + spin_unlock(&hpb->rsp_list_lock); + if (!rsp_info) + return; + + rsp_info->type = SKHPB_RSP_HPB_RESET; + + spin_lock(&hpb->rsp_list_lock); + list_add_tail(&rsp_info->list_rsp_info, &hpb->lh_rsp_info); + spin_unlock(&hpb->rsp_list_lock); + + schedule_work(&hpb->skhpb_rsp_work); + } + break; + + default: + SKHPB_DRIVER_E("hpb_type is not available : %d\n", + rsp_field->hpb_type); + break; + } +} + +static int skhpb_read_desc(struct ufs_hba *hba, + u8 desc_id, u8 desc_index, u8 *desc_buf, u32 size) +{ + int err = 0; + + err = ufshcd_query_descriptor_retry(hba, UPIU_QUERY_OPCODE_READ_DESC, + desc_id, desc_index, 0, desc_buf, &size); + if (err) { + SKHPB_DRIVER_E("reading Device Desc failed. err = %d\n", err); + } + return err; +} + +static int skhpb_read_device_desc( + struct ufs_hba *hba, u8 *desc_buf, u32 size) +{ + return skhpb_read_desc(hba, QUERY_DESC_IDN_DEVICE, 0, desc_buf, size); +} + +static int skhpb_read_geo_desc(struct ufs_hba *hba, u8 *desc_buf, u32 size) +{ + return skhpb_read_desc(hba, QUERY_DESC_IDN_GEOMETRY, 0, + desc_buf, size); +} + +static int skhpb_read_unit_desc(struct ufs_hba *hba, int lun, + u8 *desc_buf, u32 size) +{ + return skhpb_read_desc(hba, QUERY_DESC_IDN_UNIT, + lun, desc_buf, size); +} + +static inline void skhpb_add_subregion_to_req_list(struct skhpb_lu *hpb, + struct skhpb_subregion *cp) +{ + list_add_tail(&cp->list_subregion, &hpb->lh_subregion_req); + cp->subregion_state = SKHPB_SUBREGION_ISSUED; +} + +static int skhpb_execute_req(struct skhpb_lu *hpb, unsigned char *cmd, + struct skhpb_subregion *cp) +{ + struct ufs_hba *hba = hpb->hba; + struct scsi_device *sdp; + struct request_queue *q; + struct request *req; + struct scsi_request *scsireq; + struct bio bio; + struct bio *pbio = &bio; + struct scsi_sense_hdr sshdr; + unsigned long flags; + int ret = 0; + + spin_lock_irqsave(hba->host->host_lock, flags); + sdp = hba->sdev_ufs_lu[hpb->lun]; + if (sdp) { + ret = scsi_device_get(sdp); + if (!ret && !scsi_device_online(sdp)) { + ret = -ENODEV; + scsi_device_put(sdp); + } + } else { + ret = -ENODEV; + } + spin_unlock_irqrestore(hba->host->host_lock, flags); + if (ret) + return ret; + + q = sdp->request_queue; + + req = blk_get_request(q, REQ_OP_SCSI_IN, BLK_MQ_REQ_PREEMPT); + if (IS_ERR(req)) { + ret = PTR_ERR(req); + goto out_put; + } + scsireq = scsi_req(req); + + scsireq->cmd_len = COMMAND_SIZE(cmd[0]); + if (scsireq->cmd_len > sizeof(scsireq->__cmd)) { + scsireq->cmd = kmalloc(scsireq->cmd_len, __GFP_RECLAIM); + if (!scsireq->cmd) { + ret = -ENOMEM; + goto out_put_request; + } + } else { + scsireq->cmd = scsireq->__cmd; + } + memcpy(scsireq->cmd, cmd, scsireq->cmd_len); + + scsireq->retries = 3; + req->timeout = msecs_to_jiffies(10000); + req->rq_flags |= RQF_QUIET | RQF_PREEMPT; + + ret = skhpb_add_bio_page(hpb, q, &bio, hpb->bvec, cp->mctx); + if (ret) + goto out_put_scsi_req; + blk_rq_append_bio(req, &pbio); + + blk_execute_rq(q, NULL, req, 1); + + if (scsireq->result) { + scsi_normalize_sense(scsireq->sense, SCSI_SENSE_BUFFERSIZE, &sshdr); + SKHPB_DRIVER_E("code %x sense_key %x asc %x ascq %x", + sshdr.response_code, sshdr.sense_key, sshdr.asc, + sshdr.ascq); + SKHPB_DRIVER_E("byte4 %x byte5 %x byte6 %x additional_len %x", + sshdr.byte4, sshdr.byte5, sshdr.byte6, + sshdr.additional_length); + spin_lock_irqsave(&hpb->hpb_lock, flags); + skhpb_error_active_subregion(hpb, cp); + spin_unlock_irqrestore(&hpb->hpb_lock, flags); + ret = -EIO; + } else { + spin_lock_irqsave(&hpb->hpb_lock, flags); + ret = skhpb_clean_dirty_bitmap(hpb, cp); + spin_unlock_irqrestore(&hpb->hpb_lock, flags); + if (ret) { + SKHPB_DRIVER_E("skhpb_clean_dirty_bitmap error %d", ret); + } + ret = 0; + } + +out_put_scsi_req: + scsi_req_free_cmd(scsireq); +out_put_request: + blk_put_request(req); +out_put: + scsi_device_put(sdp); + return ret; +} + +static int skhpb_issue_map_req_from_list(struct skhpb_lu *hpb) +{ + struct skhpb_subregion *cp, *next_cp; + int ret; + unsigned long flags; + + LIST_HEAD(req_list); + + spin_lock_irqsave(&hpb->hpb_lock, flags); + list_splice_init(&hpb->lh_subregion_req, &req_list); + spin_unlock_irqrestore(&hpb->hpb_lock, flags); + + list_for_each_entry_safe(cp, next_cp, &req_list, list_subregion) { + int subregion_mem_size = + cp->last ? hpb->last_subregion_mem_size : hpb->subregion_mem_size; + unsigned char cmd[10] = { 0 }; + + skhpb_set_read_buf_cmd(cmd, cp->region, cp->subregion, + subregion_mem_size); + + SKHPB_DRIVER_D("issue map_request: %d - %d/%d\n", + cp->region, cp->subregion, subregion_mem_size); + + ret = skhpb_execute_req(hpb, cmd, cp); + if (ret < 0) { + SKHPB_DRIVER_E("region %d sub %d failed with err %d", + cp->region, cp->subregion, ret); + continue; + } + + spin_lock_irqsave(&hpb->hpb_lock, flags); + skhpb_clean_active_subregion(hpb, cp); + list_del_init(&cp->list_subregion); + spin_unlock_irqrestore(&hpb->hpb_lock, flags); + } + + return 0; +} + +static void skhpb_pinned_work_handler(struct work_struct *work) +{ + struct delayed_work *dwork = to_delayed_work(work); + struct skhpb_lu *hpb = + container_of(dwork, struct skhpb_lu, skhpb_pinned_work); + int ret; + + SKHPB_DRIVER_D("worker start\n"); + + if (!list_empty(&hpb->lh_subregion_req)) { + pm_runtime_get_sync(SKHPB_DEV(hpb)); + ret = skhpb_issue_map_req_from_list(hpb); + /* + * if its function failed at init time, + * skhpb-device will request map-req, + * so it is not critical-error, and just finish work-handler + */ + if (ret) + SKHPB_DRIVER_E("failed map-issue. ret %d\n", ret); + pm_runtime_mark_last_busy(SKHPB_DEV(hpb)); + pm_runtime_put_noidle(SKHPB_DEV(hpb)); + } + + SKHPB_DRIVER_D("worker end\n"); +} + +static void skhpb_map_req_retry_work_handler(struct work_struct *work) +{ + struct skhpb_lu *hpb; + struct delayed_work *dwork = to_delayed_work(work); + struct skhpb_map_req *map_req; + int ret = 0; + + LIST_HEAD(retry_list); + + hpb = container_of(dwork, struct skhpb_lu, skhpb_map_req_retry_work); + SKHPB_DRIVER_D("retry worker start"); + + spin_lock_bh(&hpb->map_list_lock); + list_splice_init(&hpb->lh_map_req_retry, &retry_list); + spin_unlock_bh(&hpb->map_list_lock); + + while (1) { + map_req = list_first_entry_or_null(&retry_list, + struct skhpb_map_req, list_map_req); + if (!map_req) { + SKHPB_DRIVER_D("There is no map_req"); + break; + } + list_del(&map_req->list_map_req); + + map_req->retry_cnt++; + + ret = skhpb_map_req_issue(hpb, map_req); + if (ret) { + SKHPB_DRIVER_E("skhpb_map_req_issue error %d", ret); + goto wakeup_ee_worker; + } + } + SKHPB_DRIVER_D("worker end"); + return; + +wakeup_ee_worker: + hpb->hba->skhpb_state = SKHPB_FAILED; + schedule_work(&hpb->hba->skhpb_eh_work); +} + +static void skhpb_delayed_rsp_work_handler(struct work_struct *work) +{ + struct skhpb_lu *hpb = container_of(work, struct skhpb_lu, skhpb_rsp_work); + struct skhpb_rsp_info *rsp_info; + unsigned long flags; + + SKHPB_DRIVER_D("rsp_work enter"); + + while (1) { + if(hpb->hba->clk_gating.is_suspended) { + SKHPB_DRIVER_D("rsp_work break"); + break; + } + spin_lock_irqsave(&hpb->rsp_list_lock, flags); + rsp_info = list_first_entry_or_null(&hpb->lh_rsp_info, + struct skhpb_rsp_info, list_rsp_info); + if (!rsp_info) { + spin_unlock_irqrestore(&hpb->rsp_list_lock, flags); + break; + } + + SKHPB_RSP_TIME(rsp_info->RSP_start); + + list_del_init(&rsp_info->list_rsp_info); + spin_unlock_irqrestore(&hpb->rsp_list_lock, flags); + + switch (rsp_info->type) { + case SKHPB_RSP_REQ_REGION_UPDATE: + skhpb_rsp_map_cmd_req(hpb, rsp_info); + break; + + case SKHPB_RSP_HPB_RESET: + skhpb_purge_active_block(hpb); + skhpb_map_loading_trigger(hpb, true, false); + break; + + default: + break; + } + + spin_lock_irqsave(&hpb->rsp_list_lock, flags); + list_add_tail(&rsp_info->list_rsp_info, &hpb->lh_rsp_info_free); + spin_unlock_irqrestore(&hpb->rsp_list_lock, flags); + } + SKHPB_DRIVER_D("rsp_work end"); +} + +static void skhpb_init_constant(void) +{ + skhpb_sects_per_blk_shift = ffs(SKHPB_BLOCK) - ffs(SKHPB_SECTOR); + SKHPB_DRIVER_D("skhpb_sects_per_blk_shift: %u %u\n", + skhpb_sects_per_blk_shift, ffs(SKHPB_SECTORS_PER_BLOCK) - 1); + + skhpb_bits_per_dword_shift = ffs(SKHPB_BITS_PER_DWORD) - 1; + skhpb_bits_per_dword_mask = SKHPB_BITS_PER_DWORD - 1; + SKHPB_DRIVER_D("bits_per_dword %u shift %u mask 0x%X\n", + SKHPB_BITS_PER_DWORD, skhpb_bits_per_dword_shift, skhpb_bits_per_dword_mask); +} + +static void skhpb_table_mempool_remove(struct skhpb_lu *hpb) +{ + struct skhpb_map_ctx *mctx, *next; + int i; + + /* + * the mctx in the lh_map_ctx has been allocated completely. + */ + list_for_each_entry_safe(mctx, next, &hpb->lh_map_ctx, list_table) { + list_del(&mctx->list_table); + + for (i = 0; i < hpb->mpages_per_subregion; i++) + __free_page(mctx->m_page[i]); + + kvfree(mctx->ppn_dirty); + kfree(mctx->m_page); + kfree(mctx); + skhpb_alloc_mctx--; + } +} + +static int skhpb_init_pinned_active_block(struct skhpb_lu *hpb, + struct skhpb_region *cb) +{ + struct skhpb_subregion *cp; + int subregion, j; + int err = 0; + unsigned long flags; + + for (subregion = 0 ; subregion < cb->subregion_count ; subregion++) { + cp = cb->subregion_tbl + subregion; + + cp->mctx = skhpb_get_map_ctx(hpb); + if (IS_ERR(cp->mctx)) { + err = PTR_ERR(cp->mctx); + goto release; + } + spin_lock_irqsave(&hpb->hpb_lock, flags); + skhpb_add_subregion_to_req_list(hpb, cp); + spin_unlock_irqrestore(&hpb->hpb_lock, flags); + } + return 0; + +release: + for (j = 0 ; j < subregion ; j++) { + cp = cb->subregion_tbl + j; + skhpb_put_map_ctx(hpb, cp->mctx); + } + return err; +} + +static inline bool skhpb_is_pinned( + struct skhpb_lu_desc *lu_desc, int region) +{ + if (lu_desc->lu_hpb_pinned_end_offset != -1 && + region >= lu_desc->hpb_pinned_region_startidx && + region <= lu_desc->lu_hpb_pinned_end_offset) + return true; + + return false; +} + +static inline void skhpb_init_jobs(struct skhpb_lu *hpb) +{ + INIT_DELAYED_WORK(&hpb->skhpb_pinned_work, skhpb_pinned_work_handler); + INIT_DELAYED_WORK(&hpb->skhpb_map_req_retry_work, skhpb_map_req_retry_work_handler); + INIT_WORK(&hpb->skhpb_rsp_work, skhpb_delayed_rsp_work_handler); +} + +static inline void skhpb_cancel_jobs(struct skhpb_lu *hpb) +{ + cancel_delayed_work_sync(&hpb->skhpb_pinned_work); + cancel_work_sync(&hpb->skhpb_rsp_work); + cancel_delayed_work_sync(&hpb->skhpb_map_req_retry_work); +} + +static void skhpb_init_subregion_tbl(struct skhpb_lu *hpb, + struct skhpb_region *cb, bool last_region) +{ + int subregion; + + for (subregion = 0 ; subregion < cb->subregion_count ; subregion++) { + struct skhpb_subregion *cp = cb->subregion_tbl + subregion; + + cp->region = cb->region; + cp->subregion = subregion; + cp->subregion_state = SKHPB_SUBREGION_UNUSED; + cp->last = (last_region && subregion == cb->subregion_count - 1); + } +} + +static inline int skhpb_alloc_subregion_tbl(struct skhpb_lu *hpb, + struct skhpb_region *cb, int subregion_count) +{ + cb->subregion_tbl = kzalloc(sizeof(struct skhpb_subregion) * subregion_count, + GFP_KERNEL); + if (!cb->subregion_tbl) + return -ENOMEM; + + cb->subregion_count = subregion_count; + + return 0; +} + +static int skhpb_table_mempool_init(struct skhpb_lu *hpb, + int num_regions, int subregions_per_region, + int entry_count, int entry_byte) +{ + int i, j; + struct skhpb_map_ctx *mctx = NULL; + + for (i = 0 ; i < num_regions * subregions_per_region ; i++) { + mctx = kzalloc(sizeof(struct skhpb_map_ctx), GFP_KERNEL); + if (!mctx) + goto release_mem; + + mctx->m_page = kzalloc(sizeof(struct page *) * + hpb->mpages_per_subregion, GFP_KERNEL); + if (!mctx->m_page) + goto release_mem; + + mctx->ppn_dirty = kvzalloc(entry_count / BITS_PER_BYTE, GFP_KERNEL); + if (!mctx->ppn_dirty) + goto release_mem; + + for (j = 0; j < hpb->mpages_per_subregion; j++) { + mctx->m_page[j] = alloc_page(GFP_KERNEL | __GFP_ZERO); + if (!mctx->m_page[j]) + goto release_mem; + } + /* SKSKHPB_DRIVER_D("[%d] mctx->m_page %p get_order %d\n", i, + mctx->m_page, get_order(hpb->mpages_per_subregion)); */ + + INIT_LIST_HEAD(&mctx->list_table); + list_add(&mctx->list_table, &hpb->lh_map_ctx); + + hpb->debug_free_table++; + } + + skhpb_alloc_mctx = num_regions * subregions_per_region; + /* SKSKHPB_DRIVER_D("number of mctx %d %d %d. debug_free_table %d\n", + num_regions * subregions_per_region, num_regions, + subregions_per_region, hpb->debug_free_table); */ + return 0; + +release_mem: + /* + * mctxs already added in lh_map_ctx will be removed + * in the caller function. + */ + if (!mctx) + goto out; + + if (mctx->m_page) { + for (j = 0; j < hpb->mpages_per_subregion; j++) + if (mctx->m_page[j]) + __free_page(mctx->m_page[j]); + kfree(mctx->m_page); + } + kvfree(mctx->ppn_dirty); + kfree(mctx); +out: + return -ENOMEM; +} + +static int skhpb_req_mempool_init(struct ufs_hba *hba, + struct skhpb_lu *hpb, int queue_depth) +{ + struct skhpb_rsp_info *rsp_info = NULL; + struct skhpb_map_req *map_req = NULL; + int i; + + if (!queue_depth) { + queue_depth = hba->nutrs; + SKHPB_DRIVER_E("lu_queue_depth is 0. we use device's queue info.\n"); + SKHPB_DRIVER_E("hba->nutrs = %d\n", hba->nutrs); + } + INIT_LIST_HEAD(&hpb->lh_rsp_info_free); + INIT_LIST_HEAD(&hpb->lh_map_req_free); + INIT_LIST_HEAD(&hpb->lh_map_req_retry); + + hpb->rsp_info = vzalloc(queue_depth * sizeof(struct skhpb_rsp_info)); + if (!hpb->rsp_info) + goto release_mem; + + hpb->map_req = vzalloc(queue_depth * sizeof(struct skhpb_map_req)); + if (!hpb->map_req) + goto release_mem; + + for (i = 0; i < queue_depth; i++) { + rsp_info = hpb->rsp_info + i; + INIT_LIST_HEAD(&rsp_info->list_rsp_info); + list_add_tail(&rsp_info->list_rsp_info, &hpb->lh_rsp_info_free); + } + + for (i = 0; i < queue_depth; i++) { + map_req = hpb->map_req + i; + INIT_LIST_HEAD(&map_req->list_map_req); + list_add_tail(&map_req->list_map_req, &hpb->lh_map_req_free); + } + + return 0; + +release_mem: + return -ENOMEM; +} + +static void skhpb_init_lu_constant(struct skhpb_lu *hpb, + struct skhpb_lu_desc *lu_desc, + struct skhpb_func_desc *func_desc) +{ + unsigned long long region_unit_size, region_mem_size; + unsigned long long last_subregion_unit_size; + int entries_per_region; + + /* From descriptors */ + region_unit_size = SKHPB_SECTOR * (1ULL << func_desc->hpb_region_size); + region_mem_size = region_unit_size / SKHPB_BLOCK * SKHPB_ENTRY_SIZE; + + hpb->subregion_unit_size = SKHPB_SECTOR * (1ULL << func_desc->hpb_subregion_size); + hpb->subregion_mem_size = hpb->subregion_unit_size / + SKHPB_BLOCK * SKHPB_ENTRY_SIZE; + if (func_desc->hpb_region_size == func_desc->hpb_subregion_size) + hpb->identical_size = true; + else + hpb->identical_size = false; + + last_subregion_unit_size = + lu_desc->lu_logblk_cnt * + (1ULL << lu_desc->lu_logblk_size) % hpb->subregion_unit_size; + hpb->last_subregion_mem_size = + last_subregion_unit_size / SKHPB_BLOCK * SKHPB_ENTRY_SIZE; + if (hpb->last_subregion_mem_size == 0) + hpb->last_subregion_mem_size = hpb->subregion_mem_size; + hpb->hpb_ver = func_desc->hpb_ver; + hpb->lu_max_active_regions = lu_desc->lu_max_active_hpb_regions; + hpb->lru_info.max_lru_active_count = + lu_desc->lu_max_active_hpb_regions + - lu_desc->lu_num_hpb_pinned_regions; + + /* relation : lu <-> region <-> sub region <-> entry */ + hpb->lu_num_blocks = lu_desc->lu_logblk_cnt; + entries_per_region = region_mem_size / SKHPB_ENTRY_SIZE; + hpb->entries_per_subregion = hpb->subregion_mem_size / SKHPB_ENTRY_SIZE; + hpb->subregions_per_region = region_mem_size / hpb->subregion_mem_size; + + hpb->hpb_control_mode = func_desc->hpb_control_mode; +#if defined(SKHPB_READ_LARGE_CHUNK_SUPPORT) + hpb->ppn_dirties_per_subregion = + hpb->entries_per_subregion/BITS_PER_PPN_DIRTY; + /* SKSKHPB_DRIVER_D("ppn_dirties_per_subregion:%d, %d \n", + hpb->ppn_dirties_per_subregion, BITS_PER_PPN_DIRTY); */ +#endif + /* + * 1. regions_per_lu + * = (lu_num_blocks * 4096) / region_unit_size + * = (lu_num_blocks * SKHPB_ENTRY_SIZE) / region_mem_size + * = lu_num_blocks / (region_mem_size / SKHPB_ENTRY_SIZE) + * + * 2. regions_per_lu = lu_num_blocks / subregion_mem_size (is trik...) + * if SKHPB_ENTRY_SIZE != subregions_per_region, it is error. + */ + hpb->regions_per_lu = (hpb->lu_num_blocks + + (region_mem_size / SKHPB_ENTRY_SIZE) - 1) + / (region_mem_size / SKHPB_ENTRY_SIZE); + hpb->subregions_per_lu = (hpb->lu_num_blocks + + (hpb->subregion_mem_size / SKHPB_ENTRY_SIZE) - 1) + / (hpb->subregion_mem_size / SKHPB_ENTRY_SIZE); + + /* mempool info */ + hpb->mpage_bytes = PAGE_SIZE; + hpb->mpages_per_subregion = hpb->subregion_mem_size / hpb->mpage_bytes; + + /* Bitmask Info. */ + hpb->dwords_per_subregion = hpb->entries_per_subregion / SKHPB_BITS_PER_DWORD; + hpb->entries_per_region_shift = ffs(entries_per_region) - 1; + hpb->entries_per_region_mask = entries_per_region - 1; + hpb->entries_per_subregion_shift = ffs(hpb->entries_per_subregion) - 1; + hpb->entries_per_subregion_mask = hpb->entries_per_subregion - 1; + + SKHPB_DRIVER_I("===== Device Descriptor =====\n"); + SKHPB_DRIVER_I("hpb_region_size = %d, hpb_subregion_size = %d\n", + func_desc->hpb_region_size, + func_desc->hpb_subregion_size); + SKHPB_DRIVER_I("===== Constant Values =====\n"); + SKHPB_DRIVER_I("region_unit_size = %llu, region_mem_size %llu\n", + region_unit_size, region_mem_size); + SKHPB_DRIVER_I("subregion_unit_size = %llu, subregion_mem_size %d\n", + hpb->subregion_unit_size, hpb->subregion_mem_size); + SKHPB_DRIVER_I("last_subregion_mem_size = %d\n", hpb->last_subregion_mem_size); + SKHPB_DRIVER_I("lu_num_blks = %llu, reg_per_lu = %d, subreg_per_lu = %d\n", + hpb->lu_num_blocks, hpb->regions_per_lu, + hpb->subregions_per_lu); + SKHPB_DRIVER_I("subregions_per_region = %d\n", + hpb->subregions_per_region); + SKHPB_DRIVER_I("entries_per_region %u shift %u mask 0x%X\n", + entries_per_region, hpb->entries_per_region_shift, + hpb->entries_per_region_mask); + SKHPB_DRIVER_I("entries_per_subregion %u shift %u mask 0x%X\n", + hpb->entries_per_subregion, + hpb->entries_per_subregion_shift, + hpb->entries_per_subregion_mask); + SKHPB_DRIVER_I("mpages_per_subregion : %d\n", + hpb->mpages_per_subregion); + SKHPB_DRIVER_I("===================================\n"); +} + +static int skhpb_lu_hpb_init(struct ufs_hba *hba, struct skhpb_lu *hpb, + struct skhpb_func_desc *func_desc, + struct skhpb_lu_desc *lu_desc, int lun, + bool *do_work_lun) +{ + struct skhpb_region *cb; + struct skhpb_subregion *cp; + int region, subregion; + int total_subregion_count, subregion_count; + int ret, j; + + *do_work_lun = false; + + spin_lock_init(&hpb->hpb_lock); + spin_lock_init(&hpb->rsp_list_lock); + spin_lock_init(&hpb->map_list_lock); + + /* init lru information */ + INIT_LIST_HEAD(&hpb->lru_info.lru); + hpb->lru_info.selection_type = TYPE_LRU; + + INIT_LIST_HEAD(&hpb->lh_subregion_req); + INIT_LIST_HEAD(&hpb->lh_rsp_info); + INIT_LIST_HEAD(&hpb->lh_map_ctx); + + hpb->lu_hpb_enable = true; + + skhpb_init_lu_constant(hpb, lu_desc, func_desc); + + hpb->region_tbl = vzalloc(sizeof(struct skhpb_region) * hpb->regions_per_lu); + if (!hpb->region_tbl) + return -ENOMEM; + + SKHPB_DRIVER_D("active_block_table bytes: %lu\n", + (sizeof(struct skhpb_region) * hpb->regions_per_lu)); + + ret = skhpb_table_mempool_init(hpb, + lu_desc->lu_max_active_hpb_regions, + hpb->subregions_per_region, + hpb->entries_per_subregion, SKHPB_ENTRY_SIZE); + if (ret) { + SKHPB_DRIVER_E("ppn table mempool init fail!\n"); + goto release_mempool; + } + + ret = skhpb_req_mempool_init(hba, hpb, lu_desc->lu_queue_depth); + if (ret) { + SKHPB_DRIVER_E("rsp_info_mempool init fail!\n"); + goto release_mempool; + } + + total_subregion_count = hpb->subregions_per_lu; + + skhpb_init_jobs(hpb); + + SKHPB_DRIVER_D("total_subregion_count: %d\n", total_subregion_count); + for (region = 0, subregion_count = 0, + total_subregion_count = hpb->subregions_per_lu; + region < hpb->regions_per_lu; + region++, total_subregion_count -= subregion_count) { + cb = hpb->region_tbl + region; + cb->region = region; + + /* init lru region information*/ + INIT_LIST_HEAD(&cb->list_region); + cb->hit_count = 0; + + subregion_count = min(total_subregion_count, + hpb->subregions_per_region); + /* SKSKHPB_DRIVER_D("total: %d subregion_count: %d\n", + total_subregion_count, subregion_count); */ + + ret = skhpb_alloc_subregion_tbl(hpb, cb, subregion_count); + if (ret) + goto release_region_cp; + skhpb_init_subregion_tbl(hpb, cb, region == hpb->regions_per_lu - 1); + + if (skhpb_is_pinned(lu_desc, region)) { + SKHPB_DRIVER_D("region: %d PINNED %d ~ %d\n", + region, lu_desc->hpb_pinned_region_startidx, + lu_desc->lu_hpb_pinned_end_offset); + ret = skhpb_init_pinned_active_block(hpb, cb); + if (ret) + goto release_region_cp; + *do_work_lun = true; + cb->is_pinned = true; + cb->region_state = SKHPB_REGION_ACTIVE; + } else { + /* SKSKHPB_DRIVER_D("region: %d inactive\n", cb->region); */ + cb->is_pinned = false; + cb->region_state = SKHPB_REGION_INACTIVE; + } + } + if (total_subregion_count != 0) { + SKHPB_DRIVER_E("error total_subregion_count: %d\n", + total_subregion_count); + goto release_region_cp; + } + hpb->hba = hba; + hpb->lun = lun; + /* + * even if creating sysfs failed, skhpb could run normally. + * so we don't deal with error handling + */ + skhpb_create_sysfs(hba, hpb); + return 0; + +release_region_cp: + for (j = 0 ; j < region ; j++) { + cb = hpb->region_tbl + j; + if (cb->subregion_tbl) { + for (subregion = 0; subregion < cb->subregion_count; + subregion++) { + cp = cb->subregion_tbl + subregion; + + if (cp->mctx) + skhpb_put_map_ctx(hpb, cp->mctx); + } + kfree(cb->subregion_tbl); + } + } + +release_mempool: + skhpb_table_mempool_remove(hpb); + *do_work_lun = false; + return ret; +} + +static int skhpb_get_hpb_lu_desc(struct ufs_hba *hba, + struct skhpb_lu_desc *lu_desc, int lun) +{ + int ret; + u8 logical_buf[SKHPB_QUERY_DESC_UNIT_MAX_SIZE] = { 0 }; + + ret = skhpb_read_unit_desc(hba, lun, logical_buf, + SKHPB_QUERY_DESC_UNIT_MAX_SIZE); + if (ret) { + SKHPB_DRIVER_E("read unit desc failed. ret %d\n", ret); + return ret; + } + + lu_desc->lu_queue_depth = logical_buf[UNIT_DESC_PARAM_LU_Q_DEPTH]; + + // 2^log, ex) 0x0C = 4KB + lu_desc->lu_logblk_size = logical_buf[UNIT_DESC_PARAM_LOGICAL_BLK_SIZE]; + lu_desc->lu_logblk_cnt = + get_unaligned_be64(&logical_buf[UNIT_DESC_PARAM_LOGICAL_BLK_COUNT]); + + if (logical_buf[UNIT_DESC_PARAM_LU_ENABLE] == LU_HPB_ENABLE) + lu_desc->lu_hpb_enable = true; + else + lu_desc->lu_hpb_enable = false; + + lu_desc->lu_max_active_hpb_regions = + get_unaligned_be16(logical_buf + + UNIT_DESC_HPB_LU_MAX_ACTIVE_REGIONS); + lu_desc->hpb_pinned_region_startidx = + get_unaligned_be16(logical_buf + + UNIT_DESC_HPB_LU_PIN_REGION_START_OFFSET); + lu_desc->lu_num_hpb_pinned_regions = + get_unaligned_be16(logical_buf + + UNIT_DESC_HPB_LU_NUM_PIN_REGIONS); + + if (lu_desc->lu_hpb_enable) { + SKHPB_DRIVER_D("LUN(%d) [0A] bLogicalBlockSize %d\n", + lun, lu_desc->lu_logblk_size); + SKHPB_DRIVER_D("LUN(%d) [0B] qLogicalBlockCount %llu\n", + lun, lu_desc->lu_logblk_cnt); + SKHPB_DRIVER_D("LUN(%d) [03] bLuEnable %d\n", + lun, logical_buf[UNIT_DESC_PARAM_LU_ENABLE]); + SKHPB_DRIVER_D("LUN(%d) [06] bLuQueueDepth %d\n", + lun, lu_desc->lu_queue_depth); + SKHPB_DRIVER_D("LUN(%d) [23:24] wLUMaxActiveHPBRegions %d\n", + lun, lu_desc->lu_max_active_hpb_regions); + SKHPB_DRIVER_D("LUN(%d) [25:26] wHPBPinnedRegionStartIdx %d\n", + lun, lu_desc->hpb_pinned_region_startidx); + SKHPB_DRIVER_D("LUN(%d) [27:28] wNumHPBPinnedRegions %d\n", + lun, lu_desc->lu_num_hpb_pinned_regions); + } + + if (lu_desc->lu_num_hpb_pinned_regions > 0) { + lu_desc->lu_hpb_pinned_end_offset = + lu_desc->hpb_pinned_region_startidx + + lu_desc->lu_num_hpb_pinned_regions - 1; + } else + lu_desc->lu_hpb_pinned_end_offset = -1; + + if (lu_desc->lu_hpb_enable) + SKHPB_DRIVER_I("Enable, LU: %d, MAX_REGION: %d, PIN: %d - %d\n", + lun, + lu_desc->lu_max_active_hpb_regions, + lu_desc->hpb_pinned_region_startidx, + lu_desc->lu_num_hpb_pinned_regions); + return 0; +} + +static void skhpb_quirk_setup(struct ufs_hba *hba, + struct skhpb_func_desc *desc) +{ + if (hba->dev_quirks & SKHPB_QUIRK_PURGE_HINT_INFO_WHEN_SLEEP) { + hba->skhpb_quirk |= SKHPB_QUIRK_PURGE_HINT_INFO_WHEN_SLEEP; + SKHPB_DRIVER_I("QUIRK set PURGE_HINT_INFO_WHEN_SLEEP\n"); + } + if (desc->hpb_ver >= 0x0101) { + hba->skhpb_quirk |= SKHPB_QUIRK_USE_READ_16_FOR_ENCRYPTION; + SKHPB_DRIVER_I("QUIRK set USE_READ_16_FOR_ENCRYPTION\n"); + } + if (desc->hpb_ver == 0x0102) { + hba->skhpb_quirk |= SKHPB_QUIRK_ALWAYS_DEVICE_CONTROL_MODE; + SKHPB_DRIVER_I("QUIRK set ALWAYS_DEVICE_CONTROL_MODE\n"); + } +} + +static int skhpb_read_dev_desc_support(struct ufs_hba *hba, + struct skhpb_func_desc *desc) +{ + u8 desc_buf[SKHPB_QUERY_DESC_DEVICE_MAX_SIZE]; + int err; + + err = skhpb_read_device_desc(hba, desc_buf, + SKHPB_QUERY_DESC_DEVICE_MAX_SIZE); + if (err) + return err; + + if (desc_buf[DEVICE_DESC_PARAM_UFS_FEAT] & + SKHPB_UFS_FEATURE_SUPPORT_HPB_BIT) { + hba->skhpb_feat |= SKHPB_UFS_FEATURE_SUPPORT_HPB_BIT; + SKHPB_DRIVER_I("FeaturesSupport= support\n"); + } else { + SKHPB_DRIVER_I("FeaturesSupport= not support\n"); + return -ENODEV; + } + + desc->lu_cnt = desc_buf[DEVICE_DESC_PARAM_NUM_LU]; + SKHPB_DRIVER_D("Dev LU count= %d\n", desc->lu_cnt); + + desc->spec_ver = + (u16)SKHPB_SHIFT_BYTE_1(desc_buf[DEVICE_DESC_PARAM_SPEC_VER]) | + (u16)SKHPB_SHIFT_BYTE_0(desc_buf[DEVICE_DESC_PARAM_SPEC_VER + 1]); + SKHPB_DRIVER_I("Dev Spec Ver= %x.%x\n", + SKHPB_GET_BYTE_1(desc->spec_ver), + SKHPB_GET_BYTE_0(desc->spec_ver) ); + + desc->hpb_ver = + (u16)SKHPB_SHIFT_BYTE_1(desc_buf[DEVICE_DESC_PARAM_HPB_VER]) | + (u16)SKHPB_SHIFT_BYTE_0(desc_buf[DEVICE_DESC_PARAM_HPB_VER + 1]); + SKHPB_DRIVER_I("Dev Ver= %x.%x.%x, DD Ver= %x.%x.%x\n", + (desc->hpb_ver >> 8) & 0xf, + (desc->hpb_ver >> 4) & 0xf, + (desc->hpb_ver >> 0) & 0xf, + SKHPB_GET_BYTE_2(SKHPB_DD_VER), + SKHPB_GET_BYTE_1(SKHPB_DD_VER), + SKHPB_GET_BYTE_0(SKHPB_DD_VER)); + + skhpb_quirk_setup(hba, desc); + + if (hba->skhpb_quirk & SKHPB_QUIRK_ALWAYS_DEVICE_CONTROL_MODE) + desc->hpb_control_mode = DEV_CTRL_MODE; + else + desc->hpb_control_mode = (u8)desc_buf[DEVICE_DESC_PARAM_HPB_CONTROL]; + + + SKHPB_DRIVER_I("HPB Control Mode = %s", + (desc->hpb_control_mode)?"DEV MODE":"HOST MODE"); + if (desc->hpb_control_mode == HOST_CTRL_MODE) { + SKHPB_DRIVER_E("Driver does not support Host Control Mode"); + return -ENODEV; + } + hba->hpb_control_mode = desc->hpb_control_mode; + return 0; +} + +static int skhpb_read_geo_desc_support(struct ufs_hba *hba, + struct skhpb_func_desc *desc) +{ + int err; + u8 geometry_buf[SKHPB_QUERY_DESC_GEOMETRY_MAX_SIZE]; + + err = skhpb_read_geo_desc(hba, geometry_buf, + SKHPB_QUERY_DESC_GEOMETRY_MAX_SIZE); + if (err) + return err; + + desc->hpb_region_size = geometry_buf[GEOMETRY_DESC_HPB_REGION_SIZE]; + desc->hpb_number_lu = geometry_buf[GEOMETRY_DESC_HPB_NUMBER_LU]; + desc->hpb_subregion_size = + geometry_buf[GEOMETRY_DESC_HPB_SUBREGION_SIZE]; + desc->hpb_device_max_active_regions = + get_unaligned_be16(geometry_buf + + GEOMETRY_DESC_HPB_DEVICE_MAX_ACTIVE_REGIONS); + + SKHPB_DRIVER_D("[48] bHPBRegionSize %u\n", desc->hpb_region_size); + SKHPB_DRIVER_D("[49] bHPBNumberLU %u\n", desc->hpb_number_lu); + SKHPB_DRIVER_D("[4A] bHPBSubRegionSize %u\n", desc->hpb_subregion_size); + SKHPB_DRIVER_D("[4B:4C] wDeviceMaxActiveHPBRegions %u\n", + desc->hpb_device_max_active_regions); + + if (desc->hpb_number_lu == 0) { + SKHPB_DRIVER_E("HPB is not supported\n"); + return -ENODEV; + } + /* for activation */ + hba->skhpb_max_regions = desc->hpb_device_max_active_regions; + return 0; +} + +int skhpb_control_validation(struct ufs_hba *hba, + struct skhpb_config_desc *config) +{ + unsigned int num_regions = 0; + int lun; + + if (!(hba->skhpb_feat & SKHPB_UFS_FEATURE_SUPPORT_HPB_BIT)) + return -ENOTSUPP; + + for (lun = 0 ; lun < UFS_UPIU_MAX_GENERAL_LUN ; lun++) { + unsigned char *unit = config->unit[lun]; + + if (unit[SKHPB_CONF_LU_ENABLE] >= LU_SET_MAX) + return -EINVAL; + + /* total should not exceed max_active_regions */ + num_regions += unit[SKHPB_CONF_ACTIVE_REGIONS] << 8; + num_regions += unit[SKHPB_CONF_ACTIVE_REGIONS + 1]; + if (num_regions > hba->skhpb_max_regions) + return -EINVAL; + } + return 0; +} + +static int skhpb_init(struct ufs_hba *hba) +{ + struct skhpb_func_desc func_desc; + int lun, ret, retries; + int hpb_dev = 0; + bool do_work; + + pm_runtime_get_sync(hba->dev); + ret = skhpb_read_dev_desc_support(hba, &func_desc); + if (ret) + goto out_state; + + ret = skhpb_read_geo_desc_support(hba, &func_desc); + if (ret) + goto out_state; + + for (retries = 0; retries < 20; retries++) { + if (!hba->lrb_in_use) { + ret = ufshcd_query_flag(hba, + UPIU_QUERY_OPCODE_SET_FLAG, + QUERY_FLAG_IDN_HPB_RESET, 0, + NULL); + if (!ret) { + SKHPB_DRIVER_I("Query fHPBReset is successfully sent retries = %d\n", retries); + break; + } + } + else + msleep(200); + } + if (ret == 0) { + bool fHPBReset = true; + + ufshcd_query_flag_retry(hba, + UPIU_QUERY_OPCODE_READ_FLAG, + QUERY_FLAG_IDN_HPB_RESET, 0, + &fHPBReset); + if (fHPBReset) + SKHPB_DRIVER_I("fHPBReset still set\n"); + } + + skhpb_init_constant(); + + do_work = false; + for (lun = 0 ; lun < UFS_UPIU_MAX_GENERAL_LUN ; lun++) { + struct skhpb_lu_desc lu_desc; + bool do_work_lun; + + ret = skhpb_get_hpb_lu_desc(hba, &lu_desc, lun); + if (ret) + goto out_state; + + if (lu_desc.lu_hpb_enable == false) + continue; + + hba->skhpb_lup[lun] = kzalloc(sizeof(struct skhpb_lu), + GFP_KERNEL); + if (!hba->skhpb_lup[lun]) { + ret = -ENOMEM; + goto out_free_mem; + } + + ret = skhpb_lu_hpb_init(hba, hba->skhpb_lup[lun], + &func_desc, &lu_desc, lun, &do_work_lun); + if (ret) { + if (ret == -ENODEV) + continue; + else + goto out_free_mem; + } + do_work |= do_work_lun; + hba->skhpb_quicklist_lu_enable[hpb_dev] = lun; + SKHPB_DRIVER_D("skhpb_quicklist_lu_enable[%d] = %d\n", hpb_dev, lun); + hpb_dev++; + } + + if (hpb_dev) + goto done; + + goto out_free_mem; + +done: + INIT_WORK(&hba->skhpb_eh_work, skhpb_error_handler); + hba->skhpb_state = SKHPB_PRESENT; + hba->issue_ioctl = false; + pm_runtime_mark_last_busy(hba->dev); + pm_runtime_put_noidle(hba->dev); + + if (do_work) { + for (lun = 0; lun < UFS_UPIU_MAX_GENERAL_LUN; lun++) { + struct skhpb_lu *hpb = hba->skhpb_lup[lun]; + + if (hpb) + schedule_delayed_work(&hpb->skhpb_pinned_work, 0); + } + } + + return 0; + +out_free_mem: + skhpb_release(hba, SKHPB_NOT_SUPPORTED); +out_state: + hba->skhpb_state = SKHPB_NOT_SUPPORTED; + pm_runtime_mark_last_busy(hba->dev); + pm_runtime_put_noidle(hba->dev); + return ret; +} + +static void skhpb_map_loading_trigger(struct skhpb_lu *hpb, + bool only_pinned, bool do_work_handler) +{ + int region, subregion; + unsigned long flags; + + if (do_work_handler) + goto work_out; + flush_delayed_work(&hpb->skhpb_pinned_work); + for (region = 0 ; region < hpb->regions_per_lu ; region++) { + struct skhpb_region *cb; + + cb = hpb->region_tbl + region; + + if (cb->region_state != SKHPB_REGION_ACTIVE && + !cb->is_pinned) + continue; + + if ((only_pinned && cb->is_pinned) || + !only_pinned) { + spin_lock_irqsave(&hpb->hpb_lock, flags); + for (subregion = 0; subregion < cb->subregion_count; + subregion++) + skhpb_add_subregion_to_req_list(hpb, + cb->subregion_tbl + subregion); + spin_unlock_irqrestore(&hpb->hpb_lock, flags); + do_work_handler = true; + } + } +work_out: + if (do_work_handler) + schedule_delayed_work(&hpb->skhpb_pinned_work, 0); +} + +static void skhpb_purge_active_block(struct skhpb_lu *hpb) +{ + int region, subregion; + int state; + struct skhpb_region *cb; + struct skhpb_subregion *cp; + unsigned long flags; + + spin_lock_irqsave(&hpb->hpb_lock, flags); + for (region = 0 ; region < hpb->regions_per_lu ; region++) { + cb = hpb->region_tbl + region; + + if (cb->region_state == SKHPB_REGION_INACTIVE) { + continue; + } + + if (cb->is_pinned){ + state = SKHPB_SUBREGION_DIRTY; + } else if (cb->region_state == SKHPB_REGION_ACTIVE) { + state = SKHPB_SUBREGION_UNUSED; + skhpb_cleanup_lru_info(&hpb->lru_info, cb); + } else { + SKHPB_DRIVER_E("Unsupported state of region\n"); + continue; + } + + SKHPB_DRIVER_D("region %d state %d dft %d\n", + region, state, + hpb->debug_free_table); + for (subregion = 0 ; subregion < cb->subregion_count; + subregion++) { + cp = cb->subregion_tbl + subregion; + + skhpb_purge_active_page(hpb, cp, state); + } + SKHPB_DRIVER_D("region %d state %d dft %d\n", + region, state, hpb->debug_free_table); + } + spin_unlock_irqrestore(&hpb->hpb_lock, flags); +} + +static void skhpb_retrieve_rsp_info(struct skhpb_lu *hpb) +{ + struct skhpb_rsp_info *rsp_info; + unsigned long flags; + + while (1) { + spin_lock_irqsave(&hpb->rsp_list_lock, flags); + rsp_info = list_first_entry_or_null(&hpb->lh_rsp_info, + struct skhpb_rsp_info, list_rsp_info); + if (!rsp_info) { + spin_unlock_irqrestore(&hpb->rsp_list_lock, flags); + break; + } + list_move_tail(&rsp_info->list_rsp_info, + &hpb->lh_rsp_info_free); + spin_unlock_irqrestore(&hpb->rsp_list_lock, flags); + SKHPB_DRIVER_D("add_list %p -> %p", + &hpb->lh_rsp_info_free, rsp_info); + } +} + +static void skhpb_probe(struct ufs_hba *hba) +{ + struct skhpb_lu *hpb; + int lu; + + for (lu = 0 ; lu < UFS_UPIU_MAX_GENERAL_LUN ; lu++) { + hpb = hba->skhpb_lup[lu]; + + if (hpb && hpb->lu_hpb_enable) { + skhpb_cancel_jobs(hpb); + skhpb_retrieve_rsp_info(hpb); + skhpb_purge_active_block(hpb); + SKHPB_DRIVER_I("SKHPB lun %d reset\n", lu); +// tasklet_init(&hpb->hpb_work_handler, +// skhpb_work_handler_fn, (unsigned long)hpb); + } + } + hba->skhpb_state = SKHPB_PRESENT; +} + +static void skhpb_destroy_subregion_tbl(struct skhpb_lu *hpb, + struct skhpb_region *cb) +{ + int subregion; + + for (subregion = 0 ; subregion < cb->subregion_count ; subregion++) { + struct skhpb_subregion *cp; + + cp = cb->subregion_tbl + subregion; + cp->subregion_state = SKHPB_SUBREGION_UNUSED; + skhpb_put_map_ctx(hpb, cp->mctx); + } + + kfree(cb->subregion_tbl); +} + +static void skhpb_destroy_region_tbl(struct skhpb_lu *hpb) +{ + int region; + + if (!hpb->region_tbl) + return; + + for (region = 0 ; region < hpb->regions_per_lu ; region++) { + struct skhpb_region *cb; + + cb = hpb->region_tbl + region; + if (cb->region_state == SKHPB_REGION_ACTIVE) { + cb->region_state = SKHPB_REGION_INACTIVE; + + skhpb_destroy_subregion_tbl(hpb, cb); + } + } + vfree(hpb->region_tbl); +} + +void skhpb_suspend(struct ufs_hba *hba) +{ + int lun; + unsigned long flags; + struct skhpb_lu *hpb; + struct skhpb_rsp_info *rsp_info; + struct skhpb_map_req *map_req; + + if (hba->skhpb_quirk & SKHPB_QUIRK_PURGE_HINT_INFO_WHEN_SLEEP) { + for (lun = 0 ; lun < UFS_UPIU_MAX_GENERAL_LUN ; lun++) { + hpb = hba->skhpb_lup[lun]; + if (!hpb) + continue; + + while (1) { + spin_lock_irqsave(&hpb->rsp_list_lock, flags); + rsp_info = list_first_entry_or_null(&hpb->lh_rsp_info, + struct skhpb_rsp_info, list_rsp_info); + if (!rsp_info) { + spin_unlock_irqrestore(&hpb->rsp_list_lock, flags); + break; + } + list_del_init(&rsp_info->list_rsp_info); + list_add_tail(&rsp_info->list_rsp_info, &hpb->lh_rsp_info_free); + atomic64_inc(&hpb->canceled_resp); + spin_unlock_irqrestore(&hpb->rsp_list_lock, flags); + } + while (1) { + spin_lock_bh(&hpb->map_list_lock); + map_req = list_first_entry_or_null(&hpb->lh_map_req_retry, + struct skhpb_map_req, list_map_req); + if (!map_req) { + spin_unlock_bh(&hpb->map_list_lock); + break; + } + list_del_init(&map_req->list_map_req); + list_add_tail(&map_req->list_map_req, &hpb->lh_map_req_free); + atomic64_inc(&hpb->canceled_map_req); + spin_unlock_bh(&hpb->map_list_lock); + } + } + } + for (lun = 0 ; lun < UFS_UPIU_MAX_GENERAL_LUN ; lun++) { + hpb = hba->skhpb_lup[lun]; + if (!hpb) + continue; + skhpb_cancel_jobs(hpb); + } +} + +void skhpb_resume(struct ufs_hba *hba) { + int lun; + struct skhpb_lu *hpb; + + for (lun = 0 ; lun < UFS_UPIU_MAX_GENERAL_LUN ; lun++) { + hpb = hba->skhpb_lup[lun]; + if (!hpb) + continue; + spin_lock_bh(&hpb->map_list_lock); + if (!list_empty(&hpb->lh_map_req_retry)) + schedule_delayed_work(&hpb->skhpb_map_req_retry_work, msecs_to_jiffies(1000)); + spin_unlock_bh(&hpb->map_list_lock); + } +} + +void skhpb_release(struct ufs_hba *hba, int state) +{ + int lun; + + hba->skhpb_state = SKHPB_FAILED; + + for (lun = 0 ; lun < UFS_UPIU_MAX_GENERAL_LUN ; lun++) { + struct skhpb_lu *hpb = hba->skhpb_lup[lun]; + + if (!hpb) + continue; + + hba->skhpb_lup[lun] = NULL; + + if (!hpb->lu_hpb_enable) + continue; + + hpb->lu_hpb_enable = false; + + skhpb_cancel_jobs(hpb); + + skhpb_destroy_region_tbl(hpb); + skhpb_table_mempool_remove(hpb); + + vfree(hpb->rsp_info); + vfree(hpb->map_req); + + kobject_uevent(&hpb->kobj, KOBJ_REMOVE); + kobject_del(&hpb->kobj); // TODO --count & del? + + kfree(hpb); + } + + if (skhpb_alloc_mctx != 0) + SKHPB_DRIVER_E("warning: skhpb_alloc_mctx %d", skhpb_alloc_mctx); + + hba->skhpb_state = state; +} + +void skhpb_init_handler(struct work_struct *work) +{ + struct delayed_work *dwork = to_delayed_work(work); + struct ufs_hba *hba = + container_of(dwork, struct ufs_hba, skhpb_init_work); + struct Scsi_Host *shost = hba->host; + bool async_scan; + + if (hba->skhpb_state == SKHPB_NOT_SUPPORTED) + return; + + spin_lock_irq(shost->host_lock); + async_scan = shost->async_scan; + spin_unlock_irq(shost->host_lock); + if (async_scan) { + schedule_delayed_work(dwork, msecs_to_jiffies(100)); + return; + } + + if (hba->skhpb_state == SKHPB_NEED_INIT) { + int err = skhpb_init(hba); + + if (hba->skhpb_state == SKHPB_NOT_SUPPORTED) + SKHPB_DRIVER_E("Run without HPB - err=%d\n", err); + } else if (hba->skhpb_state == SKHPB_RESET) { + skhpb_probe(hba); + } +} + +void ufshcd_init_hpb(struct ufs_hba *hba) +{ + int lun; + + hba->skhpb_feat = 0; + hba->skhpb_quirk = 0; + hba->skhpb_state = SKHPB_NEED_INIT; + for (lun = 0 ; lun < UFS_UPIU_MAX_GENERAL_LUN ; lun++) { + hba->skhpb_lup[lun] = NULL; + hba->sdev_ufs_lu[lun] = NULL; + hba->skhpb_quicklist_lu_enable[lun] = SKHPB_U8_MAX; + } + + INIT_DELAYED_WORK(&hba->skhpb_init_work, skhpb_init_handler); +} + +static void skhpb_error_handler(struct work_struct *work) +{ + struct ufs_hba *hba; + + hba = container_of(work, struct ufs_hba, skhpb_eh_work); + + SKHPB_DRIVER_E("SKHPB driver runs without SKHPB\n"); + SKHPB_DRIVER_E("SKHPB will be removed from the kernel\n"); + + skhpb_release(hba, SKHPB_FAILED); +} + +static void skhpb_stat_init(struct skhpb_lu *hpb) +{ + atomic64_set(&hpb->hit, 0); + atomic64_set(&hpb->size_miss, 0); + atomic64_set(&hpb->region_miss, 0); + atomic64_set(&hpb->subregion_miss, 0); + atomic64_set(&hpb->entry_dirty_miss, 0); + atomic64_set(&hpb->w_map_req_cnt, 0); +#if defined(SKHPB_READ_LARGE_CHUNK_SUPPORT) + atomic64_set(&hpb->lc_entry_dirty_miss, 0); + atomic64_set(&hpb->lc_reg_subreg_miss, 0); + atomic64_set(&hpb->lc_hit, 0); +#endif + atomic64_set(&hpb->rb_noti_cnt, 0); + atomic64_set(&hpb->reset_noti_cnt, 0); + atomic64_set(&hpb->map_req_cnt, 0); + atomic64_set(&hpb->region_evict, 0); + atomic64_set(&hpb->region_add, 0); + atomic64_set(&hpb->rb_fail, 0); + atomic64_set(&hpb->canceled_resp, 0); + atomic64_set(&hpb->canceled_map_req, 0); + atomic64_set(&hpb->alloc_map_req_cnt, 0); +} + + +static ssize_t skhpb_sysfs_info_from_region_store(struct skhpb_lu *hpb, + const char *buf, size_t count) +{ + unsigned long long value; + int region, subregion; + struct skhpb_region *cb; + struct skhpb_subregion *cp; + + if (kstrtoull(buf, 0, &value)) { + SKHPB_DRIVER_E( "kstrtoul error\n"); + return -EINVAL; + } + + if (value >= hpb->regions_per_lu) { + SKHPB_DRIVER_E("value %llu >= regions_per_lu %d error\n", + value, hpb->regions_per_lu); + return -EINVAL; + } + + region = (int)value; + cb = hpb->region_tbl + region; + + SKHPB_DRIVER_I("get_info_from_region[%d]=", region); + SKHPB_DRIVER_I("region %u state %s", region, + ((cb->region_state == SKHPB_REGION_INACTIVE) ? "INACTIVE" : + ((cb->region_state == SKHPB_REGION_ACTIVE) ? "ACTIVE" : "INVALID")) + ); + for (subregion = 0; subregion < cb->subregion_count; subregion++) { + cp = cb->subregion_tbl + subregion; + SKHPB_DRIVER_I("subregion %u state %s", subregion, + ((cp->subregion_state == SKHPB_SUBREGION_UNUSED) ? "UNUSED" : + ((cp->subregion_state == SKHPB_SUBREGION_DIRTY) ? "DIRTY" : + ((cp->subregion_state == SKHPB_SUBREGION_CLEAN) ? "CLEAN" : + (cp->subregion_state == SKHPB_SUBREGION_ISSUED) ? + "ISSUED" : "INVALID"))) + ); + } + return count; +} + +static ssize_t skhpb_sysfs_info_from_lba_store(struct skhpb_lu *hpb, + const char *buf, size_t count) +{ + skhpb_t ppn; + unsigned long long value; + unsigned int lpn; + int region, subregion, subregion_offset; + struct skhpb_region *cb; + struct skhpb_subregion *cp; + unsigned long flags; + int dirty; + + if (kstrtoull(buf, 0, &value)) { + SKHPB_DRIVER_E("kstrtoul error\n"); + return -EINVAL; + } + + if (value > hpb->lu_num_blocks * SKHPB_SECTORS_PER_BLOCK) { + SKHPB_DRIVER_E("value %llu > lu_num_blocks %llu error\n", + value, hpb->lu_num_blocks); + return -EINVAL; + } + lpn = value / SKHPB_SECTORS_PER_BLOCK; + + skhpb_get_pos_from_lpn(hpb, lpn, ®ion, &subregion, + &subregion_offset); + if(!skhpb_check_region_subregion_validity(hpb, region, subregion)) + return -EINVAL; + cb = hpb->region_tbl + region; + cp = cb->subregion_tbl + subregion; + + if (cb->region_state != SKHPB_REGION_INACTIVE) { + ppn = skhpb_get_ppn(cp->mctx, subregion_offset); + spin_lock_irqsave(&hpb->hpb_lock, flags); + dirty = skhpb_ppn_dirty_check(hpb, cp, subregion_offset); + spin_unlock_irqrestore(&hpb->hpb_lock, flags); + } else { + ppn = 0; + dirty = -1; + } + SKHPB_DRIVER_I("get_info_from_lba[%llu]=", value); + SKHPB_DRIVER_I("sector %llu region %d state %s subregion %d state %s", + value, region, + ((cb->region_state == SKHPB_REGION_INACTIVE) ? "INACTIVE" : + ((cb->region_state == SKHPB_REGION_ACTIVE) ? "ACTIVE" : "INVALID")), + subregion, + ((cp->subregion_state == SKHPB_SUBREGION_UNUSED) ? "UNUSED" : + ((cp->subregion_state == SKHPB_SUBREGION_DIRTY) ? "DIRTY" : + ((cp->subregion_state == SKHPB_SUBREGION_CLEAN) ? "CLEAN" : + (cp->subregion_state == SKHPB_SUBREGION_ISSUED) ? + "ISSUED":"INVALID"))) + ); + SKHPB_DRIVER_I("sector %llu lpn %u ppn %llx dirty %d", + value, lpn, ppn, dirty); + return count; +} + +static ssize_t skhpb_sysfs_map_req_show(struct skhpb_lu *hpb, char *buf) +{ + return snprintf(buf, PAGE_SIZE, + "map_req_count[RB_NOTI RESET_NOTI MAP_REQ]= %lld %lld %lld\n", + (long long)atomic64_read(&hpb->rb_noti_cnt), + (long long)atomic64_read(&hpb->reset_noti_cnt), + (long long)atomic64_read(&hpb->map_req_cnt)); +} + +static ssize_t skhpb_sysfs_count_reset_store(struct skhpb_lu *hpb, + const char *buf, size_t count) +{ + unsigned long debug; + + if (kstrtoul(buf, 0, &debug)) + return -EINVAL; + + skhpb_stat_init(hpb); + + return count; +} + +static ssize_t skhpb_sysfs_add_evict_show(struct skhpb_lu *hpb, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "add_evict_count[ADD EVICT]= %lld %lld\n", + (long long)atomic64_read(&hpb->region_add), + (long long)atomic64_read(&hpb->region_evict)); +} + +static ssize_t skhpb_sysfs_statistics_show(struct skhpb_lu *hpb, char *buf) +{ + long long size_miss, region_miss, subregion_miss, entry_dirty_miss, + hit, miss_all, rb_fail, canceled_resp, canceled_map_req; +#if defined(SKHPB_READ_LARGE_CHUNK_SUPPORT) + long long lc_dirty_miss = 0, lc_state_miss = 0, lc_hit = 0; +#endif + int count = 0; + + hit = atomic64_read(&hpb->hit); + size_miss = atomic64_read(&hpb->size_miss); + region_miss = atomic64_read(&hpb->region_miss); + subregion_miss = atomic64_read(&hpb->subregion_miss); + entry_dirty_miss = atomic64_read(&hpb->entry_dirty_miss); + rb_fail = atomic64_read(&hpb->rb_fail); + canceled_resp = atomic64_read(&hpb->canceled_resp); + canceled_map_req = atomic64_read(&hpb->canceled_map_req); + +#if defined(SKHPB_READ_LARGE_CHUNK_SUPPORT) + lc_dirty_miss = atomic64_read(&hpb->lc_entry_dirty_miss); + lc_state_miss = atomic64_read(&hpb->lc_reg_subreg_miss); + lc_hit = atomic64_read(&hpb->lc_hit); + entry_dirty_miss += lc_dirty_miss; + subregion_miss += lc_state_miss; +#endif + miss_all = size_miss + region_miss + subregion_miss + entry_dirty_miss; + count += snprintf(buf + count, PAGE_SIZE, + "Total: %lld\nHit_Counts: %lld\n", + hit + miss_all, hit); + count += snprintf(buf + count, PAGE_SIZE, + "Miss_Counts[ALL SIZE REG SUBREG DIRTY]= %lld %lld %lld %lld %lld\n", + miss_all, size_miss, region_miss, subregion_miss, entry_dirty_miss); + +#if defined(SKHPB_READ_LARGE_CHUNK_SUPPORT) + count += snprintf(buf + count, PAGE_SIZE, + "LARG_CHNK Hit_Count: %lld, miss_count[ALL DIRTY REG_SUBREG]= %lld %lld %lld\n", + lc_hit, lc_dirty_miss + lc_state_miss, lc_dirty_miss, lc_state_miss); +#endif + if (hpb->hba->skhpb_quirk & SKHPB_QUIRK_PURGE_HINT_INFO_WHEN_SLEEP) + count += snprintf(buf + count, PAGE_SIZE, + "READ_BUFFER miss_count[RB_FAIL CANCEL_RESP CANCEL_MAP]= %lld %lld %lld\n", + rb_fail, canceled_resp, canceled_map_req); + else + count += snprintf(buf + count, PAGE_SIZE, + "READ_BUFFER miss_count[RB_FAIL]= %lld\n", rb_fail); + return count; +} + +static ssize_t skhpb_sysfs_version_show(struct skhpb_lu *hpb, char *buf) +{ + return snprintf(buf, PAGE_SIZE, + "HPBversion[HPB DD]= %x.%x.%x %x.%x.%x\n", + (hpb->hpb_ver >> 8) & 0xf, + (hpb->hpb_ver >> 4) & 0xf, + (hpb->hpb_ver >> 0) & 0xf, + SKHPB_GET_BYTE_2(SKHPB_DD_VER), + SKHPB_GET_BYTE_1(SKHPB_DD_VER), + SKHPB_GET_BYTE_0(SKHPB_DD_VER)); +} + +static ssize_t skhpb_sysfs_active_count_show( + struct skhpb_lu *hpb, char *buf) +{ + struct skhpb_region *cb; + int region; + int pinned_cnt = 0; + + for (region = 0 ; region < hpb->regions_per_lu ; region++) { + cb = hpb->region_tbl + region; + + if (cb->is_pinned && cb->region_state == SKHPB_REGION_ACTIVE) + pinned_cnt++; + } + return snprintf(buf, PAGE_SIZE, + "active_count[ACTIVE_CNT PINNED_CNT]= %ld %d\n", + atomic64_read(&hpb->lru_info.active_count), pinned_cnt); +} + +static ssize_t skhpb_sysfs_hpb_disable_show( + struct skhpb_lu *hpb, char *buf) +{ + return snprintf(buf, PAGE_SIZE, + "[0] BOTH_enabled= %d\ + \n[1] ONLY_HPB_BUFFER_disabled= %d\ + \n[2] ONLY_HPB_READ_disabled= %d\ + \n[3] BOTH_disabled= %d\n", + (hpb->force_map_req_disable == 0 && + hpb->force_hpb_read_disable == 0)?1:0, + hpb->force_map_req_disable, + hpb->force_hpb_read_disable, + (hpb->force_map_req_disable == 1 && + hpb->force_hpb_read_disable == 1)?1:0); +} + +static ssize_t skhpb_sysfs_hpb_disable_store(struct skhpb_lu *hpb, + const char *buf, size_t count) +{ + unsigned long value; + + if (kstrtoul(buf, 0, &value)) + return -EINVAL; + + if (value > 3) { + SKHPB_DRIVER_E("Error, Only [0-3] is valid:\ + \n[0] BOTH_enable\ + \n[1] ONLY_HPB_BUFFER_disable\ + \n[2] ONLY_HPB_READ_disable\ + \n[3] BOTH_disabie\n"); + return -EINVAL; + } + + hpb->force_map_req_disable = value & 0x1; + hpb->force_hpb_read_disable = value & 0x2; + return count; +} + +static ssize_t skhpb_sysfs_hpb_reset_store(struct skhpb_lu *hpb, + const char *buf, size_t count) +{ + unsigned long value; + unsigned int doorbel; + struct skhpb_rsp_info *rsp_info; + unsigned long flags; + int ret, retries, lun; + struct skhpb_lu *hpb_lu; + + if (kstrtoul(buf, 0, &value)) + return -EINVAL; + if (!value) + return count; + + for (retries = 1; retries <= 20; retries++) { + pm_runtime_get_sync(SKHPB_DEV(hpb)); + ufshcd_hold(hpb->hba, false); + doorbel = ufshcd_readl(hpb->hba, REG_UTP_TRANSFER_REQ_DOOR_BELL); + ufshcd_release(hpb->hba); + pm_runtime_mark_last_busy(SKHPB_DEV(hpb)); + pm_runtime_put_noidle(SKHPB_DEV(hpb)); + + if (!doorbel) { + pm_runtime_get_sync(SKHPB_DEV(hpb)); + ret = ufshcd_query_flag_retry(hpb->hba, + UPIU_QUERY_OPCODE_SET_FLAG, + QUERY_FLAG_IDN_HPB_RESET, 0, + NULL); + pm_runtime_mark_last_busy(SKHPB_DEV(hpb)); + pm_runtime_put_noidle(SKHPB_DEV(hpb)); + if(!ret) { + SKHPB_DRIVER_I("Query fHPBReset is successfully sent\n"); + break; + } + } + SKHPB_DRIVER_I("fHPBReset failed and will retry[%d] after some time, DOORBELL: 0x%x\n", + retries, doorbel); + msleep(200); + } + if (ret == 0) { + bool fHPBReset = true; + pm_runtime_get_sync(SKHPB_DEV(hpb)); + ufshcd_query_flag_retry(hpb->hba, + UPIU_QUERY_OPCODE_READ_FLAG, + QUERY_FLAG_IDN_HPB_RESET, 0, + &fHPBReset); + pm_runtime_mark_last_busy(SKHPB_DEV(hpb)); + pm_runtime_put_noidle(SKHPB_DEV(hpb)); + if (fHPBReset) + SKHPB_DRIVER_E("fHPBReset is still in progress at device, but keep going\n"); + } else { + SKHPB_DRIVER_E("Fail to set fHPBReset flag\n"); + goto out; + } + flush_delayed_work(&hpb->skhpb_pinned_work); + for (lun = 0 ; lun < UFS_UPIU_MAX_GENERAL_LUN ; lun++) + { + hpb_lu = hpb->hba->skhpb_lup[lun]; + if (!hpb_lu || !hpb_lu->lu_hpb_enable) + continue; + + skhpb_stat_init(hpb_lu); + + spin_lock_irqsave(&hpb_lu->rsp_list_lock, flags); + rsp_info = skhpb_get_req_info(hpb_lu); + spin_unlock_irqrestore(&hpb_lu->rsp_list_lock, flags); + if (!rsp_info) + goto out; + rsp_info->type = SKHPB_RSP_HPB_RESET; + SKHPB_RSP_TIME(rsp_info->RSP_start); + spin_lock_irqsave(&hpb_lu->rsp_list_lock, flags); + list_add_tail(&rsp_info->list_rsp_info, &hpb_lu->lh_rsp_info); + spin_unlock_irqrestore(&hpb_lu->rsp_list_lock, flags); + SKHPB_DRIVER_I("Host HPB reset start LU%d - fHPBReset\n", lun); + schedule_work(&hpb_lu->skhpb_rsp_work); + } +out: + return count; +} + +static ssize_t skhpb_sysfs_debug_log_show( + struct skhpb_lu *hpb, char *buf) +{ + int value = skhpb_debug_mask; + + if (value == (SKHPB_LOG_OFF)) { + value = SKHPB_LOG_LEVEL_OFF; + } else if (value == (SKHPB_LOG_ERR)) { + value = SKHPB_LOG_LEVEL_ERR; + } else if (value == (SKHPB_LOG_ERR | SKHPB_LOG_INFO)) { + value = SKHPB_LOG_LEVEL_INFO; + } else if (value == (SKHPB_LOG_ERR | SKHPB_LOG_INFO | SKHPB_LOG_DEBUG)) { + value = SKHPB_LOG_LEVEL_DEBUG; + } else if (value == (SKHPB_LOG_ERR | SKHPB_LOG_INFO | SKHPB_LOG_DEBUG | SKHPB_LOG_HEX)) { + value = SKHPB_LOG_LEVEL_HEX; + } + + return snprintf(buf, PAGE_SIZE, "[0] : LOG_LEVEL_OFF\ + \n[1] : LOG_LEVEL_ERR\ + \n[2] : LOG_LEVEL_INFO\ + \n[3] : LOG_LEVEL_DEBUG\ + \n[4] : LOG_LEVEL_HEX\ + \n-----------------------\ + \nLog-Level = %d\n", value); +} + +static ssize_t skhpb_sysfs_debug_log_store(struct skhpb_lu *hpb, + const char *buf, size_t count) +{ + unsigned long value; + + if (kstrtoul(buf, 0, &value)) + return -EINVAL; + + if (value > SKHPB_LOG_LEVEL_HEX) { + SKHPB_DRIVER_E("Error, Only [0-4] is valid:\ + \n[0] : LOG_LEVEL_OFF\ + \n[1] : LOG_LEVEL_ERR\ + \n[2] : LOG_LEVEL_INFO\ + \n[3] : LOG_LEVEL_DEBUG\ + \n[4] : LOG_LEVEL_HEX\n"); + return -EINVAL; + } + + if (value == SKHPB_LOG_LEVEL_OFF) { + skhpb_debug_mask = SKHPB_LOG_OFF; + } else if (value == SKHPB_LOG_LEVEL_ERR) { + skhpb_debug_mask = SKHPB_LOG_ERR; + } else if (value == SKHPB_LOG_LEVEL_INFO) { + skhpb_debug_mask = SKHPB_LOG_ERR | SKHPB_LOG_INFO; + } else if (value == SKHPB_LOG_LEVEL_DEBUG) { + skhpb_debug_mask = SKHPB_LOG_ERR | SKHPB_LOG_INFO | SKHPB_LOG_DEBUG; + } else if (value == SKHPB_LOG_LEVEL_HEX) { + skhpb_debug_mask = SKHPB_LOG_ERR | SKHPB_LOG_INFO | SKHPB_LOG_DEBUG | SKHPB_LOG_HEX; + } + + return count; +} + +static ssize_t skhpb_sysfs_rsp_time_show(struct skhpb_lu *hpb, char *buf) +{ + return snprintf(buf, PAGE_SIZE, + "map_req_time: %s\n", (debug_map_req ? "Enable":"Disable")); +} + +static ssize_t skhpb_sysfs_rsp_time_store(struct skhpb_lu *hpb, + const char *buf, size_t count) +{ + unsigned long value; + + if (kstrtoul(buf, 0, &value)) + return -EINVAL; + + if (value > 1) + return count; + + debug_map_req = value; + return count; +} + +static struct skhpb_sysfs_entry skhpb_sysfs_entries[] = { + __ATTR(hpb_disable, 0644, + skhpb_sysfs_hpb_disable_show, + skhpb_sysfs_hpb_disable_store), + __ATTR(HPBVersion, 0444, skhpb_sysfs_version_show, NULL), + __ATTR(statistics, 0444, skhpb_sysfs_statistics_show, NULL), + __ATTR(active_count, 0444, skhpb_sysfs_active_count_show, NULL), + __ATTR(add_evict_count, 0444, skhpb_sysfs_add_evict_show, NULL), + __ATTR(count_reset, 0200, NULL, skhpb_sysfs_count_reset_store), + __ATTR(map_req_count, 0444, skhpb_sysfs_map_req_show, NULL), + __ATTR(get_info_from_region, 0200, NULL, + skhpb_sysfs_info_from_region_store), + __ATTR(get_info_from_lba, 0200, NULL, skhpb_sysfs_info_from_lba_store), + __ATTR(hpb_reset, 0200, NULL, skhpb_sysfs_hpb_reset_store), + __ATTR(debug_log, 0644, + skhpb_sysfs_debug_log_show, + skhpb_sysfs_debug_log_store), + __ATTR(response_time, 0644, + skhpb_sysfs_rsp_time_show, + skhpb_sysfs_rsp_time_store), + __ATTR_NULL +}; + +static ssize_t skhpb_attr_show(struct kobject *kobj, + struct attribute *attr, char *page) +{ + struct skhpb_sysfs_entry *entry; + struct skhpb_lu *hpb; + ssize_t error; + + entry = container_of(attr, + struct skhpb_sysfs_entry, attr); + hpb = container_of(kobj, struct skhpb_lu, kobj); + + if (!entry->show) + return -EIO; + + mutex_lock(&hpb->sysfs_lock); + error = entry->show(hpb, page); + mutex_unlock(&hpb->sysfs_lock); + return error; +} + +static ssize_t skhpb_attr_store(struct kobject *kobj, + struct attribute *attr, + const char *page, size_t length) +{ + struct skhpb_sysfs_entry *entry; + struct skhpb_lu *hpb; + ssize_t error; + + entry = container_of(attr, struct skhpb_sysfs_entry, attr); + hpb = container_of(kobj, struct skhpb_lu, kobj); + + if (!entry->store) + return -EIO; + + mutex_lock(&hpb->sysfs_lock); + error = entry->store(hpb, page, length); + mutex_unlock(&hpb->sysfs_lock); + return error; +} + +static const struct sysfs_ops skhpb_sysfs_ops = { + .show = skhpb_attr_show, + .store = skhpb_attr_store, +}; + +static struct kobj_type skhpb_ktype = { + .sysfs_ops = &skhpb_sysfs_ops, + .release = NULL, +}; + +static int skhpb_create_sysfs(struct ufs_hba *hba, + struct skhpb_lu *hpb) +{ + struct device *dev = hba->dev; + struct skhpb_sysfs_entry *entry; + int err; + + hpb->sysfs_entries = skhpb_sysfs_entries; + + skhpb_stat_init(hpb); + + kobject_init(&hpb->kobj, &skhpb_ktype); + mutex_init(&hpb->sysfs_lock); + + err = kobject_add(&hpb->kobj, kobject_get(&dev->kobj), + "ufshpb_lu%d", hpb->lun); + if (!err) { + for (entry = hpb->sysfs_entries; + entry->attr.name != NULL ; entry++) { + if (sysfs_create_file(&hpb->kobj, &entry->attr)) + break; + } + kobject_uevent(&hpb->kobj, KOBJ_ADD); + } + return err; +} diff --git a/drivers/scsi/ufs/ufshpb_skh.h b/drivers/scsi/ufs/ufshpb_skh.h new file mode 100644 index 000000000000..5359dda13a52 --- /dev/null +++ b/drivers/scsi/ufs/ufshpb_skh.h @@ -0,0 +1,518 @@ +/* + * Universal Flash Storage Host Performance Booster + * + * Original work Copyright (C) 2017-2018 Samsung Electronics Co., Ltd. + * Modified work Copyright (C) 2018, Google, Inc. + * Modified work Copyright (C) 2019 SK hynix + * + * Origianl work Authors: + * Yongmyung Lee + * Jinyoung Choi + * Modifier + * Kihyun Cho + * Sengman Shin + * Jinsu Lee + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * See the COPYING file in the top-level directory or visit + * + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * This program is provided "AS IS" and "WITH ALL FAULTS" and + * without warranty of any kind. You are solely responsible for + * determining the appropriateness of using and distributing + * the program and assume all risks associated with your exercise + * of rights with respect to the program, including but not limited + * to infringement of third party rights, the risks and costs of + * program errors, damage to or loss of data, programs or equipment, + * and unavailability or interruption of operations. Under no + * circumstances will the contributor of this Program be liable for + * any damages of any kind arising from your use or distribution of + * this program. + * + * The Linux Foundation chooses to take subject only to the GPLv2 + * license terms, and distributes only under these terms. + */ + +#ifndef _SKHPB_H_ +#define _SKHPB_H_ + +#include +#include +#include + +/* Version info*/ +#define SKHPB_DD_VER 0x010506 + +/* QUIRKs */ +/* Use READ16 instead of HPB_READ command, + * This is workaround solution to countmeasure QCT ICE issue. */ +#define SKHPB_QUIRK_USE_READ_16_FOR_ENCRYPTION (1 << 0) + +/* This quirk makes HPB driver always works as Devie Control Mode. + * To cover old Configuration descriptor format which interpret + * the bHPBControl field as RESERVED. */ +#define SKHPB_QUIRK_ALWAYS_DEVICE_CONTROL_MODE (1 << 1) + +/* Discard SubRegion activation hint information that has been processed, + * when the host enters RPM/SPM sleep. + * Must not be set the bit in ufs_quirks.h.*/ +#define SKHPB_QUIRK_PURGE_HINT_INFO_WHEN_SLEEP (1 << 20) + +/* Constant value*/ +#define SKHPB_SECTOR 512 +#define SKHPB_BLOCK 4096 +#define SKHPB_SECTORS_PER_BLOCK (SKHPB_BLOCK / SKHPB_SECTOR) +#define SKHPB_BITS_PER_DWORD 32 +#define SKHPB_MAX_ACTIVE_NUM 2 +#define SKHPB_MAX_INACTIVE_NUM 2 + +#define SKHPB_ENTRY_SIZE 0x08 +#define SKHPB_ENTREIS_PER_OS_PAGE (PAGE_SIZE / SKHPB_ENTRY_SIZE) + +/* Description */ +#define SKHPB_UFS_FEATURE_SUPPORT_HPB_BIT 0x80 + +#define SKHPB_QUERY_DESC_DEVICE_MAX_SIZE 0x43 +#define SKHPB_QUERY_DESC_CONFIGURAION_MAX_SIZE 0xE6 +#define SKHPB_QUERY_DESC_UNIT_MAX_SIZE 0x29 +#define SKHPB_QUERY_DESC_GEOMETRY_MAX_SIZE 0x4D + +/* Configuration for HPB */ +#define SKHPB_CONF_LU_ENABLE 0x00 +#define SKHPB_CONF_ACTIVE_REGIONS 0x10 +#define SKHPB_CONF_PINNED_START 0x12 +#define SKHPB_CONF_PINNED_NUM 0x14 + +/* Parameter Macros */ +#define SKHPB_DEV(h) ((h)->hba->dev) +#define SKHPB_MAX_BVEC_SIZE 128 + +/* Use for HPB activate */ +#define SKHPB_CONFIG_LEN 0xd0 + +#define SKHPB_READ_LARGE_CHUNK_SUPPORT +#define SKHPB_READ_LARGE_CHUNK_MAX_BLOCK_COUNT (128) //TRANSFER LENGTH: 8bit + +typedef u64 skhpb_t; + +enum skhpb_lu_set { + LU_DISABLE = 0x00, + LU_ENABLE = 0x01, + LU_HPB_ENABLE = 0x02, + LU_SET_MAX, +}; + +struct skhpb_config_desc { + unsigned char conf_dev_desc[16]; + unsigned char unit[UFS_UPIU_MAX_GENERAL_LUN][24]; +}; + +/* Response UPIU types */ +#define SKHPB_RSP_NONE 0x00 +#define SKHPB_RSP_REQ_REGION_UPDATE 0x01 +#define SKHPB_RSP_HPB_RESET 0x02 +#define SKHPB_PER_ACTIVE_INFO_BYTES 4 +#define SKHPB_PER_INACTIVE_INFO_BYTES 2 + +/* Vender defined OPCODE */ +#define SKHPB_READ 0xF8 +#define SKHPB_READ_BUFFER 0xF9 +#define SKHPB_WRITE_BUFFER 0xFA + +#define SKHPB_DEV_DATA_SEG_LEN 0x14 +#define SKHPB_DEV_SENSE_SEG_LEN 0x12 +#define SKHPB_DEV_DES_TYPE 0x80 +#define SKHPB_DEV_ADDITIONAL_LEN 0x10 + +/* BYTE SHIFT */ +#define SKHPB_ZERO_BYTE_SHIFT 0 +#define SKHPB_ONE_BYTE_SHIFT 8 +#define SKHPB_TWO_BYTE_SHIFT 16 +#define SKHPB_THREE_BYTE_SHIFT 24 + +#define SKHPB_SHIFT_BYTE_0(num) ((num) << SKHPB_ZERO_BYTE_SHIFT) +#define SKHPB_SHIFT_BYTE_1(num) ((num) << SKHPB_ONE_BYTE_SHIFT) + +#define SKHPB_GET_BYTE_0(num) (((num) >> SKHPB_ZERO_BYTE_SHIFT) & 0xff) +#define SKHPB_GET_BYTE_1(num) (((num) >> SKHPB_ONE_BYTE_SHIFT) & 0xff) +#define SKHPB_GET_BYTE_2(num) (((num) >> SKHPB_TWO_BYTE_SHIFT) & 0xff) +#define SKHPB_GET_BYTE_3(num) (((num) >> SKHPB_THREE_BYTE_SHIFT) & 0xff) + +#define REGION_UNIT_SIZE(bit_offset) (0x01 << (bit_offset)) + +enum SKHPB_STATE { + SKHPB_PRESENT = 1, + SKHPB_NOT_SUPPORTED = -1, + SKHPB_FAILED = -2, + SKHPB_NEED_INIT = 0, + SKHPB_RESET = -3, +}; + +enum SKHPB_BUFFER_MODE { + R_BUFFER = 0, + W_BUFFER = 1, +}; + +enum SKHPB_CMD { + SKHPB_CMD_READ = 0, + SKHPB_CMD_WRITE = 1, + SKHPB_CMD_DISCARD = 2, + SKHPB_CMD_OTHERS = 3, +}; + +enum SKHPB_REGION_STATE { + SKHPB_REGION_INACTIVE, + SKHPB_REGION_ACTIVE, +}; + +enum SKHPB_SUBREGION_STATE { + SKHPB_SUBREGION_UNUSED, + SKHPB_SUBREGION_DIRTY, + SKHPB_SUBREGION_CLEAN, + SKHPB_SUBREGION_ISSUED, +}; + +enum SKHPB_CONTROL_MODE { + HOST_CTRL_MODE = 0, + DEV_CTRL_MODE = 1, +}; + +enum SKHPB_RST_TIME { + SKHPB_MAP_RSP_DISABLE = 0, + SKHPB_MAP_RSP_ENABLE = 1, +}; + +struct skhpb_func_desc { + /*** Device Descriptor ***/ + /* 06h bNumberLU */ + int lu_cnt; + /* 10h wSpecVersion */ + u16 spec_ver; + /* 40h HPB Version */ + u16 hpb_ver; + /* 42h HPB control mode */ + u8 hpb_control_mode; + + /*** Geometry Descriptor ***/ + /* 48h bHPBRegionSize (UNIT: 512KB) */ + u8 hpb_region_size; + /* 49h bHPBNumberLU */ + u8 hpb_number_lu; + /* 4Ah bHPBSubRegionSize */ + u8 hpb_subregion_size; + /* 4B:4Ch wDeviceMaxActiveHPBRegions */ + u16 hpb_device_max_active_regions; +}; + +struct skhpb_lu_desc { + /*** Unit Descriptor ****/ + /* 03h bLUEnable */ + int lu_enable; + /* 06h lu queue depth info*/ + int lu_queue_depth; + /* 0Ah bLogicalBlockSize. default 0x0C = 4KB */ + int lu_logblk_size; + /* 0Bh qLogicalBlockCount. same as the read_capacity ret val. */ + u64 lu_logblk_cnt; + + /* 23h:24h wLUMaxActiveHPBRegions */ + u16 lu_max_active_hpb_regions; + /* 25h:26h wHPBPinnedRegionStartIdx */ + u16 hpb_pinned_region_startidx; + /* 27h:28h wNumHPBPinnedRegions */ + u16 lu_num_hpb_pinned_regions; + + + /* if 03h value is 02h, hpb_enable is set. */ + bool lu_hpb_enable; + + int lu_hpb_pinned_end_offset; +}; + +struct skhpb_rsp_active_list { + u16 region[SKHPB_MAX_ACTIVE_NUM]; + u16 subregion[SKHPB_MAX_ACTIVE_NUM]; +}; + +struct skhpb_rsp_inactive_list { + u16 region[SKHPB_MAX_INACTIVE_NUM]; +}; + +struct skhpb_rsp_update_entry { + unsigned int lpn; + skhpb_t ppn; +}; + +struct skhpb_rsp_info { + int type; + int active_cnt; + int inactive_cnt; + struct skhpb_rsp_active_list active_list; + struct skhpb_rsp_inactive_list inactive_list; + + __u64 RSP_start; + __u64 RSP_tasklet_enter; + + struct list_head list_rsp_info; +}; + +struct skhpb_rsp_field { + u8 sense_data_len[2]; + u8 desc_type; + u8 additional_len; + u8 hpb_type; + u8 lun; + u8 active_region_cnt; + u8 inactive_region_cnt; + u8 hpb_active_field[8]; + u8 hpb_inactive_field[4]; +}; + +struct skhpb_map_ctx { + struct page **m_page; + unsigned int *ppn_dirty; + + struct list_head list_table; +}; + +struct skhpb_subregion { + struct skhpb_map_ctx *mctx; + enum SKHPB_SUBREGION_STATE subregion_state; + int region; + int subregion; + bool last; + struct list_head list_subregion; +}; + +struct skhpb_region { + struct skhpb_subregion *subregion_tbl; + enum SKHPB_REGION_STATE region_state; + bool is_pinned; + int region; + int subregion_count; + /*below information is used by lru*/ + struct list_head list_region; + int hit_count; +}; + +struct skhpb_map_req { + struct skhpb_lu *hpb; + struct skhpb_map_ctx *mctx; + struct bio bio; + struct bio *pbio; + struct bio_vec bvec[SKHPB_MAX_BVEC_SIZE]; + void (*end_io)(struct request *rq, int err); + void *end_io_data; + int region; + int subregion; + int subregion_mem_size; + int lun; + int retry_cnt; + + /* for debug : RSP Profiling */ + __u64 RSP_start; // get the request from device + __u64 RSP_issue; // issue scsi cmd + __u64 RSP_end; // complete the request + + char sense[SCSI_SENSE_BUFFERSIZE]; + + struct list_head list_map_req; + int rwbuffer_flag; +}; + +enum SKHPB_SELECTION_TYPE { + TYPE_LRU = 1, + TYPE_LFU = 2, +}; + +struct skhpb_victim_select_info { + int selection_type; + struct list_head lru; + int max_lru_active_count; // supported hpb #region - pinned #region + atomic64_t active_count; +}; + +struct skhpb_lu { + struct skhpb_region *region_tbl; + struct skhpb_rsp_info *rsp_info; + struct skhpb_map_req *map_req; + + struct list_head lh_map_ctx; + struct list_head lh_subregion_req; + struct list_head lh_rsp_info; + + struct list_head lh_rsp_info_free; + struct list_head lh_map_req_free; + struct list_head lh_map_req_retry; + int debug_free_table; + + bool lu_hpb_enable; + + struct delayed_work skhpb_pinned_work; + struct delayed_work skhpb_map_req_retry_work; + struct work_struct skhpb_rsp_work; + struct bio_vec bvec[SKHPB_MAX_BVEC_SIZE]; + + int subregions_per_lu; + int regions_per_lu; + int subregion_mem_size; + int last_subregion_mem_size; + + /* for selecting victim */ + struct skhpb_victim_select_info lru_info; + + int hpb_ver; + int lu_max_active_regions; + + int entries_per_subregion; + int entries_per_subregion_shift; + int entries_per_subregion_mask; + + int entries_per_region_shift; + int entries_per_region_mask; + int subregions_per_region; + + int dwords_per_subregion; + unsigned long long subregion_unit_size; + bool identical_size; + +#define BITS_PER_PPN_DIRTY (BITS_PER_BYTE * sizeof(unsigned int)) + int ppn_dirties_per_subregion; + + int mpage_bytes; + int mpages_per_subregion; + + /* for debug constant variables */ + unsigned long long lu_num_blocks; + + int lun; + + struct ufs_hba *hba; + + spinlock_t hpb_lock; + spinlock_t rsp_list_lock; + spinlock_t map_list_lock; + + struct kobject kobj; + struct mutex sysfs_lock; + struct skhpb_sysfs_entry *sysfs_entries; + + bool hpb_control_mode; + + /* for debug */ + bool force_hpb_read_disable; + bool force_map_req_disable; + bool read_buf_debug; + atomic64_t hit; + atomic64_t size_miss; + atomic64_t region_miss; + atomic64_t subregion_miss; + atomic64_t entry_dirty_miss; + atomic64_t rb_noti_cnt; + atomic64_t rb_fail; + atomic64_t reset_noti_cnt; + atomic64_t w_map_req_cnt; +#if defined(SKHPB_READ_LARGE_CHUNK_SUPPORT) + atomic64_t lc_entry_dirty_miss; + atomic64_t lc_reg_subreg_miss; + atomic64_t lc_hit; +#endif + atomic64_t map_req_cnt; + atomic64_t region_add; + atomic64_t region_evict; + atomic64_t canceled_resp; + atomic64_t canceled_map_req; + atomic64_t alloc_map_req_cnt; +}; + +struct skhpb_sysfs_entry { + struct attribute attr; + ssize_t (*show)(struct skhpb_lu *hpb, char *buf); + ssize_t (*store)(struct skhpb_lu *hpb, const char *, size_t); +}; + +struct ufshcd_lrb; + +void ufshcd_init_hpb(struct ufs_hba *hba); +void skhpb_init_handler(struct work_struct *work); +void skhpb_prep_fn(struct ufs_hba *hba, struct ufshcd_lrb *lrbp); +void skhpb_rsp_upiu(struct ufs_hba *hba, struct ufshcd_lrb *lrbp); +void skhpb_suspend(struct ufs_hba *hba); +void skhpb_resume(struct ufs_hba *hba); +void skhpb_release(struct ufs_hba *hba, int state); +int skhpb_issue_req_dev_ctx(struct skhpb_lu *hpb, unsigned char *buf, + int buf_length); +int skhpb_control_validation(struct ufs_hba *hba, + struct skhpb_config_desc *config); + +extern u32 skhpb_debug_mask; +extern int debug_map_req; +enum SKHPB_LOG_LEVEL { + SKHPB_LOG_LEVEL_OFF = 0, + SKHPB_LOG_LEVEL_ERR = 1, + SKHPB_LOG_LEVEL_INFO = 2, + SKHPB_LOG_LEVEL_DEBUG = 3, + SKHPB_LOG_LEVEL_HEX = 4, +}; +enum SKHPB_LOG_MASK { + SKHPB_LOG_OFF = SKHPB_LOG_LEVEL_OFF, /* 0 */ + SKHPB_LOG_ERR = (1U << SKHPB_LOG_LEVEL_ERR), /* 2 */ + SKHPB_LOG_INFO = (1U << SKHPB_LOG_LEVEL_INFO), /* 4 */ + SKHPB_LOG_DEBUG = (1U << SKHPB_LOG_LEVEL_DEBUG), /* 8 */ + SKHPB_LOG_HEX = (1U << SKHPB_LOG_LEVEL_HEX), /* 16 */ +}; +#define SKHPB_DRIVER_E(fmt, args...) \ + do { \ + if(likely(skhpb_debug_mask & SKHPB_LOG_ERR)) \ + pr_err("[HPB E][%s:%d] " fmt, __func__, __LINE__, ##args); \ + } while (0) + +#define SKHPB_DRIVER_I(fmt, args...) \ + do { \ + if(unlikely(skhpb_debug_mask & SKHPB_LOG_INFO)) \ + pr_err("[HPB][%s:%d] " fmt, __func__, __LINE__, ##args); \ + } while (0) + +#define SKHPB_DRIVER_D(fmt, args...) \ + do { \ + if(unlikely(skhpb_debug_mask & SKHPB_LOG_DEBUG)) \ + printk(KERN_DEBUG "[HPB][%s:%d] " fmt, __func__, __LINE__, ##args); \ + } while (0) + +#define SKHPB_DRIVER_HEXDUMP(fmt, args...) \ + do { \ + if(unlikely(skhpb_debug_mask & SKHPB_LOG_HEX)) { \ + print_hex_dump(KERN_DEBUG, fmt, DUMP_PREFIX_ADDRESS, ##args); \ + } \ + } while (0) + +#define SKHPB_MAP_REQ_TIME(map_req, val, print) \ + do { \ + if(unlikely(debug_map_req)) { \ + val = ktime_to_us(ktime_get()); \ + if(print) { \ + SKHPB_DRIVER_I("SKHPB COMPL BUFFER %d - %d\n", \ + map_req->region, map_req->subregion); \ + SKHPB_DRIVER_I("start~issue = %lluus, issue~end = %lluus\n", \ + map_req->RSP_issue - map_req->RSP_start, \ + map_req->RSP_end - map_req->RSP_issue); \ + } \ + } \ + } while (0) + +#define SKHPB_RSP_TIME(val) \ + do { \ + if(unlikely(debug_map_req)) { \ + val = ktime_to_us(ktime_get()); \ + } \ + } while(0) + +#endif /* End of Header */ diff --git a/drivers/scsi/ufs/ufstw.c b/drivers/scsi/ufs/ufstw.c new file mode 100755 index 000000000000..b9853b118ae1 --- /dev/null +++ b/drivers/scsi/ufs/ufstw.c @@ -0,0 +1,900 @@ +/* + * Universal Flash Storage Turbo Write + * + * Copyright (C) 2017-2018 Samsung Electronics Co., Ltd. + * + * Authors: + * Yongmyung Lee + * Jinyoung Choi + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * See the COPYING file in the top-level directory or visit + * + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * This program is provided "AS IS" and "WITH ALL FAULTS" and + * without warranty of any kind. You are solely responsible for + * determining the appropriateness of using and distributing + * the program and assume all risks associated with your exercise + * of rights with respect to the program, including but not limited + * to infringement of third party rights, the risks and costs of + * program errors, damage to or loss of data, programs or equipment, + * and unavailability or interruption of operations. Under no + * circumstances will the contributor of this Program be liable for + * any damages of any kind arising from your use or distribution of + * this program. + * + * The Linux Foundation chooses to take subject only to the GPLv2 + * license terms, and distributes only under these terms. + */ + +#include "ufshcd.h" +#include "ufstw.h" + +static int ufstw_create_sysfs(struct ufsf_feature *ufsf, struct ufstw_lu *tw); + +inline int ufstw_get_state(struct ufsf_feature *ufsf) +{ + return atomic_read(&ufsf->tw_state); +} + +inline void ufstw_set_state(struct ufsf_feature *ufsf, int state) +{ + atomic_set(&ufsf->tw_state, state); +} + +static int ufstw_is_not_present(struct ufsf_feature *ufsf) +{ + enum UFSTW_STATE cur_state = ufstw_get_state(ufsf); + + if (cur_state != TW_PRESENT) { + INFO_MSG("tw_state != TW_PRESENT (%d)", cur_state); + return -ENODEV; + } + return 0; +} + +#define FLAG_IDN_NAME(idn) \ + (idn == QUERY_FLAG_IDN_TW_EN ? "tw_enable" : \ + idn == QUERY_FLAG_IDN_TW_BUF_FLUSH_EN ? "flush_enable" : \ + idn == QUERY_FLAG_IDN_TW_FLUSH_DURING_HIBERN ? \ + "flush_hibern" : "unknown") + +#define ATTR_IDN_NAME(idn) \ + (idn == QUERY_ATTR_IDN_TW_FLUSH_STATUS ? "flush_status" : \ + idn == QUERY_ATTR_IDN_TW_AVAIL_BUF_SIZE ? "avail_buffer_size" :\ + idn == QUERY_ATTR_IDN_TW_BUF_LIFETIME_EST ? "lifetime_est" : \ + idn == QUERY_ATTR_IDN_TW_CURR_BUF_SIZE ? "current_buf_size" : \ + "unknown") + +static int ufstw_read_lu_attr(struct ufstw_lu *tw, u8 idn, u32 *attr_val) +{ + struct ufs_hba *hba = tw->ufsf->hba; + int err = 0, lun; + u32 val; + + lun = (tw->lun == TW_LU_SHARED) ? 0 : tw->lun; + err = ufsf_query_attr_retry(hba, UPIU_QUERY_OPCODE_READ_ATTR, idn, + (u8)lun, &val); + if (err) { + ERR_MSG("read attr [0x%.2X](%s) failed. (%d)", idn, + ATTR_IDN_NAME(idn), err); + goto out; + } + + *attr_val = val; + + INFO_MSG("read attr LUN(%d) [0x%.2X](%s) success (%u)", + lun, idn, ATTR_IDN_NAME(idn), *attr_val); +out: + return err; +} + +static int ufstw_set_lu_flag(struct ufstw_lu *tw, u8 idn, bool *flag_res) +{ + struct ufs_hba *hba = tw->ufsf->hba; + int err = 0, lun; + + lun = (tw->lun == TW_LU_SHARED) ? 0 : tw->lun; + err = ufsf_query_flag_retry(hba, UPIU_QUERY_OPCODE_SET_FLAG, idn, + (u8)lun, NULL); + if (err) { + ERR_MSG("set flag [0x%.2X](%s) failed. (%d)", idn, + FLAG_IDN_NAME(idn), err); + goto out; + } + + *flag_res = true; + + INFO_MSG("set flag LUN(%d) [0x%.2X](%s) success. (%u)", + lun, idn, FLAG_IDN_NAME(idn), *flag_res); +out: + return err; +} + +static int ufstw_clear_lu_flag(struct ufstw_lu *tw, u8 idn, bool *flag_res) +{ + struct ufs_hba *hba = tw->ufsf->hba; + int err = 0, lun; + + lun = (tw->lun == TW_LU_SHARED) ? 0 : tw->lun; + err = ufsf_query_flag_retry(hba, UPIU_QUERY_OPCODE_CLEAR_FLAG, idn, + (u8)lun, NULL); + if (err) { + ERR_MSG("clear flag [0x%.2X](%s) failed. (%d)", idn, + FLAG_IDN_NAME(idn), err); + goto out; + } + + *flag_res = false; + + INFO_MSG("clear flag LUN(%d) [0x%.2X](%s) success. (%u)", + lun, idn, FLAG_IDN_NAME(idn), *flag_res); +out: + return err; +} + +static int ufstw_read_lu_flag(struct ufstw_lu *tw, u8 idn, bool *flag_res) +{ + struct ufs_hba *hba = tw->ufsf->hba; + int err = 0, lun; + bool val; + + lun = (tw->lun == TW_LU_SHARED) ? 0 : tw->lun; + err = ufsf_query_flag_retry(hba, UPIU_QUERY_OPCODE_READ_FLAG, idn, + (u8)lun, &val); + if (err) { + ERR_MSG("read flag [0x%.2X](%s) failed. (%d)", idn, + FLAG_IDN_NAME(idn), err); + goto out; + } + + *flag_res = val; + + INFO_MSG("read flag LUN(%d) [0x%.2X](%s) success. (%u)", + lun, idn, FLAG_IDN_NAME(idn), *flag_res); +out: + return err; +} + +static inline bool ufstw_is_write_lrbp(struct ufshcd_lrb *lrbp) +{ + if (lrbp->cmd->cmnd[0] == WRITE_10 || lrbp->cmd->cmnd[0] == WRITE_16) + return true; + + return false; +} + +static void ufstw_switch_disable_state(struct ufstw_lu *tw) +{ + int err = 0; + + WARN_MSG("dTurboWriteBUfferLifeTImeEst (0x%.2X)", tw->lifetime_est); + WARN_MSG("tw-mode will change to disable-mode"); + + mutex_lock(&tw->sysfs_lock); + ufstw_set_state(tw->ufsf, TW_FAILED); + mutex_unlock(&tw->sysfs_lock); + + if (tw->tw_enable) { + pm_runtime_get_sync(tw->ufsf->hba->dev); + err = ufstw_clear_lu_flag(tw, QUERY_FLAG_IDN_TW_EN, + &tw->tw_enable); + pm_runtime_put_sync(tw->ufsf->hba->dev); + if (err) + WARN_MSG("tw_enable flag clear failed"); + } +} + +static int ufstw_check_lifetime_not_guarantee(struct ufstw_lu *tw) +{ + bool disable_flag = false; + + if (tw->lifetime_est & MASK_UFSTW_LIFETIME_NOT_GUARANTEE) { + if (tw->lun == TW_LU_SHARED) + WARN_MSG("lun-shared lifetime_est[31] (1)"); + else + WARN_MSG("lun %d lifetime_est[31] (1)", + tw->lun); + + WARN_MSG("Device not guarantee the lifetime of TW Buffer"); +#if defined(CONFIG_UFSTW_IGNORE_GUARANTEE_BIT) + WARN_MSG("but we will ignore them for PoC"); +#else + disable_flag = true; +#endif + } + + if (disable_flag || + (tw->lifetime_est & ~MASK_UFSTW_LIFETIME_NOT_GUARANTEE) >= + UFSTW_MAX_LIFETIME_VALUE) { + ufstw_switch_disable_state(tw); + return -ENODEV; + } + + return 0; +} + +static void ufstw_lifetime_work_fn(struct work_struct *work) +{ + struct ufstw_lu *tw; + int ret; + + tw = container_of(work, struct ufstw_lu, tw_lifetime_work); + + if (ufstw_is_not_present(tw->ufsf)) + return; + + pm_runtime_get_sync(tw->ufsf->hba->dev); + ret = ufstw_read_lu_attr(tw, QUERY_ATTR_IDN_TW_BUF_LIFETIME_EST, + &tw->lifetime_est); + pm_runtime_put_sync(tw->ufsf->hba->dev); + if (ret) + return; + + ufstw_check_lifetime_not_guarantee(tw); +} + +void ufstw_prep_fn(struct ufsf_feature *ufsf, struct ufshcd_lrb *lrbp) +{ + struct ufstw_lu *tw; + + if (!lrbp || !ufsf_is_valid_lun(lrbp->lun)) + return; + + if (!ufstw_is_write_lrbp(lrbp)) + return; + + tw = ufsf->tw_lup[lrbp->lun]; + if (!tw) + return; + + if (!tw->tw_enable) + return; + + spin_lock_bh(&tw->lifetime_lock); + tw->stat_write_sec += blk_rq_sectors(lrbp->cmd->request); + + if (tw->stat_write_sec > UFSTW_LIFETIME_SECT) { + tw->stat_write_sec = 0; + spin_unlock_bh(&tw->lifetime_lock); + schedule_work(&tw->tw_lifetime_work); + return; + } + spin_unlock_bh(&tw->lifetime_lock); + + TMSG(tw->ufsf, lrbp->lun, "%s:%d tw_lifetime_work %u", + __func__, __LINE__, tw->stat_write_sec); +} + +static inline void ufstw_init_lu_jobs(struct ufstw_lu *tw) +{ + INIT_WORK(&tw->tw_lifetime_work, ufstw_lifetime_work_fn); +} + +static inline void ufstw_cancel_lu_jobs(struct ufstw_lu *tw) +{ + int ret; + + ret = cancel_work_sync(&tw->tw_lifetime_work); + INFO_MSG("cancel_work_sync(tw_lifetime_work) ufstw_lu[%d] (%d)", + tw->lun, ret); +} + +static inline int ufstw_version_check(struct ufstw_dev_info *tw_dev_info) +{ + INFO_MSG("Support TW Spec : Driver = %.4X, Device = %.4X", + UFSTW_VER, tw_dev_info->tw_ver); + + INFO_MSG("TW Driver Version : %.6X%s", UFSTW_DD_VER, + UFSTW_DD_VER_POST); + + if (tw_dev_info->tw_ver != UFSTW_VER) + return -ENODEV; + + return 0; +} + +void ufstw_get_dev_info(struct ufsf_feature *ufsf, u8 *desc_buf) +{ + struct ufstw_dev_info *tw_dev_info = &ufsf->tw_dev_info; + + if (LI_EN_32(&desc_buf[DEVICE_DESC_PARAM_EX_FEAT_SUP]) & + UFS_FEATURE_SUPPORT_TW_BIT) { + INFO_MSG("bUFSExFeaturesSupport: TW is set"); + } else { + ERR_MSG("bUFSExFeaturesSupport: TW not support"); + ufstw_set_state(ufsf, TW_FAILED); + return; + } + tw_dev_info->tw_buf_no_reduct = + desc_buf[DEVICE_DESC_PARAM_TW_RETURN_TO_USER]; + tw_dev_info->tw_buf_type = desc_buf[DEVICE_DESC_PARAM_TW_BUF_TYPE]; + tw_dev_info->tw_shared_buf_alloc_units = + LI_EN_32(&desc_buf[DEVICE_DESC_PARAM_TW_SHARED_BUF_ALLOC_UNITS]); + tw_dev_info->tw_ver = LI_EN_16(&desc_buf[DEVICE_DESC_PARAM_TW_VER]); + + if (ufstw_version_check(tw_dev_info)) { + ERR_MSG("TW Spec Version mismatch. TW disabled"); + ufstw_set_state(ufsf, TW_FAILED); + return; + } + + INFO_MSG("tw_dev [53] bTurboWriteBufferNoUserSpaceReductionEn (%u)", + tw_dev_info->tw_buf_no_reduct); + INFO_MSG("tw_dev [54] bTurboWriteBufferType (%u)", + tw_dev_info->tw_buf_type); + INFO_MSG("tw_dev [55] dNumSharedTUrboWriteBufferAllocUnits (%u)", + tw_dev_info->tw_shared_buf_alloc_units); + + if (tw_dev_info->tw_buf_type == TW_BUF_TYPE_SHARED && + tw_dev_info->tw_shared_buf_alloc_units == 0) { + ERR_MSG("TW use shared buffer. But alloc unit is (0)"); + ufstw_set_state(ufsf, TW_FAILED); + return; + } +} + +void ufstw_get_geo_info(struct ufsf_feature *ufsf, u8 *geo_buf) +{ + struct ufstw_dev_info *tw_dev_info = &ufsf->tw_dev_info; + + tw_dev_info->tw_number_lu = geo_buf[GEOMETRY_DESC_TW_NUMBER_LU]; + if (tw_dev_info->tw_number_lu == 0) { + ERR_MSG("Turbo Write is not supported"); + ufstw_set_state(ufsf, TW_FAILED); + return; + } + + INFO_MSG("tw_geo [4F:52] dTurboWriteBufferMaxNAllocUnits (%u)", + LI_EN_32(&geo_buf[GEOMETRY_DESC_TW_MAX_SIZE])); + INFO_MSG("tw_geo [53] bDeviceMaxTurboWriteLUs (%u)", + tw_dev_info->tw_number_lu); + INFO_MSG("tw_geo [54] bTurboWriteBufferCapAdjFac (%u)", + geo_buf[GEOMETRY_DESC_TW_CAP_ADJ_FAC]); + INFO_MSG("tw_geo [55] bSupportedTWBufferUserSpaceReductionTypes (%u)", + geo_buf[GEOMETRY_DESC_TW_SUPPORT_USER_REDUCTION_TYPES]); + INFO_MSG("tw_geo [56] bSupportedTurboWriteBufferTypes (%u)", + geo_buf[GEOMETRY_DESC_TW_SUPPORT_BUF_TYPE]); +} + +static void ufstw_alloc_shared_lu(struct ufsf_feature *ufsf) +{ + struct ufstw_lu *tw; + + tw = kzalloc(sizeof(struct ufstw_lu), GFP_KERNEL); + if (!tw) { + ERR_MSG("ufstw_lu[shared] memory alloc failed"); + return; + } + + tw->lun = TW_LU_SHARED; + tw->ufsf = ufsf; + ufsf->tw_lup[0] = tw; + + INFO_MSG("ufstw_lu[shared] is TurboWrite-Enabled"); +} + +static void ufstw_get_lu_info(struct ufsf_feature *ufsf, int lun, u8 *lu_buf) +{ + struct ufsf_lu_desc lu_desc; + struct ufstw_lu *tw; + + lu_desc.tw_lu_buf_size = + LI_EN_32(&lu_buf[UNIT_DESC_TW_LU_WRITE_BUFFER_ALLOC_UNIT]); + + ufsf->tw_lup[lun] = NULL; + + if (lu_desc.tw_lu_buf_size) { + ufsf->tw_lup[lun] = + kzalloc(sizeof(struct ufstw_lu), GFP_KERNEL); + if (!ufsf->tw_lup[lun]) { + ERR_MSG("ufstw_lu[%d] memory alloc faild", lun); + return; + } + + tw = ufsf->tw_lup[lun]; + tw->ufsf = ufsf; + tw->lun = lun; + INFO_MSG("ufstw_lu[%d] [29:2C] dLUNumTWBufferAllocUnits (%u)", + lun, lu_desc.tw_lu_buf_size); + INFO_MSG("ufstw_lu[%d] is TurboWrite-Enabled.", lun); + } else { + INFO_MSG("ufstw_lu[%d] [29:2C] dLUNumTWBufferAllocUnits (%u)", + lun, lu_desc.tw_lu_buf_size); + INFO_MSG("ufstw_lu[%d] is TurboWrite-disabled", lun); + } +} + +inline void ufstw_alloc_lu(struct ufsf_feature *ufsf, + int lun, u8 *lu_buf) +{ + if (ufsf->tw_dev_info.tw_buf_type == TW_BUF_TYPE_SHARED && + !ufsf->tw_lup[0]) + ufstw_alloc_shared_lu(ufsf); + else if (ufsf->tw_dev_info.tw_buf_type == TW_BUF_TYPE_LU) + ufstw_get_lu_info(ufsf, lun, lu_buf); +} + +static inline void ufstw_print_lu_flag_attr(struct ufstw_lu *tw) +{ + char lun_str[20] = { 0 }; + + if (tw->lun == TW_LU_SHARED) + snprintf(lun_str, 7, "shared"); + else + snprintf(lun_str, 2, "%d", tw->lun); + + INFO_MSG("tw_flag ufstw_lu[%s] IDN (0x%.2X) tw_enable (%d)", + lun_str, QUERY_FLAG_IDN_TW_EN, tw->tw_enable); + INFO_MSG("tw_flag ufstw_lu[%s] IDN (0x%.2X) flush_enable (%d)", + lun_str, QUERY_FLAG_IDN_TW_BUF_FLUSH_EN, + tw->flush_enable); + INFO_MSG("tw_flag ufstw_lu[%s] IDN (0x%.2X) flush_hibern (%d)", + lun_str, QUERY_FLAG_IDN_TW_FLUSH_DURING_HIBERN, + tw->flush_during_hibern_enter); + + INFO_MSG("tw_attr ufstw_lu[%s] IDN (0x%.2X) flush_status (%u)", + lun_str, QUERY_ATTR_IDN_TW_FLUSH_STATUS, tw->flush_status); + INFO_MSG("tw_attr ufstw_lu[%s] IDN (0x%.2X) buffer_size (%u)", + lun_str, QUERY_ATTR_IDN_TW_AVAIL_BUF_SIZE, + tw->available_buffer_size); + INFO_MSG("tw_attr ufstw_lu[%s] IDN (0x%.2X) buffer_lifetime (0x%.2X)", + lun_str, QUERY_ATTR_IDN_TW_BUF_LIFETIME_EST, + tw->lifetime_est); +} + +static inline void ufstw_lu_update(struct ufstw_lu *tw) +{ + /* Flag */ + pm_runtime_get_sync(tw->ufsf->hba->dev); + if (ufstw_read_lu_flag(tw, QUERY_FLAG_IDN_TW_EN, &tw->tw_enable)) + goto error_put; + + if (ufstw_read_lu_flag(tw, QUERY_FLAG_IDN_TW_BUF_FLUSH_EN, + &tw->flush_enable)) + goto error_put; + + if (ufstw_read_lu_flag(tw, QUERY_FLAG_IDN_TW_FLUSH_DURING_HIBERN, + &tw->flush_during_hibern_enter)) + goto error_put; + + /* Attribute */ + if (ufstw_read_lu_attr(tw, QUERY_ATTR_IDN_TW_FLUSH_STATUS, + &tw->flush_status)) + goto error_put; + + if (ufstw_read_lu_attr(tw, QUERY_ATTR_IDN_TW_AVAIL_BUF_SIZE, + &tw->available_buffer_size)) + goto error_put; + + ufstw_read_lu_attr(tw, QUERY_ATTR_IDN_TW_BUF_LIFETIME_EST, + &tw->lifetime_est); +error_put: + pm_runtime_put_sync(tw->ufsf->hba->dev); +} + +static int ufstw_lu_init(struct ufsf_feature *ufsf, int lun) +{ + struct ufstw_lu *tw; + int ret = 0; + + if (lun == TW_LU_SHARED) + tw = ufsf->tw_lup[0]; + else + tw = ufsf->tw_lup[lun]; + + tw->ufsf = ufsf; + spin_lock_init(&tw->lifetime_lock); + + ufstw_lu_update(tw); + + ret = ufstw_check_lifetime_not_guarantee(tw); + if (ret) + goto err_out; + + ufstw_print_lu_flag_attr(tw); + + tw->stat_write_sec = 0; + + ufstw_init_lu_jobs(tw); + +#if defined(CONFIG_UFSTW_BOOT_ENABLED) + pm_runtime_get_sync(ufsf->hba->dev); + ufstw_set_lu_flag(tw, QUERY_FLAG_IDN_TW_EN, &tw->tw_enable); + ufstw_set_lu_flag(tw, QUERY_FLAG_IDN_TW_FLUSH_DURING_HIBERN, + &tw->flush_during_hibern_enter); + pm_runtime_put_sync(ufsf->hba->dev); +#endif + ret = ufstw_create_sysfs(ufsf, tw); + if (ret) + ERR_MSG("create sysfs failed"); +err_out: + return ret; +} + +void ufstw_init(struct ufsf_feature *ufsf) +{ + int lun, ret = 0; + unsigned int tw_enabled_lun = 0; + + INFO_MSG("init start.. tw_state (%d)", ufstw_get_state(ufsf)); + + if (ufsf->tw_dev_info.tw_buf_type == TW_BUF_TYPE_SHARED) { + if (!ufsf->tw_lup[0]) { + ERR_MSG("tw_lup memory allocation failed"); + goto out; + } + BUG_ON(ufsf->tw_lup[0]->lun != TW_LU_SHARED); + + ret = ufstw_lu_init(ufsf, TW_LU_SHARED); + if (ret) + goto out_free_mem; + + INFO_MSG("ufstw_lu[shared] working"); + tw_enabled_lun++; + } else { + seq_scan_lu(lun) { + if (!ufsf->tw_lup[lun]) + continue; + + ret = ufstw_lu_init(ufsf, lun); + if (ret) + goto out_free_mem; + + INFO_MSG("ufstw_lu[%d] working", lun); + tw_enabled_lun++; + } + + if (tw_enabled_lun > ufsf->tw_dev_info.tw_number_lu) { + ERR_MSG("lu count mismatched"); + goto out_free_mem; + } + } + + if (tw_enabled_lun == 0) { + ERR_MSG("tw_enabled_lun count zero"); + goto out_free_mem; + } + + ufstw_set_state(ufsf, TW_PRESENT); + return; +out_free_mem: + seq_scan_lu(lun) { + kfree(ufsf->tw_lup[lun]); + ufsf->tw_lup[lun] = NULL; + } +out: + ERR_MSG("Turbo write initialization failed"); + + ufstw_set_state(ufsf, TW_FAILED); +} + +static inline void ufstw_remove_sysfs(struct ufstw_lu *tw) +{ + int ret; + + ret = kobject_uevent(&tw->kobj, KOBJ_REMOVE); + INFO_MSG("kobject removed (%d)", ret); + kobject_del(&tw->kobj); +} + +void ufstw_remove(struct ufsf_feature *ufsf) +{ + struct ufstw_lu *tw; + int lun; + + dump_stack(); + INFO_MSG("start release"); + + ufstw_set_state(ufsf, TW_FAILED); + + if (ufsf->tw_dev_info.tw_buf_type == TW_BUF_TYPE_SHARED) { + tw = ufsf->tw_lup[0]; + INFO_MSG("ufstw_lu[shared] %p", tw); + ufsf->tw_lup[0] = NULL; + ufstw_cancel_lu_jobs(tw); + ufstw_remove_sysfs(tw); + kfree(tw); + } else { + seq_scan_lu(lun) { + tw = ufsf->tw_lup[lun]; + INFO_MSG("ufstw_lu[%d] %p", lun, tw); + + if (!tw) + continue; + ufsf->tw_lup[lun] = NULL; + ufstw_cancel_lu_jobs(tw); + ufstw_remove_sysfs(tw); + kfree(tw); + } + } + + INFO_MSG("end release"); +} + +static void ufstw_reset_query_handling(struct ufstw_lu *tw) +{ + int ret; + + pm_runtime_get_sync(tw->ufsf->hba->dev); + if (tw->tw_enable) { + ret = ufstw_set_lu_flag(tw, QUERY_FLAG_IDN_TW_EN, + &tw->tw_enable); + if (ret) + tw->tw_enable = false; + } + + if (tw->flush_enable) { + ret = ufstw_set_lu_flag(tw, QUERY_FLAG_IDN_TW_BUF_FLUSH_EN, + &tw->flush_enable); + if (ret) + tw->flush_enable = false; + } + + if (tw->flush_during_hibern_enter) { + ret = ufstw_set_lu_flag(tw, + QUERY_FLAG_IDN_TW_FLUSH_DURING_HIBERN, + &tw->flush_during_hibern_enter); + if (ret) + tw->flush_during_hibern_enter = false; + } + + pm_runtime_put_sync(tw->ufsf->hba->dev); +} + +void ufstw_reset_host(struct ufsf_feature *ufsf) +{ + struct ufstw_lu *tw; + int lun; + + if (ufstw_is_not_present(ufsf)) + return; + + ufstw_set_state(ufsf, TW_RESET); + if (ufsf->tw_dev_info.tw_buf_type == TW_BUF_TYPE_SHARED) { + tw = ufsf->tw_lup[0]; + + INFO_MSG("ufstw_lu[shared] cancel jobs"); + ufstw_cancel_lu_jobs(tw); + } else { + seq_scan_lu(lun) { + tw = ufsf->tw_lup[lun]; + if (!tw) + continue; + + INFO_MSG("ufstw_lu[%d] cancel jobs", lun); + ufstw_cancel_lu_jobs(tw); + } + } +} + +void ufstw_reset(struct ufsf_feature *ufsf, bool resume) +{ + struct ufstw_lu *tw; + int lun; + + INFO_MSG("ufstw reset start. reason: %s", + resume ? "resume" : "reset"); + if (ufstw_get_state(ufsf) != TW_RESET) { + ERR_MSG("tw_state error (%d)", ufstw_get_state(ufsf)); + return; + } + + ufstw_set_state(ufsf, TW_PRESENT); + + if (ufsf->tw_dev_info.tw_buf_type == TW_BUF_TYPE_SHARED) { + tw = ufsf->tw_lup[0]; + + INFO_MSG("ufstw_lu[shared] reset"); + ufstw_reset_query_handling(tw); + } else { + seq_scan_lu(lun) { + tw = ufsf->tw_lup[lun]; + if (!tw) + continue; + + INFO_MSG("ufstw_lu[%d] reset", lun); + ufstw_reset_query_handling(tw); + } + } + + INFO_MSG("ufstw reset finish"); +} + +#define ufstw_sysfs_attr_show_func(_query, _name, _IDN, hex) \ +static ssize_t ufstw_sysfs_show_##_name(struct ufstw_lu *tw, char *buf) \ +{ \ + int ret; \ + \ + if (ufstw_is_not_present(tw->ufsf)) \ + return -ENODEV; \ + \ + pm_runtime_get_sync(tw->ufsf->hba->dev); \ + ret = ufstw_read_lu_##_query(tw, _IDN, &tw->_name); \ + pm_runtime_put_sync(tw->ufsf->hba->dev); \ + if (ret) \ + return -ENODEV; \ + \ + INFO_MSG("read "#_query" "#_name" %u (0x%X)", \ + tw->_name, tw->_name); \ + if (hex) \ + return snprintf(buf, PAGE_SIZE, "0x%.2X\n", tw->_name); \ + return snprintf(buf, PAGE_SIZE, "%u\n", tw->_name); \ +} + +#define ufstw_sysfs_attr_store_func(_name, _IDN) \ +static ssize_t ufstw_sysfs_store_##_name(struct ufstw_lu *tw, \ + const char *buf, \ + size_t count) \ +{ \ + unsigned long val; \ + ssize_t ret = count; \ + \ + if (kstrtoul(buf, 0, &val)) \ + return -EINVAL; \ + \ + if (!(val == 0 || val == 1)) \ + return -EINVAL; \ + \ + INFO_MSG("val %lu", val); \ + if (ufstw_is_not_present(tw->ufsf)) \ + return -ENODEV; \ + \ + pm_runtime_get_sync(tw->ufsf->hba->dev); \ + if (val) { \ + if (ufstw_set_lu_flag(tw, _IDN, &tw->_name)) \ + ret = -ENODEV; \ + } else { \ + if (ufstw_clear_lu_flag(tw, _IDN, &tw->_name)) \ + ret = -ENODEV; \ + } \ + pm_runtime_put_sync(tw->ufsf->hba->dev); \ + \ + INFO_MSG(#_name " query success"); \ + return ret; \ +} + +ufstw_sysfs_attr_show_func(flag, tw_enable, QUERY_FLAG_IDN_TW_EN, 0); +ufstw_sysfs_attr_store_func(tw_enable, QUERY_FLAG_IDN_TW_EN); +ufstw_sysfs_attr_show_func(flag, flush_enable, + QUERY_FLAG_IDN_TW_BUF_FLUSH_EN, 0); +ufstw_sysfs_attr_store_func(flush_enable, QUERY_FLAG_IDN_TW_BUF_FLUSH_EN); +ufstw_sysfs_attr_show_func(flag, flush_during_hibern_enter, + QUERY_FLAG_IDN_TW_FLUSH_DURING_HIBERN, 0); +ufstw_sysfs_attr_store_func(flush_during_hibern_enter, + QUERY_FLAG_IDN_TW_FLUSH_DURING_HIBERN); + +ufstw_sysfs_attr_show_func(attr, flush_status, + QUERY_ATTR_IDN_TW_FLUSH_STATUS, 0); +ufstw_sysfs_attr_show_func(attr, available_buffer_size, + QUERY_ATTR_IDN_TW_AVAIL_BUF_SIZE, 0); +ufstw_sysfs_attr_show_func(attr, lifetime_est, + QUERY_ATTR_IDN_TW_BUF_LIFETIME_EST, 1); +ufstw_sysfs_attr_show_func(attr, curr_buffer_size, + QUERY_ATTR_IDN_TW_CURR_BUF_SIZE, 0); + +#define ufstw_sysfs_attr_ro(_name) __ATTR(_name, 0444,\ + ufstw_sysfs_show_##_name, NULL) +#define ufstw_sysfs_attr_rw(_name) __ATTR(_name, 0644,\ + ufstw_sysfs_show_##_name, \ + ufstw_sysfs_store_##_name) + +static struct ufstw_sysfs_entry ufstw_sysfs_entries[] = { + /* Flag */ + ufstw_sysfs_attr_rw(tw_enable), + ufstw_sysfs_attr_rw(flush_enable), + ufstw_sysfs_attr_rw(flush_during_hibern_enter), + /* Attribute */ + ufstw_sysfs_attr_ro(flush_status), + ufstw_sysfs_attr_ro(available_buffer_size), + ufstw_sysfs_attr_ro(lifetime_est), + ufstw_sysfs_attr_ro(curr_buffer_size), + __ATTR_NULL +}; + +static ssize_t ufstw_attr_show(struct kobject *kobj, struct attribute *attr, + char *page) +{ + struct ufstw_sysfs_entry *entry; + struct ufstw_lu *tw; + ssize_t error; + + entry = container_of(attr, struct ufstw_sysfs_entry, attr); + if (!entry->show) + return -EIO; + + tw = container_of(kobj, struct ufstw_lu, kobj); + + mutex_lock(&tw->sysfs_lock); + error = entry->show(tw, page); + mutex_unlock(&tw->sysfs_lock); + return error; +} + +static ssize_t ufstw_attr_store(struct kobject *kobj, struct attribute *attr, + const char *page, size_t length) +{ + struct ufstw_sysfs_entry *entry; + struct ufstw_lu *tw; + ssize_t error; + + entry = container_of(attr, struct ufstw_sysfs_entry, attr); + if (!entry->store) + return -EIO; + + tw = container_of(kobj, struct ufstw_lu, kobj); + + mutex_lock(&tw->sysfs_lock); + error = entry->store(tw, page, length); + mutex_unlock(&tw->sysfs_lock); + return error; +} + +static const struct sysfs_ops ufstw_sysfs_ops = { + .show = ufstw_attr_show, + .store = ufstw_attr_store, +}; + +static struct kobj_type ufstw_ktype = { + .sysfs_ops = &ufstw_sysfs_ops, + .release = NULL, +}; + +static int ufstw_create_sysfs(struct ufsf_feature *ufsf, struct ufstw_lu *tw) +{ + struct device *dev = ufsf->hba->dev; + struct ufstw_sysfs_entry *entry; + int err; + char lun_str[20] = { 0 }; + + tw->sysfs_entries = ufstw_sysfs_entries; + + kobject_init(&tw->kobj, &ufstw_ktype); + mutex_init(&tw->sysfs_lock); + + if (tw->lun == TW_LU_SHARED) { + snprintf(lun_str, 6, "ufstw"); + INFO_MSG("ufstw creates sysfs ufstw-shared"); + } else { + snprintf(lun_str, 10, "ufstw_lu%d", tw->lun); + INFO_MSG("ufstw creates sysfs ufstw_lu%d", tw->lun); + } + + err = kobject_add(&tw->kobj, kobject_get(&dev->kobj), lun_str); + if (!err) { + for (entry = tw->sysfs_entries; entry->attr.name != NULL; + entry++) { + if (tw->lun == TW_LU_SHARED) + INFO_MSG("ufstw-shared sysfs attr creates: %s", + entry->attr.name); + else + INFO_MSG("ufstw_lu(%d) sysfs attr creates: %s", + tw->lun, entry->attr.name); + + err = sysfs_create_file(&tw->kobj, &entry->attr); + if (err) { + ERR_MSG("create entry(%s) failed", + entry->attr.name); + goto kobj_del; + } + } + kobject_uevent(&tw->kobj, KOBJ_ADD); + } else { + ERR_MSG("kobject_add failed"); + } + + return err; +kobj_del: + err = kobject_uevent(&tw->kobj, KOBJ_REMOVE); + INFO_MSG("kobject removed (%d)", err); + kobject_del(&tw->kobj); + return -EINVAL; +} diff --git a/drivers/scsi/ufs/ufstw.h b/drivers/scsi/ufs/ufstw.h new file mode 100755 index 000000000000..2d3bfc8c7d4a --- /dev/null +++ b/drivers/scsi/ufs/ufstw.h @@ -0,0 +1,126 @@ +/* + * Universal Flash Storage tw Write + * + * Copyright (C) 2017-2018 Samsung Electronics Co., Ltd. + * + * Authors: + * Yongmyung Lee + * Jinyoung Choi + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * See the COPYING file in the top-level directory or visit + * + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * This program is provided "AS IS" and "WITH ALL FAULTS" and + * without warranty of any kind. You are solely responsible for + * determining the appropriateness of using and distributing + * the program and assume all risks associated with your exercise + * of rights with respect to the program, including but not limited + * to infringement of third party rights, the risks and costs of + * program errors, damage to or loss of data, programs or equipment, + * and unavailability or interruption of operations. Under no + * circumstances will the contributor of this Program be liable for + * any damages of any kind arising from your use or distribution of + * this program. + * + * The Linux Foundation chooses to take subject only to the GPLv2 + * license terms, and distributes only under these terms. + */ + +#ifndef _UFSTW_H_ +#define _UFSTW_H_ + +#include +#include +#include +#include +#include + +#include "../../../block/blk.h" + +#define UFSTW_VER 0x0110 +#define UFSTW_DD_VER 0x010300 +#define UFSTW_DD_VER_POST UFSFEATURE_DD_VER_POST + +#define UFSTW_LIFETIME_SECT 2097152 /* 1GB */ +#define UFSTW_MAX_LIFETIME_VALUE 0x0B +#define MASK_UFSTW_LIFETIME_NOT_GUARANTEE 0x80 +#define UFS_FEATURE_SUPPORT_TW_BIT 0x100 + +#define TW_LU_SHARED -1 + +enum UFSTW_STATE { + TW_NEED_INIT = 0, + TW_PRESENT = 1, + TW_RESET = -3, + TW_FAILED = -4 +}; + +enum { + TW_BUF_TYPE_LU = 0, + TW_BUF_TYPE_SHARED, +}; + +struct ufstw_dev_info { + /* from Device Descriptor */ + u16 tw_ver; + u32 tw_shared_buf_alloc_units; + u8 tw_buf_no_reduct; + u8 tw_buf_type; + + /* from Geometry Descriptor */ + u8 tw_number_lu; +}; + +struct ufstw_lu { + struct ufsf_feature *ufsf; + + int lun; + + bool tw_enable; + bool flush_enable; + bool flush_during_hibern_enter; + + unsigned int flush_status; + unsigned int available_buffer_size; + unsigned int curr_buffer_size; + + unsigned int lifetime_est; + spinlock_t lifetime_lock; + u32 stat_write_sec; + struct work_struct tw_lifetime_work; + + /* for sysfs */ + struct kobject kobj; + struct mutex sysfs_lock; + struct ufstw_sysfs_entry *sysfs_entries; +}; + +struct ufstw_sysfs_entry { + struct attribute attr; + ssize_t (*show)(struct ufstw_lu *tw, char *buf); + ssize_t (*store)(struct ufstw_lu *tw, const char *buf, size_t count); +}; + +struct ufshcd_lrb; + +int ufstw_get_state(struct ufsf_feature *ufsf); +void ufstw_set_state(struct ufsf_feature *ufsf, int state); +void ufstw_get_dev_info(struct ufsf_feature *ufsf, u8 *desc_buf); +void ufstw_get_geo_info(struct ufsf_feature *ufsf, u8 *geo_buf); +void ufstw_alloc_lu(struct ufsf_feature *ufsf, int lun, u8 *lu_buf); + +void ufstw_prep_fn(struct ufsf_feature *ufsf, struct ufshcd_lrb *lrbp); +void ufstw_init(struct ufsf_feature *ufsf); +void ufstw_remove(struct ufsf_feature *ufsf); +void ufstw_reset_host(struct ufsf_feature *ufsf); +void ufstw_reset(struct ufsf_feature *ufsf, bool resume); +#endif /* End of Header */ diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h index dcb0763fb219..b53ecf55ceb9 100644 --- a/include/scsi/scsi_cmnd.h +++ b/include/scsi/scsi_cmnd.h @@ -147,6 +147,9 @@ struct scsi_cmnd { ANDROID_KABI_RESERVE(2); ANDROID_KABI_RESERVE(3); ANDROID_KABI_RESERVE(4); +#if defined(CONFIG_UFSFEATURE) && defined(CONFIG_UFSHPB) + u8 requeue_cnt; +#endif }; /* From 3a2623539ed1c749fc37da8992c9826b85cdf323 Mon Sep 17 00:00:00 2001 From: fuxm1 Date: Tue, 11 May 2021 09:01:47 +0800 Subject: [PATCH 345/698] defconfig: enable hpb/tw for corfup and cypfg Remark: enable hpb and tw feature for corfu-5g and cypfg on mot4350 family. disable for ibiza and denver, further project if reuse currently baseline need define it accordingly. Change-Id: I96b86b584521a88ba241b678f89332705e88e741 Signed-off-by: fuxm1 Reviewed-on: https://gerrit.mot.com/1944778 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- .../arm64/configs/vendor/ext_config/moto-holi-denver.config | 6 +++++- arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config | 4 ++++ arch/arm64/configs/vendor/holi_QGKI.config | 4 ++++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-denver.config b/arch/arm64/configs/vendor/ext_config/moto-holi-denver.config index a843ecbe8583..a3ac4fce713b 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-denver.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-denver.config @@ -19,4 +19,8 @@ CONFIG_ZRAM_WRITEBACK=y # CONFIG_THERMAL_STATISTICS is not set # CONFIG_TOUCHSCREEN_SYNAPTICS_TCM is not set # CONFIG_TOUCHSCREEN_SYNAPTICS_DSX is not set -# CONFIG_TOUCHSCREEN_FTS is not set \ No newline at end of file +# CONFIG_TOUCHSCREEN_FTS is not set +# CONFIG_UFSFEATURE is not set +# CONFIG_UFSHPB is not set +# CONFIG_UFSTW is not set +# CONFIG_SCSI_SKHPB is not set diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config b/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config index 4ba81a1528f0..62cecda746ec 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config @@ -18,3 +18,7 @@ CONFIG_IBIZA_DTB=y CONFIG_FS_EPOLL_WAKEUP_DEBUG=y CONFIG_ZRAM_WRITEBACK=y # CONFIG_THERMAL_STATISTICS is not set +# CONFIG_UFSFEATURE is not set +# CONFIG_UFSHPB is not set +# CONFIG_UFSTW is not set +# CONFIG_SCSI_SKHPB is not set diff --git a/arch/arm64/configs/vendor/holi_QGKI.config b/arch/arm64/configs/vendor/holi_QGKI.config index cdb1a8bf15ef..eeefbf2a14fa 100644 --- a/arch/arm64/configs/vendor/holi_QGKI.config +++ b/arch/arm64/configs/vendor/holi_QGKI.config @@ -199,3 +199,7 @@ CONFIG_CRYPTO_SHA1_ARM64_CE=y CONFIG_QTI_CX_IPEAK_COOLING_DEVICE=y CONFIG_TLB_CONF_HANDLER=y CONFIG_QTI_DEVFREQ_VDD_COOLING_DEVICE=y +CONFIG_UFSFEATURE=y +CONFIG_UFSHPB=y +CONFIG_UFSTW=y +CONFIG_SCSI_SKHPB=y From e6157fa89082ad067df4096d04acf43494074c23 Mon Sep 17 00:00:00 2001 From: fuxm1 Date: Tue, 4 May 2021 23:39:32 +0800 Subject: [PATCH 346/698] hpb: disable HPB feature for 4G ram Remark: parse share memory get ram size to distinguish if is 4G ram if yes, disable HPB feature(Due to 4G ram size is too senstive for camera). Change-Id: Icb8575dec742c248586e11bf4ebcc0d2bbac0d9e Signed-off-by: fuxm1 Reviewed-on: https://gerrit.mot.com/1939239 SME-Granted: SME Approvals Granted Reviewed-by: Huosheng Liao SLTApproved: Slta Waiver Tested-by: Jira Key Submit-Approved: Jira Key --- drivers/scsi/ufs/ufsfeature.c | 44 +++++++------ drivers/scsi/ufs/ufshcd.c | 118 +++++++++++++++++++++++++++++++++- drivers/scsi/ufs/ufshcd.h | 5 +- 3 files changed, 146 insertions(+), 21 deletions(-) diff --git a/drivers/scsi/ufs/ufsfeature.c b/drivers/scsi/ufs/ufsfeature.c index 7f65f74efb04..3cb57d2d412a 100755 --- a/drivers/scsi/ufs/ufsfeature.c +++ b/drivers/scsi/ufs/ufsfeature.c @@ -212,7 +212,8 @@ static int ufsf_read_dev_desc(struct ufsf_feature *ufsf, u8 selector) #if defined(CONFIG_UFSHPB) - ufshpb_get_dev_info(ufsf, desc_buf); + if (IS_RAM_SIZE_GREATER_THAN_4G(ram_size)) + ufshpb_get_dev_info(ufsf, desc_buf); #endif #if defined(CONFIG_UFSTW) ufstw_get_dev_info(ufsf, desc_buf); @@ -231,7 +232,7 @@ static int ufsf_read_geo_desc(struct ufsf_feature *ufsf, u8 selector) return ret; #if defined(CONFIG_UFSHPB) - if (ufshpb_get_state(ufsf) == HPB_NEED_INIT) + if ((ufshpb_get_state(ufsf) == HPB_NEED_INIT) && IS_RAM_SIZE_GREATER_THAN_4G(ram_size)) ufshpb_get_geo_info(ufsf, geo_buf); #endif @@ -259,7 +260,7 @@ static void ufsf_read_unit_desc(struct ufsf_feature *ufsf, int lun, u8 selector) return; #if defined(CONFIG_UFSHPB) - if (ufshpb_get_state(ufsf) == HPB_NEED_INIT) + if ((ufshpb_get_state(ufsf) == HPB_NEED_INIT) && IS_RAM_SIZE_GREATER_THAN_4G(ram_size)) ufshpb_get_lu_info(ufsf, lun, unit_buf); #endif @@ -531,7 +532,7 @@ inline void ufsf_slave_configure(struct ufsf_feature *ufsf, ufsf->slave_conf_cnt, ufsf->num_lu); #if defined(CONFIG_UFSHPB) - if (ufsf->num_lu == ufsf->slave_conf_cnt) { + if (ufsf->num_lu == ufsf->slave_conf_cnt && IS_RAM_SIZE_GREATER_THAN_4G(ram_size)) { if (ufshpb_get_state(ufsf) == HPB_NEED_INIT) { INFO_MSG("wakeup ufshpb_init_handler"); wake_up(&ufsf->hpb_wait); @@ -546,7 +547,7 @@ inline void ufsf_prep_fn(struct ufsf_feature *ufsf, { #if defined(CONFIG_UFSHPB) if (ufshpb_get_state(ufsf) == HPB_PRESENT && - ufsf->issue_ioctl == false) + ufsf->issue_ioctl == false && IS_RAM_SIZE_GREATER_THAN_4G(ram_size)) ufshpb_prep_fn(ufsf, lrbp); #endif @@ -569,10 +570,12 @@ inline void ufsf_reset_lu(struct ufsf_feature *ufsf) inline void ufsf_reset_host(struct ufsf_feature *ufsf) { #if defined(CONFIG_UFSHPB) - INFO_MSG("run reset_host.. hpb_state(%d) -> HPB_RESET", - ufshpb_get_state(ufsf)); - if (ufshpb_get_state(ufsf) == HPB_PRESENT) - ufshpb_reset_host(ufsf); + if (IS_RAM_SIZE_GREATER_THAN_4G(ram_size)) { + INFO_MSG("run reset_host.. hpb_state(%d) -> HPB_RESET", + ufshpb_get_state(ufsf)); + if (ufshpb_get_state(ufsf) == HPB_PRESENT) + ufshpb_reset_host(ufsf); + } #endif #if defined(CONFIG_UFSTW) @@ -586,7 +589,7 @@ inline void ufsf_reset_host(struct ufsf_feature *ufsf) inline void ufsf_init(struct ufsf_feature *ufsf) { #if defined(CONFIG_UFSHPB) - if (ufshpb_get_state(ufsf) == HPB_NEED_INIT) { + if ((ufshpb_get_state(ufsf) == HPB_NEED_INIT) && IS_RAM_SIZE_GREATER_THAN_4G(ram_size)) { INFO_MSG("init start.. hpb_state (%d)", HPB_NEED_INIT); schedule_work(&ufsf->hpb_init_work); } @@ -601,7 +604,7 @@ inline void ufsf_init(struct ufsf_feature *ufsf) inline void ufsf_reset(struct ufsf_feature *ufsf) { #if defined(CONFIG_UFSHPB) - if (ufshpb_get_state(ufsf) == HPB_RESET) { + if ((ufshpb_get_state(ufsf) == HPB_RESET) && IS_RAM_SIZE_GREATER_THAN_4G(ram_size)) { INFO_MSG("reset start.. hpb_state %d", HPB_RESET); ufshpb_reset(ufsf); } @@ -620,7 +623,7 @@ inline void ufsf_reset(struct ufsf_feature *ufsf) inline void ufsf_remove(struct ufsf_feature *ufsf) { #if defined(CONFIG_UFSHPB) - if (ufshpb_get_state(ufsf) == HPB_PRESENT) + if ((ufshpb_get_state(ufsf) == HPB_PRESENT) && IS_RAM_SIZE_GREATER_THAN_4G(ram_size)) ufshpb_remove(ufsf, HPB_NEED_INIT); #endif @@ -635,9 +638,13 @@ inline void ufsf_set_init_state(struct ufsf_feature *ufsf) ufsf->slave_conf_cnt = 0; ufsf->issue_ioctl = false; #if defined(CONFIG_UFSHPB) - ufshpb_set_state(ufsf, HPB_NEED_INIT); - INIT_WORK(&ufsf->hpb_init_work, ufshpb_init_handler); - init_waitqueue_head(&ufsf->hpb_wait); + if (IS_RAM_SIZE_GREATER_THAN_4G(ram_size)) { + INFO_MSG("enable HPB feature, init start!"); + INFO_MSG("ram size is %d", ram_size); + ufshpb_set_state(ufsf, HPB_NEED_INIT); + INIT_WORK(&ufsf->hpb_init_work, ufshpb_init_handler); + init_waitqueue_head(&ufsf->hpb_wait); + } #endif #if defined(CONFIG_UFSTW) ufstw_set_state(ufsf, TW_NEED_INIT); @@ -652,7 +659,7 @@ inline void ufsf_suspend(struct ufsf_feature *ufsf) * in this case, ufshpb state already had been changed to SUSPEND state. * so, we will not call ufshpb_suspend. */ - if (ufshpb_get_state(ufsf) == HPB_PRESENT) + if ((ufshpb_get_state(ufsf) == HPB_PRESENT) && IS_RAM_SIZE_GREATER_THAN_4G(ram_size)) ufshpb_suspend(ufsf); #endif } @@ -660,8 +667,9 @@ inline void ufsf_suspend(struct ufsf_feature *ufsf) inline void ufsf_resume(struct ufsf_feature *ufsf) { #if defined(CONFIG_UFSHPB) - if (ufshpb_get_state(ufsf) == HPB_SUSPEND || - ufshpb_get_state(ufsf) == HPB_PRESENT) { + if ((ufshpb_get_state(ufsf) == HPB_SUSPEND || + ufshpb_get_state(ufsf) == HPB_PRESENT) && + IS_RAM_SIZE_GREATER_THAN_4G(ram_size)) { if (ufshpb_get_state(ufsf) == HPB_PRESENT) WARN_MSG("warning.. hpb state PRESENT in resuming"); ufshpb_resume(ufsf); diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index c66f206410bd..16bbe73f36fb 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -55,6 +55,36 @@ #define CREATE_TRACE_POINTS #include +#if defined(CONFIG_SCSI_SKHPB) || defined(CONFIG_UFSHPB) +#include +#include +#include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,14,0) +#include +#define SMEM_SDRAM_INFO 135 +#else +#include +#define SMEM_SDRAM_INFO SMEM_ID_VENDOR1 +#endif + +struct { + unsigned int mr5; + unsigned int mr6; + unsigned int mr7; + unsigned int mr8; + unsigned int ramsize; +} *smem_ddr_info; + +struct storage_info { + char type[16]; /* UFS or eMMC */ + char size[16]; /* size in GB */ + char card_manufacturer[32]; + char product_name[32]; /* model ID */ + char firmware_version[32]; +}; +unsigned int ram_size; +#endif + #define UFSHCD_ENABLE_INTRS (UTP_TRANSFER_REQ_COMPL |\ UTP_TASK_REQ_COMPL |\ UFSHCD_ERROR_MASK) @@ -303,6 +333,10 @@ static struct ufs_dev_fix ufs_fixups[] = { END_FIX }; +#if defined(CONFIG_SCSI_SKHPB) || defined(CONFIG_UFSHPB) +static int get_dram_info(struct ufs_hba *hba); +static int get_storage_info(struct ufs_hba *hba); +#endif static irqreturn_t ufshcd_tmc_handler(struct ufs_hba *hba); static void ufshcd_async_scan(void *data, async_cookie_t cookie); static int ufshcd_reset_and_restore(struct ufs_hba *hba); @@ -9782,13 +9816,18 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq) */ ufshcd_set_ufs_dev_active(hba); +#if defined(CONFIG_UFSHPB) || defined(CONFIG_SCSI_SKHPB) + get_storage_info(hba); + get_dram_info(hba); +#endif + #if defined(CONFIG_UFSFEATURE) - if (is_support_hpb_200_device(storage_mfrid)){ + if (is_support_hpb_200_device(storage_mfrid)) { ufsf_set_init_state(&hba->ufsf); } #endif #if defined(CONFIG_SCSI_SKHPB) - if (is_support_hpb_100_device(storage_mfrid)){ + if (is_support_hpb_100_device(storage_mfrid) && IS_RAM_SIZE_GREATER_THAN_4G(ram_size)) { /* initialize hpb structures */ ufshcd_init_hpb(hba); } @@ -9816,6 +9855,81 @@ static int __init storage_mfrid_setup(char *str) return 1; } __setup("storage_mfrid=",storage_mfrid_setup); + +#if defined(CONFIG_SCSI_SKHPB) || defined(CONFIG_UFSHPB) +static int get_storage_info(struct ufs_hba *hba) +{ + int ret = 0; + struct property *p; + struct device_node *n; + struct storage_info *info; + unsigned int mfrid; + + n = of_find_node_by_path("/chosen/mmi,storage"); + if (n == NULL) { + ret = 1; + goto err; + } + + info = kzalloc(sizeof(struct storage_info), GFP_KERNEL); + if (!info) { + dev_err(hba->dev,"%s: failed to allocate space for mmi_storage_info\n", + __func__); + ret = 1; + goto err; + } + + for_each_property_of_node(n, p) { + if (!strcmp(p->name, "type") && p->value) + strlcpy(info->type, (char *)p->value, sizeof(info->type)); + if (!strcmp(p->name, "size") && p->value) + strlcpy(info->size, (char *)p->value, sizeof(info->size)); + if (!strcmp(p->name, "manufacturer") && p->value) + strlcpy(info->card_manufacturer, (char *)p->value, sizeof(info->card_manufacturer)); + if (!strcmp(p->name, "product") && p->value) + strlcpy(info->product_name, (char *)p->value, sizeof(info->product_name)); + if (!strcmp(p->name, "firmware") && p->value) + strlcpy(info->firmware_version, (char *)p->value, sizeof(info->firmware_version)); + } + + of_node_put(n); + + mfrid = simple_strtol(info->card_manufacturer, NULL, 16); + dev_info(hba->dev, "manufacturer parsed from choosen is %s\n",mfrid); +err: + return ret; +} + +static int get_dram_info(struct ufs_hba *hba) +{ + int ret = -1; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,14,0) + ssize_t ddr_info_size = 0; + smem_ddr_info = qcom_smem_get(QCOM_SMEM_HOST_ANY, + SMEM_SDRAM_INFO, + &ddr_info_size); + + if(smem_ddr_info) { + if(ddr_info_size < sizeof(*smem_ddr_info)) { + dev_err(hba->dev,"%s: Invalid SMEM size, cannot get RAM info\n", __func__); + goto err; + } + } +#endif + if (smem_ddr_info == NULL) { + dev_err(hba->dev,"%s: failed to access RAM info in SMEM\n", __func__); + goto err; + } + + ram_size = (smem_ddr_info->ramsize / 1024); + dev_info(hba->dev, "ram_size parsed from SMEM is %d\n",ram_size); + return ram_size; +err: + return ret; +} +#endif + EXPORT_SYMBOL_GPL(ufshcd_init); MODULE_AUTHOR("Santosh Yaragnavi "); diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index ce44b1db6e5b..b292854b0d78 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -89,7 +89,10 @@ extern unsigned int storage_mfrid; #define IS_SAMSUNG_DEVICE(mfrid) (UFS_VENDOR_SAMSUNG == (mfrid)) #define IS_SKHYNIX_DEVICE(mfrid) (UFS_VENDOR_SKHYNIX == (mfrid)) #define IS_MICRON_DEVICE(mfrid) (UFS_VENDOR_MICRON == (mfrid)) - +#if defined(CONFIG_SCSI_SKHPB) || defined(CONFIG_UFSHPB) +extern unsigned int ram_size; +#define IS_RAM_SIZE_GREATER_THAN_4G(ram_size) (ram_size > 4) +#endif struct ufs_hba; enum dev_cmd_type { From 08db6056f8c71bb633fdcbd44ff04a1cf24170ba Mon Sep 17 00:00:00 2001 From: Vasily Averin Date: Mon, 10 May 2021 18:02:05 +0530 Subject: [PATCH 347/698] netfilter: nf_conntrack_h323: lost .data_len definition for Q.931/ipv6 Could you please push this patch into stable@? it fixes memory corruption in kernels v3.5 .. v4.10 Lost .data_len definition leads to write beyond end of struct nf_ct_h323_master. Usually it corrupts following struct nf_conn_nat, however if nat is not loaded it corrupts following slab object. In mainline this problem went away in v4.11, after commit 9f0f3ebeda47 ("netfilter: helpers: remove data_len usage for inkernel helpers") however many stable kernels are still affected. Mot-CRs-fixed: (CR) CVE-Fixed: CVE-2020-14305 Bug: 174904512 Change-Id: Ib96d3374766eecef01e92a4407ceca3f8e7c192e Fixes: 1afc56794e03 ("netfilter: nf_ct_helper: implement variable length helper private data") # v3.5 cc: stable@vger.kernel.org Reviewed-by: Florian Westphal Signed-off-by: Vasily Averin Signed-off-by: Greg Kroah-Hartman Signed-off-by: Gajjala Chakradhar Reviewed-on: https://gerrit.mot.com/1957505 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Konstantin Makariev Submit-Approved: Jira Key --- net/netfilter/nf_conntrack_h323_main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/netfilter/nf_conntrack_h323_main.c b/net/netfilter/nf_conntrack_h323_main.c index 8ba037b76ad3..e24374979fdb 100644 --- a/net/netfilter/nf_conntrack_h323_main.c +++ b/net/netfilter/nf_conntrack_h323_main.c @@ -1197,6 +1197,7 @@ static struct nf_conntrack_helper nf_conntrack_helper_q931[] __read_mostly = { { .name = "Q.931", .me = THIS_MODULE, + .data_len = sizeof(struct nf_ct_h323_master), .tuple.src.l3num = AF_INET6, .tuple.src.u.tcp.port = cpu_to_be16(Q931_PORT), .tuple.dst.protonum = IPPROTO_TCP, From d9cbdd72fc692a75d7abcd7c6a81a98fd5df7df5 Mon Sep 17 00:00:00 2001 From: fuxm1 Date: Tue, 25 May 2021 21:16:23 +0800 Subject: [PATCH 348/698] ufs/hpb: enable Micron HPB feature Remark: 1. enable Micron HPB. 2. configure write booster as JEDEC WB for Micron. Change-Id: Ic256689254187059ed97004e2305b147259f1e6a Signed-off-by: fuxm1 Reviewed-on: https://gerrit.mot.com/1959521 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Huosheng Liao Reviewed-by: Zhenxin Xi Submit-Approved: Jira Key --- .../configs/vendor/ext_config/moto-holi-denver.config | 3 +++ .../configs/vendor/ext_config/moto-holi-ibiza.config | 3 +++ arch/arm64/configs/vendor/holi_QGKI.config | 3 +++ drivers/scsi/ufs/ufshcd.c | 11 ++++++++--- drivers/scsi/ufs/ufshcd.h | 4 ---- 5 files changed, 17 insertions(+), 7 deletions(-) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-denver.config b/arch/arm64/configs/vendor/ext_config/moto-holi-denver.config index a3ac4fce713b..a576b69483e6 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-denver.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-denver.config @@ -24,3 +24,6 @@ CONFIG_ZRAM_WRITEBACK=y # CONFIG_UFSHPB is not set # CONFIG_UFSTW is not set # CONFIG_SCSI_SKHPB is not set +# CONFIG_UFSTW_IGNORE_GUARANTEE_BIT is not set +# CONFIG_UFSTW_BOOT_ENABLED is not set +# CONFIG_MICRON_HPB is not set diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config b/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config index 62cecda746ec..4381a9d7398e 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config @@ -22,3 +22,6 @@ CONFIG_ZRAM_WRITEBACK=y # CONFIG_UFSHPB is not set # CONFIG_UFSTW is not set # CONFIG_SCSI_SKHPB is not set +# CONFIG_UFSTW_IGNORE_GUARANTEE_BIT is not set +# CONFIG_UFSTW_BOOT_ENABLED is not set +# CONFIG_MICRON_HPB is not set diff --git a/arch/arm64/configs/vendor/holi_QGKI.config b/arch/arm64/configs/vendor/holi_QGKI.config index eeefbf2a14fa..29c1ff5a3e5d 100644 --- a/arch/arm64/configs/vendor/holi_QGKI.config +++ b/arch/arm64/configs/vendor/holi_QGKI.config @@ -202,4 +202,7 @@ CONFIG_QTI_DEVFREQ_VDD_COOLING_DEVICE=y CONFIG_UFSFEATURE=y CONFIG_UFSHPB=y CONFIG_UFSTW=y +CONFIG_UFSTW_IGNORE_GUARANTEE_BIT=y +CONFIG_UFSTW_BOOT_ENABLED=y CONFIG_SCSI_SKHPB=y +CONFIG_MICRON_HPB=y diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 16bbe73f36fb..c946df276b66 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -7487,6 +7487,13 @@ static void ufshcd_wb_probe(struct ufs_hba *hba, u8 *desc_buf) goto wb_disabled; } +#if defined(CONFIG_UFSTW) + //disable write booster for samsung ufs. turbo write feature is used on samsung v6 or v5 ufs. + if (dev_info->wmanufacturerid == UFS_VENDOR_SAMSUNG) { + dev_err(hba->dev, "%s: it is samsung ufs, just disable wb, will enable TW.wb_disable \n",__func__); + goto wb_disabled; + } +#endif /* * WB may be supported but not configured while provisioning. * The spec says, in dedicated wb buffer mode, @@ -9863,7 +9870,6 @@ static int get_storage_info(struct ufs_hba *hba) struct property *p; struct device_node *n; struct storage_info *info; - unsigned int mfrid; n = of_find_node_by_path("/chosen/mmi,storage"); if (n == NULL) { @@ -9894,8 +9900,7 @@ static int get_storage_info(struct ufs_hba *hba) of_node_put(n); - mfrid = simple_strtol(info->card_manufacturer, NULL, 16); - dev_info(hba->dev, "manufacturer parsed from choosen is %s\n",mfrid); + dev_info(hba->dev, "manufacturer parsed from choosen is %s\n",info->card_manufacturer); err: return ret; } diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index b292854b0d78..0273ec1dcc8a 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -1160,11 +1160,7 @@ static inline bool ufshcd_is_auto_hibern8_enabled(struct ufs_hba *hba) static inline bool ufshcd_is_wb_allowed(struct ufs_hba *hba) { -#if defined(CONFIG_UFSTW) - return false; -#else return hba->caps & UFSHCD_CAP_WB_EN; -#endif } #define ufshcd_writel(hba, val, reg) \ From 5f87bbb9ecc144064dade1a31f4819b7ac08ae1a Mon Sep 17 00:00:00 2001 From: mahj8 Date: Thu, 20 May 2021 12:57:41 +0800 Subject: [PATCH 349/698] smb5: add main charging on-off IIO prop 1. add main charging on-off IIO prop 2. define more mmi IIO prop for charger pump Change-Id: Iaf49f816b53d64bb61e44fcb82fc25d8d7dd72dd Signed-off-by: mahj8 Reviewed-on: https://gerrit.mot.com/1940727 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Lu Chai Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- drivers/power/supply/qcom/smb5-iio.c | 6 ++++++ drivers/power/supply/qcom/smb5-iio.h | 1 + include/dt-bindings/iio/qti_power_supply_iio.h | 6 ++++++ 3 files changed, 13 insertions(+) diff --git a/drivers/power/supply/qcom/smb5-iio.c b/drivers/power/supply/qcom/smb5-iio.c index c3cdd4416588..7a2f368b82dd 100644 --- a/drivers/power/supply/qcom/smb5-iio.c +++ b/drivers/power/supply/qcom/smb5-iio.c @@ -266,6 +266,9 @@ int smb5_iio_get_prop(struct smb_charger *chg, int channel, int *val) case PSY_IIO_TYPEC_ACCESSORY_MODE: rc = smblib_get_usb_prop_typec_accessory_mode(chg, val); break; + case PSY_IIO_CHARGING_ENABLED: + *val = !get_effective_result(chg->chg_disable_votable); + break; default: pr_err("get prop %d is not supported\n", channel); rc = -EINVAL; @@ -495,6 +498,9 @@ int smb5_iio_set_prop(struct smb_charger *chg, int channel, int val) case PSY_IIO_FCC_STEPPER_ENABLE: chg->fcc_stepper_enable = val; break; + case PSY_IIO_CHARGING_ENABLED: + vote(chg->chg_disable_votable, USER_VOTER, !!!val, 0); + break; default: pr_err("get prop %d is not supported\n", channel); rc = -EINVAL; diff --git a/drivers/power/supply/qcom/smb5-iio.h b/drivers/power/supply/qcom/smb5-iio.h index 40753d0d28a2..800deefe37d0 100644 --- a/drivers/power/supply/qcom/smb5-iio.h +++ b/drivers/power/supply/qcom/smb5-iio.h @@ -201,6 +201,7 @@ static const struct smb5_iio_prop_channels smb5_chans_pmic[] = { SMB5_CHAN_ACTIVITY("battery_force_recharge", FORCE_RECHARGE) SMB5_CHAN_ACTIVITY("battery_fcc_stepper_enable", FCC_STEPPER_ENABLE) SMB5_CHAN_INDEX("usb_typec_accessory_mode", TYPEC_ACCESSORY_MODE) + SMB5_CHAN_INDEX("charging_enabled", CHARGING_ENABLED) }; struct iio_channel **get_ext_channels(struct device *dev, diff --git a/include/dt-bindings/iio/qti_power_supply_iio.h b/include/dt-bindings/iio/qti_power_supply_iio.h index 84611eb3bcc6..d4bd059af5f5 100644 --- a/include/dt-bindings/iio/qti_power_supply_iio.h +++ b/include/dt-bindings/iio/qti_power_supply_iio.h @@ -154,4 +154,10 @@ /* BMS */ #define PSY_IIO_CLEAR_SOH 0x7c + +/*MMI add PSY_IIO properties*/ +#define PSY_IIO_MMI_CP_INPUT_CURRENT_NOW 0x100 +#define PSY_IIO_MMI_CP_INPUT_VOLTAGE_NOW 0x101 +#define PSY_IIO_MMI_CP_STATUS1 0x102 +#define PSY_IIO_MMI_CP_CLEAR_ERROR 0x103 #endif /* __QTI_POWER_SUPPLY_IIO_H__ */ From d1b029fe40b1f48a3d63e72dc15aa7679bad265c Mon Sep 17 00:00:00 2001 From: mahj8 Date: Mon, 10 May 2021 09:44:42 +0800 Subject: [PATCH 350/698] usb:pd: Add get/select PDO api -usbpd_get_pd_info: get all PDO info from PD SOURCE, and save them to usbpd_pdo_info struct -usbpd_select_pdo: provide API to easy select the specific PDO, in order to program its voltage and current. Change-Id: I6663c04a9479b852449fa80e9e5c396ddfbc9e57 Signed-off-by: mahj8 Reviewed-on: https://gerrit.mot.com/1943692 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Lu Chai Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- drivers/usb/pd/policy_engine.c | 133 +++++++++++++++++++++++++++++++++ include/linux/usb/usbpd.h | 20 +++++ 2 files changed, 153 insertions(+) diff --git a/drivers/usb/pd/policy_engine.c b/drivers/usb/pd/policy_engine.c index 818be0ecda61..0265fda58b76 100644 --- a/drivers/usb/pd/policy_engine.c +++ b/drivers/usb/pd/policy_engine.c @@ -4343,6 +4343,139 @@ out: } EXPORT_SYMBOL(usbpd_select_pdo_match); +int usbpd_get_pdo_info(struct usbpd *pd, struct usbpd_pdo_info *pdo_info, int length) +{ + int pdo = 0; + int i; + int ret = 0; + + if (!pd || !pdo_info) + return -EINVAL; + + if (length > PD_MAX_PDO_NUM) { + usbpd_err(&pd->dev, + "the members of the struct pd_info[] array must be less than %d, " + "err length %d\n", PD_MAX_PDO_NUM, length); + return -EINVAL; + } + + mutex_lock(&pd->swap_lock); + + if (pd->current_pr == PR_SRC) { + usbpd_err(&pd->dev, "select_pdo:not support in source mode\n"); + ret = -ENOTSUPP; + goto out; + } + usbpd_err(&pd->dev, "select pdo info ,pd->current_state %d\n", pd->current_state); + + if (!is_sink_tx_ok(pd)) + usbpd_err(&pd->dev, "select pdo info , !is_sink_tx_ok\n"); + + /* Only allowed if we are already in explicit sink contract */ + if (pd->current_state != PE_SNK_READY || !is_sink_tx_ok(pd)) { + usbpd_err(&pd->dev, "select_pdo_info: Cannot select new PDO yet\n"); + ret = -EBUSY; + goto out; + } + + for (i = 0; i < length; i++) { + pdo = pd->received_pdos[i]; + if (pdo == 0) + break; + + pdo_info[i].pdo_pos = i + 1; + pdo_info[i].type = PD_SRC_PDO_TYPE(pdo); + if (pdo_info[i].type == PD_SRC_PDO_TYPE_FIXED) { + pdo_info[i].ua = PD_SRC_PDO_FIXED_MAX_CURR(pdo) * 10; + pdo_info[i].uv_max = PD_SRC_PDO_FIXED_VOLTAGE(pdo) * 50 * 1000; + pdo_info[i].uv_min = PD_SRC_PDO_FIXED_VOLTAGE(pdo) * 50 * 1000; + + printk(KERN_INFO "pdo %d, Fixed supply\n" + "Voltage:%d (uV)\n" + "Max Current:%d (uA)\n", + pdo_info[i].pdo_pos, + pdo_info[i].uv_max, + pdo_info[i].ua); + + } else if (pdo_info[i].type == PD_SRC_PDO_TYPE_AUGMENTED) { + pdo_info[i].uv_max = PD_APDO_MAX_VOLT(pdo) * 100000; + pdo_info[i].uv_min = PD_APDO_MIN_VOLT(pdo) * 100000; + pdo_info[i].ua = PD_APDO_MAX_CURR(pdo) * 50000; + + printk(KERN_INFO "pdo %d, Programmable Power supply\n" + "Voltage:%d (uV)\n" + "Max Current:%d (uA)\n", + pdo_info[i].pdo_pos, + pdo_info[i].uv_max, + pdo_info[i].ua); + + } else + usbpd_err(&pd->dev, "Only get Fixed or Programmable PDOs supported\n"); + } +out: + mutex_unlock(&pd->swap_lock); + return ret; +} +EXPORT_SYMBOL(usbpd_get_pdo_info); + +int usbpd_select_pdo(struct usbpd *pd, int pdo_pos, int uv, int ua) +{ + int ret; + + if (!pd) + return -EINVAL; + + mutex_lock(&pd->swap_lock); + + if (pd->current_pr == PR_SRC) { + usbpd_err(&pd->dev, "select_pdo:not support in source mode\n"); + ret = -ENOTSUPP; + goto out; + } + + /* Only allowed if we are already in explicit sink contract */ + if (pd->current_state != PE_SNK_READY || !is_sink_tx_ok(pd)) { + usbpd_err(&pd->dev, "select_pdo: Cannot select new PDO yet\n"); + ret = -EBUSY; + goto out; + } + + if (pdo_pos < 1 || pdo_pos > 7) { + usbpd_err(&pd->dev, "select_pdo: invalid PDO:%d\n", pdo_pos); + ret = -EINVAL; + goto out; + } + + ret = pd_select_pdo(pd, pdo_pos, uv, ua); + if (ret) + goto out; + + reinit_completion(&pd->is_ready); + pd->send_request = true; + kick_sm(pd, 0); + + /* wait for operation to complete */ + if (!wait_for_completion_timeout(&pd->is_ready, + msecs_to_jiffies(1000))) { + usbpd_err(&pd->dev, "select_pdo: request timed out\n"); + ret = -ETIMEDOUT; + goto out; + } + + /* determine if request was accepted/rejected */ + if (pd->selected_pdo != pd->requested_pdo || + pd->current_voltage != pd->requested_voltage) { + usbpd_err(&pd->dev, "select_pdo: request rejected\n"); + ret = -EINVAL; + } + +out: + pd->send_request = false; + mutex_unlock(&pd->swap_lock); + return ret; +} +EXPORT_SYMBOL(usbpd_select_pdo); + static ssize_t select_pdo_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { diff --git a/include/linux/usb/usbpd.h b/include/linux/usb/usbpd.h index 378bbab17610..b57ec920e3d6 100644 --- a/include/linux/usb/usbpd.h +++ b/include/linux/usb/usbpd.h @@ -36,6 +36,8 @@ enum usbpd_svdm_cmd_type { #define USBPD_SVDM_EXIT_MODE 0x5 #define USBPD_SVDM_ATTENTION 0x6 +#define PD_MAX_PDO_NUM 7 + /* * Implemented by client */ @@ -65,6 +67,14 @@ struct usbpd_svid_handler { bool discovered; }; +struct usbpd_pdo_info { + int pdo_pos; + int uv_max; + int uv_min; + int ua; + int type; +}; + enum plug_orientation { ORIENTATION_NONE, ORIENTATION_CC1, @@ -104,6 +114,16 @@ int usbpd_send_svdm(struct usbpd *pd, u16 svid, u8 cmd, */ int usbpd_select_pdo_match(struct usbpd *pd); +/* +* support that directly set pdo which is need in Source Mode. +*/ +int usbpd_select_pdo(struct usbpd *pd, int pdo_pos, int uv, int ua); + +/* +* Transmit all effective pdo info. +*/ +int usbpd_get_pdo_info(struct usbpd *pd, struct usbpd_pdo_info *pdo_info, int length); + /* * Get current status of CC pin orientation. * From 14ba79f9922eac588d0a03e3a43f87f38ae1df4f Mon Sep 17 00:00:00 2001 From: mahj8 Date: Fri, 28 May 2021 10:30:13 +0800 Subject: [PATCH 351/698] gki: add power supply api for mmi_parallel_charger_iio.ko add power_supply_register and power_supply_unregister api for mmi_parallel_charger_iio.ko DLKM Change-Id: I59e7dc17aea0926ab94df3643ce858ca5f096254 Signed-off-by: mahj8 Reviewed-on: https://gerrit.mot.com/1963306 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Lu Chai Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- android/abi_gki_aarch64_qcom | 2 ++ 1 file changed, 2 insertions(+) diff --git a/android/abi_gki_aarch64_qcom b/android/abi_gki_aarch64_qcom index ef98aa4dca85..82b0f695e4cf 100644 --- a/android/abi_gki_aarch64_qcom +++ b/android/abi_gki_aarch64_qcom @@ -1896,8 +1896,10 @@ power_supply_get_property power_supply_put power_supply_reg_notifier + power_supply_register power_supply_set_property power_supply_unreg_notifier + power_supply_unregister prandom_u32 preempt_schedule preempt_schedule_notrace From 2469090ab05acf37a4ecc6910225ae4683185143 Mon Sep 17 00:00:00 2001 From: wuwl10 Date: Fri, 4 Jun 2021 15:48:56 +0800 Subject: [PATCH 352/698] pinctrl-holi: revert qcom change for i2c_7 Below change will cause i2c_7 bus hung. Rever it change first until qcom provide new patch. pinctrl: qcom: function group for qup11_f* instance for holi This reverts commit 7a2620f882cb8b2a015bbed538685c088804aedb. Change-Id: Ie7b47d1fc0dd6b3fe9537bf06ea6c79bff076773 Signed-off-by: wuwl10 Reviewed-on: https://gerrit.mot.com/1970100 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Hujun Liao Submit-Approved: Jira Key --- drivers/pinctrl/qcom/pinctrl-holi.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/drivers/pinctrl/qcom/pinctrl-holi.c b/drivers/pinctrl/qcom/pinctrl-holi.c index c2125c904876..2b546eae6451 100644 --- a/drivers/pinctrl/qcom/pinctrl-holi.c +++ b/drivers/pinctrl/qcom/pinctrl-holi.c @@ -578,8 +578,7 @@ enum holi_functions { msm_mux_qup01, msm_mux_qup02, msm_mux_qup10, - msm_mux_qup11_f1, - msm_mux_qup11_f2, + msm_mux_qup11, msm_mux_qup12, msm_mux_qup13_f1, msm_mux_qup13_f2, @@ -1027,10 +1026,7 @@ static const char * const qup02_groups[] = { static const char * const qup10_groups[] = { "gpio13", "gpio14", "gpio15", "gpio16", "gpio17", }; -static const char * const qup11_f1_groups[] = { - "gpio27", "gpio28", -}; -static const char * const qup11_f2_groups[] = { +static const char * const qup11_groups[] = { "gpio27", "gpio28", }; static const char * const qup12_groups[] = { @@ -1148,8 +1144,7 @@ static const struct msm_function holi_functions[] = { FUNCTION(edp_lcd), FUNCTION(qup13_f1), FUNCTION(qup13_f2), - FUNCTION(qup11_f1), - FUNCTION(qup11_f2), + FUNCTION(qup11), FUNCTION(PLL_BIST), FUNCTION(qdss_gpio14), FUNCTION(qdss_gpio15), @@ -1335,10 +1330,10 @@ static const struct msm_pingroup holi_groups[] = { 0x9C00C, 15), [26] = PINGROUP(26, qup13_f1, qup13_f2, NA, NA, NA, NA, NA, NA, NA, 0, -1), - [27] = PINGROUP(27, qup11_f1, qup11_f2, MDP_VSYNC, PLL_BIST, NA, - qdss_gpio14, NA, NA, NA, 0x9C010, 0), - [28] = PINGROUP(28, qup11_f1, qup11_f2, MDP_VSYNC, NA, qdss_gpio15, - NA, NA, NA, NA, 0x9C010, 1), + [27] = PINGROUP(27, qup11, qup11, MDP_VSYNC, PLL_BIST, NA, qdss_gpio14, + NA, NA, NA, 0x9C010, 0), + [28] = PINGROUP(28, qup11, qup11, MDP_VSYNC, NA, qdss_gpio15, NA, NA, + NA, NA, 0x9C010, 1), [29] = PINGROUP(29, cam_mclk, NA, NA, NA, NA, NA, NA, NA, NA, 0, -1), [30] = PINGROUP(30, cam_mclk, NA, NA, NA, NA, NA, NA, NA, NA, 0, -1), [31] = PINGROUP(31, cam_mclk, NA, NA, NA, NA, NA, NA, NA, NA, 0, -1), From 8583c761b5d387e7541e8743ece2d6ca0b63331f Mon Sep 17 00:00:00 2001 From: chailu1 Date: Fri, 4 Jun 2021 19:06:51 +0800 Subject: [PATCH 353/698] charge: add qc3p driver add qc3+ authenticate process and qqc3+ voltage control interface Change-Id: I1e944ba8d6b0d16c19c70f9d5c1385bbf9a28801 Signed-off-by: chailu1 Reviewed-on: https://gerrit.mot.com/1971082 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Haijian Ma Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- drivers/power/supply/qcom/qpnp-smb5.c | 2 + drivers/power/supply/qcom/smb5-iio.c | 10 +- drivers/power/supply/qcom/smb5-iio.h | 6 + drivers/power/supply/qcom/smb5-lib.c | 184 +++++++++++++++++- drivers/power/supply/qcom/smb5-lib.h | 10 + .../dt-bindings/iio/qti_power_supply_iio.h | 1 + include/linux/qti_power_supply.h | 6 + 7 files changed, 216 insertions(+), 3 deletions(-) diff --git a/drivers/power/supply/qcom/qpnp-smb5.c b/drivers/power/supply/qcom/qpnp-smb5.c index 01f96db6d6c7..6ef6655e5640 100644 --- a/drivers/power/supply/qcom/qpnp-smb5.c +++ b/drivers/power/supply/qcom/qpnp-smb5.c @@ -626,6 +626,8 @@ static int smb5_parse_dt_misc(struct smb5 *chip, struct device_node *node) &chg->chg_param.qc4_max_icl_ua); if (chg->chg_param.qc4_max_icl_ua <= 0) chg->chg_param.qc4_max_icl_ua = MICRO_4PA; + chg->mmi_qc3p_support = of_property_read_bool(node, + "mmi,qc3p-support"); return 0; } diff --git a/drivers/power/supply/qcom/smb5-iio.c b/drivers/power/supply/qcom/smb5-iio.c index 7a2f368b82dd..d34e93e1cdd0 100644 --- a/drivers/power/supply/qcom/smb5-iio.c +++ b/drivers/power/supply/qcom/smb5-iio.c @@ -269,6 +269,9 @@ int smb5_iio_get_prop(struct smb_charger *chg, int channel, int *val) case PSY_IIO_CHARGING_ENABLED: *val = !get_effective_result(chg->chg_disable_votable); break; + case PSY_IIO_MMI_QC3P_POWER: + *val = chg->mmi_qc3p_power; + break; default: pr_err("get prop %d is not supported\n", channel); rc = -EINVAL; @@ -471,7 +474,12 @@ int smb5_iio_set_prop(struct smb_charger *chg, int channel, int val) rc = smblib_run_aicl(chg, RERUN_AICL); break; case PSY_IIO_DP_DM: - if (!chg->flash_active) + if (chg->mmi_qc3p_support) { + if ((chg->real_charger_type == QTI_POWER_SUPPLY_TYPE_USB_HVDCP_3P5) + ||(!chg->flash_active && !chg->mmi_is_qc3p_authen + && chg->real_charger_type == QTI_POWER_SUPPLY_TYPE_USB_HVDCP_3)) + rc = smblib_dp_dm(chg, val); + } else if (!chg->flash_active) rc = smblib_dp_dm(chg, val); break; case PSY_IIO_INPUT_CURRENT_LIMITED: diff --git a/drivers/power/supply/qcom/smb5-iio.h b/drivers/power/supply/qcom/smb5-iio.h index 800deefe37d0..e5ecb0308864 100644 --- a/drivers/power/supply/qcom/smb5-iio.h +++ b/drivers/power/supply/qcom/smb5-iio.h @@ -14,6 +14,7 @@ enum iio_type { QG, CP, SMB_PARALLEL, + MMI_CP, }; /* For qpnp-smb5.c and smb5-lib.c */ @@ -34,6 +35,10 @@ enum qg_chg_iio_channels { SMB5_QG_TIME_TO_FULL_NOW, }; +enum mmi_cp_iio_channels { + SC8549_INPUT_VOLTAGE_NOW, +}; + enum cp_iio_channels { CP_PARALLEL_OUTPUT_MODE, CP_MASTER_ENABLE, @@ -202,6 +207,7 @@ static const struct smb5_iio_prop_channels smb5_chans_pmic[] = { SMB5_CHAN_ACTIVITY("battery_fcc_stepper_enable", FCC_STEPPER_ENABLE) SMB5_CHAN_INDEX("usb_typec_accessory_mode", TYPEC_ACCESSORY_MODE) SMB5_CHAN_INDEX("charging_enabled", CHARGING_ENABLED) + SMB5_CHAN_INDEX("usb_qc3p_power", MMI_QC3P_POWER) }; struct iio_channel **get_ext_channels(struct device *dev, diff --git a/drivers/power/supply/qcom/smb5-lib.c b/drivers/power/supply/qcom/smb5-lib.c index 38cb13bb4cb6..f0c2491079e3 100644 --- a/drivers/power/supply/qcom/smb5-lib.c +++ b/drivers/power/supply/qcom/smb5-lib.c @@ -24,6 +24,9 @@ #include "storm-watch.h" #include "smb5-iio.h" #include "battery-profile-loader.h" +#include +#include + #define smblib_err(chg, fmt, ...) \ pr_err("%s: %s: " fmt, chg->name, \ @@ -885,6 +888,10 @@ int smblib_set_aicl_cont_threshold(struct smb_chg_param *param, /******************** * HELPER FUNCTIONS * ********************/ +/* MMI CP channels */ +static const char * const smblib_mmi_cp_ext_iio_chan[] = { + [SC8549_INPUT_VOLTAGE_NOW] = "sc8549_input_voltage_now", +}; /* CP channels */ static const char * const smblib_cp_ext_iio_chan[] = { @@ -941,6 +948,11 @@ static int smblib_read_iio_prop(struct smb_charger *chg, return -ENODEV; iio_chan_list = chg->iio_chan_list_smb_parallel[iio_chan]; break; + case MMI_CP: + if (IS_ERR_OR_NULL(chg->iio_chan_list_mmi_cp)) + return -ENODEV; + iio_chan_list = chg->iio_chan_list_mmi_cp[iio_chan]; + break; default: pr_err_ratelimited("iio_type %d is not supported\n", type); return -EINVAL; @@ -971,6 +983,11 @@ static int smblib_write_iio_prop(struct smb_charger *chg, return -ENODEV; iio_chan_list = chg->iio_chan_list_smb_parallel[iio_chan]; break; + case MMI_CP: + if (IS_ERR_OR_NULL(chg->iio_chan_list_mmi_cp)) + return -ENODEV; + iio_chan_list = chg->iio_chan_list_mmi_cp[iio_chan]; + break; default: pr_err_ratelimited("iio_type %d is not supported\n", type); return -EINVAL; @@ -979,6 +996,33 @@ static int smblib_write_iio_prop(struct smb_charger *chg, return iio_write_channel_raw(iio_chan_list, val); } +static bool is_mmi_cp_available(struct smb_charger *chg) +{ + int rc; + struct iio_channel **iio_list; + + if (IS_ERR(chg->iio_chan_list_mmi_cp)) + return false; + + if (!chg->iio_chan_list_mmi_cp) { + iio_list = get_ext_channels(chg->dev, + smblib_mmi_cp_ext_iio_chan, + ARRAY_SIZE(smblib_mmi_cp_ext_iio_chan)); + if (IS_ERR(iio_list)) { + rc = PTR_ERR(iio_list); + if (rc != -EPROBE_DEFER) { + dev_err(chg->dev, "Failed to get channels, rc=%d\n", + rc); + chg->iio_chan_list_mmi_cp = ERR_PTR(-EINVAL); + } + return false; + } + chg->iio_chan_list_mmi_cp = iio_list; + } + + return true; +} + static bool is_cp_available(struct smb_charger *chg) { int rc; @@ -1305,6 +1349,7 @@ static void smblib_uusb_removal(struct smb_charger *chg) vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, true, is_flash_active(chg) ? SDP_CURRENT_UA : SDP_100_MA); vote(chg->usb_icl_votable, SW_QC3_VOTER, false, 0); + vote(chg->usb_icl_votable, SW_QC3P_AUTHEN_VOTER, false, 0); vote(chg->usb_icl_votable, HVDCP2_ICL_VOTER, false, 0); vote(chg->usb_icl_votable, CHG_TERMINATION_VOTER, false, 0); vote(chg->usb_icl_votable, THERMAL_THROTTLE_VOTER, false, 0); @@ -2869,8 +2914,10 @@ int smblib_dp_dm(struct smb_charger *chg, int val) pr_err("Failed to force 12V\n"); break; case QTI_POWER_SUPPLY_DP_DM_CONFIRMED_HVDCP3P5: - chg->qc3p5_detected = true; - smblib_update_usb_type(chg); + if (!chg->mmi_qc3p_support) { + chg->qc3p5_detected = true; + smblib_update_usb_type(chg); + } break; case QTI_POWER_SUPPLY_DP_DM_ICL_UP: default: @@ -5862,6 +5909,113 @@ static void smblib_handle_sdp_enumeration_done(struct smb_charger *chg, rising ? "rising" : "falling"); } +static int mmi_get_vbus(struct smb_charger *chg) +{ + int rc = 0, val; + + if (!is_mmi_cp_available(chg)) + return 0; + + rc = smblib_read_iio_prop(chg, MMI_CP, SC8549_INPUT_VOLTAGE_NOW, + &val); + if (!rc) + return val; + else { + smblib_err(chg, "Couldn't read mmi cp vbus rc=%d\n", rc); + return 0; + } +} + +#define QC3P_AUTHEN_LOW_THR_MV 5500 +#define QC3P_AUTHEN_HIGH_THR_MV 6500 +#define QC3P_AUTHEN_NONE_THR_MV 9500 +#define QC3P_AUTHEN_45W_THR_MV 8500 +#define QC3P_AUTHEN_27W_THR_MV 7500 +#define QC3P_AUTHEN_18W_THR_MV 6500 +static int mmi_qc3p_kthread_handler(void *param) +{ + struct smb_charger *chg = param; + int i; + int v_aut,v_power; + unsigned long j1,j2; + struct sched_param sch_param = {.sched_priority = MAX_RT_PRIO-1}; + + sched_setscheduler(current, SCHED_FIFO, &sch_param); + do { + wait_event_interruptible(chg->mmi_timer_wait_que, chg->mmi_timer_trig_flag || kthread_should_stop()); + if (kthread_should_stop()) + break; + chg->mmi_timer_trig_flag = false; + + for (i = 0; i < 16; i++) { + smblib_dp_pulse(chg); + udelay(5000); + } + mdelay(95); + for (i = 0; i < 16; i++) { + smblib_dm_pulse(chg); + udelay(5000); + } + mdelay(100); + + j1 = jiffies; + v_aut = mmi_get_vbus(chg); + j1 = jiffies - j1; + if (v_aut < QC3P_AUTHEN_LOW_THR_MV || v_aut > QC3P_AUTHEN_HIGH_THR_MV) { + chg->mmi_qc3p_power = QTI_POWER_SUPPLY_QC3P_NONE; + smblib_err(chg, "is qc3.0 charge adatper vbus=%d\n",v_aut); + goto out; + } + + for (i = 0;i < 3; i++) { + smblib_dp_pulse(chg); + udelay(5000); + smblib_dm_pulse(chg); + udelay(5000); + } + mdelay(30); + + j2 = jiffies; + v_power = mmi_get_vbus(chg); + j2 = jiffies - j2; + + for (i = 0; i < 2; i++) { + smblib_dp_pulse(chg); + udelay(5000); + } + for (i = 0; i < 2; i++) { + smblib_dm_pulse(chg); + udelay(5000); + } + msleep(30); + + if (v_power > QC3P_AUTHEN_NONE_THR_MV) + chg->mmi_qc3p_power = QTI_POWER_SUPPLY_QC3P_NONE; + else if (v_power > QC3P_AUTHEN_45W_THR_MV) + chg->mmi_qc3p_power = QTI_POWER_SUPPLY_QC3P_45W; + else if (v_power > QC3P_AUTHEN_27W_THR_MV) + chg->mmi_qc3p_power = QTI_POWER_SUPPLY_QC3P_27W; + else if (v_power > QC3P_AUTHEN_18W_THR_MV) + chg->mmi_qc3p_power = QTI_POWER_SUPPLY_QC3P_18W; + else + chg->mmi_qc3p_power = QTI_POWER_SUPPLY_QC3P_NONE; + + if (chg->mmi_qc3p_power != QTI_POWER_SUPPLY_QC3P_NONE) + chg->qc3p5_detected = true; + smblib_update_usb_type(chg); + power_supply_changed(chg->usb_psy); + + smblib_dbg(chg, PR_MISC, "V_aut:%dms %dmV,V_power=%dms %dmV,Power =%d\n", + jiffies_to_msecs(j1), v_aut, jiffies_to_msecs(j2), v_power, chg->mmi_qc3p_power); + out: + chg->mmi_is_qc3p_authen = false; + vote(chg->usb_icl_votable, SW_QC3P_AUTHEN_VOTER, false, 0); + }while (!kthread_should_stop()); + + smblib_dbg(chg, PR_MISC, "qc3p kthread stop\n"); + return 0; +} + #define APSD_EXTENDED_TIMEOUT_MS 400 /* triggers when HVDCP 3.0 authentication has finished */ static void smblib_handle_hvdcp_3p0_auth_done(struct smb_charger *chg, @@ -5898,6 +6052,13 @@ static void smblib_handle_hvdcp_3p0_auth_done(struct smb_charger *chg, "APSD Extented timer started at %lld\n", jiffies_to_msecs(jiffies)); + if (chg->mmi_qc3p_support) { + chg->mmi_is_qc3p_authen = true; + chg->qc3p5_detected = false; + chg->mmi_qc3p_power = QTI_POWER_SUPPLY_QC3P_NONE; + vote(chg->usb_icl_votable, SW_QC3P_AUTHEN_VOTER, true, 500000); + } + mod_timer(&chg->apsd_timer, msecs_to_jiffies(APSD_EXTENDED_TIMEOUT_MS) + jiffies); @@ -6477,6 +6638,7 @@ static void typec_src_removal(struct smb_charger *chg) vote(chg->usb_icl_votable, USB_PSY_VOTER, false, 0); vote(chg->usb_icl_votable, DCP_VOTER, false, 0); vote(chg->usb_icl_votable, SW_QC3_VOTER, false, 0); + vote(chg->usb_icl_votable, SW_QC3P_AUTHEN_VOTER, false, 0); vote(chg->usb_icl_votable, CTM_VOTER, false, 0); vote(chg->usb_icl_votable, HVDCP2_ICL_VOTER, false, 0); vote(chg->usb_icl_votable, CHG_TERMINATION_VOTER, false, 0); @@ -7985,6 +8147,11 @@ static void apsd_timer_cb(struct timer_list *tm) jiffies_to_msecs(jiffies)); chg->apsd_ext_timeout = true; + + if (chg->mmi_qc3p_support) { + chg->mmi_timer_trig_flag = true; + wake_up_interruptible(&chg->mmi_timer_wait_que); + } } #define SOFT_JEITA_HYSTERESIS_OFFSET 0x200 @@ -8559,6 +8726,17 @@ int smblib_init(struct smb_charger *chg) INIT_DELAYED_WORK(&chg->pr_lock_clear_work, smblib_pr_lock_clear_work); INIT_DELAYED_WORK(&chg->pd_contract_work, smblib_pd_contract_work); + if (chg->mmi_qc3p_support) { + chg->mmi_qc3p_authen_task = kthread_create(mmi_qc3p_kthread_handler, chg, + "mmi_qc3p_authen", "mmi_qc3p_authen_task", chg); + if (IS_ERR(chg->mmi_qc3p_authen_task)) { + rc = PTR_ERR(chg->mmi_qc3p_authen_task); + smblib_err(chg, "Failed to create mmi_qc3p_authen_task rc = %d\n", rc); + return rc; + } + init_waitqueue_head(&chg->mmi_timer_wait_que); + wake_up_process(chg->mmi_qc3p_authen_task); + } timer_setup(&chg->apsd_timer, apsd_timer_cb, 0); INIT_DELAYED_WORK(&chg->role_reversal_check, @@ -8729,6 +8907,8 @@ int smblib_deinit(struct smb_charger *chg) cancel_delayed_work_sync(&chg->usbov_dbc_work); cancel_delayed_work_sync(&chg->role_reversal_check); cancel_delayed_work_sync(&chg->pr_swap_detach_work); + if (chg->mmi_qc3p_support && chg->mmi_qc3p_authen_task) + kthread_stop(chg->mmi_qc3p_authen_task); power_supply_unreg_notifier(&chg->nb); smblib_destroy_votables(chg); qcom_step_chg_deinit(); diff --git a/drivers/power/supply/qcom/smb5-lib.h b/drivers/power/supply/qcom/smb5-lib.h index 2dea1c0aff4b..75cad217ee77 100644 --- a/drivers/power/supply/qcom/smb5-lib.h +++ b/drivers/power/supply/qcom/smb5-lib.h @@ -84,6 +84,7 @@ enum print_reason { #define ICL_CHANGE_VOTER "ICL_CHANGE_VOTER" #define OVERHEAT_LIMIT_VOTER "OVERHEAT_LIMIT_VOTER" #define TYPEC_SWAP_VOTER "TYPEC_SWAP_VOTER" +#define SW_QC3P_AUTHEN_VOTER "SW_QC3P_AUTHEN_VOTER" #define BOOST_BACK_STORM_COUNT 3 #define WEAK_CHG_STORM_COUNT 8 @@ -639,6 +640,15 @@ struct smb_charger { ktime_t dcin_uv_last_time; int last_wls_vout; int usb_dcp_curr_max; + + /* mmi qc3p */ + struct iio_channel **iio_chan_list_mmi_cp; + struct task_struct *mmi_qc3p_authen_task; + wait_queue_head_t mmi_timer_wait_que; + enum mmi_qc3p_power mmi_qc3p_power; + bool mmi_is_qc3p_authen; + bool mmi_qc3p_support; + bool mmi_timer_trig_flag; }; int smblib_read(struct smb_charger *chg, u16 addr, u8 *val); diff --git a/include/dt-bindings/iio/qti_power_supply_iio.h b/include/dt-bindings/iio/qti_power_supply_iio.h index d4bd059af5f5..5bf925213ead 100644 --- a/include/dt-bindings/iio/qti_power_supply_iio.h +++ b/include/dt-bindings/iio/qti_power_supply_iio.h @@ -160,4 +160,5 @@ #define PSY_IIO_MMI_CP_INPUT_VOLTAGE_NOW 0x101 #define PSY_IIO_MMI_CP_STATUS1 0x102 #define PSY_IIO_MMI_CP_CLEAR_ERROR 0x103 +#define PSY_IIO_MMI_QC3P_POWER 0x104 #endif /* __QTI_POWER_SUPPLY_IIO_H__ */ diff --git a/include/linux/qti_power_supply.h b/include/linux/qti_power_supply.h index 8b5386389c3d..83c573e570c4 100644 --- a/include/linux/qti_power_supply.h +++ b/include/linux/qti_power_supply.h @@ -113,4 +113,10 @@ enum power_supply_typec_power_role { QTI_POWER_SUPPLY_TYPEC_PR_SOURCE, }; +enum mmi_qc3p_power { + QTI_POWER_SUPPLY_QC3P_NONE, + QTI_POWER_SUPPLY_QC3P_18W, + QTI_POWER_SUPPLY_QC3P_27W, + QTI_POWER_SUPPLY_QC3P_45W, +}; #endif /* __QTI_POWER_SUPPLY_H_ */ From 288b84103d9a9cccd64419daab571da555c06706 Mon Sep 17 00:00:00 2001 From: Paul Lawrence Date: Thu, 22 Apr 2021 13:19:19 -0700 Subject: [PATCH 354/698] Revert "ANDROID: Incremental fs: Fix selinux issues" This reverts commit 75c93eb4397b3fdbc7587e48fb8bb884775747c5. Reason for revert: rolling the three fixes into one with feature flag Bug: 174692664 Test: incfs_test passes Signed-off-by: Paul Lawrence Change-Id: I838bed85d6682aba44165a58c22e6a0e10c49d58 Mot-CRs-fixed: (CR) Reviewed-on: https://gerrit.mot.com/1975975 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: gaoyx9 Submit-Approved: gaoyx9 Tested-by: gaoyx9 Reviewed-by: Huosheng Liao --- fs/incfs/vfs.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/fs/incfs/vfs.c b/fs/incfs/vfs.c index 721fab54126d..ad25bd5ca115 100644 --- a/fs/incfs/vfs.c +++ b/fs/incfs/vfs.c @@ -903,7 +903,7 @@ static int init_new_file(struct mount_info *mi, struct dentry *dentry, .dentry = dentry }; new_file = dentry_open(&path, O_RDWR | O_NOATIME | O_LARGEFILE, - current_cred()); + mi->mi_owner); if (IS_ERR(new_file)) { error = PTR_ERR(new_file); @@ -1031,7 +1031,7 @@ static int dir_relative_path_resolve( if (dir_fd < 0) return dir_fd; - dir_f = dentry_open(base_path, O_RDONLY | O_NOATIME, current_cred()); + dir_f = dentry_open(base_path, O_RDONLY | O_NOATIME, mi->mi_owner); if (IS_ERR(dir_f)) { error = PTR_ERR(dir_f); @@ -1909,13 +1909,10 @@ static int file_open(struct inode *inode, struct file *file) struct file *backing_file = NULL; struct path backing_path = {}; int err = 0; - const struct cred *old_cred; get_incfs_backing_path(file->f_path.dentry, &backing_path); - old_cred = override_creds(mi->mi_owner); - backing_file = dentry_open(&backing_path, - O_RDWR | O_NOATIME | O_LARGEFILE, current_cred()); - revert_creds(old_cred); + backing_file = dentry_open( + &backing_path, O_RDWR | O_NOATIME | O_LARGEFILE, mi->mi_owner); path_put(&backing_path); if (IS_ERR(backing_file)) { From 4e0c72f618d8ba1ec681aac36df54a0af27556ab Mon Sep 17 00:00:00 2001 From: Paul Lawrence Date: Thu, 22 Apr 2021 13:19:39 -0700 Subject: [PATCH 355/698] Revert "ANDROID: Incremental fs: Fix memory leak on closing file" This reverts commit 152fd8f04491a5ccf26c1f1adfb1b228b3082d2c. Reason for revert: rolling the three fixes into one with feature flag Bug: 174692664 Test: incfs_test passes Signed-off-by: Paul Lawrence Change-Id: I9a2e6faa0c2293b691efca8e985390fd94bcf01a Mot-CRs-fixed: (CR) Reviewed-on: https://gerrit.mot.com/1975977 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: gaoyx9 Submit-Approved: gaoyx9 Tested-by: gaoyx9 Reviewed-by: Huosheng Liao --- fs/incfs/data_mgmt.c | 1 - 1 file changed, 1 deletion(-) diff --git a/fs/incfs/data_mgmt.c b/fs/incfs/data_mgmt.c index e0705be44fb2..db0b18dcec1b 100644 --- a/fs/incfs/data_mgmt.c +++ b/fs/incfs/data_mgmt.c @@ -199,7 +199,6 @@ void incfs_free_data_file(struct data_file *df) for (i = 0; i < ARRAY_SIZE(df->df_segments); i++) data_file_segment_destroy(&df->df_segments[i]); incfs_free_bfc(df->df_backing_file_context); - kfree(df->df_signature); kfree(df); } From 565528e8c7f3f895e29544f581a858689ff82e5b Mon Sep 17 00:00:00 2001 From: Paul Lawrence Date: Wed, 3 Feb 2021 10:33:05 -0800 Subject: [PATCH 356/698] ANDROID: Incremental fs: Set credentials before reading/writing Use same selinux scheme as incfs v2 Fix memory leak Bug: 174692664 Test: incfs_test passes Change-Id: I9a07c02a6f2caf93f88efaa3ce14fff34929804b Signed-off-by: Paul Lawrence Mot-CRs-fixed: (CR) Reviewed-on: https://gerrit.mot.com/1975978 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: gaoyx9 Submit-Approved: gaoyx9 Tested-by: gaoyx9 Reviewed-by: Huosheng Liao --- fs/incfs/data_mgmt.c | 1 + fs/incfs/vfs.c | 11 +++++++---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/fs/incfs/data_mgmt.c b/fs/incfs/data_mgmt.c index db0b18dcec1b..e0705be44fb2 100644 --- a/fs/incfs/data_mgmt.c +++ b/fs/incfs/data_mgmt.c @@ -199,6 +199,7 @@ void incfs_free_data_file(struct data_file *df) for (i = 0; i < ARRAY_SIZE(df->df_segments); i++) data_file_segment_destroy(&df->df_segments[i]); incfs_free_bfc(df->df_backing_file_context); + kfree(df->df_signature); kfree(df); } diff --git a/fs/incfs/vfs.c b/fs/incfs/vfs.c index ad25bd5ca115..721fab54126d 100644 --- a/fs/incfs/vfs.c +++ b/fs/incfs/vfs.c @@ -903,7 +903,7 @@ static int init_new_file(struct mount_info *mi, struct dentry *dentry, .dentry = dentry }; new_file = dentry_open(&path, O_RDWR | O_NOATIME | O_LARGEFILE, - mi->mi_owner); + current_cred()); if (IS_ERR(new_file)) { error = PTR_ERR(new_file); @@ -1031,7 +1031,7 @@ static int dir_relative_path_resolve( if (dir_fd < 0) return dir_fd; - dir_f = dentry_open(base_path, O_RDONLY | O_NOATIME, mi->mi_owner); + dir_f = dentry_open(base_path, O_RDONLY | O_NOATIME, current_cred()); if (IS_ERR(dir_f)) { error = PTR_ERR(dir_f); @@ -1909,10 +1909,13 @@ static int file_open(struct inode *inode, struct file *file) struct file *backing_file = NULL; struct path backing_path = {}; int err = 0; + const struct cred *old_cred; get_incfs_backing_path(file->f_path.dentry, &backing_path); - backing_file = dentry_open( - &backing_path, O_RDWR | O_NOATIME | O_LARGEFILE, mi->mi_owner); + old_cred = override_creds(mi->mi_owner); + backing_file = dentry_open(&backing_path, + O_RDWR | O_NOATIME | O_LARGEFILE, current_cred()); + revert_creds(old_cred); path_put(&backing_path); if (IS_ERR(backing_file)) { From e628b2580ed800c06e10eed2740b0be2afa4fe25 Mon Sep 17 00:00:00 2001 From: chailu1 Date: Sun, 13 Jun 2021 18:40:29 +0800 Subject: [PATCH 357/698] qg: disable charging pump when do ESR The product is designed with charging pump and use internal QG. If we don't disable CP, QG can't get valid ESR value when CP enabe. Porting from (CR) Change-Id: I27ea8ae254555afdf37676124a859ce3a179fc76 Reviewed-on: https://gerrit.mot.com/1978508 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- drivers/power/supply/qcom/qg-core.h | 1 + drivers/power/supply/qcom/qpnp-qg.c | 20 +++++++++++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/drivers/power/supply/qcom/qg-core.h b/drivers/power/supply/qcom/qg-core.h index 28bf72d26c27..5c099d1d8168 100644 --- a/drivers/power/supply/qcom/qg-core.h +++ b/drivers/power/supply/qcom/qg-core.h @@ -81,6 +81,7 @@ struct qg_dt { bool multi_profile_load; bool tcss_enable; bool bass_enable; + bool cp_use_internal_qg; }; struct qg_esr_data { diff --git a/drivers/power/supply/qcom/qpnp-qg.c b/drivers/power/supply/qcom/qpnp-qg.c index 42f6b5f3d4a9..9781572a4d6f 100644 --- a/drivers/power/supply/qcom/qpnp-qg.c +++ b/drivers/power/supply/qcom/qpnp-qg.c @@ -1103,6 +1103,15 @@ static int qg_esr_estimate(struct qpnp_qg *chip) goto done; } + if (chip->dt.cp_use_internal_qg) { + rc = qg_write_iio_chan(chip, CP_CHARGING_ENABLED, 0); + if (rc < 0) + pr_err("Failed to force disable cp rc=%d\n", rc); + else + qg_dbg(chip, QG_DEBUG_STATUS, "disable cp\n"); + msleep(1000); + } + for (i = 0; i < qg_esr_count; i++) { /* Fire ESR measurement */ rc = qg_masked_write(chip, @@ -1191,6 +1200,14 @@ static int qg_esr_estimate(struct qpnp_qg *chip) msleep(200); } + if (chip->dt.cp_use_internal_qg) { + rc = qg_write_iio_chan(chip, CP_CHARGING_ENABLED, 1); + if (rc < 0) + pr_err("Failed to force enable cp rc=%d\n", rc); + else + qg_dbg(chip, QG_DEBUG_STATUS, "enable cp\n"); + } + rc = qg_process_esr_data(chip); if (rc < 0) pr_err("Failed to process ESR data rc=%d\n", rc); @@ -4369,7 +4386,8 @@ static int qg_parse_dt(struct qpnp_qg *chip) chip->dt.esr_discharge_enable = of_property_read_bool(node, "qcom,esr-discharge-enable"); - + chip->dt.cp_use_internal_qg = of_property_read_bool(node, + "mmi,cp-use-internal-qg"); rc = of_property_read_u32(node, "qcom,esr-qual-current-ua", &temp); if (rc < 0) chip->dt.esr_qual_i_ua = DEFAULT_ESR_QUAL_CURRENT_UA; From 166bebd6e66f68765f055a582e35e4b9c790c7d4 Mon Sep 17 00:00:00 2001 From: wengjun1 Date: Tue, 15 Jun 2021 10:10:55 +0800 Subject: [PATCH 358/698] spi: Keep spi can transfer message when system in suspend Since qcom baseline upgrade import the change which will return -EACCESS when system in suspend to transfer spi message, and this will conflict with single tap feature. For keep performance and logic consistent with before, remove the new logic introduced by Qcom after discussion with Qcom(SR: 05267011) Change-Id: I6cbf9ca51b62dd9ca9519c762147f83cf3f47831 Signed-off-by: wengjun1 Reviewed-on: https://gerrit.mot.com/1979369 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- drivers/spi/spi-msm-geni.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-msm-geni.c b/drivers/spi/spi-msm-geni.c index 4a20a269906e..7cb55b6bdb1b 100644 --- a/drivers/spi/spi-msm-geni.c +++ b/drivers/spi/spi-msm-geni.c @@ -1006,13 +1006,14 @@ static int spi_geni_prepare_message(struct spi_master *spi, if (mas->shared_ee) { if (mas->setup) { +#if 0 /* Client to respect system suspend */ if (!pm_runtime_enabled(mas->dev)) { GENI_SE_ERR(mas->ipc, false, NULL, "%s: System suspended\n", __func__); return -EACCES; } - +#endif ret = pm_runtime_get_sync(mas->dev); if (ret < 0) { dev_err(mas->dev, @@ -1020,8 +1021,10 @@ static int spi_geni_prepare_message(struct spi_master *spi, __func__, ret); WARN_ON_ONCE(1); pm_runtime_put_noidle(mas->dev); +#if 0 /* Set device in suspended since resume failed */ pm_runtime_set_suspended(mas->dev); +#endif goto exit_prepare_message; } ret = 0; @@ -1342,12 +1345,14 @@ static int spi_geni_prepare_transfer_hardware(struct spi_master *spi) if (mas->is_le_vm) return 0; +#if 0 /* Client to respect system suspend */ if (!pm_runtime_enabled(mas->dev)) { GENI_SE_ERR(mas->ipc, false, NULL, "%s: System suspended\n", __func__); return -EACCES; } +#endif if (mas->gsi_mode && !mas->shared_ee) { struct se_geni_rsc *rsc; @@ -1380,8 +1385,10 @@ static int spi_geni_prepare_transfer_hardware(struct spi_master *spi) __func__, ret); WARN_ON_ONCE(1); pm_runtime_put_noidle(mas->dev); +#if 0 /* Set device in suspended since resume failed */ pm_runtime_set_suspended(mas->dev); +#endif return ret; } @@ -1667,6 +1674,7 @@ static int spi_geni_transfer_one(struct spi_master *spi, GENI_SE_DBG(mas->ipc, false, mas->dev, "current xfer_timeout:%lu ms.\n", xfer_timeout); +#if 0 /* Double check PM status, client might have not taken wakelock and * continue to queue more transfers. Post auto-suspend, system suspend * can keep driver to forced suspend, hence it's client's responsibility @@ -1677,6 +1685,7 @@ static int spi_geni_transfer_one(struct spi_master *spi, "%s: device is PM suspended\n", __func__); return -EACCES; } +#endif if (mas->cur_xfer_mode != GSI_DMA) { reinit_completion(&mas->xfer_done); From 80f26a34d54a5aede4083f8aa0ddffb5228c00f6 Mon Sep 17 00:00:00 2001 From: wuwl10 Date: Fri, 18 Jun 2021 13:37:50 +0800 Subject: [PATCH 359/698] Revert "(CR): pinctrl-holi: revert qcom change for i2c_7" This reverts commit 1957601e86ae219cdbf83594bff8d1db9c418400. We will fix the issue by adding related dts configuration on i2c_7. Change-Id: I197b88025ad89f5a73c87a0c95fe3a2fb2218dec Signed-off-by: wuwl10 Reviewed-on: https://gerrit.mot.com/1985492 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- drivers/pinctrl/qcom/pinctrl-holi.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/drivers/pinctrl/qcom/pinctrl-holi.c b/drivers/pinctrl/qcom/pinctrl-holi.c index 2b546eae6451..c2125c904876 100644 --- a/drivers/pinctrl/qcom/pinctrl-holi.c +++ b/drivers/pinctrl/qcom/pinctrl-holi.c @@ -578,7 +578,8 @@ enum holi_functions { msm_mux_qup01, msm_mux_qup02, msm_mux_qup10, - msm_mux_qup11, + msm_mux_qup11_f1, + msm_mux_qup11_f2, msm_mux_qup12, msm_mux_qup13_f1, msm_mux_qup13_f2, @@ -1026,7 +1027,10 @@ static const char * const qup02_groups[] = { static const char * const qup10_groups[] = { "gpio13", "gpio14", "gpio15", "gpio16", "gpio17", }; -static const char * const qup11_groups[] = { +static const char * const qup11_f1_groups[] = { + "gpio27", "gpio28", +}; +static const char * const qup11_f2_groups[] = { "gpio27", "gpio28", }; static const char * const qup12_groups[] = { @@ -1144,7 +1148,8 @@ static const struct msm_function holi_functions[] = { FUNCTION(edp_lcd), FUNCTION(qup13_f1), FUNCTION(qup13_f2), - FUNCTION(qup11), + FUNCTION(qup11_f1), + FUNCTION(qup11_f2), FUNCTION(PLL_BIST), FUNCTION(qdss_gpio14), FUNCTION(qdss_gpio15), @@ -1330,10 +1335,10 @@ static const struct msm_pingroup holi_groups[] = { 0x9C00C, 15), [26] = PINGROUP(26, qup13_f1, qup13_f2, NA, NA, NA, NA, NA, NA, NA, 0, -1), - [27] = PINGROUP(27, qup11, qup11, MDP_VSYNC, PLL_BIST, NA, qdss_gpio14, - NA, NA, NA, 0x9C010, 0), - [28] = PINGROUP(28, qup11, qup11, MDP_VSYNC, NA, qdss_gpio15, NA, NA, - NA, NA, 0x9C010, 1), + [27] = PINGROUP(27, qup11_f1, qup11_f2, MDP_VSYNC, PLL_BIST, NA, + qdss_gpio14, NA, NA, NA, 0x9C010, 0), + [28] = PINGROUP(28, qup11_f1, qup11_f2, MDP_VSYNC, NA, qdss_gpio15, + NA, NA, NA, NA, 0x9C010, 1), [29] = PINGROUP(29, cam_mclk, NA, NA, NA, NA, NA, NA, NA, NA, 0, -1), [30] = PINGROUP(30, cam_mclk, NA, NA, NA, NA, NA, NA, NA, NA, 0, -1), [31] = PINGROUP(31, cam_mclk, NA, NA, NA, NA, NA, NA, NA, NA, 0, -1), From 487d15b1930d449aaa8a0092095888eb729eead7 Mon Sep 17 00:00:00 2001 From: yangqh5 Date: Tue, 22 Jun 2021 12:42:47 +0800 Subject: [PATCH 360/698] cypfq: initial kernel defconfig Cyprus 5G cypfq on 4350-pro: initial configs cloned from cypfg. Change-Id: I8359a5c1f78e23c67011d46ef294120049924fc6 Reviewed-on: https://gerrit.mot.com/1987589 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiaojun Ji Reviewed-by: Huosheng Liao Submit-Approved: Liyun Zhang --- .../vendor/ext_config/debug-holi-cypfq.config | 25 +++++++++++++++++++ .../ext_config/factory-holi-cypfq.config | 16 ++++++++++++ .../vendor/ext_config/moto-holi-cypfq.config | 20 +++++++++++++++ drivers/soc/qcom/Kconfig | 8 ++++++ 4 files changed, 69 insertions(+) create mode 100644 arch/arm64/configs/vendor/ext_config/debug-holi-cypfq.config create mode 100644 arch/arm64/configs/vendor/ext_config/factory-holi-cypfq.config create mode 100644 arch/arm64/configs/vendor/ext_config/moto-holi-cypfq.config diff --git a/arch/arm64/configs/vendor/ext_config/debug-holi-cypfq.config b/arch/arm64/configs/vendor/ext_config/debug-holi-cypfq.config new file mode 100644 index 000000000000..13f71e03c466 --- /dev/null +++ b/arch/arm64/configs/vendor/ext_config/debug-holi-cypfq.config @@ -0,0 +1,25 @@ +# +# Please avoid changing the Qualcomm defconfig files and use this file to +# add any Motorola-specific configuration changes that are applicable to +# userdebug, eng, and user builds. +# +# After building, a list of all of the config files that are used can be found +# at the top of: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/mapphone_defconfig +# +# The actual output of the kernel configuration system can be found at: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/.config +# +# You can check the .config file to verify that your configuration option is +# being set as expected. +# + +# CONFIG_CGROUP_DEBUG is not set +# CONFIG_CLEANCACHE is not set +# CONFIG_CMA_ALLOW_WRITE_DEBUGFS is not set +# CONFIG_CMA_DEBUG is not set +# CONFIG_PREEMPTIRQ_EVENTS is not set +# CONFIG_PREEMPT_TRACER is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_TEST_USER_COPY is not set diff --git a/arch/arm64/configs/vendor/ext_config/factory-holi-cypfq.config b/arch/arm64/configs/vendor/ext_config/factory-holi-cypfq.config new file mode 100644 index 000000000000..830e8a22f610 --- /dev/null +++ b/arch/arm64/configs/vendor/ext_config/factory-holi-cypfq.config @@ -0,0 +1,16 @@ +# +# Please avoid changing the Qualcomm defconfig files and use this file to +# add any Motorola-specific configuration changes that are applicable to +# userdebug, eng, and user builds. +# +# After building, a list of all of the config files that are used can be found +# at the top of: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/mapphone_defconfig +# +# The actual output of the kernel configuration system can be found at: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/.config +# +# You can check the .config file to verify that your configuration option is +# being set as expected. +# + diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-cypfq.config b/arch/arm64/configs/vendor/ext_config/moto-holi-cypfq.config new file mode 100644 index 000000000000..582ede133237 --- /dev/null +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-cypfq.config @@ -0,0 +1,20 @@ +# +# Please avoid changing the Qualcomm defconfig files and use this file to +# add any Motorola-specific configuration changes that are applicable to +# userdebug, eng, and user builds. +# +# After building, a list of all of the config files that are used can be found +# at the top of: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/mapphone_defconfig +# +# The actual output of the kernel configuration system can be found at: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/.config +# +# You can check the .config file to verify that your configuration option is +# being set as expected. +# +CONFIG_CYPFQ_DTB=y +# CONFIG_NFC_QTI_I2C is not set +CONFIG_FS_EPOLL_WAKEUP_DEBUG=y +CONFIG_ZRAM_WRITEBACK=y +# CONFIG_THERMAL_STATISTICS is not set diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index 4ba2e7c11011..a8089525c123 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -44,6 +44,14 @@ config CYPFG_DTB Only include CYPFG specific DTBs to limit the number that get built during kernel compilation. +config CYPFQ_DTB + depends on ARCH_QCOM + default n + bool "CYPFQ DTBs" + help + Only include CYPFQ specific DTBs to limit the number that + get built during kernel compilation. + config QCOM_AOSS_QMP tristate "Qualcomm AOSS Driver" depends on ARCH_QCOM || COMPILE_TEST From ee00a786d37fb83fa1d00a7b61ffb4c8690751a6 Mon Sep 17 00:00:00 2001 From: yangqh5 Date: Tue, 22 Jun 2021 15:20:52 +0800 Subject: [PATCH 361/698] cypfr: initial kernel defconfig Cyprus 5G cypfr on 6375: initial configs cloned from cypfg. Change-Id: I02922d31b83f9dda121d03fb52cff4a3444a137a Reviewed-on: https://gerrit.mot.com/1987596 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiaojun Ji Reviewed-by: Huosheng Liao Submit-Approved: Liyun Zhang --- .../vendor/ext_config/debug-holi-cypfr.config | 25 +++++++++++++++++++ .../ext_config/factory-holi-cypfr.config | 16 ++++++++++++ .../vendor/ext_config/moto-holi-cypfr.config | 20 +++++++++++++++ drivers/soc/qcom/Kconfig | 8 ++++++ 4 files changed, 69 insertions(+) create mode 100644 arch/arm64/configs/vendor/ext_config/debug-holi-cypfr.config create mode 100644 arch/arm64/configs/vendor/ext_config/factory-holi-cypfr.config create mode 100644 arch/arm64/configs/vendor/ext_config/moto-holi-cypfr.config diff --git a/arch/arm64/configs/vendor/ext_config/debug-holi-cypfr.config b/arch/arm64/configs/vendor/ext_config/debug-holi-cypfr.config new file mode 100644 index 000000000000..13f71e03c466 --- /dev/null +++ b/arch/arm64/configs/vendor/ext_config/debug-holi-cypfr.config @@ -0,0 +1,25 @@ +# +# Please avoid changing the Qualcomm defconfig files and use this file to +# add any Motorola-specific configuration changes that are applicable to +# userdebug, eng, and user builds. +# +# After building, a list of all of the config files that are used can be found +# at the top of: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/mapphone_defconfig +# +# The actual output of the kernel configuration system can be found at: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/.config +# +# You can check the .config file to verify that your configuration option is +# being set as expected. +# + +# CONFIG_CGROUP_DEBUG is not set +# CONFIG_CLEANCACHE is not set +# CONFIG_CMA_ALLOW_WRITE_DEBUGFS is not set +# CONFIG_CMA_DEBUG is not set +# CONFIG_PREEMPTIRQ_EVENTS is not set +# CONFIG_PREEMPT_TRACER is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_TEST_USER_COPY is not set diff --git a/arch/arm64/configs/vendor/ext_config/factory-holi-cypfr.config b/arch/arm64/configs/vendor/ext_config/factory-holi-cypfr.config new file mode 100644 index 000000000000..830e8a22f610 --- /dev/null +++ b/arch/arm64/configs/vendor/ext_config/factory-holi-cypfr.config @@ -0,0 +1,16 @@ +# +# Please avoid changing the Qualcomm defconfig files and use this file to +# add any Motorola-specific configuration changes that are applicable to +# userdebug, eng, and user builds. +# +# After building, a list of all of the config files that are used can be found +# at the top of: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/mapphone_defconfig +# +# The actual output of the kernel configuration system can be found at: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/.config +# +# You can check the .config file to verify that your configuration option is +# being set as expected. +# + diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-cypfr.config b/arch/arm64/configs/vendor/ext_config/moto-holi-cypfr.config new file mode 100644 index 000000000000..88d63a258189 --- /dev/null +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-cypfr.config @@ -0,0 +1,20 @@ +# +# Please avoid changing the Qualcomm defconfig files and use this file to +# add any Motorola-specific configuration changes that are applicable to +# userdebug, eng, and user builds. +# +# After building, a list of all of the config files that are used can be found +# at the top of: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/mapphone_defconfig +# +# The actual output of the kernel configuration system can be found at: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/.config +# +# You can check the .config file to verify that your configuration option is +# being set as expected. +# +CONFIG_CYPFR_DTB=y +# CONFIG_NFC_QTI_I2C is not set +CONFIG_FS_EPOLL_WAKEUP_DEBUG=y +CONFIG_ZRAM_WRITEBACK=y +# CONFIG_THERMAL_STATISTICS is not set diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index a8089525c123..aa979338a66c 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -52,6 +52,14 @@ config CYPFQ_DTB Only include CYPFQ specific DTBs to limit the number that get built during kernel compilation. +config CYPFR_DTB + depends on ARCH_QCOM + default n + bool "CYPFR DTBs" + help + Only include CYPFR specific DTBs to limit the number that + get built during kernel compilation. + config QCOM_AOSS_QMP tristate "Qualcomm AOSS Driver" depends on ARCH_QCOM || COMPILE_TEST From 52a2cf3351316d4d0f4a31cb8cbd7a450e3d4b0b Mon Sep 17 00:00:00 2001 From: gaoyx9 Date: Thu, 24 Jun 2021 21:15:04 +0800 Subject: [PATCH 362/698] corfuq and corfur initial kernel defconfig initial configs cloned from corfup. Change-Id: I56787a1735cb1aa93790554379f959ba53fab5b4 Reviewed-on: https://gerrit.mot.com/1991053 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: gaoyx9 Submit-Approved: gaoyx9 Tested-by: gaoyx9 Reviewed-by: Huosheng Liao --- .../ext_config/debug-holi-corfuq.config | 25 +++++++++++++++++++ .../ext_config/debug-holi-corfur.config | 25 +++++++++++++++++++ .../ext_config/factory-holi-corfuq.config | 16 ++++++++++++ .../ext_config/factory-holi-corfur.config | 16 ++++++++++++ .../vendor/ext_config/moto-holi-corfuq.config | 22 ++++++++++++++++ .../vendor/ext_config/moto-holi-corfur.config | 22 ++++++++++++++++ drivers/soc/qcom/Kconfig | 16 ++++++++++++ 7 files changed, 142 insertions(+) create mode 100644 arch/arm64/configs/vendor/ext_config/debug-holi-corfuq.config create mode 100644 arch/arm64/configs/vendor/ext_config/debug-holi-corfur.config create mode 100644 arch/arm64/configs/vendor/ext_config/factory-holi-corfuq.config create mode 100644 arch/arm64/configs/vendor/ext_config/factory-holi-corfur.config create mode 100644 arch/arm64/configs/vendor/ext_config/moto-holi-corfuq.config create mode 100644 arch/arm64/configs/vendor/ext_config/moto-holi-corfur.config diff --git a/arch/arm64/configs/vendor/ext_config/debug-holi-corfuq.config b/arch/arm64/configs/vendor/ext_config/debug-holi-corfuq.config new file mode 100644 index 000000000000..13f71e03c466 --- /dev/null +++ b/arch/arm64/configs/vendor/ext_config/debug-holi-corfuq.config @@ -0,0 +1,25 @@ +# +# Please avoid changing the Qualcomm defconfig files and use this file to +# add any Motorola-specific configuration changes that are applicable to +# userdebug, eng, and user builds. +# +# After building, a list of all of the config files that are used can be found +# at the top of: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/mapphone_defconfig +# +# The actual output of the kernel configuration system can be found at: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/.config +# +# You can check the .config file to verify that your configuration option is +# being set as expected. +# + +# CONFIG_CGROUP_DEBUG is not set +# CONFIG_CLEANCACHE is not set +# CONFIG_CMA_ALLOW_WRITE_DEBUGFS is not set +# CONFIG_CMA_DEBUG is not set +# CONFIG_PREEMPTIRQ_EVENTS is not set +# CONFIG_PREEMPT_TRACER is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_TEST_USER_COPY is not set diff --git a/arch/arm64/configs/vendor/ext_config/debug-holi-corfur.config b/arch/arm64/configs/vendor/ext_config/debug-holi-corfur.config new file mode 100644 index 000000000000..13f71e03c466 --- /dev/null +++ b/arch/arm64/configs/vendor/ext_config/debug-holi-corfur.config @@ -0,0 +1,25 @@ +# +# Please avoid changing the Qualcomm defconfig files and use this file to +# add any Motorola-specific configuration changes that are applicable to +# userdebug, eng, and user builds. +# +# After building, a list of all of the config files that are used can be found +# at the top of: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/mapphone_defconfig +# +# The actual output of the kernel configuration system can be found at: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/.config +# +# You can check the .config file to verify that your configuration option is +# being set as expected. +# + +# CONFIG_CGROUP_DEBUG is not set +# CONFIG_CLEANCACHE is not set +# CONFIG_CMA_ALLOW_WRITE_DEBUGFS is not set +# CONFIG_CMA_DEBUG is not set +# CONFIG_PREEMPTIRQ_EVENTS is not set +# CONFIG_PREEMPT_TRACER is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_TEST_USER_COPY is not set diff --git a/arch/arm64/configs/vendor/ext_config/factory-holi-corfuq.config b/arch/arm64/configs/vendor/ext_config/factory-holi-corfuq.config new file mode 100644 index 000000000000..830e8a22f610 --- /dev/null +++ b/arch/arm64/configs/vendor/ext_config/factory-holi-corfuq.config @@ -0,0 +1,16 @@ +# +# Please avoid changing the Qualcomm defconfig files and use this file to +# add any Motorola-specific configuration changes that are applicable to +# userdebug, eng, and user builds. +# +# After building, a list of all of the config files that are used can be found +# at the top of: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/mapphone_defconfig +# +# The actual output of the kernel configuration system can be found at: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/.config +# +# You can check the .config file to verify that your configuration option is +# being set as expected. +# + diff --git a/arch/arm64/configs/vendor/ext_config/factory-holi-corfur.config b/arch/arm64/configs/vendor/ext_config/factory-holi-corfur.config new file mode 100644 index 000000000000..830e8a22f610 --- /dev/null +++ b/arch/arm64/configs/vendor/ext_config/factory-holi-corfur.config @@ -0,0 +1,16 @@ +# +# Please avoid changing the Qualcomm defconfig files and use this file to +# add any Motorola-specific configuration changes that are applicable to +# userdebug, eng, and user builds. +# +# After building, a list of all of the config files that are used can be found +# at the top of: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/mapphone_defconfig +# +# The actual output of the kernel configuration system can be found at: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/.config +# +# You can check the .config file to verify that your configuration option is +# being set as expected. +# + diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-corfuq.config b/arch/arm64/configs/vendor/ext_config/moto-holi-corfuq.config new file mode 100644 index 000000000000..b5bf64fc77d5 --- /dev/null +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-corfuq.config @@ -0,0 +1,22 @@ +# +# Please avoid changing the Qualcomm defconfig files and use this file to +# add any Motorola-specific configuration changes that are applicable to +# userdebug, eng, and user builds. +# +# After building, a list of all of the config files that are used can be found +# at the top of: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/mapphone_defconfig +# +# The actual output of the kernel configuration system can be found at: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/.config +# +# You can check the .config file to verify that your configuration option is +# being set as expected. +# +CONFIG_CORFUP_DTB=y +# CONFIG_NFC_QTI_I2C is not set +CONFIG_FS_EPOLL_WAKEUP_DEBUG=y +CONFIG_ZRAM_WRITEBACK=y +# CONFIG_THERMAL_STATISTICS is not set +# CONFIG_TOUCHSCREEN_FTS is not set +# CONFIG_TOUCHSCREEN_FTS_DIRECTORY is not set diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-corfur.config b/arch/arm64/configs/vendor/ext_config/moto-holi-corfur.config new file mode 100644 index 000000000000..b5bf64fc77d5 --- /dev/null +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-corfur.config @@ -0,0 +1,22 @@ +# +# Please avoid changing the Qualcomm defconfig files and use this file to +# add any Motorola-specific configuration changes that are applicable to +# userdebug, eng, and user builds. +# +# After building, a list of all of the config files that are used can be found +# at the top of: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/mapphone_defconfig +# +# The actual output of the kernel configuration system can be found at: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/.config +# +# You can check the .config file to verify that your configuration option is +# being set as expected. +# +CONFIG_CORFUP_DTB=y +# CONFIG_NFC_QTI_I2C is not set +CONFIG_FS_EPOLL_WAKEUP_DEBUG=y +CONFIG_ZRAM_WRITEBACK=y +# CONFIG_THERMAL_STATISTICS is not set +# CONFIG_TOUCHSCREEN_FTS is not set +# CONFIG_TOUCHSCREEN_FTS_DIRECTORY is not set diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index aa979338a66c..acf8eadfb84c 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -36,6 +36,22 @@ config CORFUP_DTB Only include CORFUP specific DTBs to limit the number that get built during kernel compilation. +config CORFUQ_DTB + depends on ARCH_QCOM + default n + bool "CORFUQ DTBs" + help + Only include CORFUQ specific DTBs to limit the number that + get built during kernel compilation. + +config CORFUR_DTB + depends on ARCH_QCOM + default n + bool "CORFUR DTBs" + help + Only include CORFUR specific DTBs to limit the number that + get built during kernel compilation. + config CYPFG_DTB depends on ARCH_QCOM default n From 7a4f190e627210104d05b7fb487cc6c1ef3f602c Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Mon, 2 Mar 2020 19:03:09 -0800 Subject: [PATCH 363/698] ANDROID: scsi: ufs: add manual_gc in sysfs with UFS 3.1 This patch adds manual_gc control via sysfs entries. > cat /sys/devices/platform/soc/1d84000.ufshc/manual_gc on > echo 1 > /sys/devices/platform/soc/1d84000.ufshc/manual_gc Mot-CRs-fixed: (CR) Link: https://android-review.googlesource.com/c/kernel/common/+/1426015 Change-Id: I265093c126d71f2e594ed305ad7653a9315b4d63 Reviewed-on: https://gerrit.mot.com/1987790 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- drivers/scsi/ufs/Kconfig | 6 ++ drivers/scsi/ufs/ufs-sysfs.c | 134 +++++++++++++++++++++++++++++++++++ drivers/scsi/ufs/ufs.h | 15 ++++ drivers/scsi/ufs/ufshcd.c | 90 +++++++++++++++++++++-- drivers/scsi/ufs/ufshcd.h | 23 +++++- 5 files changed, 263 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/ufs/Kconfig b/drivers/scsi/ufs/Kconfig index 1c3484c72b6b..f71efcca00c0 100644 --- a/drivers/scsi/ufs/Kconfig +++ b/drivers/scsi/ufs/Kconfig @@ -249,6 +249,12 @@ config SCSI_SKHPB help Activate or deactive SKHPB driver +config SCSI_SKHID + bool "Activate HPB Host-aware Performance Booster" + depends on (SCSI_UFSHCD || SCSI_UFSHCD_QTI) + help + Activate or deactive SKHPB driver + config MICRON_HPB bool "Activate micron HPB Host-aware Performance Booster" depends on SCSI_UFSHCD && UFSFEATURE && UFSHPB diff --git a/drivers/scsi/ufs/ufs-sysfs.c b/drivers/scsi/ufs/ufs-sysfs.c index 1d10866df1f6..42447e1fac49 100644 --- a/drivers/scsi/ufs/ufs-sysfs.c +++ b/drivers/scsi/ufs/ufs-sysfs.c @@ -7,6 +7,9 @@ #include #include "ufs.h" +#if defined(CONFIG_SCSI_SKHID) +#include "ufshcd.h" +#endif #include "ufs-sysfs.h" static const char *ufschd_uic_link_state_to_string( @@ -182,6 +185,129 @@ static ssize_t auto_hibern8_store(struct device *dev, return count; } +#if defined(CONFIG_SCSI_SKHID) +static ssize_t manual_gc_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ufs_hba *hba = dev_get_drvdata(dev); + u32 status = MANUAL_GC_OFF; + + if (hba->manual_gc.state == MANUAL_GC_DISABLE) + return scnprintf(buf, PAGE_SIZE, "%s", "disabled\n"); + + pm_runtime_get_sync(hba->dev); + + //down_read(&hba->query_lock); + if (hba->manual_gc.hagc_support) { + int err = ufshcd_query_attr_retry(hba, + UPIU_QUERY_OPCODE_READ_ATTR, + QUERY_ATTR_IDN_MANUAL_GC_STATUS, 0, 0, &status); + + hba->manual_gc.hagc_support = err ? false: true; + } + //up_read(&hba->query_lock); + pm_runtime_mark_last_busy(hba->dev); + pm_runtime_put_noidle(hba->dev); + + if (!hba->manual_gc.hagc_support) + return scnprintf(buf, PAGE_SIZE, "%s", "bkops\n"); + return scnprintf(buf, PAGE_SIZE, "%s", + status == MANUAL_GC_OFF ? "off\n" : "on\n"); +} + +static int manual_gc_enable(struct ufs_hba *hba, u32 *value) +{ + return ufshcd_query_attr_retry(hba, + UPIU_QUERY_OPCODE_WRITE_ATTR, + QUERY_ATTR_IDN_MANUAL_GC_CONT, 0, 0, + value); +} + +static ssize_t manual_gc_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct ufs_hba *hba = dev_get_drvdata(dev); + u32 value; + int err = 0; + + if (kstrtou32(buf, 0, &value)) + return -EINVAL; + + if (value >= MANUAL_GC_MAX) + return -EINVAL; + + if (value == MANUAL_GC_DISABLE || value == MANUAL_GC_ENABLE) { + hba->manual_gc.state = value; + return count; + } + if (hba->manual_gc.state == MANUAL_GC_DISABLE) + return count; + + pm_runtime_get_sync(hba->dev); + + if (hba->manual_gc.hagc_support) + hba->manual_gc.hagc_support = + manual_gc_enable(hba, &value) ? false : true; + + if (!hba->manual_gc.hagc_support) { + enum query_opcode opcode = (value == MANUAL_GC_ON) ? + UPIU_QUERY_OPCODE_SET_FLAG: + UPIU_QUERY_OPCODE_CLEAR_FLAG; + + err = ufshcd_bkops_ctrl(hba, (value == MANUAL_GC_ON) ? + BKOPS_STATUS_NON_CRITICAL: + BKOPS_STATUS_CRITICAL); + if (!hba->auto_bkops_enabled) + err = -EAGAIN; + + /* flush wb buffer */ + if (hba->dev_info.wspecversion >= 0x0310) { + u8 index = ufshcd_wb_get_query_index(hba); + + ufshcd_query_flag_retry(hba, opcode, + QUERY_FLAG_IDN_WB_BUFF_FLUSH_DURING_HIBERN8, + index, NULL); + ufshcd_query_flag_retry(hba, opcode, + QUERY_FLAG_IDN_WB_BUFF_FLUSH_EN, index, NULL); + } + } + + if (err || hrtimer_active(&hba->manual_gc.hrtimer)) { + pm_runtime_mark_last_busy(hba->dev); + pm_runtime_put_noidle(hba->dev); + return count; + } else { + /* pm_runtime_put_sync in delay_ms */ + hrtimer_start(&hba->manual_gc.hrtimer, + ms_to_ktime(hba->manual_gc.delay_ms), + HRTIMER_MODE_REL); + } + return count; +} + +static ssize_t manual_gc_hold_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ufs_hba *hba = dev_get_drvdata(dev); + + return snprintf(buf, PAGE_SIZE, "%lu\n", hba->manual_gc.delay_ms); +} + +static ssize_t manual_gc_hold_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct ufs_hba *hba = dev_get_drvdata(dev); + unsigned long value; + + if (kstrtoul(buf, 0, &value)) + return -EINVAL; + + hba->manual_gc.delay_ms = value; + return count; +} +#endif + static DEVICE_ATTR_RW(rpm_lvl); static DEVICE_ATTR_RO(rpm_target_dev_state); static DEVICE_ATTR_RO(rpm_target_link_state); @@ -189,6 +315,10 @@ static DEVICE_ATTR_RW(spm_lvl); static DEVICE_ATTR_RO(spm_target_dev_state); static DEVICE_ATTR_RO(spm_target_link_state); static DEVICE_ATTR_RW(auto_hibern8); +#if defined(CONFIG_SCSI_SKHID) +static DEVICE_ATTR_RW(manual_gc); +static DEVICE_ATTR_RW(manual_gc_hold); +#endif static struct attribute *ufs_sysfs_ufshcd_attrs[] = { &dev_attr_rpm_lvl.attr, @@ -198,6 +328,10 @@ static struct attribute *ufs_sysfs_ufshcd_attrs[] = { &dev_attr_spm_target_dev_state.attr, &dev_attr_spm_target_link_state.attr, &dev_attr_auto_hibern8.attr, +#if defined(CONFIG_SCSI_SKHID) + &dev_attr_manual_gc.attr, + &dev_attr_manual_gc_hold.attr, +#endif NULL }; diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h index 39a2b164c661..a77312b8a5fb 100644 --- a/drivers/scsi/ufs/ufs.h +++ b/drivers/scsi/ufs/ufs.h @@ -198,6 +198,11 @@ enum attr_idn { QUERY_ATTR_IDN_TW_BUF_LIFETIME_EST = 0x1E, QUERY_ATTR_IDN_TW_CURR_BUF_SIZE = 0x1F, #endif +#if defined(CONFIG_SCSI_SKHID) + /* use one reserved bit */ + QUERY_ATTR_IDN_MANUAL_GC_CONT = 0x12, + QUERY_ATTR_IDN_MANUAL_GC_STATUS = 0x13, +#endif #if defined(CONFIG_UFSFEATURE) QUERY_ATTR_IDN_SUP_VENDOR_OPTIONS = 0xFF, #endif @@ -385,6 +390,16 @@ enum geometry_desc_param { #endif }; +#if defined(CONFIG_SCSI_SKHID) +enum { + MANUAL_GC_OFF = 0, + MANUAL_GC_ON, + MANUAL_GC_DISABLE, + MANUAL_GC_ENABLE, + MANUAL_GC_MAX, +}; +#endif + /* Health descriptor parameters offsets in bytes*/ enum health_desc_param { HEALTH_DESC_PARAM_LEN = 0x0, diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index c946df276b66..baa238cb1f17 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -140,6 +140,11 @@ unsigned int storage_mfrid; /* Polling time to wait for fDeviceInit */ #define FDEVICEINIT_COMPL_TIMEOUT 5000 /* millisecs */ +#if defined(CONFIG_SCSI_SKHID) +/* for manual gc */ +#define UFSHCD_MANUAL_GC_HOLD_HIBERN8 2000 /* 2 seconds */ +#endif + #define ufshcd_toggle_vreg(_dev, _vreg, _on) \ ({ \ int _ret; \ @@ -1698,6 +1703,51 @@ static void ufshcd_clkscaling_init_sysfs(struct ufs_hba *hba) dev_err(hba->dev, "Failed to create sysfs for clkscale_enable\n"); } +#if defined(CONFIG_SCSI_SKHID) +static enum hrtimer_restart ufshcd_mgc_hrtimer_handler(struct hrtimer *timer) +{ + struct ufs_hba *hba = container_of(timer, struct ufs_hba, + manual_gc.hrtimer); + + queue_work(hba->manual_gc.mgc_workq, &hba->manual_gc.hibern8_work); + return HRTIMER_NORESTART; +} + +static void ufshcd_mgc_hibern8_work(struct work_struct *work) +{ + struct ufs_hba *hba = container_of(work, struct ufs_hba, + manual_gc.hibern8_work); + pm_runtime_mark_last_busy(hba->dev); + pm_runtime_put_noidle(hba->dev); + /* bkops will be disabled when power down */ +} + +static void ufshcd_init_manual_gc(struct ufs_hba *hba) +{ + struct ufs_manual_gc *mgc = &hba->manual_gc; + char wq_name[sizeof("ufs_mgc_hibern8_work")]; + + mgc->state = MANUAL_GC_ENABLE; + mgc->hagc_support = true; + mgc->delay_ms = UFSHCD_MANUAL_GC_HOLD_HIBERN8; + + hrtimer_init(&mgc->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + mgc->hrtimer.function = ufshcd_mgc_hrtimer_handler; + + INIT_WORK(&mgc->hibern8_work, ufshcd_mgc_hibern8_work); + snprintf(wq_name, ARRAY_SIZE(wq_name), "ufs_mgc_hibern8_work_%d", + hba->host->host_no); + hba->manual_gc.mgc_workq = create_singlethread_workqueue(wq_name); +} + +static void ufshcd_exit_manual_gc(struct ufs_hba *hba) +{ + hrtimer_cancel(&hba->manual_gc.hrtimer); + cancel_work_sync(&hba->manual_gc.hibern8_work); + destroy_workqueue(hba->manual_gc.mgc_workq); +} +#endif + static void ufshcd_ungate_work(struct work_struct *work) { int ret; @@ -3080,7 +3130,7 @@ static inline void ufshcd_init_query(struct ufs_hba *hba, (*request)->upiu_req.selector = selector; } -#if defined(CONFIG_SCSI_SKHPB) +#if defined(CONFIG_SCSI_SKHPB) || defined(CONFIG_SCSI_SKHID) int ufshcd_query_flag_retry(struct ufs_hba *hba, enum query_opcode opcode, enum flag_idn idn, u8 index, bool *flag_res) #else @@ -3091,6 +3141,11 @@ static int ufshcd_query_flag_retry(struct ufs_hba *hba, int ret; int retries; +#if defined(CONFIG_SCSI_SKHID) + if (ufshcd_eh_in_progress(hba)) + return -EBUSY; +#endif + for (retries = 0; retries < QUERY_REQ_RETRIES; retries++) { ret = ufshcd_query_flag(hba, opcode, idn, index, flag_res); if (ret) @@ -3255,14 +3310,25 @@ EXPORT_SYMBOL_GPL(ufshcd_query_attr); * * Returns 0 for success, non-zero in case of failure */ +#if defined(CONFIG_SCSI_SKHID) +int ufshcd_query_attr_retry(struct ufs_hba *hba, + enum query_opcode opcode, enum attr_idn idn, u8 index, u8 selector, + u32 *attr_val) +#else static int ufshcd_query_attr_retry(struct ufs_hba *hba, enum query_opcode opcode, enum attr_idn idn, u8 index, u8 selector, u32 *attr_val) +#endif { int ret = 0; u32 retries; - for (retries = QUERY_REQ_RETRIES; retries > 0; retries--) { +#if defined(CONFIG_SCSI_SKHID) + if (ufshcd_eh_in_progress(hba)) + return -EBUSY; +#endif + + for (retries = QUERY_REQ_RETRIES; retries > 0; retries--) { ret = ufshcd_query_attr(hba, opcode, idn, index, selector, attr_val); if (ret) @@ -5591,12 +5657,21 @@ static inline int ufshcd_get_bkops_status(struct ufs_hba *hba, u32 *status) * to know whether auto bkops is enabled or disabled after this function * returns control to it. */ +#if defined(CONFIG_SCSI_SKHID) +int ufshcd_bkops_ctrl(struct ufs_hba *hba, enum bkops_status status) +#else static int ufshcd_bkops_ctrl(struct ufs_hba *hba, enum bkops_status status) +#endif { int err; u32 curr_status = 0; +#if defined(CONFIG_SCSI_SKHID) + if (ufshcd_eh_in_progress(hba)) + return -EBUSY; +#endif + err = ufshcd_get_bkops_status(hba, &curr_status); if (err) { dev_err(hba->dev, "%s: failed to get BKOPS status %d\n", @@ -9557,7 +9632,9 @@ void ufshcd_remove(struct ufs_hba *hba) /* disable interrupts */ ufshcd_disable_intr(hba, hba->intr_mask); ufshcd_hba_stop(hba, true); - +#if defined(CONFIG_SCSI_SKHID) + ufshcd_exit_manual_gc(hba); +#endif ufshcd_exit_clk_scaling(hba); ufshcd_exit_clk_gating(hba); if (ufshcd_is_clkscaling_supported(hba)) @@ -9742,7 +9819,9 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq) ufshcd_init_clk_gating(hba); ufshcd_init_clk_scaling(hba); - +#if defined(CONFIG_SCSI_SKHID) + ufshcd_init_manual_gc(hba); +#endif /* * In order to avoid any spurious interrupt immediately after * registering UFS controller interrupt handler, clear any pending UFS @@ -9847,6 +9926,9 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq) out_remove_scsi_host: scsi_remove_host(hba->host); exit_gating: +#if defined(CONFIG_SCSI_SKHID) + ufshcd_exit_manual_gc(hba); +#endif ufshcd_exit_clk_scaling(hba); ufshcd_exit_clk_gating(hba); destroy_workqueue(hba->eh_wq); diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index 0273ec1dcc8a..989cc4eadebf 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -484,6 +484,18 @@ struct ufs_clk_gating { struct workqueue_struct *clk_gating_workq; }; +#if defined(CONFIG_SCSI_SKHID) +/* for manual gc */ +struct ufs_manual_gc { + int state; + bool hagc_support; + struct hrtimer hrtimer; + unsigned long delay_ms; + struct work_struct hibern8_work; + struct workqueue_struct *mgc_workq; +}; +#endif + struct ufs_saved_pwr_info { struct ufs_pa_layer_attr info; bool is_valid; @@ -936,6 +948,9 @@ struct ufs_hba { /* Keeps information of the UFS device connected to this host */ struct ufs_dev_info dev_info; bool auto_bkops_enabled; +#if defined(CONFIG_SCSI_SKHID) + struct ufs_manual_gc manual_gc; +#endif struct ufs_vreg_info vreg_info; struct list_head clk_list_head; @@ -1252,6 +1267,12 @@ extern int ufshcd_dme_get_attr(struct ufs_hba *hba, u32 attr_sel, u32 *mib_val, u8 peer); extern int ufshcd_config_pwr_mode(struct ufs_hba *hba, struct ufs_pa_layer_attr *desired_pwr_mode); +#if defined(CONFIG_SCSI_SKHID) +extern int ufshcd_query_attr_retry(struct ufs_hba *hba, + enum query_opcode opcode, enum attr_idn idn, u8 index, u8 selector, + u32 *attr_val); +extern int ufshcd_bkops_ctrl(struct ufs_hba *hba, enum bkops_status status); +#endif /* UIC command interfaces for DME primitives */ #define DME_LOCAL 0 #define DME_PEER 1 @@ -1541,7 +1562,7 @@ static inline u8 ufshcd_scsi_to_upiu_lun(unsigned int scsi_lun) return scsi_lun & UFS_UPIU_MAX_UNIT_NUM_ID; } -#if defined(CONFIG_SCSI_SKHPB) +#if defined(CONFIG_SCSI_SKHPB) || defined(CONFIG_SCSI_SKHID) int ufshcd_query_flag_retry(struct ufs_hba *hba, enum query_opcode opcode, enum flag_idn idn, u8 index, bool *flag_res); #endif From 631726a140fe2def0edc976e69750beb5ab4cc30 Mon Sep 17 00:00:00 2001 From: Kyuho Choi Date: Wed, 3 Feb 2021 02:25:14 -0500 Subject: [PATCH 364/698] drivers: scsi: ufs: Add manual_gc_status attribute This patch added manual_gc_status attriute to host. Through manual_gc_status attribute, host will get hagc status hint and can trigger hagc when device are dirty status. Mot-CRs-fixed: (CR) Change-Id: Ie8fad3c34c48dc9fe01cf8a7ecb8d19e110bd0c8 Reviewed-on: https://gerrit.mot.com/1987900 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- drivers/scsi/ufs/ufs-sysfs.c | 6 ++++++ drivers/scsi/ufs/ufshcd.c | 15 --------------- 2 files changed, 6 insertions(+), 15 deletions(-) diff --git a/drivers/scsi/ufs/ufs-sysfs.c b/drivers/scsi/ufs/ufs-sysfs.c index 42447e1fac49..57d9ca66366c 100644 --- a/drivers/scsi/ufs/ufs-sysfs.c +++ b/drivers/scsi/ufs/ufs-sysfs.c @@ -869,6 +869,9 @@ UFS_ATTRIBUTE(wb_flush_status, _WB_FLUSH_STATUS); UFS_ATTRIBUTE(wb_avail_buf, _AVAIL_WB_BUFF_SIZE); UFS_ATTRIBUTE(wb_life_time_est, _WB_BUFF_LIFE_TIME_EST); UFS_ATTRIBUTE(wb_cur_buf, _CURR_WB_BUFF_SIZE); +#if defined(CONFIG_SCSI_SKHID) +UFS_ATTRIBUTE(manual_gc_status, _MANUAL_GC_STATUS); +#endif static struct attribute *ufs_sysfs_attributes[] = { @@ -892,6 +895,9 @@ static struct attribute *ufs_sysfs_attributes[] = { &dev_attr_wb_avail_buf.attr, &dev_attr_wb_life_time_est.attr, &dev_attr_wb_cur_buf.attr, +#if defined(CONFIG_SCSI_SKHID) + &dev_attr_manual_gc_status.attr, +#endif NULL, }; diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index baa238cb1f17..87d266162cd1 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -3141,11 +3141,6 @@ static int ufshcd_query_flag_retry(struct ufs_hba *hba, int ret; int retries; -#if defined(CONFIG_SCSI_SKHID) - if (ufshcd_eh_in_progress(hba)) - return -EBUSY; -#endif - for (retries = 0; retries < QUERY_REQ_RETRIES; retries++) { ret = ufshcd_query_flag(hba, opcode, idn, index, flag_res); if (ret) @@ -3323,11 +3318,6 @@ static int ufshcd_query_attr_retry(struct ufs_hba *hba, int ret = 0; u32 retries; -#if defined(CONFIG_SCSI_SKHID) - if (ufshcd_eh_in_progress(hba)) - return -EBUSY; -#endif - for (retries = QUERY_REQ_RETRIES; retries > 0; retries--) { ret = ufshcd_query_attr(hba, opcode, idn, index, selector, attr_val); @@ -5667,11 +5657,6 @@ static int ufshcd_bkops_ctrl(struct ufs_hba *hba, int err; u32 curr_status = 0; -#if defined(CONFIG_SCSI_SKHID) - if (ufshcd_eh_in_progress(hba)) - return -EBUSY; -#endif - err = ufshcd_get_bkops_status(hba, &curr_status); if (err) { dev_err(hba->dev, "%s: failed to get BKOPS status %d\n", From 97a401f886e62bbb83713d4617e630c994a96cb7 Mon Sep 17 00:00:00 2001 From: chailu1 Date: Thu, 24 Jun 2021 15:00:50 +0800 Subject: [PATCH 365/698] QC3+: Workaround salcom qc3+ charge adapter Salcom qc3+ charge adapter have a issue:connect salcom to phone,while phone tirgger 16 Dp/Dm pluse then remove usb cable, salcom charge adaper side will not reset Dp/Dm counter. So then connect salcom charge adapter to phone again. salcom will become qc3.0 mode. So need SW workaround salcom charge adapter issue:if phone side detect qc30 will run APSD. Change-Id: I2cc913125ec70223abfaedc75dc156079e55c355 Reviewed-on: https://gerrit.mot.com/1993349 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Haijian Ma Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- drivers/power/supply/qcom/smb5-lib.c | 50 ++++++++++++++++++++++++++-- drivers/power/supply/qcom/smb5-lib.h | 1 + 2 files changed, 48 insertions(+), 3 deletions(-) diff --git a/drivers/power/supply/qcom/smb5-lib.c b/drivers/power/supply/qcom/smb5-lib.c index f0c2491079e3..7ff2e8ca4a38 100644 --- a/drivers/power/supply/qcom/smb5-lib.c +++ b/drivers/power/supply/qcom/smb5-lib.c @@ -5173,7 +5173,10 @@ int smblib_get_charge_current(struct smb_charger *chg, typec_source_rd = smblib_get_prop_ufp_mode(chg); /* QC 2.0/3.0 adapter */ - if (apsd_result->bit & QC_2P0_BIT) { + if (chg->mmi_qc3p_rerun_done){ + *total_current_ua = HVDCP_CURRENT_UA; + return 0; + } else if (apsd_result->bit & QC_2P0_BIT) { *total_current_ua = chg->chg_param.hvdcp2_max_icl_ua; return 0; } else if (apsd_result->bit & QC_3P0_BIT){ @@ -5812,6 +5815,7 @@ static void smblib_usb_plugin_locked(struct smb_charger *chg) schedule_delayed_work(&chg->pl_enable_work, msecs_to_jiffies(PL_DELAY_MS)); } else { + chg->mmi_qc3p_rerun_done = false; /* Disable SW Thermal Regulation */ rc = smblib_set_sw_thermal_regulation(chg, false); if (rc < 0) @@ -5926,6 +5930,42 @@ static int mmi_get_vbus(struct smb_charger *chg) } } +bool mmi_rerun_qc3p_det(struct smb_charger *chg) +{ + union power_supply_propval val; + int rc; + + if (!chg->mmi_qc3p_rerun_done) { + rc = smblib_get_prop_usb_present(chg, &val); + if (rc < 0) { + smblib_err(chg, "Couldn't get usb present rc = %d\n", rc); + return false; + } else if (!val.intval) { + smblib_err(chg, "usb is not present\n"); + return false; + } + + smblib_dbg(chg, PR_MISC, "rerun qcep detect\n"); + rc = smblib_request_dpdm(chg, true); + if (rc < 0) { + smblib_err(chg, "Couldn't to enable DPDM rc=%d\n", rc); + return false; + } + rc = smblib_masked_write(chg, CMD_APSD_REG, + APSD_RERUN_BIT, APSD_RERUN_BIT); + if (rc < 0) { + smblib_err(chg, "Couldn't re-run APSD rc=%d\n", rc); + return false; + } + chg->mmi_qc3p_rerun_done = true; + chg->apsd_ext_timeout = false; + + return true; + }else + return false; +} + + #define QC3P_AUTHEN_LOW_THR_MV 5500 #define QC3P_AUTHEN_HIGH_THR_MV 6500 #define QC3P_AUTHEN_NONE_THR_MV 9500 @@ -5942,6 +5982,7 @@ static int mmi_qc3p_kthread_handler(void *param) sched_setscheduler(current, SCHED_FIFO, &sch_param); do { + start: wait_event_interruptible(chg->mmi_timer_wait_que, chg->mmi_timer_trig_flag || kthread_should_stop()); if (kthread_should_stop()) break; @@ -5962,9 +6003,12 @@ static int mmi_qc3p_kthread_handler(void *param) v_aut = mmi_get_vbus(chg); j1 = jiffies - j1; if (v_aut < QC3P_AUTHEN_LOW_THR_MV || v_aut > QC3P_AUTHEN_HIGH_THR_MV) { - chg->mmi_qc3p_power = QTI_POWER_SUPPLY_QC3P_NONE; smblib_err(chg, "is qc3.0 charge adatper vbus=%d\n",v_aut); - goto out; + chg->mmi_qc3p_power = QTI_POWER_SUPPLY_QC3P_NONE; + if (mmi_rerun_qc3p_det(chg)) + goto start; + else + goto out; } for (i = 0;i < 3; i++) { diff --git a/drivers/power/supply/qcom/smb5-lib.h b/drivers/power/supply/qcom/smb5-lib.h index 75cad217ee77..4a9c88a5f26c 100644 --- a/drivers/power/supply/qcom/smb5-lib.h +++ b/drivers/power/supply/qcom/smb5-lib.h @@ -649,6 +649,7 @@ struct smb_charger { bool mmi_is_qc3p_authen; bool mmi_qc3p_support; bool mmi_timer_trig_flag; + bool mmi_qc3p_rerun_done; }; int smblib_read(struct smb_charger *chg, u16 addr, u8 *val); From d60223719c07483bd9b4f8e6cefb4ff9ee1d1b60 Mon Sep 17 00:00:00 2001 From: louhs1 Date: Tue, 29 Jun 2021 15:33:14 +0800 Subject: [PATCH 366/698] corfuq/corfur: init the kernel defconfig init the corfuq/corfur kernel defconig corfuq use 4350pro corfur use 6375 Change-Id: I4b47a50228ef9c35134c3f1483ed75a955965b6f Signed-off-by: louhs1 Reviewed-on: https://gerrit.mot.com/1995451 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi-corfuq.config | 2 +- arch/arm64/configs/vendor/ext_config/moto-holi-corfur.config | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-corfuq.config b/arch/arm64/configs/vendor/ext_config/moto-holi-corfuq.config index b5bf64fc77d5..b9ac647b582b 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-corfuq.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-corfuq.config @@ -13,7 +13,7 @@ # You can check the .config file to verify that your configuration option is # being set as expected. # -CONFIG_CORFUP_DTB=y +CONFIG_CORFUQ_DTB=y # CONFIG_NFC_QTI_I2C is not set CONFIG_FS_EPOLL_WAKEUP_DEBUG=y CONFIG_ZRAM_WRITEBACK=y diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-corfur.config b/arch/arm64/configs/vendor/ext_config/moto-holi-corfur.config index b5bf64fc77d5..f0bab2d21f39 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-corfur.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-corfur.config @@ -13,7 +13,7 @@ # You can check the .config file to verify that your configuration option is # being set as expected. # -CONFIG_CORFUP_DTB=y +CONFIG_CORFUR_DTB=y # CONFIG_NFC_QTI_I2C is not set CONFIG_FS_EPOLL_WAKEUP_DEBUG=y CONFIG_ZRAM_WRITEBACK=y From 008a545e925e27f7b1f32a769d0a7d8e52748f88 Mon Sep 17 00:00:00 2001 From: panzh2 Date: Wed, 18 Nov 2020 13:45:15 +0800 Subject: [PATCH 367/698] kernel: vibrator: diff vol for long/short vib This is a workarround to reduce the vibrator strength for long vib. Add attribute "qcom,vib-dis-short-long" in device-tree to enable the function. Change-Id: I91e2612f878e6e6614d46797bcd7987cd46b9fba Signed-off-by: wuwl10 Reviewed-on: https://gerrit.mot.com/1995828 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Wanlong Zhou Reviewed-by: Zhenghai Pan Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- drivers/leds/leds-qpnp-vibrator-ldo.c | 35 +++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/drivers/leds/leds-qpnp-vibrator-ldo.c b/drivers/leds/leds-qpnp-vibrator-ldo.c index d7d0c6112ed0..59d391aeb551 100644 --- a/drivers/leds/leds-qpnp-vibrator-ldo.c +++ b/drivers/leds/leds-qpnp-vibrator-ldo.c @@ -54,6 +54,10 @@ struct vib_ldo_chip { u64 vib_play_ms; bool vib_enabled; bool disable_overdrive; + + bool dis_short_long; + int dis_long_ms; + int vmax_uV_long; }; static inline int qpnp_vib_ldo_poll_status(struct vib_ldo_chip *chip) @@ -144,6 +148,15 @@ static int qpnp_vibrator_play_on(struct vib_ldo_chip *chip) int ret; volt_uV = chip->vmax_uV; + + if (chip->dis_short_long) { + pr_debug("vib in dis short and long, play ms=%d, dis_longms=%d, vmax_uV=%d, vmax_uV_long=%d\n", + chip->vib_play_ms, chip->dis_long_ms, chip->vmax_uV, chip->vmax_uV_long); + if (chip->vib_play_ms > chip->dis_long_ms) { + volt_uV = chip->vmax_uV_long; + } + } + if (!chip->disable_overdrive) volt_uV = chip->overdrive_volt_uV ? chip->overdrive_volt_uV : min(chip->vmax_uV * 2, QPNP_VIB_LDO_VMAX_UV); @@ -386,6 +399,28 @@ static int qpnp_vib_parse_dt(struct device *dev, struct vib_ldo_chip *chip) return ret; } + chip->dis_short_long = of_property_read_bool(dev->of_node, + "qcom,vib-dis-short-long"); + + if (chip->dis_short_long) { + pr_warn("read dis_short_long true"); + ret = of_property_read_u32(dev->of_node, "qcom,vib-dis-short-long-val", + &chip->dis_long_ms); + if (ret < 0) { + pr_err("qcom,vib-dis-short-long-val property read failed, ret=%d\n", ret); + return ret; + } + pr_warn("read dis_long_ms=%d\n", chip->dis_long_ms); + + ret = of_property_read_u32(dev->of_node, "qcom,vib-ldo-volt-uv-long", + &chip->vmax_uV_long); + if (ret < 0) { + pr_err("qcom,vib-ldo-volt-uv-long property read failed, ret=%d\n", ret); + return ret; + } + pr_warn("read vmax_uV_long=%d\n", chip->vmax_uV_long); + } + chip->disable_overdrive = of_property_read_bool(dev->of_node, "qcom,disable-overdrive"); From 26f5bd95447426c8437c6a92f0db9625c6bea9d0 Mon Sep 17 00:00:00 2001 From: houdz1 Date: Wed, 30 Jun 2021 11:15:46 +0800 Subject: [PATCH 368/698] arm64/config: cypfq: enable tps65132 For cypfq: tps65132 and ocp2131 will output VSN and VSP to panel. And tps65132 and ocp2131 are compatible completely. So we will use a driver for them. Change-Id: Ib41ce6a18ff70f3b9bf3c2bd318698188e272e88 Signed-off-by: houdz1 Reviewed-on: https://gerrit.mot.com/1996970 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Yeqing Wang Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi-cypfq.config | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-cypfq.config b/arch/arm64/configs/vendor/ext_config/moto-holi-cypfq.config index 582ede133237..e2e65c81a297 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-cypfq.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-cypfq.config @@ -18,3 +18,5 @@ CONFIG_CYPFQ_DTB=y CONFIG_FS_EPOLL_WAKEUP_DEBUG=y CONFIG_ZRAM_WRITEBACK=y # CONFIG_THERMAL_STATISTICS is not set +# CONFIG_REGULATOR_QPNP_LCDB is not set +CONFIG_REGULATOR_TPS65132=y From 789d6be2a5b7492fa8e261822c0f9f849672a99f Mon Sep 17 00:00:00 2001 From: chailu1 Date: Sat, 3 Jul 2021 14:14:22 +0800 Subject: [PATCH 369/698] ffc: config ffc interface for qg Flash fast charge config ffc interface for qg. charge side could config iterm of reprot soc 100%. proting from https://gerrit.mot.com/1551505 Change-Id: If50b19e8914979f4506e0edf4f543ac826772a5d Signed-off-by: chailu1 Reviewed-on: https://gerrit.mot.com/2001403 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Haijian Ma Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- drivers/power/supply/qcom/qpnp-qg.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/power/supply/qcom/qpnp-qg.c b/drivers/power/supply/qcom/qpnp-qg.c index 9781572a4d6f..940172326c87 100644 --- a/drivers/power/supply/qcom/qpnp-qg.c +++ b/drivers/power/supply/qcom/qpnp-qg.c @@ -2167,6 +2167,10 @@ static int qg_iio_write_raw(struct iio_dev *indio_dev, case PSY_IIO_BATT_AGE_LEVEL: rc = qg_setprop_batt_age_level(chip, val1); break; + case PSY_IIO_BATT_FULL_CURRENT: + chip->dt.iterm_ma = val1; + qg_dbg(chip, QG_DEBUG_STATUS, "set bat full current = %d\n", chip->dt.iterm_ma); + break; default: pr_debug("Unsupported QG IIO chan %d\n", chan->channel); rc = -EINVAL; From 3149e59afced68289e046fb1436489d75426e9c2 Mon Sep 17 00:00:00 2001 From: zhucc2 Date: Tue, 6 Jul 2021 10:19:54 +0800 Subject: [PATCH 370/698] scsi/ufs: port SamSung UFS HID feature. this patch is supply by SS, and based on sm4350, we also add macros to compatible with other vendors. Change-Id: Iea082bfbc8463f7cb23bad5afe2bb0b6118dab92 Reviewed-on: https://gerrit.mot.com/2002941 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- drivers/scsi/ufs/Kconfig | 18 +- drivers/scsi/ufs/Makefile | 1 + drivers/scsi/ufs/ufs-qcom.c | 2 +- drivers/scsi/ufs/ufs.h | 7 + drivers/scsi/ufs/ufsfeature.c | 53 +- drivers/scsi/ufs/ufsfeature.h | 8 +- drivers/scsi/ufs/ufshcd.c | 32 +- drivers/scsi/ufs/ufshcd.h | 3 + drivers/scsi/ufs/ufshid.c | 949 ++++++++++++++++++++++++++++++++++ drivers/scsi/ufs/ufshid.h | 144 ++++++ 10 files changed, 1204 insertions(+), 13 deletions(-) create mode 100755 drivers/scsi/ufs/ufshid.c create mode 100755 drivers/scsi/ufs/ufshid.h diff --git a/drivers/scsi/ufs/Kconfig b/drivers/scsi/ufs/Kconfig index f71efcca00c0..fbb422dfb846 100644 --- a/drivers/scsi/ufs/Kconfig +++ b/drivers/scsi/ufs/Kconfig @@ -243,6 +243,22 @@ config UFSTW_BOOT_ENABLED fTurboWriteEn and fTurboWriteBufferFlushDuringHibnerEnter flags are enabled at boot time. +config UFSHID + bool "UFS Host Initiated Defrag support" + depends on SCSI_UFSHCD && UFSFEATURE + ---help--- + UFS HID Feature Enable + +config UFSHID_POC + bool "UFSHID_POC test" + depends on SCSI_UFSHCD && UFSFEATURE && UFSHID + ---help--- + UFS HID POC test + 1. block to enter suspend state + 2. auto_hibern8 enable/disable (HCI) + 3. set flag bDefragOperation + 4. debug msg enable (default : disable) + config SCSI_SKHPB bool "Activate HPB Host-aware Performance Booster" depends on (SCSI_UFSHCD || SCSI_UFSHCD_QTI) @@ -250,7 +266,7 @@ config SCSI_SKHPB Activate or deactive SKHPB driver config SCSI_SKHID - bool "Activate HPB Host-aware Performance Booster" + bool "UFS Host Initiated Defrag supportr" depends on (SCSI_UFSHCD || SCSI_UFSHCD_QTI) help Activate or deactive SKHPB driver diff --git a/drivers/scsi/ufs/Makefile b/drivers/scsi/ufs/Makefile index f0d24fac1ee8..f1e3eaa10a05 100644 --- a/drivers/scsi/ufs/Makefile +++ b/drivers/scsi/ufs/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_SCSI_UFSHCD) += ufshcd-core.o obj-$(CONFIG_UFSFEATURE) += ufsfeature.o obj-$(CONFIG_UFSHPB) += ufshpb.o obj-$(CONFIG_UFSTW) += ufstw.o +obj-$(CONFIG_UFSHID) += ufshid.o ufshcd-core-y += ufshcd.o ufs-sysfs.o ufshcd-core-$(CONFIG_SCSI_UFS_BSG) += ufs_bsg.o obj-$(CONFIG_SCSI_SKHPB) += ufshpb_skh.o diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c index 8d976bc3e3e0..5ade5e502898 100644 --- a/drivers/scsi/ufs/ufs-qcom.c +++ b/drivers/scsi/ufs/ufs-qcom.c @@ -2259,7 +2259,7 @@ ufs_qcom_query_ioctl(struct ufs_hba *hba, u8 lun, void __user *buffer) #if defined(CONFIG_UFSFEATURE) if (ufsf_check_query(ioctl_data->opcode)) { - err = ufsf_query_ioctl(hba, lun, buffer, ioctl_data, + err = ufsf_query_ioctl(&hba->ufsf, lun, buffer, ioctl_data, UFSFEATURE_SELECTOR); goto out_release_mem; } diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h index a77312b8a5fb..dfe046fd8f3d 100644 --- a/drivers/scsi/ufs/ufs.h +++ b/drivers/scsi/ufs/ufs.h @@ -198,6 +198,10 @@ enum attr_idn { QUERY_ATTR_IDN_TW_BUF_LIFETIME_EST = 0x1E, QUERY_ATTR_IDN_TW_CURR_BUF_SIZE = 0x1F, #endif +#if defined(CONFIG_UFSHID) + QUERY_ATTR_IDN_HID_OPERATION = 0x20, + QUERY_ATTR_IDN_HID_FRAG_LEVEL = 0x21, +#endif #if defined(CONFIG_SCSI_SKHID) /* use one reserved bit */ QUERY_ATTR_IDN_MANUAL_GC_CONT = 0x12, @@ -325,6 +329,9 @@ enum device_desc_param { DEVICE_DESC_PARAM_TW_BUF_TYPE = 0x54, DEVICE_DESC_PARAM_TW_SHARED_BUF_ALLOC_UNITS = 0x55, #endif +#if defined(CONFIG_UFSHID) + DEVICE_DESC_PARAM_HID_VER = 0x59, +#endif }; /* Interconnect descriptor parameters offsets in bytes*/ diff --git a/drivers/scsi/ufs/ufsfeature.c b/drivers/scsi/ufs/ufsfeature.c index 3cb57d2d412a..71122ab54e65 100755 --- a/drivers/scsi/ufs/ufsfeature.c +++ b/drivers/scsi/ufs/ufsfeature.c @@ -218,6 +218,10 @@ static int ufsf_read_dev_desc(struct ufsf_feature *ufsf, u8 selector) #if defined(CONFIG_UFSTW) ufstw_get_dev_info(ufsf, desc_buf); #endif + +#if defined(CONFIG_UFSHID) + ufshid_get_dev_info(ufsf, desc_buf); +#endif return 0; } @@ -393,7 +397,7 @@ static inline void ufsf_set_read10_debug_cmd(unsigned char *cdb, int lba, cdb[8] = GET_BYTE_0(len); } -int ufsf_query_ioctl(struct ufs_hba *hba, int lun, void __user *buffer, +int ufsf_query_ioctl(struct ufsf_feature *ufsf, int lun, void __user *buffer, struct ufs_ioctl_query_data *ioctl_data, u8 selector) { unsigned char *kernel_buf; @@ -439,7 +443,7 @@ int ufsf_query_ioctl(struct ufs_hba *hba, int lun, void __user *buffer, index = lun; INFO_MSG("read lu desc lun: %d", index); break; -#if 0 + case QUERY_DESC_IDN_STRING: if (!ufs_is_valid_unit_desc_lun(lun)) { ERR_MSG("No unit descriptor for lun 0x%x", lun); @@ -452,7 +456,6 @@ int ufsf_query_ioctl(struct ufs_hba *hba, int lun, void __user *buffer, goto out_release_mem; goto copy_buffer; -#endif case QUERY_DESC_IDN_DEVICE: case QUERY_DESC_IDN_GEOMETRY: case QUERY_DESC_IDN_CONFIGURATION: @@ -472,15 +475,13 @@ int ufsf_query_ioctl(struct ufs_hba *hba, int lun, void __user *buffer, length = ioctl_data->buf_size; - err = ufshcd_query_descriptor_retry(hba, opcode, ioctl_data->idn, + err = ufshcd_query_descriptor_retry(ufsf->hba, opcode, ioctl_data->idn, index, selector, kernel_buf, &length); if (err) goto out_release_mem; -#if 0 -copy_buffer: -#endif +copy_buffer: if (opcode == UPIU_QUERY_OPCODE_READ_DESC) { err = copy_to_user(buffer, ioctl_data, sizeof(struct ufs_ioctl_query_data)); @@ -584,6 +585,12 @@ inline void ufsf_reset_host(struct ufsf_feature *ufsf) if (ufstw_get_state(ufsf) == TW_PRESENT) ufstw_reset_host(ufsf); #endif +#if defined(CONFIG_UFSHID) + INFO_MSG("run reset_host.. hid_state(%d) -> HID_RESET", + ufshid_get_state(ufsf)); + if (ufshid_get_state(ufsf) == HID_PRESENT) + ufshid_reset_host(ufsf); +#endif } inline void ufsf_init(struct ufsf_feature *ufsf) @@ -599,6 +606,10 @@ inline void ufsf_init(struct ufsf_feature *ufsf) if (ufstw_get_state(ufsf) == TW_NEED_INIT) ufstw_init(ufsf); #endif +#if defined(CONFIG_UFSHID) + if (ufshid_get_state(ufsf) == HID_NEED_INIT) + ufshid_init(ufsf); +#endif } inline void ufsf_reset(struct ufsf_feature *ufsf) @@ -618,6 +629,10 @@ inline void ufsf_reset(struct ufsf_feature *ufsf) ufstw_reset(ufsf, false); } #endif +#if defined(CONFIG_UFSHID) + if (ufshid_get_state(ufsf) == HID_RESET) + ufshid_reset(ufsf); +#endif } inline void ufsf_remove(struct ufsf_feature *ufsf) @@ -631,6 +646,10 @@ inline void ufsf_remove(struct ufsf_feature *ufsf) if (ufstw_get_state(ufsf) == TW_PRESENT) ufstw_remove(ufsf); #endif +#if defined(CONFIG_UFSHID) + if (ufshid_get_state(ufsf) == HID_PRESENT) + ufshid_remove(ufsf); +#endif } inline void ufsf_set_init_state(struct ufsf_feature *ufsf) @@ -649,6 +668,9 @@ inline void ufsf_set_init_state(struct ufsf_feature *ufsf) #if defined(CONFIG_UFSTW) ufstw_set_state(ufsf, TW_NEED_INIT); #endif +#if defined(CONFIG_UFSHID) + ufshid_set_state(ufsf, HID_NEED_INIT); +#endif } inline void ufsf_suspend(struct ufsf_feature *ufsf) @@ -662,6 +684,10 @@ inline void ufsf_suspend(struct ufsf_feature *ufsf) if ((ufshpb_get_state(ufsf) == HPB_PRESENT) && IS_RAM_SIZE_GREATER_THAN_4G(ram_size)) ufshpb_suspend(ufsf); #endif +#if defined(CONFIG_UFSHID) + if (ufshid_get_state(ufsf) == HID_PRESENT) + ufshid_suspend(ufsf); +#endif } inline void ufsf_resume(struct ufsf_feature *ufsf) @@ -680,8 +706,21 @@ inline void ufsf_resume(struct ufsf_feature *ufsf) if (ufstw_get_state(ufsf) == TW_RESET) ufstw_reset(ufsf, true); #endif + +#if defined(CONFIG_UFSHID) + if (ufshid_get_state(ufsf) == HID_SUSPEND) + ufshid_resume(ufsf); +#endif } +inline void ufsf_on_idle(struct ufsf_feature *ufsf, bool scsi_req) +{ +#if defined(CONFIG_UFSHID) + if (ufshid_get_state(ufsf) == HID_PRESENT && + !ufsf->hba->outstanding_reqs && scsi_req) + ufshid_on_idle(ufsf); +#endif +} inline void ufsf_change_lun(struct ufsf_feature *ufsf, struct ufshcd_lrb *lrbp) diff --git a/drivers/scsi/ufs/ufsfeature.h b/drivers/scsi/ufs/ufsfeature.h index 4b5b7b56adb2..ca0477745a8f 100755 --- a/drivers/scsi/ufs/ufsfeature.h +++ b/drivers/scsi/ufs/ufsfeature.h @@ -44,6 +44,7 @@ #include "ufshpb.h" #include "ufstw.h" +#include "ufshid.h" /* Version info */ #define UFSFEATURE_DD_VER 0x010100 @@ -157,6 +158,10 @@ struct ufsf_feature { struct ufstw_lu *tw_lup[UFS_UPIU_MAX_GENERAL_LUN]; atomic_t tw_state; #endif +#if defined(CONFIG_UFSHID) + atomic_t hid_state; + struct ufshid_dev *hid_dev; +#endif }; struct ufs_hba; @@ -165,7 +170,7 @@ struct ufs_ioctl_query_data; void ufsf_device_check(struct ufs_hba *hba); int ufsf_check_query(__u32 opcode); -int ufsf_query_ioctl(struct ufs_hba *hba, int lun, void __user *buffer, +int ufsf_query_ioctl(struct ufsf_feature *ufsf, int lun, void __user *buffer, struct ufs_ioctl_query_data *ioctl_data, u8 selector); int ufsf_query_flag_retry(struct ufs_hba *hba, enum query_opcode opcode, @@ -186,6 +191,7 @@ void ufsf_remove(struct ufsf_feature *ufsf); void ufsf_set_init_state(struct ufsf_feature *ufsf); void ufsf_suspend(struct ufsf_feature *ufsf); void ufsf_resume(struct ufsf_feature *ufsf); +void ufsf_on_idle(struct ufsf_feature *ufsf, bool scsi_req); /* for hpb */ void ufsf_hpb_noti_rb(struct ufsf_feature *ufsf, struct ufshcd_lrb *lrbp); diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 87d266162cd1..0ca91b71002d 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -423,13 +423,21 @@ static inline void ufshcd_wb_config(struct ufs_hba *hba) ufshcd_wb_toggle_flush(hba, true); } +#if defined(CONFIG_UFSFEATURE) +void ufshcd_scsi_unblock_requests(struct ufs_hba *hba) +#else static void ufshcd_scsi_unblock_requests(struct ufs_hba *hba) +#endif { if (atomic_dec_and_test(&hba->scsi_block_reqs_cnt)) scsi_unblock_requests(hba->host); } +#if defined(CONFIG_UFSFEATURE) +void ufshcd_scsi_block_requests(struct ufs_hba *hba) +#else static void ufshcd_scsi_block_requests(struct ufs_hba *hba) +#endif { if (atomic_inc_return(&hba->scsi_block_reqs_cnt) == 1) scsi_block_requests(hba->host); @@ -1208,8 +1216,12 @@ static bool ufshcd_is_devfreq_scaling_required(struct ufs_hba *hba, return false; } +#if defined(CONFIG_UFSFEATURE) +int ufshcd_wait_for_doorbell_clr(struct ufs_hba *hba, u64 wait_timeout_us) +#else static int ufshcd_wait_for_doorbell_clr(struct ufs_hba *hba, u64 wait_timeout_us) +#endif { unsigned long flags; int ret = 0; @@ -5380,6 +5392,9 @@ static void __ufshcd_transfer_req_compl(struct ufs_hba *hba, struct scsi_cmnd *cmd; int result; int index; +#if defined(CONFIG_UFSFEATURE) + bool scsi_req = false; +#endif for_each_set_bit(index, &completed_reqs, hba->nutrs) { lrbp = &hba->lrb[index]; @@ -5405,6 +5420,10 @@ static void __ufshcd_transfer_req_compl(struct ufs_hba *hba, /* Do not touch lrbp after scsi done */ cmd->scsi_done(cmd); __ufshcd_release(hba); +#if defined(CONFIG_UFSFEATURE) + if (IS_SAMSUNG_DEVICE(storage_mfrid)) + scsi_req = true; +#endif } else if (lrbp->command_type == UTP_CMD_TYPE_DEV_MANAGE || lrbp->command_type == UTP_CMD_TYPE_UFS_STORAGE) { lrbp->compl_time_stamp = ktime_get(); @@ -5425,6 +5444,10 @@ static void __ufshcd_transfer_req_compl(struct ufs_hba *hba, /* we might have free'd some tags above */ wake_up(&hba->dev_cmd.tag_wq); +#if defined(CONFIG_UFSFEATURE) + if (IS_SAMSUNG_DEVICE(storage_mfrid)) + ufsf_on_idle(&hba->ufsf, scsi_req); +#endif } /** @@ -9618,7 +9641,8 @@ void ufshcd_remove(struct ufs_hba *hba) ufshcd_disable_intr(hba, hba->intr_mask); ufshcd_hba_stop(hba, true); #if defined(CONFIG_SCSI_SKHID) - ufshcd_exit_manual_gc(hba); + if (IS_SKHYNIX_DEVICE(storage_mfrid)) + ufshcd_exit_manual_gc(hba); #endif ufshcd_exit_clk_scaling(hba); ufshcd_exit_clk_gating(hba); @@ -9805,7 +9829,8 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq) ufshcd_init_clk_scaling(hba); #if defined(CONFIG_SCSI_SKHID) - ufshcd_init_manual_gc(hba); + if (IS_SKHYNIX_DEVICE(storage_mfrid)) + ufshcd_init_manual_gc(hba); #endif /* * In order to avoid any spurious interrupt immediately after @@ -9912,7 +9937,8 @@ out_remove_scsi_host: scsi_remove_host(hba->host); exit_gating: #if defined(CONFIG_SCSI_SKHID) - ufshcd_exit_manual_gc(hba); + if (IS_SKHYNIX_DEVICE(storage_mfrid)) + ufshcd_exit_manual_gc(hba); #endif ufshcd_exit_clk_scaling(hba); ufshcd_exit_clk_gating(hba); diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index 989cc4eadebf..aeba90206c3e 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -1356,6 +1356,9 @@ void ufshcd_fixup_dev_quirks(struct ufs_hba *hba, struct ufs_dev_fix *fixups); #define SD_RAW false #if defined(CONFIG_UFSFEATURE) +void ufshcd_scsi_unblock_requests(struct ufs_hba *hba); +void ufshcd_scsi_block_requests(struct ufs_hba *hba); +int ufshcd_wait_for_doorbell_clr(struct ufs_hba *hba, u64 wait_timeout_us); int ufshcd_exec_dev_cmd(struct ufs_hba *hba, enum dev_cmd_type cmd_type, int timeout); #endif diff --git a/drivers/scsi/ufs/ufshid.c b/drivers/scsi/ufs/ufshid.c new file mode 100755 index 000000000000..1f10b9f53a99 --- /dev/null +++ b/drivers/scsi/ufs/ufshid.c @@ -0,0 +1,949 @@ +/* + * Universal Flash Storage Host Initiated Defrag (UFS HID) + * + * Copyright (C) 2019-2019 Samsung Electronics Co., Ltd. + * + * Authors: + * Yongmyung Lee + * Jieon Seol + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * See the COPYING file in the top-level directory or visit + * + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * This program is provided "AS IS" and "WITH ALL FAULTS" and + * without warranty of any kind. You are solely responsible for + * determining the appropriateness of using and distributing + * the program and assume all risks associated with your exercise + * of rights with respect to the program, including but not limited + * to infringement of third party rights, the risks and costs of + * program errors, damage to or loss of data, programs or equipment, + * and unavailability or interruption of operations. Under no + * circumstances will the contributor of this Program be liable for + * any damages of any kind arising from your use or distribution of + * this program. + * + * The Linux Foundation chooses to take subject only to the GPLv2 + * license terms, and distributes only under these terms. + */ + +#include "ufshcd.h" +#include "ufsfeature.h" +#include "ufshid.h" + +static int ufshid_create_sysfs(struct ufshid_dev *hid); + +inline int ufshid_get_state(struct ufsf_feature *ufsf) +{ + return atomic_read(&ufsf->hid_state); +} + +inline void ufshid_set_state(struct ufsf_feature *ufsf, int state) +{ + atomic_set(&ufsf->hid_state, state); +} + +static inline int ufshid_is_not_present(struct ufshid_dev *hid) +{ + enum UFSHID_STATE cur_state = ufshid_get_state(hid->ufsf); + + if (cur_state != HID_PRESENT) { + INFO_MSG("hid_state != HID_PRESENT (%d)", cur_state); + return -ENODEV; + } + return 0; +} + +static int ufshid_read_attr(struct ufshid_dev *hid, u8 idn, u32 *attr_val) +{ + struct ufs_hba *hba = hid->ufsf->hba; + int ret = 0; + + pm_runtime_get_sync(hba->dev); + + ret = ufsf_query_attr_retry(hba, UPIU_QUERY_OPCODE_READ_ATTR, idn, 0, + attr_val); + if (ret) { + ERR_MSG("read attr [0x%.2X] fail. (%d)", idn, ret); + goto err_out; + } + + HID_DEBUG(hid, "hid_attr read [0x%.2X] %u (0x%X)", idn, *attr_val, + *attr_val); + TMSG(hid->ufsf, 0, "[ufshid] read_attr IDN %s (%d)", + idn == QUERY_ATTR_IDN_HID_OPERATION ? "HID_OP" : + idn == QUERY_ATTR_IDN_HID_FRAG_LEVEL ? "HID_LEV" : "UNKNOWN", idn); +err_out: + pm_runtime_mark_last_busy(hba->dev); + pm_runtime_put_noidle(hba->dev); + + return ret; +} + +static int ufshid_write_attr(struct ufshid_dev *hid, u8 idn, u32 val) +{ + struct ufs_hba *hba = hid->ufsf->hba; + int ret = 0; + + pm_runtime_get_sync(hba->dev); + + ret = ufsf_query_attr_retry(hba, UPIU_QUERY_OPCODE_WRITE_ATTR, idn, 0, + &val); + if (ret) { + ERR_MSG("write attr [0x%.2X] fail. (%d)", idn, ret); + goto err_out; + } + + HID_DEBUG(hid, "hid_attr write [0x%.2X] %u (0x%X)", idn, val, val); + TMSG(hid->ufsf, 0, "[ufshid] write_attr IDN %s (%d)", + idn == QUERY_ATTR_IDN_HID_OPERATION ? "HID_OP" : + idn == QUERY_ATTR_IDN_HID_FRAG_LEVEL ? "HID_LEV" : "UNKNOWN", idn); +err_out: + pm_runtime_mark_last_busy(hba->dev); + pm_runtime_put_noidle(hba->dev); + + return ret; +} + +static inline int ufshid_version_check(int spec_version) +{ + INFO_MSG("Support HID Spec : Driver = (%.4x), Device = (%.4x)", + UFSHID_VER, spec_version); + INFO_MSG("HID Driver version (%.6X%s)", + UFSHID_DD_VER, UFSHID_DD_VER_POST); + + if (spec_version != UFSHID_VER) { + ERR_MSG("UFS HID version mismatched"); + return -ENODEV; + } + return 0; +} + +void ufshid_get_dev_info(struct ufsf_feature *ufsf, u8 *desc_buf) +{ + int ret = 0, spec_version; + + ufsf->hid_dev = NULL; + + if (!(LI_EN_32(&desc_buf[DEVICE_DESC_PARAM_EX_FEAT_SUP]) & + UFS_FEATURE_SUPPORT_HID_BIT)) { + INFO_MSG("bUFSExFeaturesSupport: HID not support"); + goto err_out; + } + + INFO_MSG("bUFSExFeaturesSupport: HID support"); + spec_version = + LI_EN_16(&desc_buf[DEVICE_DESC_PARAM_HID_VER]); + ret = ufshid_version_check(spec_version); + if (ret) + goto err_out; + + ufsf->hid_dev = kzalloc(sizeof(struct ufshid_dev), GFP_KERNEL); + if (!ufsf->hid_dev) { + ERR_MSG("hid_dev memalloc fail"); + goto err_out; + } + + ufsf->hid_dev->ufsf = ufsf; + return; +err_out: + ufshid_set_state(ufsf, HID_FAILED); +} + +static int ufshid_get_analyze_and_issue_execute(struct ufshid_dev *hid) +{ + u32 attr_val; + int frag_level; + + if (ufshid_write_attr(hid, QUERY_ATTR_IDN_HID_OPERATION, + HID_OP_EXECUTE)) + return -EINVAL; + if (ufshid_read_attr(hid, QUERY_ATTR_IDN_HID_FRAG_LEVEL, &attr_val)) + return -EINVAL; + + frag_level = attr_val & HID_FRAG_LEVEL_MASK; + HID_DEBUG(hid, "Frag_lv %d Freg_stat %d HID_need_exec %d", + frag_level, HID_FRAG_UPDATE_STAT(attr_val), + HID_EXECUTE_REQ_STAT(attr_val)); + + if (frag_level == HID_LEV_GRAY) + return -EAGAIN; + + return (HID_EXECUTE_REQ_STAT(attr_val)) ? + HID_REQUIRED : HID_NOT_REQUIRED; +} + +static int ufshid_issue_disable(struct ufshid_dev *hid) +{ + u32 attr_val; + + if (ufshid_write_attr(hid, QUERY_ATTR_IDN_HID_OPERATION, + HID_OP_DISABLE)) + return -EINVAL; + if (ufshid_read_attr(hid, QUERY_ATTR_IDN_HID_FRAG_LEVEL, &attr_val)) + return -EINVAL; + + HID_DEBUG(hid, "Frag_lv %d Freg_stat %d HID_need_exec %d", + attr_val & HID_FRAG_LEVEL_MASK, + HID_FRAG_UPDATE_STAT(attr_val), + HID_EXECUTE_REQ_STAT(attr_val)); + + return 0; +} + +/* + * Lock status: hid_sysfs lock was held when called. + */ +static void ufshid_auto_hibern8_enable(struct ufshid_dev *hid, + unsigned int val) +{ + struct ufs_hba *hba = hid->ufsf->hba; + unsigned long flags; + u32 reg; + + val = !!val; + + /* Update auto hibern8 timer value if supported */ + if (!ufshcd_is_auto_hibern8_supported(hba)) + return; + + pm_runtime_get_sync(hba->dev); + ufshcd_hold(hba, false); + down_write(&hba->clk_scaling_lock); + ufshcd_scsi_block_requests(hba); + /* wait for all the outstanding requests to finish */ + ufshcd_wait_for_doorbell_clr(hba, U64_MAX); + spin_lock_irqsave(hba->host->host_lock, flags); + + reg = ufshcd_readl(hba, REG_AUTO_HIBERNATE_IDLE_TIMER); + INFO_MSG("ahit-reg 0x%X", reg); + + if (val ^ (reg == hba->ahit)) { + ufshcd_writel(hba, val ? hba->ahit : HID_AUTO_HIBERN8_DISABLE, + REG_AUTO_HIBERNATE_IDLE_TIMER); + /* Make sure the timer gets applied before further operations */ + mb(); + + INFO_MSG("[Before] is_auto_enabled %d", hid->is_auto_enabled); + hid->is_auto_enabled = val; + + reg = ufshcd_readl(hba, REG_AUTO_HIBERNATE_IDLE_TIMER); + INFO_MSG("[After] is_auto_enabled %d ahit-reg 0x%X", + hid->is_auto_enabled, reg); + } else { + INFO_MSG("is_auto_enabled %d. so it does not changed", + hid->is_auto_enabled); + } + + spin_unlock_irqrestore(hba->host->host_lock, flags); + ufshcd_scsi_unblock_requests(hba); + up_write(&hba->clk_scaling_lock); + ufshcd_release(hba); + pm_runtime_mark_last_busy(hba->dev); + pm_runtime_put_noidle(hba->dev); +} + +static void ufshid_block_enter_suspend(struct ufshid_dev *hid) +{ + struct ufs_hba *hba = hid->ufsf->hba; + unsigned long flags; + +#if defined(CONFIG_UFSHID_POC) + if (unlikely(hid->block_suspend)) + return; + + hid->block_suspend = true; +#endif + pm_runtime_get_sync(hba->dev); + ufshcd_hold(hba, false); + + spin_lock_irqsave(hba->host->host_lock, flags); + HID_DEBUG(hid, + "dev->power.usage_count %d hba->clk_gating.active_reqs %d", + atomic_read(&hba->dev->power.usage_count), + hba->clk_gating.active_reqs); + spin_unlock_irqrestore(hba->host->host_lock, flags); +} + +/* + * If the return value is not err, pm_runtime_put_noidle() must be called once. + * IMPORTANT : ufshid_hold_runtime_pm() & ufshid_release_runtime_pm() pair. + */ +static int ufshid_hold_runtime_pm(struct ufshid_dev *hid) +{ + struct ufs_hba *hba = hid->ufsf->hba; + + if (ufshid_get_state(hid->ufsf) == HID_SUSPEND) { + /* Check that device was suspended by System PM */ + pm_runtime_get_sync(hba->dev); + + /* If it success, device was suspended by Runtime PM */ + if (ufshid_get_state(hid->ufsf) == HID_PRESENT && + hba->curr_dev_pwr_mode == UFS_ACTIVE_PWR_MODE && + hba->uic_link_state == UIC_LINK_ACTIVE_STATE) + goto resume_success; + + INFO_MSG("RPM resume failed. Maybe it was SPM suspend"); + INFO_MSG("UFS state (POWER = %d LINK = %d)", + hba->curr_dev_pwr_mode, hba->uic_link_state); + + pm_runtime_mark_last_busy(hba->dev); + pm_runtime_put_noidle(hba->dev); + return -ENODEV; + } + + if (ufshid_is_not_present(hid)) + return -ENODEV; + + pm_runtime_get_sync(hba->dev); +resume_success: + return 0; +} + +static inline void ufshid_release_runtime_pm(struct ufshid_dev *hid) +{ + struct ufs_hba *hba = hid->ufsf->hba; + + pm_runtime_mark_last_busy(hba->dev); + pm_runtime_put_noidle(hba->dev); +} + +/* + * Lock status: hid_sysfs lock was held when called. + */ +static int ufshid_trigger_on(struct ufshid_dev *hid) + __must_hold(&hid->sysfs_lock) +{ + int ret; + + if (hid->hid_trigger) + return 0; + + ret = ufshid_hold_runtime_pm(hid); + if (ret) + return ret; + + hid->hid_trigger = true; + HID_DEBUG(hid, "trigger 0 -> 1"); + + ufshid_block_enter_suspend(hid); + + ufshid_auto_hibern8_enable(hid, 0); + + schedule_delayed_work(&hid->hid_trigger_work, 0); + + ufshid_release_runtime_pm(hid); + + return 0; +} + +static void ufshid_allow_enter_suspend(struct ufshid_dev *hid) +{ + struct ufs_hba *hba = hid->ufsf->hba; + unsigned long flags; + +#if defined(CONFIG_UFSHID_POC) + if (unlikely(!hid->block_suspend)) + return; + + hid->block_suspend = false; +#endif + ufshcd_release(hba); + pm_runtime_mark_last_busy(hba->dev); + pm_runtime_put_noidle(hba->dev); + + spin_lock_irqsave(hba->host->host_lock, flags); + HID_DEBUG(hid, + "dev->power.usage_count %d hba->clk_gating.active_reqs %d", + atomic_read(&hba->dev->power.usage_count), + hba->clk_gating.active_reqs); + spin_unlock_irqrestore(hba->host->host_lock, flags); +} + +/* + * Lock status: hid_sysfs lock was held when called. + */ +static int ufshid_trigger_off(struct ufshid_dev *hid) + __must_hold(&hid->sysfs_lock) +{ + int ret; + + if (!hid->hid_trigger) + return 0; + + ret = ufshid_hold_runtime_pm(hid); + if (ret) + return ret; + + hid->hid_trigger = false; + HID_DEBUG(hid, "hid_trigger 1 -> 0"); + + ufshid_issue_disable(hid); + + ufshid_auto_hibern8_enable(hid, 1); + + ufshid_allow_enter_suspend(hid); + + ufshid_release_runtime_pm(hid); + + return 0; +} + +static void ufshid_trigger_work_fn(struct work_struct *dwork) +{ + struct ufshid_dev *hid; + int ret; + + hid = container_of(dwork, struct ufshid_dev, hid_trigger_work.work); + + if (ufshid_is_not_present(hid)) + return; + + HID_DEBUG(hid, "start hid_trigger_work_fn"); + + ret = ufshid_get_analyze_and_issue_execute(hid); + + mutex_lock(&hid->sysfs_lock); + if (!hid->hid_trigger) { + HID_DEBUG(hid, "hid_trigger == false, return"); + goto finish_work; + } + + if (ret == HID_NOT_REQUIRED) { + ret = ufshid_trigger_off(hid); + if (likely(!ret)) + goto finish_work; + + WARN_MSG("trigger off fail.. must check it"); + + } else if (ret == HID_REQUIRED) { + HID_DEBUG(hid, "HID_REQUIRED, so sched (%d ms)", + hid->hid_trigger_delay); + + } else { + HID_DEBUG(hid, "issue_HID ERR(%X), so resched for retry", ret); + } + mutex_unlock(&hid->sysfs_lock); + + schedule_delayed_work(&hid->hid_trigger_work, + msecs_to_jiffies(hid->hid_trigger_delay)); + + HID_DEBUG(hid, "end hid_trigger_work_fn"); + return; +finish_work: + mutex_unlock(&hid->sysfs_lock); +} + +void ufshid_init(struct ufsf_feature *ufsf) +{ + struct ufshid_dev *hid; + int ret; + + INFO_MSG("HID_INIT_START"); + + hid = ufsf->hid_dev; + BUG_ON(!hid); + + hid->hid_trigger = false; + hid->hid_trigger_delay = HID_TRIGGER_WORKER_DELAY_MS_DEFAULT; + INIT_DELAYED_WORK(&hid->hid_trigger_work, ufshid_trigger_work_fn); + + hid->hid_debug = false; +#if defined(CONFIG_UFSHID_POC) + hid->hid_debug = true; + hid->block_suspend = false; +#endif + + /* If HCI supports auto hibern8, UFS Driver use it default */ + if (ufshcd_is_auto_hibern8_supported(ufsf->hba)) + hid->is_auto_enabled = true; + else + hid->is_auto_enabled = false; + + ret = ufshid_create_sysfs(hid); + if (ret) { + ERR_MSG("sysfs init fail. so hid driver disabled"); + kfree(hid); + ufshid_set_state(ufsf, HID_FAILED); + return; + } + + INFO_MSG("UFS HID create sysfs finished"); + + ufshid_set_state(ufsf, HID_PRESENT); +} + +void ufshid_reset_host(struct ufsf_feature *ufsf) +{ + struct ufshid_dev *hid = ufsf->hid_dev; + + if (!hid) + return; + + ufshid_set_state(ufsf, HID_RESET); + cancel_delayed_work_sync(&hid->hid_trigger_work); +} + +void ufshid_reset(struct ufsf_feature *ufsf) +{ + struct ufshid_dev *hid = ufsf->hid_dev; + + if (!hid) + return; + + ufshid_set_state(ufsf, HID_PRESENT); + + /* + * hid_trigger will be checked under sysfs_lock in worker. + */ + if (hid->hid_trigger) + schedule_delayed_work(&hid->hid_trigger_work, 0); + + INFO_MSG("reset completed."); +} + +static inline void ufshid_remove_sysfs(struct ufshid_dev *hid) +{ + int ret; + + ret = kobject_uevent(&hid->kobj, KOBJ_REMOVE); + INFO_MSG("kobject removed (%d)", ret); + kobject_del(&hid->kobj); +} + +void ufshid_remove(struct ufsf_feature *ufsf) +{ + struct ufshid_dev *hid = ufsf->hid_dev; + int ret; + + if (!hid) + return; + + INFO_MSG("start HID release"); + + mutex_lock(&hid->sysfs_lock); + + ret = ufshid_trigger_off(hid); + if (unlikely(ret)) + ERR_MSG("trigger off fail ret (%d)", ret); + + ufshid_remove_sysfs(hid); + + ufshid_set_state(ufsf, HID_FAILED); + + mutex_unlock(&hid->sysfs_lock); + + cancel_delayed_work_sync(&hid->hid_trigger_work); + + kfree(hid); + + INFO_MSG("end HID release"); +} + +void ufshid_suspend(struct ufsf_feature *ufsf) +{ + struct ufshid_dev *hid = ufsf->hid_dev; + + if (!hid) + return; + + if (unlikely(hid->hid_trigger)) + ERR_MSG("hid_trigger was set to block the suspend. so weird"); + ufshid_set_state(ufsf, HID_SUSPEND); + + cancel_delayed_work_sync(&hid->hid_trigger_work); +} + +void ufshid_resume(struct ufsf_feature *ufsf) +{ + struct ufshid_dev *hid = ufsf->hid_dev; + + if (!hid) + return; + + if (unlikely(hid->hid_trigger)) + ERR_MSG("hid_trigger need to off"); + ufshid_set_state(ufsf, HID_PRESENT); +} + +/* + * this function is called in irq context. + * so cancel_delayed_work_sync() do not use due to waiting. + */ +void ufshid_on_idle(struct ufsf_feature *ufsf) +{ + struct ufshid_dev *hid = ufsf->hid_dev; + + if (!hid) + return; + /* + * When hid_trigger_work will be scheduled, + * check hid_trigger under sysfs_lock. + */ + if (!hid->hid_trigger) + return; + + if (delayed_work_pending(&hid->hid_trigger_work)) + cancel_delayed_work(&hid->hid_trigger_work); + + schedule_delayed_work(&hid->hid_trigger_work, 0); +} + +/* sysfs function */ +static ssize_t ufshid_sysfs_show_version(struct ufshid_dev *hid, char *buf) +{ + INFO_MSG("HID version (%.4X) D/D version (%.6X%s)", + UFSHID_VER, UFSHID_DD_VER, UFSHID_DD_VER_POST); + + return snprintf(buf, PAGE_SIZE, + "HID version (%.4X) D/D version (%.6X%s)\n", + UFSHID_VER, UFSHID_DD_VER, UFSHID_DD_VER_POST); +} + +static ssize_t ufshid_sysfs_show_trigger(struct ufshid_dev *hid, char *buf) +{ + INFO_MSG("hid_trigger %d", hid->hid_trigger); + + return snprintf(buf, PAGE_SIZE, "%d\n", hid->hid_trigger); +} + +static ssize_t ufshid_sysfs_store_trigger(struct ufshid_dev *hid, + const char *buf, size_t count) +{ + unsigned long val; + ssize_t ret; + + if (kstrtoul(buf, 0, &val)) + return -EINVAL; + + if (val != 0 && val != 1) + return -EINVAL; + + INFO_MSG("HID_trigger %lu", val); + + if (val == hid->hid_trigger) + return count; + + if (val) + ret = ufshid_trigger_on(hid); + else + ret = ufshid_trigger_off(hid); + + if (ret) { + INFO_MSG("Changing trigger val %lu is fail (%ld)", val, ret); + return ret; + } + + return count; +} + +static ssize_t ufshid_sysfs_show_trigger_interval(struct ufshid_dev *hid, + char *buf) +{ + INFO_MSG("hid_trigger_interval %d", hid->hid_trigger_delay); + + return snprintf(buf, PAGE_SIZE, "%d\n", hid->hid_trigger_delay); +} + +static ssize_t ufshid_sysfs_store_trigger_interval(struct ufshid_dev *hid, + const char *buf, + size_t count) +{ + unsigned long val; + + if (kstrtoul(buf, 0, &val)) + return -EINVAL; + + if (val < HID_TRIGGER_WORKER_DELAY_MS_MIN || + val > HID_TRIGGER_WORKER_DELAY_MS_MAX) { + INFO_MSG("hid_trigger_interval (min) %4dms ~ (max) %4dms", + HID_TRIGGER_WORKER_DELAY_MS_MIN, + HID_TRIGGER_WORKER_DELAY_MS_MAX); + return -EINVAL; + } + + hid->hid_trigger_delay = (unsigned int)val; + INFO_MSG("hid_trigger_interval %d", hid->hid_trigger_delay); + + return count; +} + +static ssize_t ufshid_sysfs_show_debug(struct ufshid_dev *hid, char *buf) +{ + INFO_MSG("debug %d", hid->hid_debug); + + return snprintf(buf, PAGE_SIZE, "%d\n", hid->hid_debug); +} + +static ssize_t ufshid_sysfs_store_debug(struct ufshid_dev *hid, const char *buf, + size_t count) +{ + unsigned long val; + + if (kstrtoul(buf, 0, &val)) + return -EINVAL; + + if (val != 0 && val != 1) + return -EINVAL; + + hid->hid_debug = val ? true : false; + + INFO_MSG("debug %d", hid->hid_debug); + + return count; +} + +static ssize_t ufshid_sysfs_show_color(struct ufshid_dev *hid, char *buf) +{ + u32 attr_val; + int frag_level; + + if (ufshid_write_attr(hid, QUERY_ATTR_IDN_HID_OPERATION, + HID_OP_ANALYZE)) { + ERR_MSG("query HID_OPERATION fail"); + return -EINVAL; + } + + if (ufshid_read_attr(hid, QUERY_ATTR_IDN_HID_FRAG_LEVEL, &attr_val)) { + ERR_MSG("query HID_FRAG_LEVEL fail"); + return -EINVAL; + } + + frag_level = attr_val & HID_FRAG_LEVEL_MASK; + INFO_MSG("Frag_lv %d Freg_stat %d HID_need_exec %d", frag_level, + HID_FRAG_UPDATE_STAT(attr_val), + HID_EXECUTE_REQ_STAT(attr_val)); + + return snprintf(buf, PAGE_SIZE, "%s\n", + frag_level == HID_LEV_RED ? "RED" : + frag_level == HID_LEV_YELLOW ? "YELLOW" : + frag_level == HID_LEV_GREEN ? "GREEN" : + frag_level == HID_LEV_GRAY ? "GRAY" : "UNKNOWN"); +} + +#if defined(CONFIG_UFSHID_POC) +static ssize_t ufshid_sysfs_show_debug_op(struct ufshid_dev *hid, char *buf) +{ + u32 attr_val; + + if (ufshid_read_attr(hid, QUERY_ATTR_IDN_HID_OPERATION, &attr_val)) + return -EINVAL; + + INFO_MSG("hid_op %d", attr_val); + + return snprintf(buf, PAGE_SIZE, "%d\n", attr_val); +} + +static ssize_t ufshid_sysfs_store_debug_op(struct ufshid_dev *hid, + const char *buf, size_t count) +{ + unsigned long val; + + if (kstrtoul(buf, 0, &val)) + return -EINVAL; + + if (val >= HID_OP_MAX) + return -EINVAL; + + if (hid->hid_trigger) { + ERR_MSG("debug_op cannot change, current hid_trigger is ON"); + return -EINVAL; + } + + if (ufshid_write_attr(hid, QUERY_ATTR_IDN_HID_OPERATION, val)) + return -EINVAL; + + INFO_MSG("hid_op %ld is set!", val); + return count; +} + +static ssize_t ufshid_sysfs_show_block_suspend(struct ufshid_dev *hid, + char *buf) +{ + INFO_MSG("block suspend %d", hid->block_suspend); + + return snprintf(buf, PAGE_SIZE, "%d\n", hid->block_suspend); +} + +static ssize_t ufshid_sysfs_store_block_suspend(struct ufshid_dev *hid, + const char *buf, size_t count) +{ + unsigned long val; + + if (kstrtoul(buf, 0, &val)) + return -EINVAL; + + if (val != 0 && val != 1) + return -EINVAL; + + INFO_MSG("HID_block_suspend %lu", val); + + if (val == hid->block_suspend) + return count; + + if (val) + ufshid_block_enter_suspend(hid); + else + ufshid_allow_enter_suspend(hid); + + hid->block_suspend = val ? true : false; + + return count; +} + +static ssize_t ufshid_sysfs_show_auto_hibern8_enable(struct ufshid_dev *hid, + char *buf) +{ + INFO_MSG("HCI auto hibern8 %d", hid->is_auto_enabled); + + return snprintf(buf, PAGE_SIZE, "%d\n", hid->is_auto_enabled); +} + +static ssize_t ufshid_sysfs_store_auto_hibern8_enable(struct ufshid_dev *hid, + const char *buf, + size_t count) +{ + unsigned long val; + + if (kstrtoul(buf, 0, &val)) + return -EINVAL; + + if (val != 0 && val != 1) + return -EINVAL; + + ufshid_auto_hibern8_enable(hid, val); + + return count; +} +#endif + +/* SYSFS DEFINE */ +#define define_sysfs_ro(_name) __ATTR(_name, 0444, \ + ufshid_sysfs_show_##_name, NULL) +#define define_sysfs_rw(_name) __ATTR(_name, 0644, \ + ufshid_sysfs_show_##_name, \ + ufshid_sysfs_store_##_name) + +static struct ufshid_sysfs_entry ufshid_sysfs_entries[] = { + define_sysfs_ro(version), + define_sysfs_ro(color), + + define_sysfs_rw(trigger), + define_sysfs_rw(trigger_interval), + + /* debug */ + define_sysfs_rw(debug), +#if defined(CONFIG_UFSHID_POC) + /* Attribute (RAW) */ + define_sysfs_rw(debug_op), + define_sysfs_rw(block_suspend), + define_sysfs_rw(auto_hibern8_enable), +#endif + __ATTR_NULL +}; + +static ssize_t ufshid_attr_show(struct kobject *kobj, struct attribute *attr, + char *page) +{ + struct ufshid_sysfs_entry *entry; + struct ufshid_dev *hid; + ssize_t error; + + entry = container_of(attr, struct ufshid_sysfs_entry, attr); + if (!entry->show) + return -EIO; + + hid = container_of(kobj, struct ufshid_dev, kobj); + error = ufshid_hold_runtime_pm(hid); + if (error) + return error; + + mutex_lock(&hid->sysfs_lock); + error = entry->show(hid, page); + mutex_unlock(&hid->sysfs_lock); + + ufshid_release_runtime_pm(hid); + return error; +} + +static ssize_t ufshid_attr_store(struct kobject *kobj, struct attribute *attr, + const char *page, size_t length) +{ + struct ufshid_sysfs_entry *entry; + struct ufshid_dev *hid; + ssize_t error; + + entry = container_of(attr, struct ufshid_sysfs_entry, attr); + if (!entry->store) + return -EIO; + + hid = container_of(kobj, struct ufshid_dev, kobj); + error = ufshid_hold_runtime_pm(hid); + if (error) + return error; + + mutex_lock(&hid->sysfs_lock); + error = entry->store(hid, page, length); + mutex_unlock(&hid->sysfs_lock); + + ufshid_release_runtime_pm(hid); + return error; +} + +static const struct sysfs_ops ufshid_sysfs_ops = { + .show = ufshid_attr_show, + .store = ufshid_attr_store, +}; + +static struct kobj_type ufshid_ktype = { + .sysfs_ops = &ufshid_sysfs_ops, + .release = NULL, +}; + +static int ufshid_create_sysfs(struct ufshid_dev *hid) +{ + struct device *dev = hid->ufsf->hba->dev; + struct ufshid_sysfs_entry *entry; + int err; + + hid->sysfs_entries = ufshid_sysfs_entries; + + kobject_init(&hid->kobj, &ufshid_ktype); + mutex_init(&hid->sysfs_lock); + + INFO_MSG("ufshid creates sysfs ufshid %p dev->kobj %p", + &hid->kobj, &dev->kobj); + + err = kobject_add(&hid->kobj, kobject_get(&dev->kobj), "ufshid"); + if (!err) { + for (entry = hid->sysfs_entries; entry->attr.name != NULL; + entry++) { + INFO_MSG("ufshid sysfs attr creates: %s", + entry->attr.name); + err = sysfs_create_file(&hid->kobj, &entry->attr); + if (err) { + ERR_MSG("create entry(%s) failed", + entry->attr.name); + goto kobj_del; + } + } + kobject_uevent(&hid->kobj, KOBJ_ADD); + } else { + ERR_MSG("kobject_add failed"); + } + + return err; +kobj_del: + err = kobject_uevent(&hid->kobj, KOBJ_REMOVE); + INFO_MSG("kobject removed (%d)", err); + kobject_del(&hid->kobj); + return -EINVAL; +} diff --git a/drivers/scsi/ufs/ufshid.h b/drivers/scsi/ufs/ufshid.h new file mode 100755 index 000000000000..849822ed5121 --- /dev/null +++ b/drivers/scsi/ufs/ufshid.h @@ -0,0 +1,144 @@ +/* + * Universal Flash Storage Host Initiated Defrag (UFS HID) + * + * Copyright (C) 2019-2019 Samsung Electronics Co., Ltd. + * + * Authors: + * Yongmyung Lee + * Jieon Seol + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * See the COPYING file in the top-level directory or visit + * + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * This program is provided "AS IS" and "WITH ALL FAULTS" and + * without warranty of any kind. You are solely responsible for + * determining the appropriateness of using and distributing + * the program and assume all risks associated with your exercise + * of rights with respect to the program, including but not limited + * to infringement of third party rights, the risks and costs of + * program errors, damage to or loss of data, programs or equipment, + * and unavailability or interruption of operations. Under no + * circumstances will the contributor of this Program be liable for + * any damages of any kind arising from your use or distribution of + * this program. + * + * The Linux Foundation chooses to take subject only to the GPLv2 + * license terms, and distributes only under these terms. + */ + +#ifndef _UFSHID_H_ +#define _UFSHID_H_ + +#include +#include +#include +#include +#include +#include + +#include "../../../block/blk.h" + +#define UFSHID_VER 0x0101 +#define UFSHID_DD_VER 0x010202 +#define UFSHID_DD_VER_POST "" + +#define UFS_FEATURE_SUPPORT_HID_BIT 0x400 + +#define HID_TRIGGER_WORKER_DELAY_MS_DEFAULT 2000 +#define HID_TRIGGER_WORKER_DELAY_MS_MIN 100 +#define HID_TRIGGER_WORKER_DELAY_MS_MAX 10000 + +#define HID_FRAG_LEVEL_MASK 0xF +#define HID_FRAG_UPDATE_STAT_SHIFT 30 +#define HID_EXECUTE_REQ_STAT_SHIFT 31 +#define HID_FRAG_UPDATE_STAT(val) ((val >> HID_FRAG_UPDATE_STAT_SHIFT) & 0x1) +#define HID_EXECUTE_REQ_STAT(val) ((val >> HID_EXECUTE_REQ_STAT_SHIFT) & 0x1) + +#define HID_AUTO_HIBERN8_DISABLE (FIELD_PREP(UFSHCI_AHIBERN8_TIMER_MASK, 0) | \ + FIELD_PREP(UFSHCI_AHIBERN8_SCALE_MASK, 3)) + + +#define HID_DEBUG(hid, msg, args...) \ + do { if (hid->hid_debug) \ + pr_err("%40s:%3d [%01d%02d%02d] " msg "\n", \ + __func__, __LINE__, \ + hid->hid_trigger, \ + atomic_read(&hid->ufsf->hba->dev->power.usage_count),\ + hid->ufsf->hba->clk_gating.active_reqs, ##args); \ + } while (0) + +enum UFSHID_STATE { + HID_NEED_INIT = 0, + HID_PRESENT = 1, + HID_SUSPEND = 2, + HID_FAILED = -2, + HID_RESET = -3, +}; + +enum { + HID_OP_DISABLE = 0, + HID_OP_ANALYZE = 1, + HID_OP_EXECUTE = 2, + HID_OP_MAX +}; + +enum { + HID_NOT_REQUIRED = 0, + HID_REQUIRED = 1 +}; + +enum { + HID_LEV_GRAY = 0, + HID_LEV_GREEN = 1, + HID_LEV_YELLOW = 2, + HID_LEV_RED = 3, +}; + +struct ufshid_dev { + struct ufsf_feature *ufsf; + + unsigned int hid_trigger; /* default value is false */ + struct delayed_work hid_trigger_work; + unsigned int hid_trigger_delay; + + bool is_auto_enabled; + + /* for sysfs */ + struct kobject kobj; + struct mutex sysfs_lock; + struct ufshid_sysfs_entry *sysfs_entries; + + /* for debug */ + bool hid_debug; +#if defined(CONFIG_UFSHID_POC) + bool block_suspend; +#endif +}; + +struct ufshid_sysfs_entry { + struct attribute attr; + ssize_t (*show)(struct ufshid_dev *hid, char *buf); + ssize_t (*store)(struct ufshid_dev *hid, const char *buf, size_t count); +}; + +int ufshid_get_state(struct ufsf_feature *ufsf); +void ufshid_set_state(struct ufsf_feature *ufsf, int state); +void ufshid_get_dev_info(struct ufsf_feature *ufsf, u8 *desc_buf); +void ufshid_set_init_state(struct ufsf_feature *ufsf); +void ufshid_init(struct ufsf_feature *ufsf); +void ufshid_reset(struct ufsf_feature *ufsf); +void ufshid_reset_host(struct ufsf_feature *ufsf); +void ufshid_remove(struct ufsf_feature *ufsf); +void ufshid_suspend(struct ufsf_feature *ufsf); +void ufshid_resume(struct ufsf_feature *ufsf); +void ufshid_on_idle(struct ufsf_feature *ufsf); +#endif /* End of Header */ From 88978ac3043e44ecf8db4e2b48b4b6bfec1e1d3f Mon Sep 17 00:00:00 2001 From: zhucc2 Date: Tue, 6 Jul 2021 16:40:24 +0800 Subject: [PATCH 371/698] arm64/config: enable SamSung HID feature. Remark: enable SS hid feature for cyprus 5G and corfu 5G on mot4350 family. disable for ibiza and denver,further project if reuse currently baseline need define it accordingly. Change-Id: I5ced032ca6e22e7e36386a6124c4765bbae6b2b7 Reviewed-on: https://gerrit.mot.com/2003424 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi-denver.config | 2 ++ .../configs/vendor/ext_config/moto-holi-ibiza-cmcc-extra.config | 2 ++ arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config | 2 ++ arch/arm64/configs/vendor/holi_QGKI.config | 2 ++ 4 files changed, 8 insertions(+) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-denver.config b/arch/arm64/configs/vendor/ext_config/moto-holi-denver.config index a576b69483e6..cd03c1226d93 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-denver.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-denver.config @@ -27,3 +27,5 @@ CONFIG_ZRAM_WRITEBACK=y # CONFIG_UFSTW_IGNORE_GUARANTEE_BIT is not set # CONFIG_UFSTW_BOOT_ENABLED is not set # CONFIG_MICRON_HPB is not set +# CONFIG_UFSHID is not set +# CONFIG_UFSHID_POC is not set diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza-cmcc-extra.config b/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza-cmcc-extra.config index b1fcb086bf73..88f1979131a7 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza-cmcc-extra.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza-cmcc-extra.config @@ -1 +1,3 @@ CONFIG_ZRAM_WRITEBACK=y +# CONFIG_UFSHID is not set +# CONFIG_UFSHID_POC is not set diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config b/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config index 4381a9d7398e..59a77ec09610 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config @@ -25,3 +25,5 @@ CONFIG_ZRAM_WRITEBACK=y # CONFIG_UFSTW_IGNORE_GUARANTEE_BIT is not set # CONFIG_UFSTW_BOOT_ENABLED is not set # CONFIG_MICRON_HPB is not set +# CONFIG_UFSHID is not set +# CONFIG_UFSHID_POC is not set diff --git a/arch/arm64/configs/vendor/holi_QGKI.config b/arch/arm64/configs/vendor/holi_QGKI.config index 29c1ff5a3e5d..2c65b3e7acfa 100644 --- a/arch/arm64/configs/vendor/holi_QGKI.config +++ b/arch/arm64/configs/vendor/holi_QGKI.config @@ -206,3 +206,5 @@ CONFIG_UFSTW_IGNORE_GUARANTEE_BIT=y CONFIG_UFSTW_BOOT_ENABLED=y CONFIG_SCSI_SKHPB=y CONFIG_MICRON_HPB=y +CONFIG_UFSHID=y +CONFIG_UFSHID_POC=y From 0195c133d57b1f4a6e30b8ac5cbeee8463cb35fa Mon Sep 17 00:00:00 2001 From: zhouwl Date: Wed, 7 Jul 2021 15:35:16 +0800 Subject: [PATCH 372/698] gki: Fix aw882xx_acf.ko compile failure aw882xx_acf.ko compile failure when make user build add whitelist. ERROR: "class_remove_file_ns" [techpack/audio/asoc/codecs/aw882xxacf/aw882xx_acf.ko] undefined! ERROR: "class_create_file_ns" [techpack/audio/asoc/codecs/aw882xxacf/aw882xx_acf.ko] undefined! Change-Id: I519cde4702a223dc2a171eba4f90114fa4fdec20 Signed-off-by: zhouwl Reviewed-on: https://gerrit.mot.com/2004700 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Minghui Wei Reviewed-by: Hujun Liao Submit-Approved: gaoyx9 --- android/abi_gki_aarch64_qcom | 2 ++ 1 file changed, 2 insertions(+) diff --git a/android/abi_gki_aarch64_qcom b/android/abi_gki_aarch64_qcom index 82b0f695e4cf..31ba65dc0fbc 100644 --- a/android/abi_gki_aarch64_qcom +++ b/android/abi_gki_aarch64_qcom @@ -186,6 +186,8 @@ __class_create class_destroy class_find_device + class_create_file_ns + class_remove_file_ns class_interface_unregister __class_register class_unregister From c67b0a7b7ab4e0177c7050869fa574d90d246580 Mon Sep 17 00:00:00 2001 From: zhucc2 Date: Thu, 8 Jul 2021 16:08:28 +0800 Subject: [PATCH 373/698] arm64/config: disable SamSung hid on cypfg. For the market device is sm4350 pro, we disable HID deature on cypfg device. However, this is a bug, For Micron MT064GASA02U21(4+64) is not support HID, if enable HID fearture on Micron device, will casue panic. we wil fixed it on cypfq. Change-Id: I6e78d4bc32dde6b089d8918ecdc0055c490f05cf Reviewed-on: https://gerrit.mot.com/2006650 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi-cypfg.config | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-cypfg.config b/arch/arm64/configs/vendor/ext_config/moto-holi-cypfg.config index e805d169eea8..884ddaa921a2 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-cypfg.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-cypfg.config @@ -18,3 +18,5 @@ CONFIG_CYPFG_DTB=y CONFIG_FS_EPOLL_WAKEUP_DEBUG=y CONFIG_ZRAM_WRITEBACK=y # CONFIG_THERMAL_STATISTICS is not set +# CONFIG_UFSHID is not set +# CONFIG_UFSHID_POC is not set From c76cbe7a053b305d1ecc06b36650dd5ae9989f9f Mon Sep 17 00:00:00 2001 From: zhucc2 Date: Wed, 7 Jul 2021 16:12:00 +0800 Subject: [PATCH 374/698] scsi/ufs: use macroes to control Hynix HID sys node. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For make Hynix HID driver disable for other vendors, we use macroes to restrict its power. note: "manual_gc_status" is moved from "/sys/device/platform/soc/4804000.ufshc/attributes" to "/sys/device/platform/soc/4804000.ufshc/attributes_hid", APP or Script need update this path. Change-Id: Ic9d8350bac14945acb29fba8d00ad90994c2d062 Reviewed-on: https://gerrit.mot.com/2004779 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- drivers/scsi/ufs/ufs-sysfs.c | 51 +++++++++++++++++++++++++++++++----- 1 file changed, 44 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/ufs/ufs-sysfs.c b/drivers/scsi/ufs/ufs-sysfs.c index 57d9ca66366c..c1ee9fbd4684 100644 --- a/drivers/scsi/ufs/ufs-sysfs.c +++ b/drivers/scsi/ufs/ufs-sysfs.c @@ -318,6 +318,16 @@ static DEVICE_ATTR_RW(auto_hibern8); #if defined(CONFIG_SCSI_SKHID) static DEVICE_ATTR_RW(manual_gc); static DEVICE_ATTR_RW(manual_gc_hold); + +static struct attribute *ufs_sysfs_ufshcd_hagc_attrs[] = { + &dev_attr_manual_gc.attr, + &dev_attr_manual_gc_hold.attr, + NULL +}; + +static const struct attribute_group ufs_sysfs_hagc_default_group = { + .attrs = ufs_sysfs_ufshcd_hagc_attrs, +}; #endif static struct attribute *ufs_sysfs_ufshcd_attrs[] = { @@ -328,10 +338,6 @@ static struct attribute *ufs_sysfs_ufshcd_attrs[] = { &dev_attr_spm_target_dev_state.attr, &dev_attr_spm_target_link_state.attr, &dev_attr_auto_hibern8.attr, -#if defined(CONFIG_SCSI_SKHID) - &dev_attr_manual_gc.attr, - &dev_attr_manual_gc_hold.attr, -#endif NULL }; @@ -871,6 +877,16 @@ UFS_ATTRIBUTE(wb_life_time_est, _WB_BUFF_LIFE_TIME_EST); UFS_ATTRIBUTE(wb_cur_buf, _CURR_WB_BUFF_SIZE); #if defined(CONFIG_SCSI_SKHID) UFS_ATTRIBUTE(manual_gc_status, _MANUAL_GC_STATUS); + +static struct attribute *ufs_sysfs_hagc_attributes[] = { + &dev_attr_manual_gc_status.attr, + NULL, +}; + +static const struct attribute_group ufs_sysfs_hagc_attributes_group = { + .name = "attributes_hid", + .attrs = ufs_sysfs_hagc_attributes, +}; #endif @@ -895,9 +911,6 @@ static struct attribute *ufs_sysfs_attributes[] = { &dev_attr_wb_avail_buf.attr, &dev_attr_wb_life_time_est.attr, &dev_attr_wb_cur_buf.attr, -#if defined(CONFIG_SCSI_SKHID) - &dev_attr_manual_gc_status.attr, -#endif NULL, }; @@ -919,6 +932,14 @@ static const struct attribute_group *ufs_sysfs_groups[] = { NULL, }; +#if defined(CONFIG_SCSI_SKHID) +static const struct attribute_group *ufs_sysfs_hagc_groups[] = { + &ufs_sysfs_hagc_default_group, + &ufs_sysfs_hagc_attributes_group, + NULL, +}; +#endif + #define UFS_LUN_DESC_PARAM(_pname, _puname, _duname, _size) \ static ssize_t _pname##_show(struct device *dev, \ struct device_attribute *attr, char *buf) \ @@ -1013,9 +1034,25 @@ void ufs_sysfs_add_nodes(struct device *dev) dev_err(dev, "%s: sysfs groups creation failed (err = %d)\n", __func__, ret); + + #if defined(CONFIG_SCSI_SKHID) + if (IS_SKHYNIX_DEVICE(storage_mfrid)) { + ret = sysfs_create_groups(&dev->kobj, ufs_sysfs_hagc_groups); + if (ret) + dev_err(dev, + "%s: sysfs hagc groups creation failed (err = %d)\n", + __func__, ret); + } + #endif } void ufs_sysfs_remove_nodes(struct device *dev) { sysfs_remove_groups(&dev->kobj, ufs_sysfs_groups); + + #if defined(CONFIG_SCSI_SKHID) + if (IS_SKHYNIX_DEVICE(storage_mfrid)) { + sysfs_remove_groups(&dev->kobj, ufs_sysfs_hagc_groups); + } + #endif } From d4ab62c1c12524d6d1eee2a25a381d3963703842 Mon Sep 17 00:00:00 2001 From: zhucc2 Date: Wed, 7 Jul 2021 16:28:30 +0800 Subject: [PATCH 375/698] arm64/config: enable Hynix HID feature. Remark: enable Hynix hid feature for cyprus 5G and corfu 5G on mot4350 family. disable for ibiza and denver,further project if reuse currently baseline need define it accordingly. Change-Id: I0e45c7096d3c9354a1c7580f5a8f4b151d7b5beb Reviewed-on: https://gerrit.mot.com/2004803 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi-denver.config | 1 + .../configs/vendor/ext_config/moto-holi-ibiza-cmcc-extra.config | 1 + arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config | 1 + arch/arm64/configs/vendor/holi_QGKI.config | 1 + 4 files changed, 4 insertions(+) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-denver.config b/arch/arm64/configs/vendor/ext_config/moto-holi-denver.config index cd03c1226d93..c55932f0bed9 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-denver.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-denver.config @@ -29,3 +29,4 @@ CONFIG_ZRAM_WRITEBACK=y # CONFIG_MICRON_HPB is not set # CONFIG_UFSHID is not set # CONFIG_UFSHID_POC is not set +# CONFIG_SCSI_SKHID is not set diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza-cmcc-extra.config b/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza-cmcc-extra.config index 88f1979131a7..4055bd9f9dd6 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza-cmcc-extra.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza-cmcc-extra.config @@ -1,3 +1,4 @@ CONFIG_ZRAM_WRITEBACK=y # CONFIG_UFSHID is not set # CONFIG_UFSHID_POC is not set +# CONFIG_SCSI_SKHID is not set diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config b/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config index 59a77ec09610..b896d63fc957 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config @@ -27,3 +27,4 @@ CONFIG_ZRAM_WRITEBACK=y # CONFIG_MICRON_HPB is not set # CONFIG_UFSHID is not set # CONFIG_UFSHID_POC is not set +# CONFIG_SCSI_SKHID is not set diff --git a/arch/arm64/configs/vendor/holi_QGKI.config b/arch/arm64/configs/vendor/holi_QGKI.config index 2c65b3e7acfa..38c2b4fb20e6 100644 --- a/arch/arm64/configs/vendor/holi_QGKI.config +++ b/arch/arm64/configs/vendor/holi_QGKI.config @@ -208,3 +208,4 @@ CONFIG_SCSI_SKHPB=y CONFIG_MICRON_HPB=y CONFIG_UFSHID=y CONFIG_UFSHID_POC=y +CONFIG_SCSI_SKHID=y From 25e06ff369244743f8b96158de3c557f12664648 Mon Sep 17 00:00:00 2001 From: zhucc2 Date: Mon, 12 Jul 2021 14:16:23 +0800 Subject: [PATCH 376/698] scsi/ufs: make ufsf_device_check() result return. SS HID driver not check the result, will do ufs feature init continuely, include tw, hpb and hid, if the ufs is ufs2.1 FW, l(CR) Micron MT064GASA02U21(4+64), not suport hid, will cause kernel panic. Change-Id: I4e683ca090dc84169ab16e4ee6added0a01898f3 Reviewed-on: https://gerrit.mot.com/2009108 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- drivers/scsi/ufs/ufsfeature.c | 7 ++++--- drivers/scsi/ufs/ufsfeature.h | 2 +- drivers/scsi/ufs/ufshcd.c | 3 ++- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/ufs/ufsfeature.c b/drivers/scsi/ufs/ufsfeature.c index 71122ab54e65..c706ffcd1390 100755 --- a/drivers/scsi/ufs/ufsfeature.c +++ b/drivers/scsi/ufs/ufsfeature.c @@ -276,7 +276,7 @@ out: return; } -void ufsf_device_check(struct ufs_hba *hba) +int ufsf_device_check(struct ufs_hba *hba) { struct ufsf_feature *ufsf = &hba->ufsf; int ret, lun; @@ -291,14 +291,15 @@ void ufsf_device_check(struct ufs_hba *hba) ret = ufsf_read_dev_desc(ufsf, UFSFEATURE_SELECTOR); if (ret) - return; + return ret; ret = ufsf_read_geo_desc(ufsf, UFSFEATURE_SELECTOR); if (ret) - return; + return ret; seq_scan_lu(lun) ufsf_read_unit_desc(ufsf, lun, UFSFEATURE_SELECTOR); + return 0; } static int ufsf_execute_dev_ctx_req(struct ufsf_feature *ufsf, diff --git a/drivers/scsi/ufs/ufsfeature.h b/drivers/scsi/ufs/ufsfeature.h index ca0477745a8f..6d1372c5eabc 100755 --- a/drivers/scsi/ufs/ufsfeature.h +++ b/drivers/scsi/ufs/ufsfeature.h @@ -168,7 +168,7 @@ struct ufs_hba; struct ufshcd_lrb; struct ufs_ioctl_query_data; -void ufsf_device_check(struct ufs_hba *hba); +int ufsf_device_check(struct ufs_hba *hba); int ufsf_check_query(__u32 opcode); int ufsf_query_ioctl(struct ufsf_feature *ufsf, int lun, void __user *buffer, struct ufs_ioctl_query_data *ioctl_data, diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 0ca91b71002d..7b1ed7744336 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -8069,7 +8069,8 @@ static int ufshcd_add_lus(struct ufs_hba *hba) #if defined(CONFIG_UFSFEATURE) if (is_support_hpb_200_device(storage_mfrid)){ - ufsf_device_check(hba); + if (ufsf_device_check(hba)) + goto out; ufsf_init(&hba->ufsf); } #endif From 4488d1afd8f0f7da69be963b13bf46e8c3d72b54 Mon Sep 17 00:00:00 2001 From: liuwang2 Date: Thu, 1 Jul 2021 18:06:19 +0800 Subject: [PATCH 377/698] arm64/config: add CONFIG_AF_NOISE_ELIMINATION [detail] add CONFIG_AF_NOISE_ELIMINATION for mot actuator driver Change-Id: I4183beb716fc64314c77349fca0c0362b102a4dd Signed-off-by: liuwang2 Reviewed-on: https://gerrit.mot.com/1999367 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Long Cheng Reviewed-by: Shuo Wang Reviewed-by: XiaoFeng Wang Reviewed-by: Zhenxin Xi Submit-Approved: Jira Key --- arch/arm64/Kconfig | 6 ++++++ arch/arm64/configs/vendor/ext_config/moto-holi-cypfg.config | 1 + arch/arm64/configs/vendor/ext_config/moto-holi-cypfq.config | 1 + 3 files changed, 8 insertions(+) diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index b69899d7741c..e22b1348ecb5 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -1867,3 +1867,9 @@ source "arch/arm64/kvm/Kconfig" if CRYPTO source "arch/arm64/crypto/Kconfig" endif + +config AF_NOISE_ELIMINATION + bool "For elimnating AF resonance noise" + default n + help + Enable it only for produts that suffering AF resonance noise. diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-cypfg.config b/arch/arm64/configs/vendor/ext_config/moto-holi-cypfg.config index 884ddaa921a2..2bdee17c4d7d 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-cypfg.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-cypfg.config @@ -20,3 +20,4 @@ CONFIG_ZRAM_WRITEBACK=y # CONFIG_THERMAL_STATISTICS is not set # CONFIG_UFSHID is not set # CONFIG_UFSHID_POC is not set +CONFIG_AF_NOISE_ELIMINATION=y diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-cypfq.config b/arch/arm64/configs/vendor/ext_config/moto-holi-cypfq.config index e2e65c81a297..4fc54a9b9a23 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-cypfq.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-cypfq.config @@ -20,3 +20,4 @@ CONFIG_ZRAM_WRITEBACK=y # CONFIG_THERMAL_STATISTICS is not set # CONFIG_REGULATOR_QPNP_LCDB is not set CONFIG_REGULATOR_TPS65132=y +CONFIG_AF_NOISE_ELIMINATION=y From 33afc9c2c20db072fa04b509c8803fc326833c17 Mon Sep 17 00:00:00 2001 From: chenlj2 Date: Wed, 14 Jul 2021 11:17:52 +0800 Subject: [PATCH 378/698] pinctrl:remove GPIO17 from the reserved GPIO list GPIO17-----FPS INT FPS bringup work on6375 remove GPIO17 from the reserved GPIO list Otherwise the fingerprint driver cannot apply for this GPIO Change-Id: I963f7dc55369f435bfb6bb0d58cc9bd42e51576a Signed-off-by: chenlj2 Reviewed-on: https://gerrit.mot.com/2011805 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Yan Zhang Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- drivers/pinctrl/qcom/pinctrl-blair.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pinctrl/qcom/pinctrl-blair.c b/drivers/pinctrl/qcom/pinctrl-blair.c index 39ee6e4674c0..62d2dbe83ed4 100644 --- a/drivers/pinctrl/qcom/pinctrl-blair.c +++ b/drivers/pinctrl/qcom/pinctrl-blair.c @@ -1593,7 +1593,7 @@ static const struct msm_pingroup blair_groups[] = { }; static const int blair_reserved_gpios[] = { - 13, 14, 15, 16, 17, 45, 46, 48, 56, 57, -1 + 13, 14, 15, 16, 45, 46, 48, 56, 57, -1 }; static const struct msm_gpio_wakeirq_map blair_mpm_map[] = { From b97c5ab46a5728ec443704f138d77b3adf83d137 Mon Sep 17 00:00:00 2001 From: zoujc Date: Thu, 1 Jul 2021 11:13:01 +0800 Subject: [PATCH 379/698] arm64/config: disable coresight on sm4350 user version. coresight is not used by any module. disable it to avoid irq wakeup issue. https://gerrit.mot.com/#/c/1863643/ will enable coresight on debug version. Change-Id: I0d84be965ce088bd13e14b071b3a103b2bc5646e Signed-off-by: zoujc Reviewed-on: https://gerrit.mot.com/1998604 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Jianqi Yang Submit-Approved: Jira Key Reviewed-on: https://gerrit.mot.com/2014590 Reviewed-by: Huosheng Liao --- arch/arm64/configs/vendor/ext_config/moto-holi.config | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi.config b/arch/arm64/configs/vendor/ext_config/moto-holi.config index aef6a24d0481..8c7923319548 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi.config @@ -30,3 +30,12 @@ CONFIG_SCHED_STACK_END_CHECK=y CONFIG_MEDIA_USB_SUPPORT=y CONFIG_USB_VIDEO_CLASS=y +# CONFIG_CORESIGHT_LINK_AND_SINK_TMC is not set +# CONFIG_CORESIGHT_SOURCE_ETM4X is not set +# CONFIG_CORESIGHT_CTI is not set +# CONFIG_CORESIGHT_TPDA is not set +# CONFIG_CORESIGHT_TPDM is not set +# CONFIG_CORESIGHT_HWEVENT is not set +# CONFIG_CORESIGHT_DUMMY is not set +# CONFIG_CORESIGHT_REMOTE_ETM is not set +# CONFIG_CORESIGHT_TGU is not set From a007e73b8942436179caa2c467888431120cc681 Mon Sep 17 00:00:00 2001 From: houdz1 Date: Mon, 26 Jul 2021 16:09:13 +0800 Subject: [PATCH 380/698] arm64/config: cypfq: disable tps65132 Change the default output voltage through I2C bus at XBL. And store the default value to EEPROM. So we can nod make I2C operation at kernel. Only pull up/down gpio to enable/disable regulator. Change-Id: Ie6c7a781257efe97aea8e7fe84a7efa20c6359aa Signed-off-by: houdz1 Reviewed-on: https://gerrit.mot.com/2020886 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi-cypfq.config | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-cypfq.config b/arch/arm64/configs/vendor/ext_config/moto-holi-cypfq.config index 4fc54a9b9a23..db9784141a24 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-cypfq.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-cypfq.config @@ -19,5 +19,4 @@ CONFIG_FS_EPOLL_WAKEUP_DEBUG=y CONFIG_ZRAM_WRITEBACK=y # CONFIG_THERMAL_STATISTICS is not set # CONFIG_REGULATOR_QPNP_LCDB is not set -CONFIG_REGULATOR_TPS65132=y CONFIG_AF_NOISE_ELIMINATION=y From cd85b3feb02d48427a72951755ebd32440e5713a Mon Sep 17 00:00:00 2001 From: chailu1 Date: Tue, 27 Jul 2021 14:01:40 +0800 Subject: [PATCH 381/698] charge: Rename sc8549 to cp For charge pump common interface,use cp name replace sc8549. Change-Id: Ibbe393fceba8b5e97daf87e0f59ac37c4c9520a8 Signed-off-by: chailu1 Reviewed-on: https://gerrit.mot.com/2024887 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Haijian Ma Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- drivers/power/supply/qcom/smb5-iio.h | 2 +- drivers/power/supply/qcom/smb5-lib.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/power/supply/qcom/smb5-iio.h b/drivers/power/supply/qcom/smb5-iio.h index e5ecb0308864..bbd90bf7367d 100644 --- a/drivers/power/supply/qcom/smb5-iio.h +++ b/drivers/power/supply/qcom/smb5-iio.h @@ -36,7 +36,7 @@ enum qg_chg_iio_channels { }; enum mmi_cp_iio_channels { - SC8549_INPUT_VOLTAGE_NOW, + CP_INPUT_VOLTAGE_NOW, }; enum cp_iio_channels { diff --git a/drivers/power/supply/qcom/smb5-lib.c b/drivers/power/supply/qcom/smb5-lib.c index 7ff2e8ca4a38..1ac1808d29c1 100644 --- a/drivers/power/supply/qcom/smb5-lib.c +++ b/drivers/power/supply/qcom/smb5-lib.c @@ -890,7 +890,7 @@ int smblib_set_aicl_cont_threshold(struct smb_chg_param *param, ********************/ /* MMI CP channels */ static const char * const smblib_mmi_cp_ext_iio_chan[] = { - [SC8549_INPUT_VOLTAGE_NOW] = "sc8549_input_voltage_now", + [CP_INPUT_VOLTAGE_NOW] = "cp_input_voltage_now", }; /* CP channels */ @@ -5920,7 +5920,7 @@ static int mmi_get_vbus(struct smb_charger *chg) if (!is_mmi_cp_available(chg)) return 0; - rc = smblib_read_iio_prop(chg, MMI_CP, SC8549_INPUT_VOLTAGE_NOW, + rc = smblib_read_iio_prop(chg, MMI_CP, CP_INPUT_VOLTAGE_NOW, &val); if (!rc) return val; From b67ec45e73d2b45ea9b8c5d387851ead81ca3c63 Mon Sep 17 00:00:00 2001 From: Zhizhong Ge Date: Fri, 30 Jul 2021 17:09:07 +0800 Subject: [PATCH 382/698] config: reduce the holi user-debug kernel config Reduce the config on userdbug to improve the perforamce CONFIG_DEBUG_SECTION_MISMATCH is not set CONFIG_DEBUG_PAGEALLOC is not set CONFIG_DEBUG_PAGEALLOC_ENABLE_DEFAULT is not set CONFIG_DEBUG_KMEMLEAK is not set CONFIG_DEBUG_VIRTUAL is not set CONFIG_DEBUG_RT_MUTEXES is not set CONFIG_DEBUG_SPINLOCK is not set CONFIG_DEBUG_MUTEXES is not set CONFIG_DEBUG_LOCK_ALLOC is not set CONFIG_DEBUG_LOCKDEP is not set CONFIG_DEBUG_ATOMIC_SLEEP is not set CONFIG_DEBUG_FS is not set CONFIG_RCU_TRACE is not set CONFIG_PREEMPT_TRACER is not set CONFIG_STACKDEPOT is not set CONFIG_SCHED_STACK_END_CHECK is not set CONFIG_PAGE_OWNER is not set CONFIG_DM_DEBUG is not set CONFIG_EXT4_DEBUG is not set CONFIG_LOCK_STAT is not set Change-Id: Ia918fa32e73984d6f93560bc24aa45052123207c Reviewed-on: https://gerrit.mot.com/2029094 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Yonghui Jia Reviewed-by: Chuanchun Zhu Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- .../vendor/ext_config/debug-holi.config | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/arch/arm64/configs/vendor/ext_config/debug-holi.config b/arch/arm64/configs/vendor/ext_config/debug-holi.config index ff9ff6c35dd6..ce00eb1f6ad0 100644 --- a/arch/arm64/configs/vendor/ext_config/debug-holi.config +++ b/arch/arm64/configs/vendor/ext_config/debug-holi.config @@ -48,3 +48,23 @@ CONFIG_CORESIGHT_HWEVENT=y CONFIG_CORESIGHT_DUMMY=y CONFIG_CORESIGHT_REMOTE_ETM=y CONFIG_CORESIGHT_TGU=y +# CONFIG_DEBUG_SECTION_MISMATCH is not set +# CONFIG_DEBUG_PAGEALLOC is not set +# CONFIG_DEBUG_PAGEALLOC_ENABLE_DEFAULT is not set +# CONFIG_DEBUG_KMEMLEAK is not set +# CONFIG_DEBUG_VIRTUAL is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_DEBUG_LOCKDEP is not set +# CONFIG_DEBUG_ATOMIC_SLEEP is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_RCU_TRACE is not set +# CONFIG_PREEMPT_TRACER is not set +# CONFIG_STACKDEPOT is not set +# CONFIG_SCHED_STACK_END_CHECK is not set +# CONFIG_PAGE_OWNER is not set +# CONFIG_DM_DEBUG is not set +# CONFIG_EXT4_DEBUG is not set +# CONFIG_LOCK_STAT is not set From cff390b6c71edcf4e876b88308db53b4526082d1 Mon Sep 17 00:00:00 2001 From: mahj8 Date: Fri, 30 Jul 2021 15:35:03 +0800 Subject: [PATCH 383/698] smb5: remove pd2.0 policy in smb5-lib.c For add PD charging(include PPS/Fixed) policy in DLKM for single charge path(only pmic charging), so need to remove pd2.0 policy in smb5-lib.c Change-Id: I10807a7c73eb6d5372019bfa9c1db0e99993cb89 Signed-off-by: mahj8 Reviewed-on: https://gerrit.mot.com/2029012 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Lu Chai Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- drivers/power/supply/qcom/smb5-lib.c | 84 ---------------------------- drivers/power/supply/qcom/smb5-lib.h | 7 --- 2 files changed, 91 deletions(-) diff --git a/drivers/power/supply/qcom/smb5-lib.c b/drivers/power/supply/qcom/smb5-lib.c index 1ac1808d29c1..f13e50d0c136 100644 --- a/drivers/power/supply/qcom/smb5-lib.c +++ b/drivers/power/supply/qcom/smb5-lib.c @@ -801,7 +801,6 @@ static int smblib_set_usb_pd_allowed_voltage(struct smb_charger *chg, int rc, aicl_threshold; u8 vbus_allowance = FORCE_NULL; -#ifdef QCOM_BASE if (chg->chg_param.smb_version == PMI632) return 0; @@ -836,14 +835,6 @@ static int smblib_set_usb_pd_allowed_voltage(struct smb_charger *chg, return rc; } -#else - if (chg->pd_active && (chg->pd_contract_uv <= 0)) { - cancel_delayed_work(&chg->pd_contract_work); - schedule_delayed_work(&chg->pd_contract_work, - msecs_to_jiffies(0)); - } -#endif - if (vbus_allowance != CONTINUOUS) return 0; @@ -4827,8 +4818,6 @@ int smblib_set_prop_pd_voltage_max(struct smb_charger *chg, max_uv = max(val, chg->voltage_min_uv); if (chg->voltage_max_uv == max_uv) return 0; - else if (chg->pd_active) - chg->pd_contract_uv = 0; rc = smblib_set_usb_pd_fsw(chg, max_uv); if (rc < 0) { @@ -4899,11 +4888,6 @@ int smblib_set_prop_pd_active(struct smb_charger *chg, dev_err(chg->dev, "Couldn't enable secondary charger rc=%d\n", rc); } - if (chg->pd_contract_uv <= 0) { - cancel_delayed_work(&chg->pd_contract_work); - schedule_delayed_work(&chg->pd_contract_work, - msecs_to_jiffies(0)); - } } else { vote(chg->usb_icl_votable, PD_VOTER, false, 0); vote(chg->limited_irq_disable_votable, CHARGER_TYPE_VOTER, @@ -6722,7 +6706,6 @@ static void typec_src_removal(struct smb_charger *chg) chg->voltage_max_uv = MICRO_5V; chg->usbin_forced_max_uv = 0; chg->chg_param.forced_main_fcc = 0; - chg->pd_contract_uv = 0; chg->typec_apsd_rerun_done = false; /* Reset all CC mode votes */ @@ -7624,72 +7607,6 @@ int smblib_set_prop_pr_swap_in_progress(struct smb_charger *chg, /*************** * Work Queues * ***************/ -#define MAX_INPUT_PWR_UW 18000000 -static void smblib_pd_contract_work(struct work_struct *work) -{ - struct smb_charger *chg = container_of(work, struct smb_charger, - pd_contract_work.work); - int rc, max_ua; - - if (!chg->pd) { - chg->pd = devm_usbpd_get_by_phandle(chg->dev, - "qcom,usbpd-phandle"); - if (IS_ERR_OR_NULL(chg->pd)) { - pr_err("Error getting the pd phandle %ld\n", - PTR_ERR(chg->pd)); - chg->pd = NULL; - } - } - if (!chg->pd || !chg->pd_active) - return; - - if (!chg->pd_voltage_max_uv) { - rc = of_property_read_u32(chg->dev->of_node, - "qcom,pd-voltage-max-uv", - &chg->pd_voltage_max_uv); - if (rc < 0) { - chg->pd_voltage_max_uv = MICRO_5V; - smblib_err(chg, "Failed to get pd_voltage_max_uv" - "from device tree, rc = %d\n", rc); - } - - if (chg->pd_voltage_max_uv < MICRO_5V) - chg->pd_voltage_max_uv = MICRO_5V; - else if (chg->pd_voltage_max_uv > MICRO_12V) - chg->pd_voltage_max_uv = MICRO_12V; - } - chg->voltage_max_uv = chg->pd_voltage_max_uv; - - chg->pd_contract_uv = usbpd_select_pdo_match(chg->pd); - - if (chg->pd_contract_uv == -ENOTSUPP) - return; - - if (chg->pd_contract_uv <= 0) { - schedule_delayed_work(&chg->pd_contract_work, - msecs_to_jiffies(100)); - return; - } else - power_supply_changed(chg->usb_psy); - - if (chg->pd_contract_uv >= MICRO_9V) - smblib_set_opt_switcher_freq(chg, chg->chg_freq.freq_9V); - else - smblib_set_opt_switcher_freq(chg, chg->chg_freq.freq_5V); - - max_ua = (MAX_INPUT_PWR_UW / (chg->pd_contract_uv / 1000)) * 1000; - - if (get_client_vote(chg->usb_icl_votable, PD_VOTER) > 0) - max_ua = min(max_ua, get_client_vote(chg->usb_icl_votable, PD_VOTER)); - - smblib_err(chg, "smblib_pd_contract_work: %d uV, %d uA\n", - chg->pd_contract_uv, max_ua); - - rc = vote(chg->usb_icl_votable, PD_VOTER, true, max_ua); - if (rc < 0) - smblib_err(chg, "Error setting %d uA rc=%d\n", max_ua, rc); -} - static void smblib_pr_lock_clear_work(struct work_struct *work) { struct smb_charger *chg = container_of(work, struct smb_charger, @@ -8769,7 +8686,6 @@ int smblib_init(struct smb_charger *chg) smblib_pr_swap_detach_work); INIT_DELAYED_WORK(&chg->pr_lock_clear_work, smblib_pr_lock_clear_work); - INIT_DELAYED_WORK(&chg->pd_contract_work, smblib_pd_contract_work); if (chg->mmi_qc3p_support) { chg->mmi_qc3p_authen_task = kthread_create(mmi_qc3p_kthread_handler, chg, "mmi_qc3p_authen", "mmi_qc3p_authen_task", chg); diff --git a/drivers/power/supply/qcom/smb5-lib.h b/drivers/power/supply/qcom/smb5-lib.h index 4a9c88a5f26c..8d9f93a717b8 100644 --- a/drivers/power/supply/qcom/smb5-lib.h +++ b/drivers/power/supply/qcom/smb5-lib.h @@ -17,7 +17,6 @@ #include #include #include -#include #include "storm-watch.h" #include "battery.h" @@ -611,12 +610,6 @@ struct smb_charger { /* extcon for VBUS / ID notification to USB for uUSB */ struct extcon_dev *extcon; - /* USB PD interactions */ - struct usbpd *pd; - int pd_contract_uv; - int pd_voltage_max_uv; - struct delayed_work pd_contract_work; - /* battery profile */ int batt_profile_fcc_ua; int batt_profile_fv_uv; From 2b419dee3f88f700cb2c672912a7a84e07d9d02e Mon Sep 17 00:00:00 2001 From: Yifu Lin Date: Fri, 6 Aug 2021 02:07:23 -0500 Subject: [PATCH 384/698] Revert "(CR) arm64/config: disable coresight on sm4350 user version." This reverts commit 585af9cffc7ae94d3a33bcfe65b020618b944248. Re-enable coresight in user build. We need to enable coresight feature to supporting the collection of modem log Change-Id: If4d109d8575e34388ef6d425b80ad59874921b6e Reviewed-on: https://gerrit.mot.com/2034963 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi.config | 9 --------- 1 file changed, 9 deletions(-) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi.config b/arch/arm64/configs/vendor/ext_config/moto-holi.config index 8c7923319548..aef6a24d0481 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi.config @@ -30,12 +30,3 @@ CONFIG_SCHED_STACK_END_CHECK=y CONFIG_MEDIA_USB_SUPPORT=y CONFIG_USB_VIDEO_CLASS=y -# CONFIG_CORESIGHT_LINK_AND_SINK_TMC is not set -# CONFIG_CORESIGHT_SOURCE_ETM4X is not set -# CONFIG_CORESIGHT_CTI is not set -# CONFIG_CORESIGHT_TPDA is not set -# CONFIG_CORESIGHT_TPDM is not set -# CONFIG_CORESIGHT_HWEVENT is not set -# CONFIG_CORESIGHT_DUMMY is not set -# CONFIG_CORESIGHT_REMOTE_ETM is not set -# CONFIG_CORESIGHT_TGU is not set From 239929ee25f48a437b7ec4534693973f4de5291f Mon Sep 17 00:00:00 2001 From: chailu1 Date: Thu, 15 Jul 2021 14:23:46 +0800 Subject: [PATCH 385/698] charge: Enhance qc3+ detect If detect qc3+ detect power is invalid, rerun qc3+ detect again. Change-Id: Ia8e94e0ad7379f365ae97e014da3521517f041f3 Reviewed-on: https://gerrit.mot.com/2024886 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- drivers/power/supply/qcom/smb5-lib.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/power/supply/qcom/smb5-lib.c b/drivers/power/supply/qcom/smb5-lib.c index f13e50d0c136..f4e0ea2aaca9 100644 --- a/drivers/power/supply/qcom/smb5-lib.c +++ b/drivers/power/supply/qcom/smb5-lib.c @@ -6028,10 +6028,14 @@ static int mmi_qc3p_kthread_handler(void *param) else chg->mmi_qc3p_power = QTI_POWER_SUPPLY_QC3P_NONE; - if (chg->mmi_qc3p_power != QTI_POWER_SUPPLY_QC3P_NONE) + if (chg->mmi_qc3p_power != QTI_POWER_SUPPLY_QC3P_NONE) { chg->qc3p5_detected = true; - smblib_update_usb_type(chg); - power_supply_changed(chg->usb_psy); + smblib_update_usb_type(chg); + power_supply_changed(chg->usb_psy); + } else { + smblib_err(chg, "qc3p power is invalid, rerun qc3p detect\n"); + mmi_rerun_qc3p_det(chg); + } smblib_dbg(chg, PR_MISC, "V_aut:%dms %dmV,V_power=%dms %dmV,Power =%d\n", jiffies_to_msecs(j1), v_aut, jiffies_to_msecs(j2), v_power, chg->mmi_qc3p_power); From 944ceedfc791d8c00f06a44cbc7ab8b7a75fe931 Mon Sep 17 00:00:00 2001 From: jixj Date: Wed, 4 Aug 2021 16:52:10 +0800 Subject: [PATCH 386/698] arm64/configs: Add Milan 5G defconfig Add initial defconfig for Milan 5G branch bringup, these configs are copied from cypfq. Change-Id: I90094a35cf65035476da061ef5d07fb532fa1d02 Reviewed-on: https://gerrit.mot.com/2032542 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- .../ext_config/debug-holi-milanf.config | 25 +++++++++++++++++++ .../ext_config/factory-holi-milanf.config | 16 ++++++++++++ .../vendor/ext_config/moto-holi-milanf.config | 21 ++++++++++++++++ drivers/soc/qcom/Kconfig | 8 ++++++ 4 files changed, 70 insertions(+) create mode 100644 arch/arm64/configs/vendor/ext_config/debug-holi-milanf.config create mode 100644 arch/arm64/configs/vendor/ext_config/factory-holi-milanf.config create mode 100644 arch/arm64/configs/vendor/ext_config/moto-holi-milanf.config diff --git a/arch/arm64/configs/vendor/ext_config/debug-holi-milanf.config b/arch/arm64/configs/vendor/ext_config/debug-holi-milanf.config new file mode 100644 index 000000000000..13f71e03c466 --- /dev/null +++ b/arch/arm64/configs/vendor/ext_config/debug-holi-milanf.config @@ -0,0 +1,25 @@ +# +# Please avoid changing the Qualcomm defconfig files and use this file to +# add any Motorola-specific configuration changes that are applicable to +# userdebug, eng, and user builds. +# +# After building, a list of all of the config files that are used can be found +# at the top of: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/mapphone_defconfig +# +# The actual output of the kernel configuration system can be found at: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/.config +# +# You can check the .config file to verify that your configuration option is +# being set as expected. +# + +# CONFIG_CGROUP_DEBUG is not set +# CONFIG_CLEANCACHE is not set +# CONFIG_CMA_ALLOW_WRITE_DEBUGFS is not set +# CONFIG_CMA_DEBUG is not set +# CONFIG_PREEMPTIRQ_EVENTS is not set +# CONFIG_PREEMPT_TRACER is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_TEST_USER_COPY is not set diff --git a/arch/arm64/configs/vendor/ext_config/factory-holi-milanf.config b/arch/arm64/configs/vendor/ext_config/factory-holi-milanf.config new file mode 100644 index 000000000000..830e8a22f610 --- /dev/null +++ b/arch/arm64/configs/vendor/ext_config/factory-holi-milanf.config @@ -0,0 +1,16 @@ +# +# Please avoid changing the Qualcomm defconfig files and use this file to +# add any Motorola-specific configuration changes that are applicable to +# userdebug, eng, and user builds. +# +# After building, a list of all of the config files that are used can be found +# at the top of: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/mapphone_defconfig +# +# The actual output of the kernel configuration system can be found at: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/.config +# +# You can check the .config file to verify that your configuration option is +# being set as expected. +# + diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-milanf.config b/arch/arm64/configs/vendor/ext_config/moto-holi-milanf.config new file mode 100644 index 000000000000..8795c9754ae5 --- /dev/null +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-milanf.config @@ -0,0 +1,21 @@ +# +# Please avoid changing the Qualcomm defconfig files and use this file to +# add any Motorola-specific configuration changes that are applicable to +# userdebug, eng, and user builds. +# +# After building, a list of all of the config files that are used can be found +# at the top of: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/mapphone_defconfig +# +# The actual output of the kernel configuration system can be found at: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/.config +# +# You can check the .config file to verify that your configuration option is +# being set as expected. +# +CONFIG_MILANF_DTB=y +# CONFIG_NFC_QTI_I2C is not set +CONFIG_FS_EPOLL_WAKEUP_DEBUG=y +CONFIG_ZRAM_WRITEBACK=y +# CONFIG_THERMAL_STATISTICS is not set +# CONFIG_REGULATOR_QPNP_LCDB is not set diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index acf8eadfb84c..80180dc6f4d3 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -76,6 +76,14 @@ config CYPFR_DTB Only include CYPFR specific DTBs to limit the number that get built during kernel compilation. +config MILANF_DTB + depends on ARCH_QCOM + default n + bool "MILANF DTBs" + help + Only include MILANF specific DTBs to limit the number that + get built during kernel compilation. + config QCOM_AOSS_QMP tristate "Qualcomm AOSS Driver" depends on ARCH_QCOM || COMPILE_TEST From 43f49cc99aff73a068c53e92c6fd2edddf3a4cc3 Mon Sep 17 00:00:00 2001 From: liuwang2 Date: Thu, 12 Aug 2021 11:32:28 +0800 Subject: [PATCH 387/698] arm64/config: cypfr: add CONFIG_AF_NOISE_ELIMINATION [detail] enable CONFIG_AF_NOISE_ELIMINATION in cypfr Change-Id: I5f42b8f21c1d390caca89b66af282ad2b4c8d249 Signed-off-by: liuwang2 Reviewed-on: https://gerrit.mot.com/2039638 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Bolei Shang Reviewed-by: Zhenxin Xi Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi-cypfr.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-cypfr.config b/arch/arm64/configs/vendor/ext_config/moto-holi-cypfr.config index 88d63a258189..539ab3c730d3 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-cypfr.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-cypfr.config @@ -18,3 +18,4 @@ CONFIG_CYPFR_DTB=y CONFIG_FS_EPOLL_WAKEUP_DEBUG=y CONFIG_ZRAM_WRITEBACK=y # CONFIG_THERMAL_STATISTICS is not set +CONFIG_AF_NOISE_ELIMINATION=y From 59dc457ecd8c94333b4a410d0aab964468fcf3a1 Mon Sep 17 00:00:00 2001 From: weiweij Date: Wed, 11 Aug 2021 17:30:48 +0800 Subject: [PATCH 388/698] driver/usb: add adb force enable logic For some debug situations, we need to force adb function enabled without charger notification. So we add the forcing logic. And it is controlled by a dts configuration("qcom,force-adb-enable") Change-Id: I1a779c0e8b9f60cdbf978d555b3f1e537db4740f Reviewed-on: https://gerrit.mot.com/2038917 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Haijian Ma Reviewed-by: Huosheng Liao Reviewed-by: Yuecai Liu Submit-Approved: Jira Key --- drivers/usb/dwc3/dwc3-msm.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c index f28fe021e7bc..02838de73116 100644 --- a/drivers/usb/dwc3/dwc3-msm.c +++ b/drivers/usb/dwc3/dwc3-msm.c @@ -5099,6 +5099,12 @@ static int dwc3_msm_probe(struct platform_device *pdev) device_create_file(&pdev->dev, &dev_attr_speed); device_create_file(&pdev->dev, &dev_attr_bus_vote); + if (of_property_read_bool(mdwc->dev->of_node, + "qcom,force-adb-enable")) { + dev_err(mdwc->dev, "%s: force usb start device mode\n", __func__); + dwc3_start_stop_device(mdwc, true); + } + return 0; put_dwc3: From 8b19b578750106d5a8fa9eddc1615a7ee71240b3 Mon Sep 17 00:00:00 2001 From: duxu1 Date: Thu, 12 Aug 2021 16:24:22 +0800 Subject: [PATCH 389/698] Enable CONFIG_DEBUG_FS CONFIG_DEBUG_FS is used to collect uart ipc logs to debug uart issue. Change-Id: I12f0a6f01e105e79aac317d034f6197d0dface89 Signed-off-by: duxu1 Reviewed-on: https://gerrit.mot.com/2039979 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Hongshu Lou Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/debug-holi.config | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm64/configs/vendor/ext_config/debug-holi.config b/arch/arm64/configs/vendor/ext_config/debug-holi.config index ce00eb1f6ad0..2aad8fa96812 100644 --- a/arch/arm64/configs/vendor/ext_config/debug-holi.config +++ b/arch/arm64/configs/vendor/ext_config/debug-holi.config @@ -59,7 +59,6 @@ CONFIG_CORESIGHT_TGU=y # CONFIG_DEBUG_LOCK_ALLOC is not set # CONFIG_DEBUG_LOCKDEP is not set # CONFIG_DEBUG_ATOMIC_SLEEP is not set -# CONFIG_DEBUG_FS is not set # CONFIG_RCU_TRACE is not set # CONFIG_PREEMPT_TRACER is not set # CONFIG_STACKDEPOT is not set From 5e221066a4ed5469204009b481352ed78fe0f6b0 Mon Sep 17 00:00:00 2001 From: chailu1 Date: Fri, 13 Aug 2021 10:22:24 +0800 Subject: [PATCH 390/698] gki: add smbus and typec api for rt17xx driver gki/pd/rt17xx add smbus and typec api for rt17xx driver Change-Id: I7fbab6c45390177896a69af573ce8b97e54354d3 Signed-off-by: chailu1 Reviewed-on: https://gerrit.mot.com/2040743 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- android/abi_gki_aarch64_qcom | 3 +++ 1 file changed, 3 insertions(+) diff --git a/android/abi_gki_aarch64_qcom b/android/abi_gki_aarch64_qcom index 31ba65dc0fbc..0c7673225a44 100644 --- a/android/abi_gki_aarch64_qcom +++ b/android/abi_gki_aarch64_qcom @@ -186,6 +186,7 @@ __class_create class_destroy class_find_device + class_for_each_device class_create_file_ns class_remove_file_ns class_interface_unregister @@ -390,6 +391,7 @@ device_property_read_u8_array device_register device_remove_file + device_set_of_node_from_dev device_set_wakeup_capable device_show_int device_store_int @@ -2586,6 +2588,7 @@ typec_altmode_vdm typec_get_drvdata typec_partner_register_altmode + typec_partner_set_identity typec_port_register_altmode typec_register_partner typec_register_port From b65c5b882ab2ff69ded35bb8712224f03c3f84e6 Mon Sep 17 00:00:00 2001 From: Xiaofeng Wang Date: Mon, 2 Aug 2021 15:36:52 +0800 Subject: [PATCH 391/698] corfu5g: add CONFIG_AF_NOISE_ELIMINATION [detail] add CONFIG_AF_NOISE_ELIMINATION for mot actuator driver Change-Id: I0bb23b1a8703afa249d71f8f68c67bc391e055de Signed-off-by: Xiaofeng Wang Reviewed-on: https://gerrit.mot.com/2030402 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Wang Liu Reviewed-by: Xingyun Fu Reviewed-by: Bolei Shang Reviewed-by: Ji Zhao Reviewed-by: Zhuoran Xu Reviewed-by: Shuo Wang Reviewed-by: Zhichao Chen Reviewed-by: Zhenxin Xi Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi-corfup.config | 1 + arch/arm64/configs/vendor/ext_config/moto-holi-corfuq.config | 1 + arch/arm64/configs/vendor/ext_config/moto-holi-corfur.config | 1 + 3 files changed, 3 insertions(+) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-corfup.config b/arch/arm64/configs/vendor/ext_config/moto-holi-corfup.config index b5bf64fc77d5..31f9f7d0bfc3 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-corfup.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-corfup.config @@ -20,3 +20,4 @@ CONFIG_ZRAM_WRITEBACK=y # CONFIG_THERMAL_STATISTICS is not set # CONFIG_TOUCHSCREEN_FTS is not set # CONFIG_TOUCHSCREEN_FTS_DIRECTORY is not set +CONFIG_AF_NOISE_ELIMINATION=y diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-corfuq.config b/arch/arm64/configs/vendor/ext_config/moto-holi-corfuq.config index b9ac647b582b..65809cff3f81 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-corfuq.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-corfuq.config @@ -20,3 +20,4 @@ CONFIG_ZRAM_WRITEBACK=y # CONFIG_THERMAL_STATISTICS is not set # CONFIG_TOUCHSCREEN_FTS is not set # CONFIG_TOUCHSCREEN_FTS_DIRECTORY is not set +CONFIG_AF_NOISE_ELIMINATION=y diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-corfur.config b/arch/arm64/configs/vendor/ext_config/moto-holi-corfur.config index f0bab2d21f39..37814268502a 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-corfur.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-corfur.config @@ -20,3 +20,4 @@ CONFIG_ZRAM_WRITEBACK=y # CONFIG_THERMAL_STATISTICS is not set # CONFIG_TOUCHSCREEN_FTS is not set # CONFIG_TOUCHSCREEN_FTS_DIRECTORY is not set +CONFIG_AF_NOISE_ELIMINATION=y From 7f4f01daed3ce96828e56afce2d27e3bb77c3884 Mon Sep 17 00:00:00 2001 From: liuyc20 Date: Wed, 18 Aug 2021 11:23:27 +0800 Subject: [PATCH 392/698] gki: add i2c_smbug api for sd77426 driver gki build fail. add i2c_smbus_read_word_data/i2c_smbus_write_word_data, build pass Change-Id: I218e26eebec3c3fcc664a1c64ca7bede9b35da19 Signed-off-by: liuyc20 Reviewed-on: https://gerrit.mot.com/2044706 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- android/abi_gki_aarch64_qcom | 2 ++ 1 file changed, 2 insertions(+) diff --git a/android/abi_gki_aarch64_qcom b/android/abi_gki_aarch64_qcom index 0c7673225a44..985b52de2495 100644 --- a/android/abi_gki_aarch64_qcom +++ b/android/abi_gki_aarch64_qcom @@ -1134,10 +1134,12 @@ i2c_smbus_read_byte_data i2c_smbus_read_byte_data i2c_smbus_read_i2c_block_data + i2c_smbus_read_word_data i2c_smbus_write_byte i2c_smbus_write_byte_data i2c_smbus_write_byte_data i2c_smbus_write_i2c_block_data + i2c_smbus_write_word_data __i2c_smbus_xfer i2c_smbus_xfer __i2c_transfer From d8f0098f4199b6a111909c1aa837bd7a62602ea6 Mon Sep 17 00:00:00 2001 From: wangyq13 Date: Fri, 20 Aug 2021 14:27:09 +0800 Subject: [PATCH 393/698] defconfig: corfur: remove novatek touch driver defconfig: Remove novatek touch driver from corfur. Because corfur does not support novatek touch, and use ko to load driver. Change-Id: I1c060069985dcf6ff54cd60909a69f4a6920b512 Signed-off-by: wangyq13 Reviewed-on: https://gerrit.mot.com/2046837 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi-corfur.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-corfur.config b/arch/arm64/configs/vendor/ext_config/moto-holi-corfur.config index 37814268502a..3f89ba5942b1 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-corfur.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-corfur.config @@ -21,3 +21,4 @@ CONFIG_ZRAM_WRITEBACK=y # CONFIG_TOUCHSCREEN_FTS is not set # CONFIG_TOUCHSCREEN_FTS_DIRECTORY is not set CONFIG_AF_NOISE_ELIMINATION=y +# CONFIG_TOUCHSCREEN_NT36XXX is not set From b83ef54899d97a8db54b6d6623f46b71838be77f Mon Sep 17 00:00:00 2001 From: mahj8 Date: Tue, 24 Aug 2021 17:26:08 +0800 Subject: [PATCH 394/698] kernel: add ADC5_GPIO3_DIV3 adc channel add ADC5_GPIO3_DIV3 adc channel for read vbus voltage for nopmi project Change-Id: I930bfe91555db745599fceb23f55f4337d24e859 Signed-off-by: mahj8 Reviewed-on: https://gerrit.mot.com/2049614 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- drivers/iio/adc/qcom-spmi-adc5.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/iio/adc/qcom-spmi-adc5.c b/drivers/iio/adc/qcom-spmi-adc5.c index d4c1e58c0d21..aa17f046d7ca 100644 --- a/drivers/iio/adc/qcom-spmi-adc5.c +++ b/drivers/iio/adc/qcom-spmi-adc5.c @@ -991,6 +991,8 @@ static const struct adc5_channels adc5_chans_pmic[ADC5_MAX_CHANNEL] = { SCALE_HW_CALIB_THERM_100K_PULLUP) [ADC5_GPIO4_100K_PU] = ADC5_CHAN_TEMP("gpio4_100k_pu", 0, SCALE_HW_CALIB_THERM_100K_PULLUP) + [ADC5_GPIO3_DIV3] = ADC5_CHAN_VOLT("gpio3_div3", 1, + SCALE_HW_CALIB_DEFAULT) }; static const struct adc5_channels adc7_chans_pmic[ADC5_MAX_CHANNEL] = { From 605d56765624b806b1562503d07cdd0144adb0e2 Mon Sep 17 00:00:00 2001 From: duqiu2 Date: Fri, 10 Sep 2021 14:39:00 +0800 Subject: [PATCH 395/698] wisl: cofur: FM_IC_ENABLE_01 failed merge QC patch to enhance uart stability: I7e1392cd82a93b1da6b19f05dbe67b66d46193f1_missing_cr#3782237.patch I566d79145ba887de71482642655b63c5bd640fc8_missing_cr#2992638.patch Change-Id: I2a0ab55ab5793a6eeb64de329f5df685b499b898 Signed-off-by: duqiu2 Reviewed-on: https://gerrit.mot.com/2063919 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Ying Xu Reviewed-by: Zhenxin Xi Submit-Approved: Jira Key --- drivers/tty/serial/msm_geni_serial.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/tty/serial/msm_geni_serial.c b/drivers/tty/serial/msm_geni_serial.c index 065278bba5e2..03dd04274462 100644 --- a/drivers/tty/serial/msm_geni_serial.c +++ b/drivers/tty/serial/msm_geni_serial.c @@ -1581,7 +1581,6 @@ static int stop_rx_sequencer(struct uart_port *uport) * for interrupt latency or system delay cases. */ udelay(STALE_DELAY); - dma_rx_status = geni_read_reg_nolog(uport->membase, SE_DMA_RX_IRQ_STAT); /* The transfer is completed at HW level and the completion From a7396a742a671792806baeddd67318b54ecc5a29 Mon Sep 17 00:00:00 2001 From: Yifu Lin Date: Tue, 14 Sep 2021 22:50:54 -0500 Subject: [PATCH 396/698] arm64/config: disable coresight on sm4350 user version. This change is experimental in nature during development phase. We need some soak data to decide if we could keep coresight off for use build. Change-Id: Iec48446f1aded3e60fb5e110fd3664c9e4af2d70 Reviewed-on: https://gerrit.mot.com/2066960 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Zhongsheng Xia Reviewed-by: Yifu Lin Reviewed-by: Chuanchun Zhu Reviewed-by: Yeqing Wang Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi.config | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi.config b/arch/arm64/configs/vendor/ext_config/moto-holi.config index aef6a24d0481..8c7923319548 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi.config @@ -30,3 +30,12 @@ CONFIG_SCHED_STACK_END_CHECK=y CONFIG_MEDIA_USB_SUPPORT=y CONFIG_USB_VIDEO_CLASS=y +# CONFIG_CORESIGHT_LINK_AND_SINK_TMC is not set +# CONFIG_CORESIGHT_SOURCE_ETM4X is not set +# CONFIG_CORESIGHT_CTI is not set +# CONFIG_CORESIGHT_TPDA is not set +# CONFIG_CORESIGHT_TPDM is not set +# CONFIG_CORESIGHT_HWEVENT is not set +# CONFIG_CORESIGHT_DUMMY is not set +# CONFIG_CORESIGHT_REMOTE_ETM is not set +# CONFIG_CORESIGHT_TGU is not set From 2208e80231bc2e65751f82849dbe30ef90c61764 Mon Sep 17 00:00:00 2001 From: quebs2 Date: Wed, 22 Sep 2021 10:23:59 +0800 Subject: [PATCH 397/698] qseecom: Suppress suspend warning if without bus scaling. Recorded from QC SR: 05399803 as if the qseecom_supsend will only cancel the workqueque when the crypto bus scaling is enabled. Hence restrict the operation if without the configuration. Change-Id: I8d6d347a6393da76641fc8fa4601016629b4a53c Signed-off-by: quebs2 Reviewed-on: https://gerrit.mot.com/2072405 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- drivers/misc/qseecom.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c index 423b96f0f0c3..2c9b0232a465 100644 --- a/drivers/misc/qseecom.c +++ b/drivers/misc/qseecom.c @@ -9760,7 +9760,9 @@ static int qseecom_suspend(struct platform_device *pdev, pm_message_t state) mutex_unlock(&clk_access_lock); mutex_unlock(&qsee_bw_mutex); - cancel_work_sync(&qseecom.bw_inactive_req_ws); + if (qseecom.support_bus_scaling) { + cancel_work_sync(&qseecom.bw_inactive_req_ws); + } return 0; } From 355bcec5d93ada58bc6eea42783e52e4a0fb1584 Mon Sep 17 00:00:00 2001 From: wuwl10 Date: Wed, 22 Sep 2021 10:25:04 +0800 Subject: [PATCH 398/698] kernel: blair: remove gpio48 from reserved gpios NXP SN100P use gpio48 as Ven gpio. Blair platfom reserverd gpio48. Change-Id: Id019ce0d131e8ec1a8a0649b3031df07da946d97 Signed-off-by: wuwl10 Reviewed-on: https://gerrit.mot.com/2072536 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- drivers/pinctrl/qcom/pinctrl-blair.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pinctrl/qcom/pinctrl-blair.c b/drivers/pinctrl/qcom/pinctrl-blair.c index 62d2dbe83ed4..5b23ea19041a 100644 --- a/drivers/pinctrl/qcom/pinctrl-blair.c +++ b/drivers/pinctrl/qcom/pinctrl-blair.c @@ -1593,7 +1593,7 @@ static const struct msm_pingroup blair_groups[] = { }; static const int blair_reserved_gpios[] = { - 13, 14, 15, 16, 45, 46, 48, 56, 57, -1 + 13, 14, 15, 16, 45, 46, 56, 57, -1 }; static const struct msm_gpio_wakeirq_map blair_mpm_map[] = { From e9443419621b51fd4290a9dc0cdf0c42cb1f2927 Mon Sep 17 00:00:00 2001 From: yexh1 Date: Wed, 29 Sep 2021 17:01:30 +0800 Subject: [PATCH 399/698] kernel/config: disable the CONFIG_DM_VERITY_AVB Hardware randomly unstable will trigger "dm-verity device corrupted" and reboot the phone. Then it will not stamp the vbmeta partition with the "AVE0" flag, which is persistent. Then it will boot up failed at the next boot with AVB header check failed. Moto has own Google verified boot process with the RED alert logo. so we ignore this. Change-Id: I631a601e5b0f6e2f4ef06f19bb53dd29b2534c7d Reviewed-on: https://gerrit.mot.com/2079554 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiaojun Ji Reviewed-by: Minghui Wei Reviewed-by: Zhenxin Xi Submit-Approved: Jira Key --- arch/arm64/configs/vendor/holi_QGKI.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/vendor/holi_QGKI.config b/arch/arm64/configs/vendor/holi_QGKI.config index 38c2b4fb20e6..29e2a6118487 100644 --- a/arch/arm64/configs/vendor/holi_QGKI.config +++ b/arch/arm64/configs/vendor/holi_QGKI.config @@ -209,3 +209,4 @@ CONFIG_MICRON_HPB=y CONFIG_UFSHID=y CONFIG_UFSHID_POC=y CONFIG_SCSI_SKHID=y +# CONFIG_DM_VERITY_AVB is not set From 74ea94bc5070f0e257bd64e6f6fd93bcb385fb4c Mon Sep 17 00:00:00 2001 From: liuyc20 Date: Fri, 15 Oct 2021 16:18:15 +0800 Subject: [PATCH 400/698] gki: add memset32 and regmap_raw_write ABI to qcom whitelist memset32 & regmap_raw_write are in GKI Whitelist and they have been used by RT9426A_mmi_fg.ko. so add it to qcom whitelist for user build. Change-Id: Ic7a09e482808786eecb3a8c456307bdf76fa21eb Signed-off-by: liuyc20 Reviewed-on: https://gerrit.mot.com/2090736 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Huosheng Liao Reviewed-by: Minghui Wei Submit-Approved: Jira Key --- android/abi_gki_aarch64_qcom | 2 ++ 1 file changed, 2 insertions(+) diff --git a/android/abi_gki_aarch64_qcom b/android/abi_gki_aarch64_qcom index 985b52de2495..33e7be91243d 100644 --- a/android/abi_gki_aarch64_qcom +++ b/android/abi_gki_aarch64_qcom @@ -1500,6 +1500,7 @@ mempool_free_slab memremap memset + memset32 __memset_io memunmap memweight @@ -2038,6 +2039,7 @@ regmap_irq_get_virq regmap_mmio_detach_clk regmap_raw_read + regmap_raw_write regmap_read regmap_register_patch regmap_update_bits_base From fbb79eff17b40cf0b1916a7f380bea636b7b9d98 Mon Sep 17 00:00:00 2001 From: houdz1 Date: Fri, 15 Oct 2021 16:54:37 +0800 Subject: [PATCH 401/698] gki: update qcom whitelist for leds_lm3697.ko mfd_add_devices/mfd_remove_devices and devm_pwm_get are in GKI Whitelist and they have been used by leds_lm3697.ko. so add it to qcom whitelist for user build. Change-Id: I73e25d25bbbcade53d5ca072c3175202188b40fb Signed-off-by: houdz1 Reviewed-on: https://gerrit.mot.com/2090764 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- android/abi_gki_aarch64_qcom | 3 +++ 1 file changed, 3 insertions(+) diff --git a/android/abi_gki_aarch64_qcom b/android/abi_gki_aarch64_qcom index 33e7be91243d..177f3527b302 100644 --- a/android/abi_gki_aarch64_qcom +++ b/android/abi_gki_aarch64_qcom @@ -461,6 +461,7 @@ devm_platform_ioremap_resource devm_power_supply_get_by_phandle devm_power_supply_register + devm_pwm_get devm_pwm_put devm_regmap_add_irq_chip devm_regmap_del_irq_chip @@ -1504,6 +1505,8 @@ __memset_io memunmap memweight + mfd_add_devices + mfd_remove_devices mii_check_media mii_ethtool_get_link_ksettings mii_ethtool_gset From a15d58af3ca9947a5c423726bf251eecd8d55f9c Mon Sep 17 00:00:00 2001 From: gaoyx9 Date: Mon, 18 Oct 2021 20:31:30 +0800 Subject: [PATCH 402/698] rhodep initial kernel defconfig initial configs cloned from milanf. Change-Id: I01b922d184a48c5a1603920c179dfa5e99fb54dc Reviewed-on: https://gerrit.mot.com/2092383 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Xiaojun Ji Reviewed-by: gaoyx9 Submit-Approved: gaoyx9 Tested-by: gaoyx9 Reviewed-by: Huosheng Liao --- drivers/soc/qcom/Kconfig | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index 80180dc6f4d3..adca921aa08d 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -84,6 +84,14 @@ config MILANF_DTB Only include MILANF specific DTBs to limit the number that get built during kernel compilation. +config RHODEP_DTB + depends on ARCH_QCOM + default n + bool "RHODEP DTBs" + help + Only include RHODEP specific DTBs to limit the number that + get built during kernel compilation. + config QCOM_AOSS_QMP tristate "Qualcomm AOSS Driver" depends on ARCH_QCOM || COMPILE_TEST From 00bdb710c49142e1d47b5f9d4031ba359105d279 Mon Sep 17 00:00:00 2001 From: gaoyx9 Date: Mon, 18 Oct 2021 18:19:34 +0800 Subject: [PATCH 403/698] rhodep initial kernel defconfig initial configs cloned from milanf. Change-Id: I25944a40ee534a2773b963adc122d4db71f84e3a Reviewed-on: https://gerrit.mot.com/2092297 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiaojun Ji Reviewed-by: gaoyx9 Submit-Approved: gaoyx9 Tested-by: gaoyx9 Reviewed-by: Huosheng Liao --- .../ext_config/debug-holi-rhodep.config | 25 +++++++++++++++++++ .../ext_config/factory-holi-rhodep.config | 16 ++++++++++++ .../vendor/ext_config/moto-holi-rhodep.config | 21 ++++++++++++++++ 3 files changed, 62 insertions(+) create mode 100644 arch/arm64/configs/vendor/ext_config/debug-holi-rhodep.config create mode 100644 arch/arm64/configs/vendor/ext_config/factory-holi-rhodep.config create mode 100644 arch/arm64/configs/vendor/ext_config/moto-holi-rhodep.config diff --git a/arch/arm64/configs/vendor/ext_config/debug-holi-rhodep.config b/arch/arm64/configs/vendor/ext_config/debug-holi-rhodep.config new file mode 100644 index 000000000000..13f71e03c466 --- /dev/null +++ b/arch/arm64/configs/vendor/ext_config/debug-holi-rhodep.config @@ -0,0 +1,25 @@ +# +# Please avoid changing the Qualcomm defconfig files and use this file to +# add any Motorola-specific configuration changes that are applicable to +# userdebug, eng, and user builds. +# +# After building, a list of all of the config files that are used can be found +# at the top of: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/mapphone_defconfig +# +# The actual output of the kernel configuration system can be found at: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/.config +# +# You can check the .config file to verify that your configuration option is +# being set as expected. +# + +# CONFIG_CGROUP_DEBUG is not set +# CONFIG_CLEANCACHE is not set +# CONFIG_CMA_ALLOW_WRITE_DEBUGFS is not set +# CONFIG_CMA_DEBUG is not set +# CONFIG_PREEMPTIRQ_EVENTS is not set +# CONFIG_PREEMPT_TRACER is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_TEST_USER_COPY is not set diff --git a/arch/arm64/configs/vendor/ext_config/factory-holi-rhodep.config b/arch/arm64/configs/vendor/ext_config/factory-holi-rhodep.config new file mode 100644 index 000000000000..830e8a22f610 --- /dev/null +++ b/arch/arm64/configs/vendor/ext_config/factory-holi-rhodep.config @@ -0,0 +1,16 @@ +# +# Please avoid changing the Qualcomm defconfig files and use this file to +# add any Motorola-specific configuration changes that are applicable to +# userdebug, eng, and user builds. +# +# After building, a list of all of the config files that are used can be found +# at the top of: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/mapphone_defconfig +# +# The actual output of the kernel configuration system can be found at: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/.config +# +# You can check the .config file to verify that your configuration option is +# being set as expected. +# + diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-rhodep.config b/arch/arm64/configs/vendor/ext_config/moto-holi-rhodep.config new file mode 100644 index 000000000000..45d1ef05d2e6 --- /dev/null +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-rhodep.config @@ -0,0 +1,21 @@ +# +# Please avoid changing the Qualcomm defconfig files and use this file to +# add any Motorola-specific configuration changes that are applicable to +# userdebug, eng, and user builds. +# +# After building, a list of all of the config files that are used can be found +# at the top of: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/mapphone_defconfig +# +# The actual output of the kernel configuration system can be found at: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/.config +# +# You can check the .config file to verify that your configuration option is +# being set as expected. +# +CONFIG_RHODEP_DTB=y +# CONFIG_NFC_QTI_I2C is not set +CONFIG_FS_EPOLL_WAKEUP_DEBUG=y +CONFIG_ZRAM_WRITEBACK=y +# CONFIG_THERMAL_STATISTICS is not set +# CONFIG_REGULATOR_QPNP_LCDB is not set From d1f79327f4f39859c3a3b003a0e3f805375de004 Mon Sep 17 00:00:00 2001 From: mahj8 Date: Tue, 19 Oct 2021 19:22:31 +0800 Subject: [PATCH 404/698] gki: add some api to qcom gki white list for build user version error, so need to add some api to qcom gki white list Change-Id: I0da80b6b41bbdb3e9cb416a8f7385c3d46c44976 Signed-off-by: mahj8 Reviewed-on: https://gerrit.mot.com/2093395 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- android/abi_gki_aarch64_qcom | 1 + 1 file changed, 1 insertion(+) diff --git a/android/abi_gki_aarch64_qcom b/android/abi_gki_aarch64_qcom index 177f3527b302..75f9178ca925 100644 --- a/android/abi_gki_aarch64_qcom +++ b/android/abi_gki_aarch64_qcom @@ -1329,6 +1329,7 @@ kernel_connect kernel_getsockname kernel_kobj + kernel_power_off kernel_read kernel_recvmsg kernel_restart From 90a3c8edd093fef7b043d8ed6f827434d64f16cd Mon Sep 17 00:00:00 2001 From: mahj8 Date: Wed, 13 Oct 2021 14:27:23 +0800 Subject: [PATCH 405/698] iio: add otg enable iio psy property add otg enable iio psy property for discrete charging Change-Id: I8a10f22ecc0c24adb08e203c713f75528e1cf1b9 Signed-off-by: mahj8 Reviewed-on: https://gerrit.mot.com/2088700 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- include/dt-bindings/iio/qti_power_supply_iio.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/dt-bindings/iio/qti_power_supply_iio.h b/include/dt-bindings/iio/qti_power_supply_iio.h index 5bf925213ead..7b4e312f3de4 100644 --- a/include/dt-bindings/iio/qti_power_supply_iio.h +++ b/include/dt-bindings/iio/qti_power_supply_iio.h @@ -161,4 +161,7 @@ #define PSY_IIO_MMI_CP_STATUS1 0x102 #define PSY_IIO_MMI_CP_CLEAR_ERROR 0x103 #define PSY_IIO_MMI_QC3P_POWER 0x104 + +/*MMI add PSY_IIO properties for discrete charging*/ +#define PSY_IIO_MMI_OTG_ENABLE 0x105 #endif /* __QTI_POWER_SUPPLY_IIO_H__ */ From 48f1e3f22f53ab16806cb08cbbfeb27a4ed0c76a Mon Sep 17 00:00:00 2001 From: liaohj Date: Thu, 21 Oct 2021 18:24:28 +0800 Subject: [PATCH 406/698] configs:milanf:enable AW882XX_PARAMS_FROM_BIN 1.seperate aw params from acdb. stored in aw_skt.bin use CONFIG_AW882XX_PARAMS_FROM_BIN macro 2.use profile for different scene. 3.need to match new skt algo V5.3.1.1 enable it for milanf Change-Id: I0ddc5c916e4ce1e84787be259264b8ff5eba411d Signed-off-by: liaohj Reviewed-on: https://gerrit.mot.com/2095738 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Wanlong Zhou Reviewed-by: Hong Zhang Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- arch/arm64/Kconfig | 6 ++++++ .../arm64/configs/vendor/ext_config/moto-holi-milanf.config | 1 + 2 files changed, 7 insertions(+) diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index e22b1348ecb5..ca0ac285b78b 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -1873,3 +1873,9 @@ config AF_NOISE_ELIMINATION default n help Enable it only for produts that suffering AF resonance noise. + +config AW882XX_PARAMS_FROM_BIN + bool "params is stored in bin file" + default n + help + Enable it only for params of smartPA is stored in bin file. diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-milanf.config b/arch/arm64/configs/vendor/ext_config/moto-holi-milanf.config index 8795c9754ae5..f91c1d87a794 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-milanf.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-milanf.config @@ -19,3 +19,4 @@ CONFIG_FS_EPOLL_WAKEUP_DEBUG=y CONFIG_ZRAM_WRITEBACK=y # CONFIG_THERMAL_STATISTICS is not set # CONFIG_REGULATOR_QPNP_LCDB is not set +CONFIG_AW882XX_PARAMS_FROM_BIN=y From d39e4609fc1195fbef8db8d2c721ab1758df56eb Mon Sep 17 00:00:00 2001 From: panyq6 Date: Tue, 26 Oct 2021 18:33:09 +0800 Subject: [PATCH 407/698] rhodec initial kernel defconfig initial configs base on cypfq Change-Id: I6aecf198b46d9b3145c586c87e2a6aa285492e01 Reviewed-on: https://gerrit.mot.com/2101526 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Hongshu Lou Reviewed-by: Zhenxin Xi Submit-Approved: panyq6 --- .../ext_config/debug-holi-rhodec.config | 25 +++++++++++++++++++ .../ext_config/factory-holi-rhodec.config | 16 ++++++++++++ .../vendor/ext_config/moto-holi-rhodec.config | 22 ++++++++++++++++ drivers/soc/qcom/Kconfig | 10 ++++++++ 4 files changed, 73 insertions(+) create mode 100644 arch/arm64/configs/vendor/ext_config/debug-holi-rhodec.config create mode 100644 arch/arm64/configs/vendor/ext_config/factory-holi-rhodec.config create mode 100644 arch/arm64/configs/vendor/ext_config/moto-holi-rhodec.config diff --git a/arch/arm64/configs/vendor/ext_config/debug-holi-rhodec.config b/arch/arm64/configs/vendor/ext_config/debug-holi-rhodec.config new file mode 100644 index 000000000000..13f71e03c466 --- /dev/null +++ b/arch/arm64/configs/vendor/ext_config/debug-holi-rhodec.config @@ -0,0 +1,25 @@ +# +# Please avoid changing the Qualcomm defconfig files and use this file to +# add any Motorola-specific configuration changes that are applicable to +# userdebug, eng, and user builds. +# +# After building, a list of all of the config files that are used can be found +# at the top of: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/mapphone_defconfig +# +# The actual output of the kernel configuration system can be found at: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/.config +# +# You can check the .config file to verify that your configuration option is +# being set as expected. +# + +# CONFIG_CGROUP_DEBUG is not set +# CONFIG_CLEANCACHE is not set +# CONFIG_CMA_ALLOW_WRITE_DEBUGFS is not set +# CONFIG_CMA_DEBUG is not set +# CONFIG_PREEMPTIRQ_EVENTS is not set +# CONFIG_PREEMPT_TRACER is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_TEST_USER_COPY is not set diff --git a/arch/arm64/configs/vendor/ext_config/factory-holi-rhodec.config b/arch/arm64/configs/vendor/ext_config/factory-holi-rhodec.config new file mode 100644 index 000000000000..830e8a22f610 --- /dev/null +++ b/arch/arm64/configs/vendor/ext_config/factory-holi-rhodec.config @@ -0,0 +1,16 @@ +# +# Please avoid changing the Qualcomm defconfig files and use this file to +# add any Motorola-specific configuration changes that are applicable to +# userdebug, eng, and user builds. +# +# After building, a list of all of the config files that are used can be found +# at the top of: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/mapphone_defconfig +# +# The actual output of the kernel configuration system can be found at: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/.config +# +# You can check the .config file to verify that your configuration option is +# being set as expected. +# + diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-rhodec.config b/arch/arm64/configs/vendor/ext_config/moto-holi-rhodec.config new file mode 100644 index 000000000000..2a143ddb0d04 --- /dev/null +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-rhodec.config @@ -0,0 +1,22 @@ +# +# Please avoid changing the Qualcomm defconfig files and use this file to +# add any Motorola-specific configuration changes that are applicable to +# userdebug, eng, and user builds. +# +# After building, a list of all of the config files that are used can be found +# at the top of: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/mapphone_defconfig +# +# The actual output of the kernel configuration system can be found at: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/.config +# +# You can check the .config file to verify that your configuration option is +# being set as expected. +# +CONFIG_RHODEC_DTB=y +# CONFIG_NFC_QTI_I2C is not set +CONFIG_FS_EPOLL_WAKEUP_DEBUG=y +CONFIG_ZRAM_WRITEBACK=y +# CONFIG_THERMAL_STATISTICS is not set +# CONFIG_REGULATOR_QPNP_LCDB is not set +CONFIG_AF_NOISE_ELIMINATION=y diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index adca921aa08d..4211e11b9f94 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -68,6 +68,16 @@ config CYPFQ_DTB Only include CYPFQ specific DTBs to limit the number that get built during kernel compilation. + +config RHODEC_DTB + depends on ARCH_QCOM + default n + bool "RHODEC DTBs" + help + Only include RHODEC specific DTBs to limit the number that + get built during kernel compilation. + + config CYPFR_DTB depends on ARCH_QCOM default n From cf6832f1f8df509610a438b406bfdc771ca600b7 Mon Sep 17 00:00:00 2001 From: liaohj Date: Fri, 12 Nov 2021 16:27:56 +0800 Subject: [PATCH 408/698] config:Rhodep:add CONFIG_AW882XX_STEREO_SMARTPA Rhode5G+ use 6375+ two aw88261 smart pa. add CONFIG_AW882XX_STEREO_SMARTPA macro for dual pa. Change-Id: I6f79294cd669993fc677e5b9ec99c813ef66dfd3 Signed-off-by: liaohj Reviewed-on: https://gerrit.mot.com/2114845 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Wanlong Zhou Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- arch/arm64/Kconfig | 6 ++++++ .../arm64/configs/vendor/ext_config/moto-holi-rhodep.config | 1 + 2 files changed, 7 insertions(+) diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index ca0ac285b78b..6ca32117e06e 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -1879,3 +1879,9 @@ config AW882XX_PARAMS_FROM_BIN default n help Enable it only for params of smartPA is stored in bin file. + +config AW882XX_STEREO_SMARTPA + bool "aw dual smart pa" + default n + help + Enable it only for params of smartPA is stored in bin file. diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-rhodep.config b/arch/arm64/configs/vendor/ext_config/moto-holi-rhodep.config index 45d1ef05d2e6..f2af595b2c57 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-rhodep.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-rhodep.config @@ -19,3 +19,4 @@ CONFIG_FS_EPOLL_WAKEUP_DEBUG=y CONFIG_ZRAM_WRITEBACK=y # CONFIG_THERMAL_STATISTICS is not set # CONFIG_REGULATOR_QPNP_LCDB is not set +CONFIG_AW882XX_STEREO_SMARTPA=y From f1fe70af8cf47e7d04f1dbe2a74995ec9cf4d61b Mon Sep 17 00:00:00 2001 From: liaohj Date: Thu, 11 Nov 2021 16:16:46 +0800 Subject: [PATCH 409/698] configs:milanf:delete CONFIG_AW882XX_PARAMS_FROM_BIN AW skt5.3.1.1 put skt params in afe side. can't deal cowork scene. as KP liyif request. return back to skt params in acdb method. and use the latest skt v5.3.0 algo. delete params from bin config for milanf. Change-Id: Id0dbdedec26bba231031742853a01655667cadcf Signed-off-by: liaohj Reviewed-on: https://gerrit.mot.com/2113315 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Wanlong Zhou Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi-milanf.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-milanf.config b/arch/arm64/configs/vendor/ext_config/moto-holi-milanf.config index f91c1d87a794..ba61159db870 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-milanf.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-milanf.config @@ -19,4 +19,4 @@ CONFIG_FS_EPOLL_WAKEUP_DEBUG=y CONFIG_ZRAM_WRITEBACK=y # CONFIG_THERMAL_STATISTICS is not set # CONFIG_REGULATOR_QPNP_LCDB is not set -CONFIG_AW882XX_PARAMS_FROM_BIN=y +# CONFIG_AW882XX_PARAMS_FROM_BIN is not set From f04f8628d308b638635a672d8a5ea623b47de773 Mon Sep 17 00:00:00 2001 From: zhucc2 Date: Fri, 8 Oct 2021 12:51:14 +0800 Subject: [PATCH 410/698] ufs: Add Micron UFS HID support As Micron said, Micron UFS HID could reuse SamSung HID driver, but need change some flags and attibutes definitions. Change-Id: If485cd01b6b69f1f14947fe84520c190262d966f Reviewed-on: https://gerrit.mot.com/2085180 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Dongliang Yue Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- drivers/scsi/ufs/Kconfig | 8 +- drivers/scsi/ufs/ufs.h | 7 ++ drivers/scsi/ufs/ufshid.c | 218 +++++++++++++++++++++++++++++--------- drivers/scsi/ufs/ufshid.h | 14 +++ 4 files changed, 193 insertions(+), 54 deletions(-) diff --git a/drivers/scsi/ufs/Kconfig b/drivers/scsi/ufs/Kconfig index fbb422dfb846..b9a0f6728fd5 100644 --- a/drivers/scsi/ufs/Kconfig +++ b/drivers/scsi/ufs/Kconfig @@ -269,10 +269,16 @@ config SCSI_SKHID bool "UFS Host Initiated Defrag supportr" depends on (SCSI_UFSHCD || SCSI_UFSHCD_QTI) help - Activate or deactive SKHPB driver + Activate or deactive SKHID driver config MICRON_HPB bool "Activate micron HPB Host-aware Performance Booster" depends on SCSI_UFSHCD && UFSFEATURE && UFSHPB help Activate or deactive micron HPB driver + +config MICRON_UFSHID + bool "UFS Host Initiated Defrag supportr" + depends on (SCSI_UFSHCD || SCSI_UFSHCD_QTI) + help + Activate or deactive micron hid driver diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h index dfe046fd8f3d..c2ba85d07aa8 100644 --- a/drivers/scsi/ufs/ufs.h +++ b/drivers/scsi/ufs/ufs.h @@ -160,6 +160,9 @@ enum flag_idn { QUERY_FLAG_IDN_TW_BUF_FLUSH_EN = 0x0F, QUERY_FLAG_IDN_TW_FLUSH_DURING_HIBERN = 0x10, #endif +#if defined(CONFIG_MICRON_UFSHID) + QUERY_FLAG_IDN_HID_EN = 0x13 +#endif }; /* Attribute idn for Query requests */ @@ -210,6 +213,10 @@ enum attr_idn { #if defined(CONFIG_UFSFEATURE) QUERY_ATTR_IDN_SUP_VENDOR_OPTIONS = 0xFF, #endif +#if defined(CONFIG_MICRON_UFSHID) + QUERY_ATTR_IDN_HID_FRAG_STATUS = 0x31, + QUERY_ATTR_IDN_HID_PROGRESS = 0x32, +#endif }; #define QUERY_ATTR_IDN_BOOT_LU_EN_MAX 0x02 diff --git a/drivers/scsi/ufs/ufshid.c b/drivers/scsi/ufs/ufshid.c index 1f10b9f53a99..acb33f5d5013 100755 --- a/drivers/scsi/ufs/ufshid.c +++ b/drivers/scsi/ufs/ufshid.c @@ -113,6 +113,54 @@ err_out: return ret; } +#if defined(CONFIG_MICRON_UFSHID) +static int ufshid_set_flag(struct ufshid_dev *hid, u8 idn) +{ + struct ufs_hba *hba = hid->ufsf->hba; + int ret = 0; + bool flag_result; + pm_runtime_get_sync(hba->dev); + + ret = ufsf_query_flag_retry(hba, UPIU_QUERY_OPCODE_SET_FLAG, idn, 0, + &flag_result); + + if (ret) { + ERR_MSG("set flag [0x%.2X] fail. (%d)", idn, ret); + goto err_out; + } + + HID_DEBUG(hid, "hid_flag set [0x%.2X] result [0x%.2X] ", idn, flag_result); +err_out: + pm_runtime_mark_last_busy(hba->dev); + pm_runtime_put_noidle(hba->dev); + + return ret; +} + +static int ufshid_clear_flag(struct ufshid_dev *hid, u8 idn) +{ + struct ufs_hba *hba = hid->ufsf->hba; + int ret = 0; + + pm_runtime_get_sync(hba->dev); + + ret = ufsf_query_flag_retry(hba, UPIU_QUERY_OPCODE_CLEAR_FLAG, idn, 0, + NULL); + if (ret) { + ERR_MSG("clear flag [0x%.2X] fail. (%d)", idn, ret); + goto err_out; + } + + HID_DEBUG(hid, "hid_flag set [0x%.2X] ", idn); +err_out: + pm_runtime_mark_last_busy(hba->dev); + pm_runtime_put_noidle(hba->dev); + + return ret; +} +#endif + + static inline int ufshid_version_check(int spec_version) { INFO_MSG("Support HID Spec : Driver = (%.4x), Device = (%.4x)", @@ -133,18 +181,27 @@ void ufshid_get_dev_info(struct ufsf_feature *ufsf, u8 *desc_buf) ufsf->hid_dev = NULL; - if (!(LI_EN_32(&desc_buf[DEVICE_DESC_PARAM_EX_FEAT_SUP]) & - UFS_FEATURE_SUPPORT_HID_BIT)) { - INFO_MSG("bUFSExFeaturesSupport: HID not support"); - goto err_out; + if(IS_SAMSUNG_DEVICE(storage_mfrid)) { + if (!(LI_EN_32(&desc_buf[DEVICE_DESC_PARAM_EX_FEAT_SUP]) & + UFS_FEATURE_SUPPORT_HID_BIT)) { + INFO_MSG("bUFSExFeaturesSupport: HID not support"); + goto err_out; + } + + INFO_MSG("bUFSExFeaturesSupport: HID support"); + spec_version = + LI_EN_16(&desc_buf[DEVICE_DESC_PARAM_HID_VER]); + ret = ufshid_version_check(spec_version); + if (ret) + goto err_out; } - INFO_MSG("bUFSExFeaturesSupport: HID support"); - spec_version = - LI_EN_16(&desc_buf[DEVICE_DESC_PARAM_HID_VER]); - ret = ufshid_version_check(spec_version); - if (ret) +#ifndef CONFIG_MICRON_UFSHID + if(IS_MICRON_DEVICE(storage_mfrid)){ + INFO_MSG("micron: HID not support"); goto err_out; + } +#endif ufsf->hid_dev = kzalloc(sizeof(struct ufshid_dev), GFP_KERNEL); if (!ufsf->hid_dev) { @@ -163,39 +220,79 @@ static int ufshid_get_analyze_and_issue_execute(struct ufshid_dev *hid) u32 attr_val; int frag_level; - if (ufshid_write_attr(hid, QUERY_ATTR_IDN_HID_OPERATION, - HID_OP_EXECUTE)) + if(IS_MICRON_DEVICE(storage_mfrid)) { + #if defined(CONFIG_MICRON_UFSHID) + //get micron ufs frag level + if (ufshid_read_attr(hid, QUERY_ATTR_IDN_HID_FRAG_STATUS, &frag_level)) + return -EINVAL; + //get micron ufs hid execution progress + if (ufshid_read_attr(hid, QUERY_ATTR_IDN_HID_PROGRESS, &attr_val)) + return -EINVAL; + HID_DEBUG(hid, "micron frag_level= %d attr_val= %d",frag_level,attr_val); + + if (attr_val != HID_PROG_ONGOING) { + if(frag_level!= HID_LEV_GREEN_MICRON) { + ufshid_set_flag(hid, QUERY_FLAG_IDN_HID_EN); + return HID_REQUIRED; + } else { + return HID_NOT_REQUIRED; + } + } else { + return HID_REQUIRED; + } + #else + return HID_NOT_REQUIRED; + #endif + } else if(IS_SAMSUNG_DEVICE(storage_mfrid)) { + if (ufshid_write_attr(hid, QUERY_ATTR_IDN_HID_OPERATION, + HID_OP_EXECUTE)) + return -EINVAL; + if (ufshid_read_attr(hid, QUERY_ATTR_IDN_HID_FRAG_LEVEL, &attr_val)) + return -EINVAL; + + frag_level = attr_val & HID_FRAG_LEVEL_MASK; + HID_DEBUG(hid, "Frag_lv %d Freg_stat %d HID_need_exec %d", + frag_level, HID_FRAG_UPDATE_STAT(attr_val), + HID_EXECUTE_REQ_STAT(attr_val)); + + if (frag_level == HID_LEV_GRAY) + return -EAGAIN; + + return (HID_EXECUTE_REQ_STAT(attr_val)) ? + HID_REQUIRED : HID_NOT_REQUIRED; + } else { return -EINVAL; - if (ufshid_read_attr(hid, QUERY_ATTR_IDN_HID_FRAG_LEVEL, &attr_val)) - return -EINVAL; - - frag_level = attr_val & HID_FRAG_LEVEL_MASK; - HID_DEBUG(hid, "Frag_lv %d Freg_stat %d HID_need_exec %d", - frag_level, HID_FRAG_UPDATE_STAT(attr_val), - HID_EXECUTE_REQ_STAT(attr_val)); - - if (frag_level == HID_LEV_GRAY) - return -EAGAIN; - - return (HID_EXECUTE_REQ_STAT(attr_val)) ? - HID_REQUIRED : HID_NOT_REQUIRED; + } } static int ufshid_issue_disable(struct ufshid_dev *hid) { u32 attr_val; - if (ufshid_write_attr(hid, QUERY_ATTR_IDN_HID_OPERATION, - HID_OP_DISABLE)) - return -EINVAL; - if (ufshid_read_attr(hid, QUERY_ATTR_IDN_HID_FRAG_LEVEL, &attr_val)) - return -EINVAL; + if(IS_MICRON_DEVICE(storage_mfrid)) { + #if defined(CONFIG_MICRON_UFSHID) + //get micron ufs hid execution progress + if (ufshid_read_attr(hid, QUERY_ATTR_IDN_HID_PROGRESS, &attr_val)) + return -EINVAL; + HID_DEBUG(hid, "micron hid progress = %d",attr_val); - HID_DEBUG(hid, "Frag_lv %d Freg_stat %d HID_need_exec %d", - attr_val & HID_FRAG_LEVEL_MASK, - HID_FRAG_UPDATE_STAT(attr_val), - HID_EXECUTE_REQ_STAT(attr_val)); + if(attr_val == HID_PROG_ONGOING) { + if (ufshid_clear_flag(hid, QUERY_FLAG_IDN_HID_EN)) + return -EINVAL; + } + #endif + }else if(IS_SAMSUNG_DEVICE(storage_mfrid)) { + if (ufshid_write_attr(hid, QUERY_ATTR_IDN_HID_OPERATION, + HID_OP_DISABLE)) + return -EINVAL; + if (ufshid_read_attr(hid, QUERY_ATTR_IDN_HID_FRAG_LEVEL, &attr_val)) + return -EINVAL; + HID_DEBUG(hid, "Frag_lv %d Freg_stat %d HID_need_exec %d", + attr_val & HID_FRAG_LEVEL_MASK, + HID_FRAG_UPDATE_STAT(attr_val), + HID_EXECUTE_REQ_STAT(attr_val)); + } return 0; } @@ -706,27 +803,42 @@ static ssize_t ufshid_sysfs_show_color(struct ufshid_dev *hid, char *buf) u32 attr_val; int frag_level; - if (ufshid_write_attr(hid, QUERY_ATTR_IDN_HID_OPERATION, - HID_OP_ANALYZE)) { - ERR_MSG("query HID_OPERATION fail"); - return -EINVAL; + if(IS_MICRON_DEVICE(storage_mfrid)){ + #if defined(CONFIG_MICRON_UFSHID) + if (ufshid_read_attr(hid, QUERY_ATTR_IDN_HID_FRAG_STATUS, &attr_val)) + return -EINVAL; + frag_level = attr_val; + /*Micron only has two levels RED & GREEN*/ + return snprintf(buf, PAGE_SIZE, "%s\n", + ((frag_level == HID_LEV_GREEN_MICRON)) ? "GREEN" : + ((frag_level ==HID_LEV_RED_MICRON))?"RED":"UNKNOWN"); + + return snprintf(buf, PAGE_SIZE, "%s\n","Error."); + #endif + } else if(IS_SAMSUNG_DEVICE(storage_mfrid)) { + if (ufshid_write_attr(hid, QUERY_ATTR_IDN_HID_OPERATION, + HID_OP_ANALYZE)) { + ERR_MSG("query HID_OPERATION fail"); + return -EINVAL; + } + + if (ufshid_read_attr(hid, QUERY_ATTR_IDN_HID_FRAG_LEVEL, &attr_val)) { + ERR_MSG("query HID_FRAG_LEVEL fail"); + return -EINVAL; + } + + frag_level = attr_val & HID_FRAG_LEVEL_MASK; + INFO_MSG("Frag_lv %d Freg_stat %d HID_need_exec %d", frag_level, + HID_FRAG_UPDATE_STAT(attr_val), + HID_EXECUTE_REQ_STAT(attr_val)); + + return snprintf(buf, PAGE_SIZE, "%s\n", + frag_level == HID_LEV_RED ? "RED" : + frag_level == HID_LEV_YELLOW ? "YELLOW" : + frag_level == HID_LEV_GREEN ? "GREEN" : + frag_level == HID_LEV_GRAY ? "GRAY" : "UNKNOWN"); } - - if (ufshid_read_attr(hid, QUERY_ATTR_IDN_HID_FRAG_LEVEL, &attr_val)) { - ERR_MSG("query HID_FRAG_LEVEL fail"); - return -EINVAL; - } - - frag_level = attr_val & HID_FRAG_LEVEL_MASK; - INFO_MSG("Frag_lv %d Freg_stat %d HID_need_exec %d", frag_level, - HID_FRAG_UPDATE_STAT(attr_val), - HID_EXECUTE_REQ_STAT(attr_val)); - - return snprintf(buf, PAGE_SIZE, "%s\n", - frag_level == HID_LEV_RED ? "RED" : - frag_level == HID_LEV_YELLOW ? "YELLOW" : - frag_level == HID_LEV_GREEN ? "GREEN" : - frag_level == HID_LEV_GRAY ? "GRAY" : "UNKNOWN"); + return -EINVAL; } #if defined(CONFIG_UFSHID_POC) diff --git a/drivers/scsi/ufs/ufshid.h b/drivers/scsi/ufs/ufshid.h index 849822ed5121..10a2989cd435 100755 --- a/drivers/scsi/ufs/ufshid.h +++ b/drivers/scsi/ufs/ufshid.h @@ -103,6 +103,20 @@ enum { HID_LEV_RED = 3, }; +#if defined(CONFIG_MICRON_UFSHID) +enum { + HID_LEV_GREEN_MICRON = 0, + HID_LEV_RED_MICRON = 1, +}; + +enum { + HID_PROG_IDLE = 0, + HID_PROG_ONGOING = 1, + HID_PROG_STOP = 2, //stopped by Host + HID_PROG_COMPLETE = 3, +}; +#endif + struct ufshid_dev { struct ufsf_feature *ufsf; From 95625f94c41d895498b01c2566467123e9184755 Mon Sep 17 00:00:00 2001 From: zhucc2 Date: Tue, 26 Oct 2021 16:32:50 +0800 Subject: [PATCH 411/698] arm64/config: enable Micron HID on milanf. Remark: enable Micron hid feature for milan 5G on mot4350 family. disable for denver,ibiza, cyprus 5G, corfu 5G and rhodep,for these projetcs not use Micorn uMCP, or the Micron uMCP used is not support HID feature. further project if reuse currently baseline need define it accordingly. Change-Id: I24f2fe21260a4329df3f96f263efd0ba169c0460 Reviewed-on: https://gerrit.mot.com/2099662 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi-corfup.config | 1 + arch/arm64/configs/vendor/ext_config/moto-holi-corfuq.config | 1 + arch/arm64/configs/vendor/ext_config/moto-holi-corfur.config | 1 + arch/arm64/configs/vendor/ext_config/moto-holi-cypfg.config | 1 + arch/arm64/configs/vendor/ext_config/moto-holi-cypfq.config | 1 + arch/arm64/configs/vendor/ext_config/moto-holi-cypfr.config | 1 + arch/arm64/configs/vendor/ext_config/moto-holi-denver.config | 1 + .../configs/vendor/ext_config/moto-holi-ibiza-cmcc-extra.config | 1 + arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config | 1 + arch/arm64/configs/vendor/ext_config/moto-holi-rhodep.config | 1 + arch/arm64/configs/vendor/holi_QGKI.config | 1 + 11 files changed, 11 insertions(+) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-corfup.config b/arch/arm64/configs/vendor/ext_config/moto-holi-corfup.config index 31f9f7d0bfc3..4a26a09a25e7 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-corfup.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-corfup.config @@ -21,3 +21,4 @@ CONFIG_ZRAM_WRITEBACK=y # CONFIG_TOUCHSCREEN_FTS is not set # CONFIG_TOUCHSCREEN_FTS_DIRECTORY is not set CONFIG_AF_NOISE_ELIMINATION=y +# CONFIG_MICRON_UFSHID is not set diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-corfuq.config b/arch/arm64/configs/vendor/ext_config/moto-holi-corfuq.config index 65809cff3f81..82b9d5a96b57 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-corfuq.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-corfuq.config @@ -21,3 +21,4 @@ CONFIG_ZRAM_WRITEBACK=y # CONFIG_TOUCHSCREEN_FTS is not set # CONFIG_TOUCHSCREEN_FTS_DIRECTORY is not set CONFIG_AF_NOISE_ELIMINATION=y +# CONFIG_MICRON_UFSHID is not set diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-corfur.config b/arch/arm64/configs/vendor/ext_config/moto-holi-corfur.config index 3f89ba5942b1..19b89fafefc0 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-corfur.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-corfur.config @@ -22,3 +22,4 @@ CONFIG_ZRAM_WRITEBACK=y # CONFIG_TOUCHSCREEN_FTS_DIRECTORY is not set CONFIG_AF_NOISE_ELIMINATION=y # CONFIG_TOUCHSCREEN_NT36XXX is not set +# CONFIG_MICRON_UFSHID is not set diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-cypfg.config b/arch/arm64/configs/vendor/ext_config/moto-holi-cypfg.config index 2bdee17c4d7d..ecc6c0c9be42 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-cypfg.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-cypfg.config @@ -21,3 +21,4 @@ CONFIG_ZRAM_WRITEBACK=y # CONFIG_UFSHID is not set # CONFIG_UFSHID_POC is not set CONFIG_AF_NOISE_ELIMINATION=y +# CONFIG_MICRON_UFSHID is not set diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-cypfq.config b/arch/arm64/configs/vendor/ext_config/moto-holi-cypfq.config index db9784141a24..4997380fc123 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-cypfq.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-cypfq.config @@ -20,3 +20,4 @@ CONFIG_ZRAM_WRITEBACK=y # CONFIG_THERMAL_STATISTICS is not set # CONFIG_REGULATOR_QPNP_LCDB is not set CONFIG_AF_NOISE_ELIMINATION=y +# CONFIG_MICRON_UFSHID is not set diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-cypfr.config b/arch/arm64/configs/vendor/ext_config/moto-holi-cypfr.config index 539ab3c730d3..e001d00ba3d1 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-cypfr.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-cypfr.config @@ -19,3 +19,4 @@ CONFIG_FS_EPOLL_WAKEUP_DEBUG=y CONFIG_ZRAM_WRITEBACK=y # CONFIG_THERMAL_STATISTICS is not set CONFIG_AF_NOISE_ELIMINATION=y +# CONFIG_MICRON_UFSHID is not set diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-denver.config b/arch/arm64/configs/vendor/ext_config/moto-holi-denver.config index c55932f0bed9..6ad84c083ec4 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-denver.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-denver.config @@ -30,3 +30,4 @@ CONFIG_ZRAM_WRITEBACK=y # CONFIG_UFSHID is not set # CONFIG_UFSHID_POC is not set # CONFIG_SCSI_SKHID is not set +# CONFIG_MICRON_UFSHID is not set diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza-cmcc-extra.config b/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza-cmcc-extra.config index 4055bd9f9dd6..1c648ce6d55e 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza-cmcc-extra.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza-cmcc-extra.config @@ -2,3 +2,4 @@ CONFIG_ZRAM_WRITEBACK=y # CONFIG_UFSHID is not set # CONFIG_UFSHID_POC is not set # CONFIG_SCSI_SKHID is not set +# CONFIG_MICRON_UFSHID is not set diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config b/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config index b896d63fc957..2dbb45a3e4ee 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config @@ -28,3 +28,4 @@ CONFIG_ZRAM_WRITEBACK=y # CONFIG_UFSHID is not set # CONFIG_UFSHID_POC is not set # CONFIG_SCSI_SKHID is not set +# CONFIG_MICRON_UFSHID is not set diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-rhodep.config b/arch/arm64/configs/vendor/ext_config/moto-holi-rhodep.config index f2af595b2c57..8348c8dec1ca 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-rhodep.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-rhodep.config @@ -20,3 +20,4 @@ CONFIG_ZRAM_WRITEBACK=y # CONFIG_THERMAL_STATISTICS is not set # CONFIG_REGULATOR_QPNP_LCDB is not set CONFIG_AW882XX_STEREO_SMARTPA=y +# CONFIG_MICRON_UFSHID is not set diff --git a/arch/arm64/configs/vendor/holi_QGKI.config b/arch/arm64/configs/vendor/holi_QGKI.config index 29e2a6118487..45369dfd5143 100644 --- a/arch/arm64/configs/vendor/holi_QGKI.config +++ b/arch/arm64/configs/vendor/holi_QGKI.config @@ -210,3 +210,4 @@ CONFIG_UFSHID=y CONFIG_UFSHID_POC=y CONFIG_SCSI_SKHID=y # CONFIG_DM_VERITY_AVB is not set +CONFIG_MICRON_UFSHID=y From 2666f2d657831b2bdad3a4547ba1a14947af4d52 Mon Sep 17 00:00:00 2001 From: wutao Date: Wed, 17 Nov 2021 19:31:25 +0800 Subject: [PATCH 412/698] kernel: remove reserved gpio45/46/56/57 from HLOS For Rhode5gp project, Move SPI to GPIO from TZ to HLOS , refer to this change : https://gerrit.mot.com/#/c/2119002/ wt6670f irq pin use gpio56, Display use gpio46 to enable VCI. Charge use gpio45 , gpio57 so remove gpio45/46/56/57 reserved from HLOS Change-Id: Iadc24906dcd17ba72d320394fa74824286c4089f Reviewed-on: https://gerrit.mot.com/2119174 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- drivers/pinctrl/qcom/pinctrl-blair.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pinctrl/qcom/pinctrl-blair.c b/drivers/pinctrl/qcom/pinctrl-blair.c index 5b23ea19041a..43f4a7660198 100644 --- a/drivers/pinctrl/qcom/pinctrl-blair.c +++ b/drivers/pinctrl/qcom/pinctrl-blair.c @@ -1593,7 +1593,7 @@ static const struct msm_pingroup blair_groups[] = { }; static const int blair_reserved_gpios[] = { - 13, 14, 15, 16, 45, 46, 56, 57, -1 + 13, 14, 15, 16, -1 }; static const struct msm_gpio_wakeirq_map blair_mpm_map[] = { From 8bbe2b36c39726cbb6ad6dc68afa71878a6ab084 Mon Sep 17 00:00:00 2001 From: weiweij Date: Fri, 19 Nov 2021 10:23:44 +0800 Subject: [PATCH 413/698] pinctrl: distinguish reserve gpio list by macro definition For each project has its own reserve gpio list. So we should have the way to distinguish it in every different products. We use a macro definition for this. If the gpios are not assigned to TZ, they should be removed from the list. Change-Id: I0837a3abdf8d7398aa2e7138563cb891b9f53780 Reviewed-on: https://gerrit.mot.com/2121376 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi-rhodep.config | 1 + drivers/pinctrl/qcom/Kconfig | 3 +++ drivers/pinctrl/qcom/Makefile | 2 ++ drivers/pinctrl/qcom/pinctrl-blair.c | 4 ++++ 4 files changed, 10 insertions(+) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-rhodep.config b/arch/arm64/configs/vendor/ext_config/moto-holi-rhodep.config index 8348c8dec1ca..2459a902c68a 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-rhodep.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-rhodep.config @@ -21,3 +21,4 @@ CONFIG_ZRAM_WRITEBACK=y # CONFIG_REGULATOR_QPNP_LCDB is not set CONFIG_AW882XX_STEREO_SMARTPA=y # CONFIG_MICRON_UFSHID is not set +CONFIG_QUP0_SE2_AP=y diff --git a/drivers/pinctrl/qcom/Kconfig b/drivers/pinctrl/qcom/Kconfig index d20e59378909..e374c49d01e2 100644 --- a/drivers/pinctrl/qcom/Kconfig +++ b/drivers/pinctrl/qcom/Kconfig @@ -343,4 +343,7 @@ config PINCTRL_BLAIR Say Y here to compile statically, or M here to compile it as a module. If unsure, say N. +config QUP0_SE2_AP + bool "Set GPIO of QUP0_SE2 as AP side" + endif diff --git a/drivers/pinctrl/qcom/Makefile b/drivers/pinctrl/qcom/Makefile index 1ba4ba27a173..24ad4cb8a9f7 100644 --- a/drivers/pinctrl/qcom/Makefile +++ b/drivers/pinctrl/qcom/Makefile @@ -1,5 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 # Qualcomm pin control drivers +ccflags-$(CONFIG_QUP0_SE2_AP) += -DQUP0_SE2_AP + obj-$(CONFIG_PINCTRL_MSM) += pinctrl-msm.o obj-$(CONFIG_PINCTRL_APQ8064) += pinctrl-apq8064.o obj-$(CONFIG_PINCTRL_APQ8084) += pinctrl-apq8084.o diff --git a/drivers/pinctrl/qcom/pinctrl-blair.c b/drivers/pinctrl/qcom/pinctrl-blair.c index 43f4a7660198..648e457c3974 100644 --- a/drivers/pinctrl/qcom/pinctrl-blair.c +++ b/drivers/pinctrl/qcom/pinctrl-blair.c @@ -1593,7 +1593,11 @@ static const struct msm_pingroup blair_groups[] = { }; static const int blair_reserved_gpios[] = { +#ifdef QUP0_SE2_AP 13, 14, 15, 16, -1 +#else + 13, 14, 15, 16, 45, 46, 56, 57, -1 +#endif }; static const struct msm_gpio_wakeirq_map blair_mpm_map[] = { From 6b6c627d23e1cf333e34b4e587e3c008030e843c Mon Sep 17 00:00:00 2001 From: liaohj Date: Thu, 25 Nov 2021 15:28:15 +0800 Subject: [PATCH 414/698] configs:rhodep:aw882xx use params from bin. aw882xx use params from bin. add CONFIG_AW882XX_PARAMS_FROM_BIN macro. Change-Id: I2b8e779c9ea7925bcdbcd3105bd4494db2dd3af0 Signed-off-by: liaohj Reviewed-on: https://gerrit.mot.com/2127349 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Wanlong Zhou Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi-rhodep.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-rhodep.config b/arch/arm64/configs/vendor/ext_config/moto-holi-rhodep.config index 2459a902c68a..421a8bf160c3 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-rhodep.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-rhodep.config @@ -20,5 +20,6 @@ CONFIG_ZRAM_WRITEBACK=y # CONFIG_THERMAL_STATISTICS is not set # CONFIG_REGULATOR_QPNP_LCDB is not set CONFIG_AW882XX_STEREO_SMARTPA=y +CONFIG_AW882XX_PARAMS_FROM_BIN=y # CONFIG_MICRON_UFSHID is not set CONFIG_QUP0_SE2_AP=y From a7b30f0325a260193ac35ead1164636c2e25f133 Mon Sep 17 00:00:00 2001 From: wuwl10 Date: Wed, 1 Dec 2021 09:57:49 +0800 Subject: [PATCH 415/698] abi: add strcat to ABI list to fix build error Focal_fps_mmi.ko will use strcat to cat version. we need to add it to abi list to avoid build error on user build. Change-Id: I2fd3e35faff5c239111d417b5a5d9efd56ebec4b Signed-off-by: wuwl10 Reviewed-on: https://gerrit.mot.com/2131504 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: gaoyx9 Submit-Approved: gaoyx9 Tested-by: gaoyx9 Reviewed-by: Minghui Wei Reviewed-by: Huosheng Liao --- android/abi_gki_aarch64_qcom | 1 + 1 file changed, 1 insertion(+) diff --git a/android/abi_gki_aarch64_qcom b/android/abi_gki_aarch64_qcom index 75f9178ca925..55a98c126978 100644 --- a/android/abi_gki_aarch64_qcom +++ b/android/abi_gki_aarch64_qcom @@ -2473,6 +2473,7 @@ __stack_chk_guard stack_trace_print strcasecmp + strcat strchr strchrnul strcmp From 4d0fffa802c8f518ae156d8f72d443fc5d6e4494 Mon Sep 17 00:00:00 2001 From: zhouwl Date: Wed, 1 Dec 2021 16:20:02 +0800 Subject: [PATCH 416/698] defconfg: Rhodec audio bringup Bringup for Rhodec audio, define stereo speaker. Change-Id: I0afdc2e5eed366c9b2744b58eb1d177db2e24feb Signed-off-by: zhouwl Reviewed-on: https://gerrit.mot.com/2131925 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Hujun Liao Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi-rhodec.config | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-rhodec.config b/arch/arm64/configs/vendor/ext_config/moto-holi-rhodec.config index 2a143ddb0d04..b8ff80461d91 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-rhodec.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-rhodec.config @@ -20,3 +20,5 @@ CONFIG_ZRAM_WRITEBACK=y # CONFIG_THERMAL_STATISTICS is not set # CONFIG_REGULATOR_QPNP_LCDB is not set CONFIG_AF_NOISE_ELIMINATION=y +CONFIG_AW882XX_STEREO_SMARTPA=y +CONFIG_AW882XX_PARAMS_FROM_BIN=y From 03e0add8c98861fb0d9e93ac0343f444a6d06582 Mon Sep 17 00:00:00 2001 From: huaqin85 Date: Thu, 2 Dec 2021 21:59:37 +0800 Subject: [PATCH 417/698] qcom: Update qcom whitelist for bq2597x Build Error log: ERROR: "__regmap_init_i2c" [../../motorola/kernel/modules/drivers/power/bq2597x_mmi_iio/bq2597x_mmi_iio.ko] undefined! Change-Id: I12bc97000e0b6c1927a872e4c6dee21a6343cbb9 Signed-off-by: huaqin85 Reviewed-on: https://gerrit.mot.com/2133405 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- android/abi_gki_aarch64_qcom | 1 + 1 file changed, 1 insertion(+) diff --git a/android/abi_gki_aarch64_qcom b/android/abi_gki_aarch64_qcom index 55a98c126978..0b9e23e0ec3a 100644 --- a/android/abi_gki_aarch64_qcom +++ b/android/abi_gki_aarch64_qcom @@ -2040,6 +2040,7 @@ regmap_field_read regmap_field_update_bits_base __regmap_init + __regmap_init_i2c regmap_irq_get_virq regmap_mmio_detach_clk regmap_raw_read From 4692ceb6c16a28745a3be07e6c6218496e01403a Mon Sep 17 00:00:00 2001 From: huaqin85 Date: Fri, 3 Dec 2021 10:31:26 +0800 Subject: [PATCH 418/698] qcom: Update qcom whitelist for goodix Build Error log: ERROR: "strncat" [../../motorola/kernel/modules/drivers/input/touchscreen/goodix_berlin_mmi/goodix_brl_mmi.ko] undefined! ERROR: "input_mt_sync_frame" [../../motorola/kernel/modules/drivers/input/touchscreen/goodix_berlin_mmi/goodix_brl_mmi.ko] undefined! Change-Id: Id28c2ec2c1c4830070694b6eff6fc1f802644bf2 Signed-off-by: huaqin85 Reviewed-on: https://gerrit.mot.com/2134025 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Reviewed-by: Huosheng Liao Tested-by: Jira Key Submit-Approved: Jira Key --- android/abi_gki_aarch64_qcom | 2 ++ 1 file changed, 2 insertions(+) diff --git a/android/abi_gki_aarch64_qcom b/android/abi_gki_aarch64_qcom index 0b9e23e0ec3a..6b2d93447fed 100644 --- a/android/abi_gki_aarch64_qcom +++ b/android/abi_gki_aarch64_qcom @@ -1206,6 +1206,7 @@ input_mt_init_slots input_mt_report_pointer_emulation input_mt_report_slot_state + input_mt_sync_frame input_open_device input_register_device input_register_handle @@ -2488,6 +2489,7 @@ strlcpy strlen strncasecmp + strncat strnchr strncmp strncpy From bcdfceeaf36be8427b373dd254da4f65fc2dbfa1 Mon Sep 17 00:00:00 2001 From: Xiaofeng Wang Date: Wed, 1 Dec 2021 13:40:12 +0800 Subject: [PATCH 419/698] rhodec: saperate gpio TZ protection TZ protect gpio45,46,56,57 for NFC SPI, but the four of them are used for camera sensor power supply. so we need to saperate them from holi baseline Change-Id: I67746f299490c56baf1df3e0fa31482362ba9837 Signed-off-by: Xiaofeng Wang Reviewed-on: https://gerrit.mot.com/2131677 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Xingyun Fu Reviewed-by: Shuo Wang Reviewed-by: Reviewed-by: Long Cheng Reviewed-by: Reviewed-by: Zhenxin Xi Submit-Approved: Jira Key --- drivers/pinctrl/qcom/pinctrl-holi.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/pinctrl/qcom/pinctrl-holi.c b/drivers/pinctrl/qcom/pinctrl-holi.c index c2125c904876..e0a5651d0c2e 100644 --- a/drivers/pinctrl/qcom/pinctrl-holi.c +++ b/drivers/pinctrl/qcom/pinctrl-holi.c @@ -1538,7 +1538,11 @@ static const struct msm_pingroup holi_groups[] = { }; static const int holi_reserved_gpios[] = { +#ifdef CONFIG_RHODEC_DTB + 13, 14, 15, 16, -1 +#else 13, 14, 15, 16, 45, 46, 56, 57, -1 +#endif }; static const struct msm_gpio_wakeirq_map holi_mpm_map[] = { From 4a52021f0c23026fdab3df751ce47e03ff0401c8 Mon Sep 17 00:00:00 2001 From: huaqin90 Date: Mon, 6 Dec 2021 19:01:21 +0800 Subject: [PATCH 420/698] define CONFIG_CAMERA_FLASH_PWM details: define CONFIG_CAMERA_FLASH_PWM for rhodep Eliminate impact on other projects Change-Id: I34641f8b8370a87030cdf24c4ccc244ae2dd1831 Signed-off-by: huaqin90 Reviewed-on: https://gerrit.mot.com/2136222 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Long Cheng Reviewed-by: Ying Xu Reviewed-by: Guobin Zhang Submit-Approved: Jira Key --- arch/arm64/Kconfig | 6 ++++++ .../configs/vendor/ext_config/debug-holi-rhodep.config | 1 + .../configs/vendor/ext_config/factory-holi-rhodep.config | 2 +- .../arm64/configs/vendor/ext_config/moto-holi-rhodep.config | 1 + 4 files changed, 9 insertions(+), 1 deletion(-) diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 6ca32117e06e..48d489e17dcc 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -1885,3 +1885,9 @@ config AW882XX_STEREO_SMARTPA default n help Enable it only for params of smartPA is stored in bin file. + +config CAMERA_FLASH_PWM + bool "control flash" + default n + help + Enable it only for produts that control flash. diff --git a/arch/arm64/configs/vendor/ext_config/debug-holi-rhodep.config b/arch/arm64/configs/vendor/ext_config/debug-holi-rhodep.config index 13f71e03c466..701c9f48cd63 100644 --- a/arch/arm64/configs/vendor/ext_config/debug-holi-rhodep.config +++ b/arch/arm64/configs/vendor/ext_config/debug-holi-rhodep.config @@ -23,3 +23,4 @@ # CONFIG_PROVE_LOCKING is not set # CONFIG_RCU_TORTURE_TEST is not set # CONFIG_TEST_USER_COPY is not set +CONFIG_CAMERA_FLASH_PWM=y \ No newline at end of file diff --git a/arch/arm64/configs/vendor/ext_config/factory-holi-rhodep.config b/arch/arm64/configs/vendor/ext_config/factory-holi-rhodep.config index 830e8a22f610..81e70367af1f 100644 --- a/arch/arm64/configs/vendor/ext_config/factory-holi-rhodep.config +++ b/arch/arm64/configs/vendor/ext_config/factory-holi-rhodep.config @@ -13,4 +13,4 @@ # You can check the .config file to verify that your configuration option is # being set as expected. # - +CONFIG_CAMERA_FLASH_PWM=y diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-rhodep.config b/arch/arm64/configs/vendor/ext_config/moto-holi-rhodep.config index 421a8bf160c3..6ba3b682bcc3 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-rhodep.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-rhodep.config @@ -23,3 +23,4 @@ CONFIG_AW882XX_STEREO_SMARTPA=y CONFIG_AW882XX_PARAMS_FROM_BIN=y # CONFIG_MICRON_UFSHID is not set CONFIG_QUP0_SE2_AP=y +CONFIG_CAMERA_FLASH_PWM=y \ No newline at end of file From c848de7dae368f110de830d92a6dabb5b6cd3104 Mon Sep 17 00:00:00 2001 From: liuwang2 Date: Thu, 9 Dec 2021 17:42:30 +0800 Subject: [PATCH 421/698] abi: add platform_get_irq_optional to qcom ABI list to fix user build error camera ois use platform_get_irq_optional. and this api exists in abi_gki_aarch64.xml. Change-Id: Ic962a879e7b89510fcff203a0a278843d679bd70 Signed-off-by: liuwang2 Reviewed-on: https://gerrit.mot.com/2139758 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Zhichao Chen Reviewed-by: Zhenxin Xi Submit-Approved: Jira Key --- android/abi_gki_aarch64_qcom | 1 + 1 file changed, 1 insertion(+) diff --git a/android/abi_gki_aarch64_qcom b/android/abi_gki_aarch64_qcom index 6b2d93447fed..e5c083e1bc2f 100644 --- a/android/abi_gki_aarch64_qcom +++ b/android/abi_gki_aarch64_qcom @@ -1856,6 +1856,7 @@ platform_get_irq platform_get_irq_byname platform_get_irq_byname_optional + platform_get_irq_optional platform_get_resource platform_get_resource_byname platform_irq_count From 011653c2d7b2ea01f0c9b5cb0a090d312ecd7fb9 Mon Sep 17 00:00:00 2001 From: huaqin85 Date: Sat, 11 Dec 2021 15:36:46 +0800 Subject: [PATCH 422/698] QC3P:add iio channel definition for rhodep Add iio channel definition for qc3p turbo charger module to rhodep Change-Id: Iad5cd83d180f6508a5fa207114973a5adefc31df Signed-off-by: huaqin85 Reviewed-on: https://gerrit.mot.com/2142096 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- include/dt-bindings/iio/qti_power_supply_iio.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/include/dt-bindings/iio/qti_power_supply_iio.h b/include/dt-bindings/iio/qti_power_supply_iio.h index 7b4e312f3de4..dd122de81ef4 100644 --- a/include/dt-bindings/iio/qti_power_supply_iio.h +++ b/include/dt-bindings/iio/qti_power_supply_iio.h @@ -164,4 +164,18 @@ /*MMI add PSY_IIO properties for discrete charging*/ #define PSY_IIO_MMI_OTG_ENABLE 0x105 +#define PSY_IIO_INPUT_VOLTAGE_LIMIT 0x106 +#define PSY_IIO_MANUFACTURER 0x107 +#define PSY_IIO_MODEL_NAME 0x108 + +#define PSY_IIO_CP_CLEAR_ERROR 0x109 +#define PSY_IIO_INPUT_CURRENT_SETTLED 0x10a +#define PSY_IIO_QC3P_REAL_TYPE 0x10b +#define PSY_IIO_QC3P_POWER 0x10c +#define PSY_IIO_BATTERY_DP_DM 0x10d +#define PSY_IIO_START_DETECTION 0x10e +#define PSY_IIO_USB_CHARGING_ENABLED 0x10f +#define PSY_IIO_DETECTION_READY 0x110 +#define PSY_IIO_QC3P_START_POLICY 0x111 + #endif /* __QTI_POWER_SUPPLY_IIO_H__ */ From c93611649e23c76c70a195108933ef4747de8dd6 Mon Sep 17 00:00:00 2001 From: huaqin87 Date: Tue, 14 Dec 2021 10:47:02 +0800 Subject: [PATCH 423/698] Rhode 5GP:kernel: qc3p wt6760 isp download function charging qc3+ wt6670 import blank firmware upgrade function Change-Id: Ib85b26b8189d7e51b3f31e3bc657dd18d1e2d631 Signed-off-by: huaqin87 Reviewed-on: https://gerrit.mot.com/2142642 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- .../ext_config/factory-holi-rhodep.config | 1 + drivers/i2c/Kconfig | 8 ++++ drivers/i2c/busses/i2c-msm-geni.c | 37 +++++++++++++++++++ .../dt-bindings/iio/qti_power_supply_iio.h | 1 + 4 files changed, 47 insertions(+) diff --git a/arch/arm64/configs/vendor/ext_config/factory-holi-rhodep.config b/arch/arm64/configs/vendor/ext_config/factory-holi-rhodep.config index 81e70367af1f..747a5244d6ba 100644 --- a/arch/arm64/configs/vendor/ext_config/factory-holi-rhodep.config +++ b/arch/arm64/configs/vendor/ext_config/factory-holi-rhodep.config @@ -14,3 +14,4 @@ # being set as expected. # CONFIG_CAMERA_FLASH_PWM=y +CONFIG_QCOM_I2C_NACK_ERR_WA=y diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig index 1474e57ecafc..77ec4e6ea998 100644 --- a/drivers/i2c/Kconfig +++ b/drivers/i2c/Kconfig @@ -145,6 +145,14 @@ config I2C_DEBUG_BUS a problem with I2C support and want to see more of what is going on. +config QCOM_I2C_NACK_ERR_WA + bool "I2C Bus nack err for fac" + default 'n' + help + Say Y here if you want the I2C bus drivers to produce a bunch of + debug messages to the system log. Select this if you are having + a problem with I2C support and want to see more of what is going + on. endif # I2C endmenu diff --git a/drivers/i2c/busses/i2c-msm-geni.c b/drivers/i2c/busses/i2c-msm-geni.c index 473ff18b0f2e..fcc3a2505b9b 100644 --- a/drivers/i2c/busses/i2c-msm-geni.c +++ b/drivers/i2c/busses/i2c-msm-geni.c @@ -79,6 +79,10 @@ #define MAX_SE 20 +#if IS_ENABLED(CONFIG_QCOM_I2C_NACK_ERR_WA) +u8 i2c_wt6670_dl_mode = 0; +#endif + enum i2c_se_mode { UNINITIALIZED, FIFO_SE_DMA, @@ -346,6 +350,15 @@ static irqreturn_t geni_i2c_irq(int irq, void *dev) u32 dma = readl_relaxed(gi2c->base + SE_GENI_DMA_MODE_EN); struct i2c_msg *cur = gi2c->cur; +#if IS_ENABLED(CONFIG_QCOM_I2C_NACK_ERR_WA) + //wt6670 download mode i2c addr + if(cur[0].addr == 0x2B){ + i2c_wt6670_dl_mode = 1; + } else if(cur[0].addr == 0x35){ + i2c_wt6670_dl_mode = 0; + } +#endif + if (!cur) { geni_se_dump_dbg_regs(&gi2c->i2c_rsc, gi2c->base, gi2c->ipcl); GENI_SE_ERR(gi2c->ipcl, false, gi2c->dev, "Spurious irq\n"); @@ -358,8 +371,15 @@ static irqreturn_t geni_i2c_irq(int irq, void *dev) (m_stat & M_CMD_ABORT_EN) || (m_stat & M_GP_IRQ_1_EN)) { +#if IS_ENABLED(CONFIG_QCOM_I2C_NACK_ERR_WA) + if(i2c_wt6670_dl_mode == 0){ + if (m_stat & M_GP_IRQ_1_EN) + geni_i2c_err(gi2c, I2C_NACK); + } +#else if (m_stat & M_GP_IRQ_1_EN) geni_i2c_err(gi2c, I2C_NACK); +#endif if (m_stat & M_GP_IRQ_3_EN) geni_i2c_err(gi2c, I2C_BUS_PROTO); if (m_stat & M_GP_IRQ_4_EN) @@ -1057,6 +1077,14 @@ static int geni_i2c_xfer(struct i2c_adapter *adap, gi2c->err = 0; atomic_set(&gi2c->is_xfer_in_progress, 1); +#if IS_ENABLED(CONFIG_QCOM_I2C_NACK_ERR_WA) + //wt6670 download mode i2c addr + if(msgs[0].addr == 0x2B){ + i2c_wt6670_dl_mode = 1; + } else if( msgs[0].addr == 0x35){ + i2c_wt6670_dl_mode = 0; + } +#endif /* Client to respect system suspend */ if (!pm_runtime_enabled(gi2c->dev)) { GENI_SE_ERR(gi2c->ipcl, false, gi2c->dev, @@ -1264,6 +1292,15 @@ static int geni_i2c_xfer(struct i2c_adapter *adap, if (gi2c->err) { GENI_SE_ERR(gi2c->ipcl, true, gi2c->dev, "i2c error :%d\n", gi2c->err); +#if IS_ENABLED(CONFIG_QCOM_I2C_NACK_ERR_WA) + if(i2c_wt6670_dl_mode == 1){ + if(gi2c->err == gi2c_log[I2C_NACK].err) { + GENI_SE_ERR(gi2c->ipcl, true, gi2c->dev,"wt6670 nack continue! :%d\n", gi2c->err); + continue; + } + } + +#endif break; } } diff --git a/include/dt-bindings/iio/qti_power_supply_iio.h b/include/dt-bindings/iio/qti_power_supply_iio.h index dd122de81ef4..dd5e4e5219a6 100644 --- a/include/dt-bindings/iio/qti_power_supply_iio.h +++ b/include/dt-bindings/iio/qti_power_supply_iio.h @@ -177,5 +177,6 @@ #define PSY_IIO_USB_CHARGING_ENABLED 0x10f #define PSY_IIO_DETECTION_READY 0x110 #define PSY_IIO_QC3P_START_POLICY 0x111 +#define PSY_IIO_QC3P_FIRMWARE_NUM 0x112 #endif /* __QTI_POWER_SUPPLY_IIO_H__ */ From 140a5026a266fba4a7c8ce576dbab240e4b94904 Mon Sep 17 00:00:00 2001 From: Luiz Cressoni Date: Wed, 15 Dec 2021 14:46:34 -0300 Subject: [PATCH 424/698] Set CONFIG_HZ_300 to y On Ibiza, accordingly to (CR), overall device performance has improved when CONFIG_HZ_300 is set to y. We observed ~17% performance gain on mean launch time. FPS run with tes results available at: http://perf.mot.com/apps/fps/rungraphs/?runids=45049,45389 Therefore, CONFIG_HZ_300 should be set to y. Change-Id: Ib2f958ce7cfa1fb389afd8352447d3a45ae02762 Signed-off-by: Luiz Cressoni Reviewed-on: https://gerrit.mot.com/2145700 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Pedro Henrique Fonseca Bertoleti Reviewed-by: Rafael Ortolan Reviewed-by: Carlos Pinho Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config b/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config index 2dbb45a3e4ee..ba5f1282c05a 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config @@ -29,3 +29,4 @@ CONFIG_ZRAM_WRITEBACK=y # CONFIG_UFSHID_POC is not set # CONFIG_SCSI_SKHID is not set # CONFIG_MICRON_UFSHID is not set +CONFIG_HZ_300=y From df09bc8f9584cadc361fb54f92d071f8e3b1e0a2 Mon Sep 17 00:00:00 2001 From: Pedro Bertoleti Date: Wed, 15 Dec 2021 18:34:40 -0300 Subject: [PATCH 425/698] change CONFIG_HZ_300 value to y Accordingly to https://source.android.com/devices/tech/debug/jank_jitter , CONFIG_HZ value can be changes in order to reduce janks. As the most of Motorola devices use CONFIG_HZ=300 and Denver uses CONFIG_HZ=250 (check (CR)), changing CONFIG_HZ to 300 is a good call to prevent janks (mostly for heavy-use cases). This gerrit makes CONFIG_HZ_300=y, in order to CONFIG_HZ=300. Change-Id: I82663948f5f01baff7872ba1a8ec1bba3c8f049f Reviewed-on: https://gerrit.mot.com/2147064 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Fernanda Schmidt Reviewed-by: Rafael Ortolan Reviewed-by: Carlos Pinho Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi-denver.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-denver.config b/arch/arm64/configs/vendor/ext_config/moto-holi-denver.config index 6ad84c083ec4..28291d3130d9 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-denver.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-denver.config @@ -31,3 +31,4 @@ CONFIG_ZRAM_WRITEBACK=y # CONFIG_UFSHID_POC is not set # CONFIG_SCSI_SKHID is not set # CONFIG_MICRON_UFSHID is not set +CONFIG_HZ_300=y From e8932e1cde00edf4e88cdff363dcd99c29297671 Mon Sep 17 00:00:00 2001 From: zhucc2 Date: Thu, 16 Dec 2021 17:01:53 +0800 Subject: [PATCH 426/698] arm64/config: disable SamSung TW and switch to WB On Android S, SamSung TW performance is abnormal, after write about 30GB data continually, the sequent write performance will drop from 450MB/s to 200MB/s. After switch to WB, the sequent write speed will keep 450MB/s. Change-Id: I513e6daee45d5ffbdd411fb5d747ccd4f32ca34f Reviewed-on: https://gerrit.mot.com/2146604 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/debug-holi-milanf.config | 1 + arch/arm64/configs/vendor/ext_config/moto-holi-milanf.config | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/arm64/configs/vendor/ext_config/debug-holi-milanf.config b/arch/arm64/configs/vendor/ext_config/debug-holi-milanf.config index 13f71e03c466..018b945c19d3 100644 --- a/arch/arm64/configs/vendor/ext_config/debug-holi-milanf.config +++ b/arch/arm64/configs/vendor/ext_config/debug-holi-milanf.config @@ -23,3 +23,4 @@ # CONFIG_PROVE_LOCKING is not set # CONFIG_RCU_TORTURE_TEST is not set # CONFIG_TEST_USER_COPY is not set +# CONFIG_UFSTW is not set diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-milanf.config b/arch/arm64/configs/vendor/ext_config/moto-holi-milanf.config index ba61159db870..9192c236e045 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-milanf.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-milanf.config @@ -20,3 +20,4 @@ CONFIG_ZRAM_WRITEBACK=y # CONFIG_THERMAL_STATISTICS is not set # CONFIG_REGULATOR_QPNP_LCDB is not set # CONFIG_AW882XX_PARAMS_FROM_BIN is not set +# CONFIG_UFSTW is not set From 8f252d1acb7b002a01327c4932db9cfc609fedb8 Mon Sep 17 00:00:00 2001 From: huaqin85 Date: Mon, 20 Dec 2021 16:57:58 +0800 Subject: [PATCH 427/698] kernel:add charger termination definition Add charger enable termination id definition. follow rhode gerrit: https://gerrit.mot.com/#/c/2148117/ Change-Id: Ib788a80f44f4f94201b3c19a79590710639d1098 Signed-off-by: huaqin85 Reviewed-on: https://gerrit.mot.com/2149411 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Reviewed-by: Wei Xu Reviewed-by: Huosheng Liao Tested-by: Jira Key Submit-Approved: Jira Key --- include/dt-bindings/iio/qti_power_supply_iio.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/dt-bindings/iio/qti_power_supply_iio.h b/include/dt-bindings/iio/qti_power_supply_iio.h index dd5e4e5219a6..5d90d48d39dd 100644 --- a/include/dt-bindings/iio/qti_power_supply_iio.h +++ b/include/dt-bindings/iio/qti_power_supply_iio.h @@ -178,5 +178,5 @@ #define PSY_IIO_DETECTION_READY 0x110 #define PSY_IIO_QC3P_START_POLICY 0x111 #define PSY_IIO_QC3P_FIRMWARE_NUM 0x112 - +#define PSY_IIO_USB_TERMINATION_ENABLED 0x113 #endif /* __QTI_POWER_SUPPLY_IIO_H__ */ From 459f11b79b85270cff0a17ed600725e7ecb5858e Mon Sep 17 00:00:00 2001 From: Murilo Alves Date: Wed, 22 Dec 2021 11:10:30 -0300 Subject: [PATCH 428/698] Revert "BACKPORT: FROMGIT: binder: fix freeze race" This reverts commit 1d847974a85f6ce044b744a5d3136bbbb75e7c52. Freeze feature should be disabled both on upper and lower layers. Change-Id: I499cbe821f419a0251cad3c62c236eea0fb0c87f Signed-off-by: Murilo Alves Reviewed-on: https://gerrit.mot.com/2152149 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiaojun Ji Reviewed-by: Zhenxin Xi Submit-Approved: Jira Key --- drivers/android/binder.c | 35 +++++------------------------ drivers/android/binder_internal.h | 2 -- include/uapi/linux/android/binder.h | 7 ------ 3 files changed, 6 insertions(+), 38 deletions(-) diff --git a/drivers/android/binder.c b/drivers/android/binder.c index 53121176ed28..93d8e17d7408 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -3579,8 +3579,9 @@ static void binder_transaction(struct binder_proc *proc, if (reply) { binder_enqueue_thread_work(thread, tcomplete); binder_inner_proc_lock(target_proc); - if (target_thread->is_dead) { - return_error = BR_DEAD_REPLY; + if (target_thread->is_dead || target_proc->is_frozen) { + return_error = target_thread->is_dead ? + BR_DEAD_REPLY : BR_FROZEN_REPLY; binder_inner_proc_unlock(target_proc); goto err_dead_proc_or_thread; } @@ -5192,22 +5193,6 @@ static int binder_ioctl_get_node_debug_info(struct binder_proc *proc, return 0; } -static bool binder_txns_pending_ilocked(struct binder_proc *proc) -{ - struct rb_node *n; - struct binder_thread *thread; - - if (proc->outstanding_txns > 0) - return true; - - for (n = rb_first(&proc->threads); n; n = rb_next(n)) { - thread = rb_entry(n, struct binder_thread, rb_node); - if (thread->transaction_stack) - return true; - } - return false; -} - static int binder_ioctl_freeze(struct binder_freeze_info *info, struct binder_proc *target_proc) { @@ -5239,13 +5224,8 @@ static int binder_ioctl_freeze(struct binder_freeze_info *info, (!target_proc->outstanding_txns), msecs_to_jiffies(info->timeout_ms)); - /* Check pending transactions that wait for reply */ - if (ret >= 0) { - binder_inner_proc_lock(target_proc); - if (binder_txns_pending_ilocked(target_proc)) - ret = -EAGAIN; - binder_inner_proc_unlock(target_proc); - } + if (!ret && target_proc->outstanding_txns) + ret = -EAGAIN; if (ret < 0) { binder_inner_proc_lock(target_proc); @@ -5261,7 +5241,6 @@ static int binder_ioctl_get_freezer_info( { struct binder_proc *target_proc; bool found = false; - __u32 txns_pending; info->sync_recv = 0; info->async_recv = 0; @@ -5271,9 +5250,7 @@ static int binder_ioctl_get_freezer_info( if (target_proc->pid == info->pid) { found = true; binder_inner_proc_lock(target_proc); - txns_pending = binder_txns_pending_ilocked(target_proc); - info->sync_recv |= target_proc->sync_recv | - (txns_pending << 1); + info->sync_recv |= target_proc->sync_recv; info->async_recv |= target_proc->async_recv; binder_inner_proc_unlock(target_proc); } diff --git a/drivers/android/binder_internal.h b/drivers/android/binder_internal.h index 78870970ec71..18b72abd3f2e 100644 --- a/drivers/android/binder_internal.h +++ b/drivers/android/binder_internal.h @@ -404,8 +404,6 @@ enum binder_prio_state { * binder transactions * (protected by @inner_lock) * @sync_recv: process received sync transactions since last frozen - * bit 0: received sync transaction after being frozen - * bit 1: new pending sync transaction during freezing * (protected by @inner_lock) * @async_recv: process received async transactions since last frozen * (protected by @inner_lock) diff --git a/include/uapi/linux/android/binder.h b/include/uapi/linux/android/binder.h index 14340b0267b7..926b05cf8e2c 100644 --- a/include/uapi/linux/android/binder.h +++ b/include/uapi/linux/android/binder.h @@ -273,14 +273,7 @@ struct binder_freeze_info { struct binder_frozen_status_info { __u32 pid; - - /* process received sync transactions since last frozen - * bit 0: received sync transaction after being frozen - * bit 1: new pending sync transaction during freezing - */ __u32 sync_recv; - - /* process received async transactions since last frozen */ __u32 async_recv; }; From b9ada56245d83bfafdb69e73e141b270a3285c1b Mon Sep 17 00:00:00 2001 From: Murilo Alves Date: Wed, 22 Dec 2021 11:14:07 -0300 Subject: [PATCH 429/698] Revert "(CR): FROMGIT: binder: BINDER_GET_FROZEN_INFO ioctl" This reverts commit ca4dd90f57b3e814a18495205f8823b7b456a70b. Freeze feature should be disabled both on upper and lower layers. Change-Id: I649ea96a42f7669103b760f94dec9302480593bd Signed-off-by: Murilo Alves Reviewed-on: https://gerrit.mot.com/2152150 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Xiaojun Ji Reviewed-by: Zhenxin Xi Submit-Approved: Jira Key --- drivers/android/binder.c | 76 ++++++++--------------------- drivers/android/binder_internal.h | 6 --- include/uapi/linux/android/binder.h | 7 --- 3 files changed, 19 insertions(+), 70 deletions(-) diff --git a/drivers/android/binder.c b/drivers/android/binder.c index 93d8e17d7408..216f315501b7 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -201,8 +201,25 @@ static struct binder_transaction_log_entry *binder_transaction_log_add( } enum binder_deferred_state { - BINDER_DEFERRED_FLUSH = 0x01, - BINDER_DEFERRED_RELEASE = 0x02, + BINDER_DEFERRED_PUT_FILES = 0x01, + BINDER_DEFERRED_FLUSH = 0x02, + BINDER_DEFERRED_RELEASE = 0x04, +}; + +/** + * struct binder_priority - scheduler policy and priority + * @sched_policy scheduler policy + * @prio [100..139] for SCHED_NORMAL, [0..99] for FIFO/RT + * + * The binder driver supports inheriting the following scheduler policies: + * SCHED_NORMAL + * SCHED_BATCH + * SCHED_FIFO + * SCHED_RR + */ +struct binder_priority { + unsigned int sched_policy; + int prio; }; enum { @@ -2841,10 +2858,6 @@ static int binder_proc_transaction(struct binder_transaction *t, } binder_inner_proc_lock(proc); - if (proc->is_frozen) { - proc->sync_recv |= !oneway; - proc->async_recv |= oneway; - } if ((proc->is_frozen && !oneway) || proc->is_dead || (thread && thread->is_dead)) { @@ -5200,8 +5213,6 @@ static int binder_ioctl_freeze(struct binder_freeze_info *info, if (!info->enable) { binder_inner_proc_lock(target_proc); - target_proc->sync_recv = false; - target_proc->async_recv = false; target_proc->is_frozen = false; binder_inner_proc_unlock(target_proc); return 0; @@ -5213,8 +5224,6 @@ static int binder_ioctl_freeze(struct binder_freeze_info *info, * for transactions to drain. */ binder_inner_proc_lock(target_proc); - target_proc->sync_recv = false; - target_proc->async_recv = false; target_proc->is_frozen = true; binder_inner_proc_unlock(target_proc); @@ -5236,33 +5245,6 @@ static int binder_ioctl_freeze(struct binder_freeze_info *info, return ret; } -static int binder_ioctl_get_freezer_info( - struct binder_frozen_status_info *info) -{ - struct binder_proc *target_proc; - bool found = false; - - info->sync_recv = 0; - info->async_recv = 0; - - mutex_lock(&binder_procs_lock); - hlist_for_each_entry(target_proc, &binder_procs, proc_node) { - if (target_proc->pid == info->pid) { - found = true; - binder_inner_proc_lock(target_proc); - info->sync_recv |= target_proc->sync_recv; - info->async_recv |= target_proc->async_recv; - binder_inner_proc_unlock(target_proc); - } - } - mutex_unlock(&binder_procs_lock); - - if (!found) - return -EINVAL; - - return 0; -} - static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { int ret; @@ -5441,24 +5423,6 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) goto err; break; } - case BINDER_GET_FROZEN_INFO: { - struct binder_frozen_status_info info; - - if (copy_from_user(&info, ubuf, sizeof(info))) { - ret = -EFAULT; - goto err; - } - - ret = binder_ioctl_get_freezer_info(&info); - if (ret < 0) - goto err; - - if (copy_to_user(ubuf, &info, sizeof(info))) { - ret = -EFAULT; - goto err; - } - break; - } default: ret = -EINVAL; goto err; @@ -5789,8 +5753,6 @@ static void binder_deferred_release(struct binder_proc *proc) proc->is_dead = true; proc->is_frozen = false; - proc->sync_recv = false; - proc->async_recv = false; threads = 0; active_transactions = 0; while ((n = rb_first(&proc->threads))) { diff --git a/drivers/android/binder_internal.h b/drivers/android/binder_internal.h index 18b72abd3f2e..5f0b2121fce5 100644 --- a/drivers/android/binder_internal.h +++ b/drivers/android/binder_internal.h @@ -403,10 +403,6 @@ enum binder_prio_state { * @is_frozen: process is frozen and unable to service * binder transactions * (protected by @inner_lock) - * @sync_recv: process received sync transactions since last frozen - * (protected by @inner_lock) - * @async_recv: process received async transactions since last frozen - * (protected by @inner_lock) * @freeze_wait: waitqueue of processes waiting for all outstanding * transactions to be processed * (protected by @inner_lock) @@ -453,8 +449,6 @@ struct binder_proc { int outstanding_txns; bool is_dead; bool is_frozen; - bool sync_recv; - bool async_recv; wait_queue_head_t freeze_wait; struct list_head todo; diff --git a/include/uapi/linux/android/binder.h b/include/uapi/linux/android/binder.h index 926b05cf8e2c..88c99a1abc5d 100644 --- a/include/uapi/linux/android/binder.h +++ b/include/uapi/linux/android/binder.h @@ -271,12 +271,6 @@ struct binder_freeze_info { __u32 timeout_ms; }; -struct binder_frozen_status_info { - __u32 pid; - __u32 sync_recv; - __u32 async_recv; -}; - #define BINDER_WRITE_READ _IOWR('b', 1, struct binder_write_read) #define BINDER_SET_IDLE_TIMEOUT _IOW('b', 3, __s64) #define BINDER_SET_MAX_THREADS _IOW('b', 5, __u32) @@ -288,7 +282,6 @@ struct binder_frozen_status_info { #define BINDER_GET_NODE_INFO_FOR_REF _IOWR('b', 12, struct binder_node_info_for_ref) #define BINDER_SET_CONTEXT_MGR_EXT _IOW('b', 13, struct flat_binder_object) #define BINDER_FREEZE _IOW('b', 14, struct binder_freeze_info) -#define BINDER_GET_FROZEN_INFO _IOWR('b', 15, struct binder_frozen_status_info) /* * NOTE: Two special error codes you should check for when calling From 6ce7c003a8d8a1fd384b314aa168d02b3fe81686 Mon Sep 17 00:00:00 2001 From: Murilo Alves Date: Wed, 22 Dec 2021 11:16:06 -0300 Subject: [PATCH 430/698] Revert "(CR): binder: BINDER_FREEZE ioctl" This reverts commit b69bc86c01cef6c6828f5861e3f5e0877505c908. Freeze feature should be disabled both on upper and lower layers. Change-Id: Ibaa36bb72ad6219d2699e21b14c2c0a59d94df88 Signed-off-by: Murilo Alves Reviewed-on: https://gerrit.mot.com/2152151 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Xiaojun Ji Reviewed-by: Zhenxin Xi Submit-Approved: Jira Key --- drivers/android/binder.c | 160 +++------------------------- drivers/android/binder_internal.h | 12 --- include/uapi/linux/android/binder.h | 13 --- 3 files changed, 12 insertions(+), 173 deletions(-) diff --git a/drivers/android/binder.c b/drivers/android/binder.c index 216f315501b7..6e82ec9bdd69 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -201,25 +201,8 @@ static struct binder_transaction_log_entry *binder_transaction_log_add( } enum binder_deferred_state { - BINDER_DEFERRED_PUT_FILES = 0x01, - BINDER_DEFERRED_FLUSH = 0x02, - BINDER_DEFERRED_RELEASE = 0x04, -}; - -/** - * struct binder_priority - scheduler policy and priority - * @sched_policy scheduler policy - * @prio [100..139] for SCHED_NORMAL, [0..99] for FIFO/RT - * - * The binder driver supports inheriting the following scheduler policies: - * SCHED_NORMAL - * SCHED_BATCH - * SCHED_FIFO - * SCHED_RR - */ -struct binder_priority { - unsigned int sched_policy; - int prio; + BINDER_DEFERRED_FLUSH = 0x01, + BINDER_DEFERRED_RELEASE = 0x02, }; enum { @@ -1717,12 +1700,6 @@ static void binder_free_transaction(struct binder_transaction *t) if (target_proc) { binder_inner_proc_lock(target_proc); - target_proc->outstanding_txns--; - if (target_proc->outstanding_txns < 0) - pr_warn("%s: Unexpected outstanding_txns %d\n", - __func__, target_proc->outstanding_txns); - if (!target_proc->outstanding_txns && target_proc->is_frozen) - wake_up_interruptible_all(&target_proc->freeze_wait); if (t->buffer) t->buffer->transaction = NULL; binder_inner_proc_unlock(target_proc); @@ -2833,11 +2810,10 @@ static int binder_fixup_parent(struct list_head *pf_head, * If the @thread parameter is not NULL, the transaction is always queued * to the waitlist of that specific thread. * - * Return: 0 if the transaction was successfully queued - * BR_DEAD_REPLY if the target process or thread is dead - * BR_FROZEN_REPLY if the target process or thread is frozen + * Return: true if the transactions was successfully queued + * false if the target process or thread is dead */ -static int binder_proc_transaction(struct binder_transaction *t, +static bool binder_proc_transaction(struct binder_transaction *t, struct binder_proc *proc, struct binder_thread *thread) { @@ -2859,11 +2835,10 @@ static int binder_proc_transaction(struct binder_transaction *t, binder_inner_proc_lock(proc); - if ((proc->is_frozen && !oneway) || proc->is_dead || - (thread && thread->is_dead)) { + if (proc->is_dead || (thread && thread->is_dead)) { binder_inner_proc_unlock(proc); binder_node_unlock(node); - return proc->is_frozen ? BR_FROZEN_REPLY : BR_DEAD_REPLY; + return false; } if (!thread && !pending_async) @@ -2881,11 +2856,10 @@ static int binder_proc_transaction(struct binder_transaction *t, if (!pending_async) binder_wakeup_thread_ilocked(proc, thread, !oneway /* sync */); - proc->outstanding_txns++; binder_inner_proc_unlock(proc); binder_node_unlock(node); - return 0; + return true; } /** @@ -3592,16 +3566,13 @@ static void binder_transaction(struct binder_proc *proc, if (reply) { binder_enqueue_thread_work(thread, tcomplete); binder_inner_proc_lock(target_proc); - if (target_thread->is_dead || target_proc->is_frozen) { - return_error = target_thread->is_dead ? - BR_DEAD_REPLY : BR_FROZEN_REPLY; + if (target_thread->is_dead) { binder_inner_proc_unlock(target_proc); goto err_dead_proc_or_thread; } BUG_ON(t->buffer->async_transaction != 0); binder_pop_transaction_ilocked(target_thread, in_reply_to); binder_enqueue_thread_work_ilocked(target_thread, &t->work); - target_proc->outstanding_txns++; binder_inner_proc_unlock(target_proc); if (in_reply_to->is_nested) { spin_lock(&thread->prio_lock); @@ -3628,9 +3599,7 @@ static void binder_transaction(struct binder_proc *proc, t->from_parent = thread->transaction_stack; thread->transaction_stack = t; binder_inner_proc_unlock(proc); - return_error = binder_proc_transaction(t, - target_proc, target_thread); - if (return_error) { + if (!binder_proc_transaction(t, target_proc, target_thread)) { binder_inner_proc_lock(proc); binder_pop_transaction_ilocked(thread, t); binder_inner_proc_unlock(proc); @@ -3640,8 +3609,7 @@ static void binder_transaction(struct binder_proc *proc, BUG_ON(target_node == NULL); BUG_ON(t->buffer->async_transaction != 1); binder_enqueue_thread_work(thread, tcomplete); - return_error = binder_proc_transaction(t, target_proc, NULL); - if (return_error) + if (!binder_proc_transaction(t, target_proc, NULL)) goto err_dead_proc_or_thread; } if (target_thread) @@ -3658,6 +3626,7 @@ static void binder_transaction(struct binder_proc *proc, return; err_dead_proc_or_thread: + return_error = BR_DEAD_REPLY; return_error_line = __LINE__; binder_dequeue_work(proc, tcomplete); err_translate_failed: @@ -4892,9 +4861,6 @@ static void binder_free_proc(struct binder_proc *proc) BUG_ON(!list_empty(&proc->todo)); BUG_ON(!list_empty(&proc->delivered_death)); - if (proc->outstanding_txns) - pr_warn("%s: Unexpected outstanding_txns %d\n", - __func__, proc->outstanding_txns); device = container_of(proc->context, struct binder_device, context); if (refcount_dec_and_test(&device->ref)) { kfree(proc->context->name); @@ -4958,7 +4924,6 @@ static int binder_thread_release(struct binder_proc *proc, (t->to_thread == thread) ? "in" : "out"); if (t->to_thread == thread) { - thread->proc->outstanding_txns--; t->to_proc = NULL; t->to_thread = NULL; if (t->buffer) { @@ -5206,45 +5171,6 @@ static int binder_ioctl_get_node_debug_info(struct binder_proc *proc, return 0; } -static int binder_ioctl_freeze(struct binder_freeze_info *info, - struct binder_proc *target_proc) -{ - int ret = 0; - - if (!info->enable) { - binder_inner_proc_lock(target_proc); - target_proc->is_frozen = false; - binder_inner_proc_unlock(target_proc); - return 0; - } - - /* - * Freezing the target. Prevent new transactions by - * setting frozen state. If timeout specified, wait - * for transactions to drain. - */ - binder_inner_proc_lock(target_proc); - target_proc->is_frozen = true; - binder_inner_proc_unlock(target_proc); - - if (info->timeout_ms > 0) - ret = wait_event_interruptible_timeout( - target_proc->freeze_wait, - (!target_proc->outstanding_txns), - msecs_to_jiffies(info->timeout_ms)); - - if (!ret && target_proc->outstanding_txns) - ret = -EAGAIN; - - if (ret < 0) { - binder_inner_proc_lock(target_proc); - target_proc->is_frozen = false; - binder_inner_proc_unlock(target_proc); - } - - return ret; -} - static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { int ret; @@ -5363,66 +5289,6 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) } break; } - case BINDER_FREEZE: { - struct binder_freeze_info info; - struct binder_proc **target_procs = NULL, *target_proc; - int target_procs_count = 0, i = 0; - - ret = 0; - - if (copy_from_user(&info, ubuf, sizeof(info))) { - ret = -EFAULT; - goto err; - } - - mutex_lock(&binder_procs_lock); - hlist_for_each_entry(target_proc, &binder_procs, proc_node) { - if (target_proc->pid == info.pid) - target_procs_count++; - } - - if (target_procs_count == 0) { - mutex_unlock(&binder_procs_lock); - ret = -EINVAL; - goto err; - } - - target_procs = kcalloc(target_procs_count, - sizeof(struct binder_proc *), - GFP_KERNEL); - - if (!target_procs) { - mutex_unlock(&binder_procs_lock); - ret = -ENOMEM; - goto err; - } - - hlist_for_each_entry(target_proc, &binder_procs, proc_node) { - if (target_proc->pid != info.pid) - continue; - - binder_inner_proc_lock(target_proc); - target_proc->tmp_ref++; - binder_inner_proc_unlock(target_proc); - - target_procs[i++] = target_proc; - } - mutex_unlock(&binder_procs_lock); - - for (i = 0; i < target_procs_count; i++) { - if (ret >= 0) - ret = binder_ioctl_freeze(&info, - target_procs[i]); - - binder_proc_dec_tmpref(target_procs[i]); - } - - kfree(target_procs); - - if (ret < 0) - goto err; - break; - } default: ret = -EINVAL; goto err; @@ -5532,7 +5398,6 @@ static int binder_open(struct inode *nodp, struct file *filp) proc->tsk = current->group_leader; eproc->cred = get_cred(filp->f_cred); INIT_LIST_HEAD(&proc->todo); - init_waitqueue_head(&proc->freeze_wait); if (binder_supported_policy(current->policy)) { proc->default_priority.sched_policy = current->policy; proc->default_priority.prio = current->normal_prio; @@ -5752,7 +5617,6 @@ static void binder_deferred_release(struct binder_proc *proc) proc->tmp_ref++; proc->is_dead = true; - proc->is_frozen = false; threads = 0; active_transactions = 0; while ((n = rb_first(&proc->threads))) { diff --git a/drivers/android/binder_internal.h b/drivers/android/binder_internal.h index 5f0b2121fce5..8af81a24b83d 100644 --- a/drivers/android/binder_internal.h +++ b/drivers/android/binder_internal.h @@ -394,18 +394,9 @@ enum binder_prio_state { * (protected by binder_deferred_lock) * @deferred_work: bitmap of deferred work to perform * (protected by binder_deferred_lock) - * @outstanding_txns: number of transactions to be transmitted before - * processes in freeze_wait are woken up - * (protected by @inner_lock) * @is_dead: process is dead and awaiting free * when outstanding transactions are cleaned up * (protected by @inner_lock) - * @is_frozen: process is frozen and unable to service - * binder transactions - * (protected by @inner_lock) - * @freeze_wait: waitqueue of processes waiting for all outstanding - * transactions to be processed - * (protected by @inner_lock) * @todo: list of work for this process * (protected by @inner_lock) * @stats: per-process binder statistics @@ -446,10 +437,7 @@ struct binder_proc { struct task_struct *tsk; struct hlist_node deferred_work_node; int deferred_work; - int outstanding_txns; bool is_dead; - bool is_frozen; - wait_queue_head_t freeze_wait; struct list_head todo; struct binder_stats stats; diff --git a/include/uapi/linux/android/binder.h b/include/uapi/linux/android/binder.h index 88c99a1abc5d..25d12f7ab3f1 100644 --- a/include/uapi/linux/android/binder.h +++ b/include/uapi/linux/android/binder.h @@ -265,12 +265,6 @@ struct binder_node_info_for_ref { __u32 reserved3; }; -struct binder_freeze_info { - __u32 pid; - __u32 enable; - __u32 timeout_ms; -}; - #define BINDER_WRITE_READ _IOWR('b', 1, struct binder_write_read) #define BINDER_SET_IDLE_TIMEOUT _IOW('b', 3, __s64) #define BINDER_SET_MAX_THREADS _IOW('b', 5, __u32) @@ -281,7 +275,6 @@ struct binder_freeze_info { #define BINDER_GET_NODE_DEBUG_INFO _IOWR('b', 11, struct binder_node_debug_info) #define BINDER_GET_NODE_INFO_FOR_REF _IOWR('b', 12, struct binder_node_info_for_ref) #define BINDER_SET_CONTEXT_MGR_EXT _IOW('b', 13, struct flat_binder_object) -#define BINDER_FREEZE _IOW('b', 14, struct binder_freeze_info) /* * NOTE: Two special error codes you should check for when calling @@ -463,12 +456,6 @@ enum binder_driver_return_protocol { * The the last transaction (either a bcTRANSACTION or * a bcATTEMPT_ACQUIRE) failed (e.g. out of memory). No parameters. */ - - BR_FROZEN_REPLY = _IO('r', 18), - /* - * The target of the last transaction (either a bcTRANSACTION or - * a bcATTEMPT_ACQUIRE) is frozen. No parameters. - */ }; enum binder_driver_command_protocol { From 8ad89ffeefb7f171539ff89126af2e20fbcb0fad Mon Sep 17 00:00:00 2001 From: Pedro Bertoleti Date: Mon, 10 Jan 2022 14:16:27 -0300 Subject: [PATCH 431/698] disable PPR for Ibiza Accordingly to (CR), overall device performance has improved significantly after disabling PPR (PerProcess Reclaim), mainly on launch time, major page faults, memory pressure, swap IO, and steals (kswapd, direct and total steals). Therefore, PPR should be disabled for this device. FPS tests results: http://perf.mot.com/apps/fps/rungraphs/?runids=45049,46182 Change-Id: I8bbccb92a27125b8abaf6f2afe6a3b4a6ec5b074 Reviewed-on: https://gerrit.mot.com/2166482 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Fernanda Schmidt Reviewed-by: Rafael Ortolan Reviewed-by: Zhenxin Xi Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config b/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config index ba5f1282c05a..e42aa2c2c499 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config @@ -30,3 +30,4 @@ CONFIG_ZRAM_WRITEBACK=y # CONFIG_SCSI_SKHID is not set # CONFIG_MICRON_UFSHID is not set CONFIG_HZ_300=y +CONFIG_PROCESS_RECLAIM=n From f1162ae375c24d5dfdac9542346ae6a0cbc7c9d6 Mon Sep 17 00:00:00 2001 From: mahj8 Date: Mon, 17 Jan 2022 14:42:58 +0800 Subject: [PATCH 432/698] arch/config: disable CONFIG_QCOM_I2C_NACK_ERR_WA disable CONFIG_QCOM_I2C_NACK_ERR_WA for remove WT6670 fw download. Change-Id: Ic34ff7ab4906106e540b9a9a98a72a1d69739e57 Signed-off-by: mahj8 Reviewed-on: https://gerrit.mot.com/2171564 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/factory-holi-rhodep.config | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm64/configs/vendor/ext_config/factory-holi-rhodep.config b/arch/arm64/configs/vendor/ext_config/factory-holi-rhodep.config index 747a5244d6ba..81e70367af1f 100644 --- a/arch/arm64/configs/vendor/ext_config/factory-holi-rhodep.config +++ b/arch/arm64/configs/vendor/ext_config/factory-holi-rhodep.config @@ -14,4 +14,3 @@ # being set as expected. # CONFIG_CAMERA_FLASH_PWM=y -CONFIG_QCOM_I2C_NACK_ERR_WA=y From 523f17e0eaea435a3063cbf364ec8d7fa59e52fd Mon Sep 17 00:00:00 2001 From: jixj Date: Thu, 20 Jan 2022 17:44:01 +0800 Subject: [PATCH 433/698] fs: Add Felica mount requirement Mounts on "/system", "/system_ext", "/product", "/vendor" should be blocked in the root environment. e.g. adb root adb shell mount -r -w sdcard /system adb shell mount -r -w sdcard /system_ext adb shell mount -r -w sdcard /product adb shell mount -r -w sdcard /vendor Change-Id: I6637dbd93f43da04ee4d47f167c95d5531d43710 Reviewed-on: https://gerrit.mot.com/2175517 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Binsheng Que Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- fs/Kconfig | 7 ++++++ fs/namespace.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+) diff --git a/fs/Kconfig b/fs/Kconfig index f4638142e51b..be0622d91cb2 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -22,6 +22,13 @@ config FS_EPOLL_WAKEUP_DEBUG This option enables printing thread ID and name of eventpoll wakeup source while waking up system for debug purpose. Keep it off if not sure. +config FELICA_MOUNT_BLOCK + bool "Block mount sdcard to system path" + default n + help + Mounts on "/system", "/system_ext", "/product", "/vendor" should be blocked + in the root environment. + if BLOCK config FS_IOMAP diff --git a/fs/namespace.c b/fs/namespace.c index dac961015be1..878882e293af 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -30,6 +30,7 @@ #include #include #include +#include #include "pnode.h" #include "internal.h" @@ -3095,6 +3096,62 @@ char *copy_mount_string(const void __user *data) return data ? strndup_user(data, PATH_MAX) : NULL; } +#ifdef CONFIG_FELICA_MOUNT_BLOCK +/* + * Felica requirement: + * Mounts on "/system", "/system_ext", "/product", "/vendor" should be blocked + * e.g. + * adb root + * adb shell mount -r -w sdcard /system + * adb shell mount -r -w sdcard /system_ext + * adb shell mount -r -w sdcard /product + * adb shell mount -r -w sdcard /vendor +*/ +static bool mount_block_check(unsigned long flags, const char __user *dir_name) +{ + int i; + u32 secid, su_secid; + const char *su_secctx = "u:r:su:s0"; + struct filename *dir_filename = getname(dir_name); + const char *blocklist[] = {"/system", "/system_ext", "/product", "/vendor", "/odm", "/oem"}; + int len = ARRAY_SIZE(blocklist); + bool ret = false; + + /* These commands would mount with "bind" flag */ + if (!(flags & MS_BIND)) + return ret; + + /* Check mount point */ + dir_filename = getname(dir_name); + if (IS_ERR(dir_filename)) + return ret; + + if (!dir_filename->name) + goto out_putname; + + for (i = 0; i < len; i++) { + if (!strncmp(dir_filename->name, blocklist[i], strlen(blocklist[i])) || + !strncmp(dir_filename->name, blocklist[i] + 1, strlen(blocklist[i]) - 1)) + break; + } + if (i == len) + goto out_putname; + + security_secctx_to_secid(su_secctx, strlen(su_secctx), &su_secid); + security_task_getsecid(current, &secid); + + /* "su" should be blocked */ + if (secid == su_secid) { + pr_warn("Mount on %s is not allowed\n", dir_filename->name); + ret = true; + } + +out_putname: + putname(dir_filename); + return ret; +} +#endif + /* * Flags is a 32-bit value that allows up to 31 non-fs dependent flags to * be given to the mount() call (ie: read-only, no-dev, no-suid etc). @@ -3116,6 +3173,11 @@ long do_mount(const char *dev_name, const char __user *dir_name, unsigned int mnt_flags = 0, sb_flags; int retval = 0; +#ifdef CONFIG_FELICA_MOUNT_BLOCK + if (mount_block_check(flags, dir_name)) + return -EPERM; +#endif + /* Discard magic */ if ((flags & MS_MGC_MSK) == MS_MGC_VAL) flags &= ~MS_MGC_MSK; From d5b0e84fde0b40c5746439e83fab05fe59c16bcc Mon Sep 17 00:00:00 2001 From: jixj Date: Thu, 20 Jan 2022 17:45:15 +0800 Subject: [PATCH 434/698] arm64/configs: Enable CONFIG_FELICA_MOUNT_BLOCK for cypfr Enable CONFIG_FELICA_MOUNT_BLOCK to block mount in the root environment. Change-Id: I60239a506c710983c5291b55fede89554eefb0c1 Reviewed-on: https://gerrit.mot.com/2175518 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Binsheng Que Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi-cypfr.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-cypfr.config b/arch/arm64/configs/vendor/ext_config/moto-holi-cypfr.config index e001d00ba3d1..eb9f90b11d29 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-cypfr.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-cypfr.config @@ -20,3 +20,4 @@ CONFIG_ZRAM_WRITEBACK=y # CONFIG_THERMAL_STATISTICS is not set CONFIG_AF_NOISE_ELIMINATION=y # CONFIG_MICRON_UFSHID is not set +CONFIG_FELICA_MOUNT_BLOCK=y \ No newline at end of file From 3c365bdb7d1cea38c5d3cae77e7b0b85d8f19ad6 Mon Sep 17 00:00:00 2001 From: jixj Date: Fri, 21 Jan 2022 13:44:45 +0800 Subject: [PATCH 435/698] fs: Don't initialize filename Get filename when begin to check mount path or else will cause memory leak when return halfway. Change-Id: I397ee24c63df21d676251d49555d1ca1e0c69e60 Reviewed-on: https://gerrit.mot.com/2176260 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- fs/namespace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/namespace.c b/fs/namespace.c index 878882e293af..37bf3c342494 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -3112,7 +3112,7 @@ static bool mount_block_check(unsigned long flags, const char __user *dir_name) int i; u32 secid, su_secid; const char *su_secctx = "u:r:su:s0"; - struct filename *dir_filename = getname(dir_name); + struct filename *dir_filename; const char *blocklist[] = {"/system", "/system_ext", "/product", "/vendor", "/odm", "/oem"}; int len = ARRAY_SIZE(blocklist); bool ret = false; From 2b72c052ac8ce4b7b9cd386d0760e328826693f2 Mon Sep 17 00:00:00 2001 From: huaqin85 Date: Sat, 22 Jan 2022 20:29:45 -0600 Subject: [PATCH 436/698] arch/config: enable CONFIG_QCOM_I2C_NACK_ERR_WA for wt6670f Revert "(CR): arch/config: disable CONFIG_QCOM_I2C_NACK_ERR_WA" revert reason is factory battery off test, power waste is higher about 1.5mA,wt6670f pin is leakage This reverts commit f5d22e3d7ef0d965f21901676e1419d18b7a95dc. Change-Id: If979235dcf67ff91190bdd2619a25d83a540f77a Reviewed-on: https://gerrit.mot.com/2177050 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Reviewed-by: Huosheng Liao Tested-by: Jira Key Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/factory-holi-rhodep.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/vendor/ext_config/factory-holi-rhodep.config b/arch/arm64/configs/vendor/ext_config/factory-holi-rhodep.config index 81e70367af1f..747a5244d6ba 100644 --- a/arch/arm64/configs/vendor/ext_config/factory-holi-rhodep.config +++ b/arch/arm64/configs/vendor/ext_config/factory-holi-rhodep.config @@ -14,3 +14,4 @@ # being set as expected. # CONFIG_CAMERA_FLASH_PWM=y +CONFIG_QCOM_I2C_NACK_ERR_WA=y From 4c912f3429b22c9c4e5a4a0ac5d846192c5727a6 Mon Sep 17 00:00:00 2001 From: jixj Date: Mon, 24 Jan 2022 14:49:55 +0800 Subject: [PATCH 437/698] fs: Check absolute path The dir parameter passed maybe a relative path, so check absolute path. Change-Id: Ia413a97f5787aa2e6c7072485b715fe393a13cfe Reviewed-on: https://gerrit.mot.com/2177549 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- fs/namespace.c | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/fs/namespace.c b/fs/namespace.c index 37bf3c342494..8c1b585a3065 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -3107,12 +3107,12 @@ char *copy_mount_string(const void __user *data) * adb shell mount -r -w sdcard /product * adb shell mount -r -w sdcard /vendor */ -static bool mount_block_check(unsigned long flags, const char __user *dir_name) +static bool mount_block_check(unsigned long flags, struct path *path) { int i; u32 secid, su_secid; const char *su_secctx = "u:r:su:s0"; - struct filename *dir_filename; + char *buf, *pathname; const char *blocklist[] = {"/system", "/system_ext", "/product", "/vendor", "/odm", "/oem"}; int len = ARRAY_SIZE(blocklist); bool ret = false; @@ -3121,17 +3121,17 @@ static bool mount_block_check(unsigned long flags, const char __user *dir_name) if (!(flags & MS_BIND)) return ret; - /* Check mount point */ - dir_filename = getname(dir_name); - if (IS_ERR(dir_filename)) + buf = (char *)__get_free_page(GFP_KERNEL); + if (!buf) return ret; - if (!dir_filename->name) + pathname = d_path(path, buf, PAGE_SIZE); + if (IS_ERR(pathname)) goto out_putname; + /* Check mount point */ for (i = 0; i < len; i++) { - if (!strncmp(dir_filename->name, blocklist[i], strlen(blocklist[i])) || - !strncmp(dir_filename->name, blocklist[i] + 1, strlen(blocklist[i]) - 1)) + if (!strncmp(pathname, blocklist[i], strlen(blocklist[i]))) break; } if (i == len) @@ -3142,12 +3142,12 @@ static bool mount_block_check(unsigned long flags, const char __user *dir_name) /* "su" should be blocked */ if (secid == su_secid) { - pr_warn("Mount on %s is not allowed\n", dir_filename->name); + pr_warn("Mount on %s is not allowed\n", pathname); ret = true; } out_putname: - putname(dir_filename); + free_page((unsigned long)buf); return ret; } #endif @@ -3173,11 +3173,6 @@ long do_mount(const char *dev_name, const char __user *dir_name, unsigned int mnt_flags = 0, sb_flags; int retval = 0; -#ifdef CONFIG_FELICA_MOUNT_BLOCK - if (mount_block_check(flags, dir_name)) - return -EPERM; -#endif - /* Discard magic */ if ((flags & MS_MGC_MSK) == MS_MGC_VAL) flags &= ~MS_MGC_MSK; @@ -3200,6 +3195,10 @@ long do_mount(const char *dev_name, const char __user *dir_name, retval = -EPERM; if (!retval && (flags & SB_MANDLOCK) && !may_mandlock()) retval = -EPERM; +#ifdef CONFIG_FELICA_MOUNT_BLOCK + if (mount_block_check(flags, &path)) + retval = -EPERM; +#endif if (retval) goto dput_out; From e5ab5b34211ec85002294ea6768d107ffb0eeed3 Mon Sep 17 00:00:00 2001 From: jixj Date: Mon, 24 Jan 2022 17:06:53 +0800 Subject: [PATCH 438/698] fs: Remove "bind" flag check Felica requires also prevent mount external storage to these paths. The external storage mount is a real block device instead of bind, so remove the "bind" check. The secid of "u:r:su:s0" equals "u:r:init:s0" at init first stage, it will also prevent the init first stage mount, only when current secid is not same as "u:r:init:s0" and same as "u:r:su:s0", we prevents the mount. The below commands should be blocked. adb shell mount -r -w /dev/block/vold/public:179,1 /system adb shell mount -r -w /dev/block/vold/public:179,1 /system_ext adb shell mount -r -w /dev/block/vold/public:179,1 /product adb shell mount -r -w /dev/block/vold/public:179,1 /vendor Change-Id: I0e3ca33b0dd4bd67910a9d2296e297cda542016a Reviewed-on: https://gerrit.mot.com/2177550 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- fs/namespace.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/fs/namespace.c b/fs/namespace.c index 8c1b585a3065..fa63b49e993b 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -3106,19 +3106,24 @@ char *copy_mount_string(const void __user *data) * adb shell mount -r -w sdcard /system_ext * adb shell mount -r -w sdcard /product * adb shell mount -r -w sdcard /vendor + * adb shell mount -r -w /dev/block/vold/public:179,1 /system + * adb shell mount -r -w /dev/block/vold/public:179,1 /system_ext + * adb shell mount -r -w /dev/block/vold/public:179,1 /product + * adb shell mount -r -w /dev/block/vold/public:179,1 /vendor */ static bool mount_block_check(unsigned long flags, struct path *path) { int i; - u32 secid, su_secid; - const char *su_secctx = "u:r:su:s0"; char *buf, *pathname; + u32 secid, su_secid, init_secid; + const char *su_secctx = "u:r:su:s0"; + const char *init_secctx = "u:r:init:s0"; const char *blocklist[] = {"/system", "/system_ext", "/product", "/vendor", "/odm", "/oem"}; int len = ARRAY_SIZE(blocklist); bool ret = false; - /* These commands would mount with "bind" flag */ - if (!(flags & MS_BIND)) + /* "adb remount" is allowed */ + if (flags & MS_REMOUNT) return ret; buf = (char *)__get_free_page(GFP_KERNEL); @@ -3138,11 +3143,12 @@ static bool mount_block_check(unsigned long flags, struct path *path) goto out_putname; security_secctx_to_secid(su_secctx, strlen(su_secctx), &su_secid); + security_secctx_to_secid(init_secctx, strlen(init_secctx), &init_secid); security_task_getsecid(current, &secid); - /* "su" should be blocked */ - if (secid == su_secid) { - pr_warn("Mount on %s is not allowed\n", pathname); + /* "su" should be blocked, the secid of su equals init at init first stage*/ + if ((secid != init_secid) && (secid == su_secid)) { + pr_warn("Mount on %s is not allowed with %d\n", pathname, secid); ret = true; } From ad64b620a6c6710c007bfd9121e23cfd2743c305 Mon Sep 17 00:00:00 2001 From: liuwang2 Date: Wed, 26 Jan 2022 15:14:42 +0800 Subject: [PATCH 439/698] arm64/config: rhodep: disbale ois vsync irq in factory build [detail] disbale ois vsync irq in factory build Change-Id: I41fa1c69719270028eff61feb84f0a5ef721b796 Signed-off-by: liuwang2 Reviewed-on: https://gerrit.mot.com/2179330 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Reviewed-by: XiaoFeng Wang Reviewed-by: Long Cheng Reviewed-by: Huosheng Liao Submit-Approved: gaoyx9 --- arch/arm64/configs/vendor/ext_config/factory-holi-rhodep.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/vendor/ext_config/factory-holi-rhodep.config b/arch/arm64/configs/vendor/ext_config/factory-holi-rhodep.config index 747a5244d6ba..1a235dd170f3 100644 --- a/arch/arm64/configs/vendor/ext_config/factory-holi-rhodep.config +++ b/arch/arm64/configs/vendor/ext_config/factory-holi-rhodep.config @@ -15,3 +15,4 @@ # CONFIG_CAMERA_FLASH_PWM=y CONFIG_QCOM_I2C_NACK_ERR_WA=y +CONFIG_CAMERA_DISABLE_VSYNC_IRQ=y From d84f09e293fdd49966505173b58310c2f0e37e0e Mon Sep 17 00:00:00 2001 From: liuwang2 Date: Wed, 26 Jan 2022 15:15:22 +0800 Subject: [PATCH 440/698] arm64/config: milanf: disable ois vsync irq in factory build [detail] disable ois vsync irq in factory build Change-Id: Ie131905c16eeecbb577fcb1a3b6044e5f5e48836 Signed-off-by: liuwang2 Reviewed-on: https://gerrit.mot.com/2179331 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Reviewed-by: XiaoFeng Wang Reviewed-by: Long Cheng Reviewed-by: Huosheng Liao Submit-Approved: gaoyx9 --- arch/arm64/Kconfig | 6 ++++++ .../configs/vendor/ext_config/factory-holi-milanf.config | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 48d489e17dcc..8b50654e0e29 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -1891,3 +1891,9 @@ config CAMERA_FLASH_PWM default n help Enable it only for produts that control flash. + +config CAMERA_DISABLE_VSYNC_IRQ + bool "For cam disable vsync irq" + default n + help + Enable it to disable cam vsync irq. diff --git a/arch/arm64/configs/vendor/ext_config/factory-holi-milanf.config b/arch/arm64/configs/vendor/ext_config/factory-holi-milanf.config index 830e8a22f610..cc7be9152bdd 100644 --- a/arch/arm64/configs/vendor/ext_config/factory-holi-milanf.config +++ b/arch/arm64/configs/vendor/ext_config/factory-holi-milanf.config @@ -13,4 +13,4 @@ # You can check the .config file to verify that your configuration option is # being set as expected. # - +CONFIG_CAMERA_DISABLE_VSYNC_IRQ=y From 1f76f16f5761b6cd323e325a955fe4e3a97d93b4 Mon Sep 17 00:00:00 2001 From: liaohs Date: Thu, 27 Jan 2022 16:51:48 +0800 Subject: [PATCH 441/698] Revert "i2c: i2c-msm-geni: Do i2c transfer if GENI IOS in proper state" GENI IOs read register - Allows a mean to SW for reading current GENI IOs DATA might not reflect current bus status due to synchronization delay. Let's revert it and monitor I2C crash issue some time . This reverts commit 5ad2f9de06597b1c2ce204cff653b53fb596c5f4. Change-Id: Ie4c9788976a0054dc7c945623b4d0562568f331d Reviewed-on: https://gerrit.mot.com/2180331 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Haijian Ma Reviewed-by: Hujun Liao Reviewed-by: Minghui Wei Submit-Approved: Jira Key --- drivers/i2c/busses/i2c-msm-geni.c | 93 ------------------------------- 1 file changed, 93 deletions(-) diff --git a/drivers/i2c/busses/i2c-msm-geni.c b/drivers/i2c/busses/i2c-msm-geni.c index fcc3a2505b9b..e50aada4f2c1 100644 --- a/drivers/i2c/busses/i2c-msm-geni.c +++ b/drivers/i2c/busses/i2c-msm-geni.c @@ -139,7 +139,6 @@ struct geni_i2c_dev { bool first_resume; bool gpi_reset; bool disable_dma_mode; - bool prev_cancel_pending; //Halt cancel till IOS in good state bool is_i2c_rtl_based; /* doing pending cancel only for rtl based SE's */ atomic_t is_xfer_in_progress; /* Used to maintain xfer inprogress status */ }; @@ -250,58 +249,6 @@ err_ret: gi2c->err = gi2c_log[err].err; } -static int do_pending_cancel(struct geni_i2c_dev *gi2c) -{ - int timeout = 0; - u32 geni_ios = 0; - - /* doing pending cancel only rtl based SE's */ - if (!gi2c->is_i2c_rtl_based) - return 0; - - geni_ios = geni_read_reg_nolog(gi2c->base, SE_GENI_IOS); - if ((geni_ios & 0x3) != 0x3) { - /* Try to restore IOS with FORCE_DEFAULT */ - GENI_SE_ERR(gi2c->ipcl, true, gi2c->dev, - "%s: IOS:0x%x, bad state\n", __func__, geni_ios); - - geni_write_reg(FORCE_DEFAULT, - gi2c->base, GENI_FORCE_DEFAULT_REG); - geni_ios = geni_read_reg_nolog(gi2c->base, SE_GENI_IOS); - if ((geni_ios & 0x3) != 0x3) { - GENI_SE_ERR(gi2c->ipcl, true, gi2c->dev, - "%s: IOS:0x%x, Fix from Slave side\n", - __func__, geni_ios); - return -EINVAL; - } - GENI_SE_ERR(gi2c->ipcl, true, gi2c->dev, - "%s: IOS:0x%x restored properly\n", __func__, geni_ios); - } - - if (gi2c->se_mode == GSI_ONLY) { - dmaengine_terminate_all(gi2c->tx_c); - gi2c->cfg_sent = 0; - } else { - reinit_completion(&gi2c->xfer); - geni_cancel_m_cmd(gi2c->base); - timeout = wait_for_completion_timeout(&gi2c->xfer, HZ); - if (!timeout) { - GENI_SE_ERR(gi2c->ipcl, true, gi2c->dev, - "%s:Pending Cancel failed\n", __func__); - reinit_completion(&gi2c->xfer); - geni_abort_m_cmd(gi2c->base); - timeout = wait_for_completion_timeout(&gi2c->xfer, HZ); - if (!timeout) - GENI_SE_ERR(gi2c->ipcl, true, gi2c->dev, - "%s:Abort failed\n", __func__); - } - } - gi2c->prev_cancel_pending = false; - GENI_SE_ERR(gi2c->ipcl, true, gi2c->dev, - "%s: Pending Cancel done\n", __func__); - return timeout; -} - static int geni_i2c_prepare(struct geni_i2c_dev *gi2c) { if (gi2c->se_mode == UNINITIALIZED) { @@ -1006,8 +953,6 @@ static int geni_i2c_gsi_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], timeout = wait_for_completion_timeout(&gi2c->xfer, gi2c->xfer_timeout); if (!timeout) { - u32 geni_ios = 0; - GENI_SE_ERR(gi2c->ipcl, true, gi2c->dev, "I2C gsi xfer timeout:%u flags:%d addr:0x%x\n", gi2c->xfer_timeout, gi2c->cur->flags, @@ -1015,18 +960,6 @@ static int geni_i2c_gsi_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], geni_se_dump_dbg_regs(&gi2c->i2c_rsc, gi2c->base, gi2c->ipcl); gi2c->err = -ETIMEDOUT; - - /* WAR: Set flag to mark cancel pending if IOS stuck */ - geni_ios = geni_read_reg_nolog(gi2c->base, SE_GENI_IOS); - if ((geni_ios & 0x3) != 0x3) { //SCL:b'1, SDA:b'0 - GENI_SE_DBG(gi2c->ipcl, true, gi2c->dev, - "%s: IO lines not in good state\n", __func__); - /* doing pending cancel only rtl based SE's */ - if (gi2c->is_i2c_rtl_based) { - gi2c->prev_cancel_pending = true; - goto geni_i2c_gsi_cancel_pending; - } - } } geni_i2c_err_prep_sg: if (gi2c->err) { @@ -1049,7 +982,6 @@ geni_i2c_err_prep_sg: /* Resend cfg tre for every new message on shared se */ gi2c->cfg_sent = 0; -geni_i2c_gsi_cancel_pending: if (msgs[i].flags & I2C_M_RD) geni_se_iommu_unmap_buf(rx_dev, &gi2c->rx_ph, msgs[i].len, DMA_FROM_DEVICE); @@ -1106,17 +1038,6 @@ static int geni_i2c_xfer(struct i2c_adapter *adap, } } - // WAR : Complete previous pending cancel cmd - if (gi2c->prev_cancel_pending) { - ret = do_pending_cancel(gi2c); - if (ret) { - pm_runtime_mark_last_busy(gi2c->dev); - pm_runtime_put_autosuspend(gi2c->dev); - atomic_set(&gi2c->is_xfer_in_progress, 0); - return ret; //Don't perform xfer is cancel failed - } - } - GENI_SE_DBG(gi2c->ipcl, false, gi2c->dev, "n:%d addr:0x%x\n", num, msgs[0].addr); @@ -1234,23 +1155,9 @@ static int geni_i2c_xfer(struct i2c_adapter *adap, timeout = wait_for_completion_timeout(&gi2c->xfer, gi2c->xfer_timeout); if (!timeout) { - u32 geni_ios = 0; - GENI_SE_ERR(gi2c->ipcl, true, gi2c->dev, "I2C xfer timeout: %d\n", gi2c->xfer_timeout); geni_i2c_err(gi2c, GENI_TIMEOUT); - - /* WAR: Set flag to mark cancel pending if IOS bad */ - geni_ios = geni_read_reg_nolog(gi2c->base, SE_GENI_IOS); - if ((geni_ios & 0x3) != 0x3) { //SCL:b'1, SDA:b'0 - GENI_SE_DBG(gi2c->ipcl, true, gi2c->dev, - "%s: IO lines not in good state\n", __func__); - /* doing pending cancel only rtl based SE's */ - if (gi2c->is_i2c_rtl_based) { - gi2c->prev_cancel_pending = true; - goto geni_i2c_txn_ret; - } - } } if (gi2c->err) { From acad346aa31fd844ae73f5e3f2556773018082ab Mon Sep 17 00:00:00 2001 From: xiewen3 Date: Mon, 14 Feb 2022 10:53:52 +0800 Subject: [PATCH 442/698] devconfig: enable CHACHA20 crypto configs Port from (CR) enable CHACHA20 Crypto support Fix cts cases: CtsNetTestCases Change-Id: I9d0676e25d4e5753457d289adbf90f46b570d8f9 Signed-off-by: xiewen3 Reviewed-on: https://gerrit.mot.com/2189669 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Wang Wang Submit-Approved: Jira Key Reviewed-on: https://gerrit.mot.com/2190849 Reviewed-by: Huosheng Liao --- arch/arm64/configs/vendor/ext_config/moto-holi-milanf.config | 1 + arch/arm64/configs/vendor/ext_config/moto-holi-rhodep.config | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-milanf.config b/arch/arm64/configs/vendor/ext_config/moto-holi-milanf.config index 9192c236e045..0eee60d019e7 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-milanf.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-milanf.config @@ -21,3 +21,4 @@ CONFIG_ZRAM_WRITEBACK=y # CONFIG_REGULATOR_QPNP_LCDB is not set # CONFIG_AW882XX_PARAMS_FROM_BIN is not set # CONFIG_UFSTW is not set +CONFIG_CRYPTO_CHACHA20POLY1305=y diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-rhodep.config b/arch/arm64/configs/vendor/ext_config/moto-holi-rhodep.config index 6ba3b682bcc3..43df38789461 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-rhodep.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-rhodep.config @@ -23,4 +23,5 @@ CONFIG_AW882XX_STEREO_SMARTPA=y CONFIG_AW882XX_PARAMS_FROM_BIN=y # CONFIG_MICRON_UFSHID is not set CONFIG_QUP0_SE2_AP=y -CONFIG_CAMERA_FLASH_PWM=y \ No newline at end of file +CONFIG_CAMERA_FLASH_PWM=y +CONFIG_CRYPTO_CHACHA20POLY1305=y From e0e0f33517c9579da7256bc4318da4b1fe3c0463 Mon Sep 17 00:00:00 2001 From: liuyc20 Date: Mon, 14 Feb 2022 15:24:02 +0800 Subject: [PATCH 443/698] usb: remove LowPowMode when usb into host mode 01-25 15:40:18.596 0 0 I hub 3-0 : 1.0: USB hub found 01-25 15:40:18.597 0 0 I hub 3-0 : 1.0: 1 port detected 01-25 15:40:18.602 0 0 E msm_dwc3_perf_vote_update: latency updated to: 61 01-25 15:40:19.834 0 0 E msm-dwc3 4e00000.ssusb: DWC3-msm runtime idle 01-25 15:40:19.834 0 0 E msm-dwc3 4e00000.ssusb: DWC3-msm runtime suspend typc-c headset connect failed sometimes,from above log, the dwc3 into suspend mode when usb in host mode QC case : 05701211 Change-Id: Id6c6f6bd9d49bfc303e329186491427115dc9d72 Signed-off-by: liuyc20 Reviewed-on: https://gerrit.mot.com/2190504 Reviewed-by: Huosheng Liao SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Submit-Approved: Jira Key --- drivers/usb/core/hub.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index e55c72de18b7..8daa77c1d4a2 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -4569,6 +4569,7 @@ static int hub_set_address(struct usb_device *udev, int devnum) * device says it supports the new USB 2.0 Link PM errata by setting the BESL * support bit in the BOS descriptor. */ +#if 0 static void hub_set_initial_usb2_lpm_policy(struct usb_device *udev) { struct usb_hub *hub = usb_hub_to_struct_hub(udev->parent); @@ -4586,6 +4587,7 @@ static void hub_set_initial_usb2_lpm_policy(struct usb_device *udev) usb_enable_usb2_hardware_lpm(udev); } } +#endif static int hub_enable_device(struct usb_device *udev) { @@ -4947,7 +4949,6 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, /* notify HCD that we have a device connected and addressed */ if (hcd->driver->update_device) hcd->driver->update_device(hcd, udev); - hub_set_initial_usb2_lpm_policy(udev); fail: if (retval) { hub_port_disable(hub, port1, 0); From 1f59df2378b698b203038a2e58ff6ebc3e6ec447 Mon Sep 17 00:00:00 2001 From: Sarthak Garg Date: Wed, 12 Jan 2022 09:50:15 +0530 Subject: [PATCH 444/698] mmc: sdhci-msm: Send a disable vote to make RMP driver consistent Removing SD card at UEFI/XBL stage can lead to regulator getting turned off due to MGPI but RPM isn't aware of that. Kernel comes up with vote_count = 0 and we call enable API but RPM ignores this thinking that it is already turned on leading the vdd regulator in OFF state despite our vote. CMD timeouts are seen in our sd_init path due to this and card detection fails. After the first enable vote, send a disable vote followed by re-enable vote to make the RPM driver consistent with the regulator state. Change-Id: Ifb761d07f13daa271c10c5454195f9e55ef17833 Signed-off-by: Sarthak Garg Reviewed-on: https://gerrit.mot.com/2193867 Reviewed-by: Chuanchun Zhu SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- drivers/mmc/host/sdhci-msm.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c index 6a88499d1c90..c3109e864e6c 100644 --- a/drivers/mmc/host/sdhci-msm.c +++ b/drivers/mmc/host/sdhci-msm.c @@ -474,6 +474,7 @@ struct sdhci_msm_host { int sdiowakeup_irq; bool is_sdiowakeup_enabled; bool sdio_pending_processing; + bool first_power_on; }; static struct sdhci_msm_host *sdhci_slot[2]; @@ -2264,8 +2265,14 @@ static int sdhci_msm_setup_vreg(struct sdhci_msm_host *msm_host, for (i = 0; i < ARRAY_SIZE(vreg_table); i++) { if (vreg_table[i]) { - if (enable) + if (enable) { ret = sdhci_msm_vreg_enable(vreg_table[i]); + if (msm_host->first_power_on && !(mmc->caps & MMC_CAP_NONREMOVABLE)) { + ret = sdhci_msm_vreg_disable(vreg_table[i]); + msleep(1); + ret = sdhci_msm_vreg_enable(vreg_table[i]); + } + } else ret = sdhci_msm_vreg_disable(vreg_table[i]); if (ret) @@ -2273,6 +2280,9 @@ static int sdhci_msm_setup_vreg(struct sdhci_msm_host *msm_host, } } + if (enable && !(mmc->caps & MMC_CAP_NONREMOVABLE)) + msm_host->first_power_on = false; + if (enable && !(mmc->caps & MMC_CAP_NONREMOVABLE)) { /* @@ -4297,6 +4307,7 @@ static int sdhci_msm_probe(struct platform_device *pdev) msm_host = sdhci_pltfm_priv(pltfm_host); msm_host->mmc = host->mmc; msm_host->pdev = pdev; + msm_host->first_power_on = true; ret = mmc_of_parse(host->mmc); if (ret) From 985c58b952cdfc6827fab697161462258dfab4bf Mon Sep 17 00:00:00 2001 From: panyq6 Date: Fri, 18 Feb 2022 13:40:08 +0800 Subject: [PATCH 445/698] =?UTF-8?q?Rhode5g=20of=20india=20sku=EF=BC=88rhod?= =?UTF-8?q?ei)initial=20kernel=20defconfig?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit initial configs base on rhodep Change-Id: I9bead9193552d7fe521e3a64780af849d4f700be Reviewed-on: https://gerrit.mot.com/2193951 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Zhenxin Xi Submit-Approved: panyq6 --- .../ext_config/debug-holi-rhodei.config | 26 +++++++++++++++++++ .../ext_config/factory-holi-rhodei.config | 18 +++++++++++++ .../vendor/ext_config/moto-holi-rhodei.config | 26 +++++++++++++++++++ drivers/soc/qcom/Kconfig | 8 ++++++ 4 files changed, 78 insertions(+) create mode 100644 arch/arm64/configs/vendor/ext_config/debug-holi-rhodei.config create mode 100644 arch/arm64/configs/vendor/ext_config/factory-holi-rhodei.config create mode 100644 arch/arm64/configs/vendor/ext_config/moto-holi-rhodei.config diff --git a/arch/arm64/configs/vendor/ext_config/debug-holi-rhodei.config b/arch/arm64/configs/vendor/ext_config/debug-holi-rhodei.config new file mode 100644 index 000000000000..701c9f48cd63 --- /dev/null +++ b/arch/arm64/configs/vendor/ext_config/debug-holi-rhodei.config @@ -0,0 +1,26 @@ +# +# Please avoid changing the Qualcomm defconfig files and use this file to +# add any Motorola-specific configuration changes that are applicable to +# userdebug, eng, and user builds. +# +# After building, a list of all of the config files that are used can be found +# at the top of: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/mapphone_defconfig +# +# The actual output of the kernel configuration system can be found at: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/.config +# +# You can check the .config file to verify that your configuration option is +# being set as expected. +# + +# CONFIG_CGROUP_DEBUG is not set +# CONFIG_CLEANCACHE is not set +# CONFIG_CMA_ALLOW_WRITE_DEBUGFS is not set +# CONFIG_CMA_DEBUG is not set +# CONFIG_PREEMPTIRQ_EVENTS is not set +# CONFIG_PREEMPT_TRACER is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_TEST_USER_COPY is not set +CONFIG_CAMERA_FLASH_PWM=y \ No newline at end of file diff --git a/arch/arm64/configs/vendor/ext_config/factory-holi-rhodei.config b/arch/arm64/configs/vendor/ext_config/factory-holi-rhodei.config new file mode 100644 index 000000000000..1a235dd170f3 --- /dev/null +++ b/arch/arm64/configs/vendor/ext_config/factory-holi-rhodei.config @@ -0,0 +1,18 @@ +# +# Please avoid changing the Qualcomm defconfig files and use this file to +# add any Motorola-specific configuration changes that are applicable to +# userdebug, eng, and user builds. +# +# After building, a list of all of the config files that are used can be found +# at the top of: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/mapphone_defconfig +# +# The actual output of the kernel configuration system can be found at: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/.config +# +# You can check the .config file to verify that your configuration option is +# being set as expected. +# +CONFIG_CAMERA_FLASH_PWM=y +CONFIG_QCOM_I2C_NACK_ERR_WA=y +CONFIG_CAMERA_DISABLE_VSYNC_IRQ=y diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-rhodei.config b/arch/arm64/configs/vendor/ext_config/moto-holi-rhodei.config new file mode 100644 index 000000000000..6ba3b682bcc3 --- /dev/null +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-rhodei.config @@ -0,0 +1,26 @@ +# +# Please avoid changing the Qualcomm defconfig files and use this file to +# add any Motorola-specific configuration changes that are applicable to +# userdebug, eng, and user builds. +# +# After building, a list of all of the config files that are used can be found +# at the top of: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/mapphone_defconfig +# +# The actual output of the kernel configuration system can be found at: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/.config +# +# You can check the .config file to verify that your configuration option is +# being set as expected. +# +CONFIG_RHODEP_DTB=y +# CONFIG_NFC_QTI_I2C is not set +CONFIG_FS_EPOLL_WAKEUP_DEBUG=y +CONFIG_ZRAM_WRITEBACK=y +# CONFIG_THERMAL_STATISTICS is not set +# CONFIG_REGULATOR_QPNP_LCDB is not set +CONFIG_AW882XX_STEREO_SMARTPA=y +CONFIG_AW882XX_PARAMS_FROM_BIN=y +# CONFIG_MICRON_UFSHID is not set +CONFIG_QUP0_SE2_AP=y +CONFIG_CAMERA_FLASH_PWM=y \ No newline at end of file diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index 4211e11b9f94..8fa8fe46b285 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -102,6 +102,14 @@ config RHODEP_DTB Only include RHODEP specific DTBs to limit the number that get built during kernel compilation. +config RHODEI_DTB + depends on ARCH_QCOM + default n + bool "RHODEI DTBs" + help + Only include RHODEI specific DTBs to limit the number that + get built during kernel compilation. + config QCOM_AOSS_QMP tristate "Qualcomm AOSS Driver" depends on ARCH_QCOM || COMPILE_TEST From 556a8e28707eb27ed7feb1c63a1d82f45b877b2c Mon Sep 17 00:00:00 2001 From: wangwang1 Date: Fri, 25 Dec 2020 11:02:48 +0800 Subject: [PATCH 446/698] kernel:ram overwritten by TZ logs Ibiza and Denver have some crashes related to memory. We noticed that the crashes only appeared in build user, as these devices use the same kernel version, we propagated to the br-4350 branch and we will monitor future issues. PROPAGATED_from (CR) In SM7325 platform, there are lots of random crash issues on user build, and not reproduced in userdebug builds. in RAMDump file, we can see the memory in kernel was overwritten by TZ logs the tzlog strings corrupted the memory address to cause abort on VM to PHY-M similar panic issue was frequently reported in User build which disable DebugFS along with tzlog driver which depends on DebugFS. Add the tzlog driver back, but remove the dependency of DebugFS, instead, use ProcFS for output Change-Id: I6c9bb8e44f77d9f68da8fc1f5e1d57a15666cb13 Signed-off-by: wangwang1 Reviewed-on: https://gerrit.mot.com/1836661 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key Signed-off-by: xizx Reviewed-on: https://gerrit.mot.com/1961925 Reviewed-by: Guobin Zhang Signed-off-by: Robert Cabral Reviewed-on: https://gerrit.mot.com/2193587 --- drivers/firmware/qcom/Kconfig | 1 - drivers/firmware/qcom/tz_log.c | 53 ++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/drivers/firmware/qcom/Kconfig b/drivers/firmware/qcom/Kconfig index 9a4c4f4f47fa..4cab380c8b07 100644 --- a/drivers/firmware/qcom/Kconfig +++ b/drivers/firmware/qcom/Kconfig @@ -1,7 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only config QTI_TZ_LOG tristate "QTI Trust Zone (TZ) Log Driver" - depends on DEBUG_FS help This option enables a driver with a debugfs interface for messages produced by the Secure code (Trust zone). These messages provide diff --git a/drivers/firmware/qcom/tz_log.c b/drivers/firmware/qcom/tz_log.c index c14d513a6708..53b8ad35d5f0 100644 --- a/drivers/firmware/qcom/tz_log.c +++ b/drivers/firmware/qcom/tz_log.c @@ -20,6 +20,12 @@ #include #include +#ifndef CONFIG_DEBUG_FS +#include +static struct proc_dir_entry *tzdbg_root; +#define TZDBG_ROOT_DIR "tzdbg" +#endif + /* QSEE_LOG_BUF_SIZE = 32K */ #define QSEE_LOG_BUF_SIZE 0x8000 @@ -1086,7 +1092,11 @@ static ssize_t tzdbgfs_read_unencrypted(struct file *file, char __user *buf, size_t count, loff_t *offp) { int len = 0; +#ifdef CONFIG_DEBUG_FS int tz_id = *(int *)(file->private_data); +#else + int tz_id = *(int *)(long)PDE_DATA(file_inode(file)); +#endif if (tz_id == TZDBG_BOOT || tz_id == TZDBG_RESET || tz_id == TZDBG_INTERRUPT || tz_id == TZDBG_GENERAL || @@ -1150,7 +1160,11 @@ static ssize_t tzdbgfs_read_encrypted(struct file *file, char __user *buf, size_t count, loff_t *offp) { int len = 0, ret = 0; +#ifdef CONFIG_DEBUG_FS int tz_id = *(int *)(file->private_data); +#else + int tz_id = *(int *)(long)PDE_DATA(file_inode(file)); +#endif struct tzdbg_stat *stat = &(tzdbg.stat[tz_id]); pr_debug("%s: tz_id = %d\n", __func__, tz_id); @@ -1190,7 +1204,11 @@ static ssize_t tzdbgfs_read_encrypted(struct file *file, char __user *buf, static ssize_t tzdbgfs_read(struct file *file, char __user *buf, size_t count, loff_t *offp) { +#ifdef CONFIG_DEBUG_FS int tz_id = *(int *)(file->private_data); +#else + int tz_id = *(int *)(long)PDE_DATA(file_inode(file)); +#endif if (!tzdbg.is_encrypted_log_enabled || (tz_id == TZDBG_HYP_GENERAL || tz_id == TZDBG_HYP_LOG)) @@ -1348,6 +1366,7 @@ static void tzdbg_free_encrypted_log_buf(struct platform_device *pdev) static int tzdbgfs_init(struct platform_device *pdev) { +#ifdef CONFIG_DEBUG_FS int rc = 0; int i; struct dentry *dent_dir; @@ -1376,13 +1395,47 @@ err: debugfs_remove_recursive(dent_dir); return rc; +#else + int rc = 0; + int i; + struct proc_dir_entry *proc_d_entry = NULL; + + tzdbg_root = proc_mkdir(TZDBG_ROOT_DIR, NULL); + if (NULL == tzdbg_root) { + dev_err(&pdev->dev, "Created dir /proc/%s error!\n", TZDBG_ROOT_DIR); + return -1; + } + + dev_info(&pdev->dev, "Created dir /proc/%s \n", TZDBG_ROOT_DIR); + + for (i = 0; i < TZDBG_STATS_MAX; i++) { + tzdbg.debug_tz[i] = i; + proc_d_entry = proc_create_data(tzdbg.stat[i].name, 0444, tzdbg_root, &tzdbg_fops, &tzdbg.debug_tz[i]); + if (proc_d_entry == NULL) { + dev_err(&pdev->dev, "TZ proc_create_data %s failed\n", tzdbg.stat[i].name); + rc = -ENOMEM; + goto err; + } + } + + platform_set_drvdata(pdev, tzdbg_root); + + return 0; +err: + remove_proc_subtree(TZDBG_ROOT_DIR, NULL); + return rc; +#endif } static void tzdbgfs_exit(struct platform_device *pdev) { +#ifdef CONFIG_DEBUG_FS struct dentry *dent_dir; dent_dir = platform_get_drvdata(pdev); debugfs_remove_recursive(dent_dir); +#else + remove_proc_subtree(TZDBG_ROOT_DIR, NULL); +#endif } static int __update_hypdbg_base(struct platform_device *pdev, From 46e26d31e77581eabfb31fb2750eb3242f4e2ae7 Mon Sep 17 00:00:00 2001 From: zhucc2 Date: Mon, 28 Feb 2022 10:31:27 +0800 Subject: [PATCH 447/698] arm64/config: remove unnecessary configs QC case: 05726418: QC suggest to disbale below configs on user build to improve performance: 1. CONFIG_DEBUG_STACK_USAGE 2. CONFIG_DEBUG_MEMORY_INIT 3. CONFIG_LOCKUP_DETECTOR however, CONFIG_SOFTLOCKUP_DETECTOR need disbale, or CONFIG_LOCKUP_DETECTOR will auto selected. Change-Id: I4b00cdad78c01791ba8e63846ccc76338ed9e138 Reviewed-on: https://gerrit.mot.com/2202807 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi-milanf.config | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-milanf.config b/arch/arm64/configs/vendor/ext_config/moto-holi-milanf.config index 0eee60d019e7..bf9a38672d50 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-milanf.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-milanf.config @@ -22,3 +22,8 @@ CONFIG_ZRAM_WRITEBACK=y # CONFIG_AW882XX_PARAMS_FROM_BIN is not set # CONFIG_UFSTW is not set CONFIG_CRYPTO_CHACHA20POLY1305=y + +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_MEMORY_INIT is not set +# CONFIG_LOCKUP_DETECTOR is not set +# CONFIG_SOFTLOCKUP_DETECTOR is not set From 4b7a563db6e14ac6437d61a5b98d400ec21d33c4 Mon Sep 17 00:00:00 2001 From: louhs1 Date: Tue, 1 Mar 2022 10:20:15 +0800 Subject: [PATCH 448/698] defconfig/rhode5g enable CHACHA20 crypto config enable CHACHA20 crypto config fix the CTS issue:CtsNetTestCases Change-Id: I947d6a45964c425c7e5c8522f3b97c93a72393be Signed-off-by: louhs1 Reviewed-on: https://gerrit.mot.com/2203787 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Chuanchun Zhu Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi-rhodec.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-rhodec.config b/arch/arm64/configs/vendor/ext_config/moto-holi-rhodec.config index b8ff80461d91..610de4886222 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-rhodec.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-rhodec.config @@ -22,3 +22,4 @@ CONFIG_ZRAM_WRITEBACK=y CONFIG_AF_NOISE_ELIMINATION=y CONFIG_AW882XX_STEREO_SMARTPA=y CONFIG_AW882XX_PARAMS_FROM_BIN=y +CONFIG_CRYPTO_CHACHA20POLY1305=y From 4148db0fd2ff5a642d51099388177f6ea39ef6d0 Mon Sep 17 00:00:00 2001 From: zhoujs3 Date: Mon, 28 Feb 2022 13:55:37 +0800 Subject: [PATCH 449/698] Bring up miami on sm2021 Init config for new product miami Base on rhodep Change-Id: I680b5e4d272007f0e99b98609bbd7abf0ce8b7c4 Signed-off-by: zhoujs3 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Submit-Approved: Jira Key Tested-by: Jira Key Reviewed-on: https://gerrit.mot.com/2205187 Reviewed-by: Zhenxin Xi --- .../vendor/ext_config/debug-holi-miami.config | 26 ++++++++++++++++++ .../ext_config/factory-holi-miami.config | 18 +++++++++++++ .../vendor/ext_config/moto-holi-miami.config | 27 +++++++++++++++++++ drivers/soc/qcom/Kconfig | 8 ++++++ 4 files changed, 79 insertions(+) create mode 100644 arch/arm64/configs/vendor/ext_config/debug-holi-miami.config create mode 100644 arch/arm64/configs/vendor/ext_config/factory-holi-miami.config create mode 100644 arch/arm64/configs/vendor/ext_config/moto-holi-miami.config diff --git a/arch/arm64/configs/vendor/ext_config/debug-holi-miami.config b/arch/arm64/configs/vendor/ext_config/debug-holi-miami.config new file mode 100644 index 000000000000..701c9f48cd63 --- /dev/null +++ b/arch/arm64/configs/vendor/ext_config/debug-holi-miami.config @@ -0,0 +1,26 @@ +# +# Please avoid changing the Qualcomm defconfig files and use this file to +# add any Motorola-specific configuration changes that are applicable to +# userdebug, eng, and user builds. +# +# After building, a list of all of the config files that are used can be found +# at the top of: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/mapphone_defconfig +# +# The actual output of the kernel configuration system can be found at: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/.config +# +# You can check the .config file to verify that your configuration option is +# being set as expected. +# + +# CONFIG_CGROUP_DEBUG is not set +# CONFIG_CLEANCACHE is not set +# CONFIG_CMA_ALLOW_WRITE_DEBUGFS is not set +# CONFIG_CMA_DEBUG is not set +# CONFIG_PREEMPTIRQ_EVENTS is not set +# CONFIG_PREEMPT_TRACER is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_TEST_USER_COPY is not set +CONFIG_CAMERA_FLASH_PWM=y \ No newline at end of file diff --git a/arch/arm64/configs/vendor/ext_config/factory-holi-miami.config b/arch/arm64/configs/vendor/ext_config/factory-holi-miami.config new file mode 100644 index 000000000000..1a235dd170f3 --- /dev/null +++ b/arch/arm64/configs/vendor/ext_config/factory-holi-miami.config @@ -0,0 +1,18 @@ +# +# Please avoid changing the Qualcomm defconfig files and use this file to +# add any Motorola-specific configuration changes that are applicable to +# userdebug, eng, and user builds. +# +# After building, a list of all of the config files that are used can be found +# at the top of: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/mapphone_defconfig +# +# The actual output of the kernel configuration system can be found at: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/.config +# +# You can check the .config file to verify that your configuration option is +# being set as expected. +# +CONFIG_CAMERA_FLASH_PWM=y +CONFIG_QCOM_I2C_NACK_ERR_WA=y +CONFIG_CAMERA_DISABLE_VSYNC_IRQ=y diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-miami.config b/arch/arm64/configs/vendor/ext_config/moto-holi-miami.config new file mode 100644 index 000000000000..43df38789461 --- /dev/null +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-miami.config @@ -0,0 +1,27 @@ +# +# Please avoid changing the Qualcomm defconfig files and use this file to +# add any Motorola-specific configuration changes that are applicable to +# userdebug, eng, and user builds. +# +# After building, a list of all of the config files that are used can be found +# at the top of: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/mapphone_defconfig +# +# The actual output of the kernel configuration system can be found at: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/.config +# +# You can check the .config file to verify that your configuration option is +# being set as expected. +# +CONFIG_RHODEP_DTB=y +# CONFIG_NFC_QTI_I2C is not set +CONFIG_FS_EPOLL_WAKEUP_DEBUG=y +CONFIG_ZRAM_WRITEBACK=y +# CONFIG_THERMAL_STATISTICS is not set +# CONFIG_REGULATOR_QPNP_LCDB is not set +CONFIG_AW882XX_STEREO_SMARTPA=y +CONFIG_AW882XX_PARAMS_FROM_BIN=y +# CONFIG_MICRON_UFSHID is not set +CONFIG_QUP0_SE2_AP=y +CONFIG_CAMERA_FLASH_PWM=y +CONFIG_CRYPTO_CHACHA20POLY1305=y diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index 8fa8fe46b285..72e2ebc33b54 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -102,6 +102,14 @@ config RHODEP_DTB Only include RHODEP specific DTBs to limit the number that get built during kernel compilation. +config MIAMI_DTB + depends on ARCH_QCOM + default n + bool "MIAMI DTBs" + help + Only include MIAMI specific DTBs to limit the number that + get built during kernel compilation. + config RHODEI_DTB depends on ARCH_QCOM default n From 4b2c8bda0ab19fef394f61b6a0edca2bc33f477a Mon Sep 17 00:00:00 2001 From: louhs1 Date: Mon, 28 Feb 2022 13:44:59 +0800 Subject: [PATCH 450/698] Rhodei change the kernel config from rhodec remark: change kernel config based rhodec Change-Id: Ic76a6580da2a8fbe2bc051ac5f14c04520a97cf2 Signed-off-by: louhs1 Reviewed-on: https://gerrit.mot.com/2203000 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- .../configs/vendor/ext_config/debug-holi-rhodei.config | 1 - .../configs/vendor/ext_config/factory-holi-rhodei.config | 4 +--- .../arm64/configs/vendor/ext_config/moto-holi-rhodei.config | 6 ++---- 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/arch/arm64/configs/vendor/ext_config/debug-holi-rhodei.config b/arch/arm64/configs/vendor/ext_config/debug-holi-rhodei.config index 701c9f48cd63..13f71e03c466 100644 --- a/arch/arm64/configs/vendor/ext_config/debug-holi-rhodei.config +++ b/arch/arm64/configs/vendor/ext_config/debug-holi-rhodei.config @@ -23,4 +23,3 @@ # CONFIG_PROVE_LOCKING is not set # CONFIG_RCU_TORTURE_TEST is not set # CONFIG_TEST_USER_COPY is not set -CONFIG_CAMERA_FLASH_PWM=y \ No newline at end of file diff --git a/arch/arm64/configs/vendor/ext_config/factory-holi-rhodei.config b/arch/arm64/configs/vendor/ext_config/factory-holi-rhodei.config index 1a235dd170f3..830e8a22f610 100644 --- a/arch/arm64/configs/vendor/ext_config/factory-holi-rhodei.config +++ b/arch/arm64/configs/vendor/ext_config/factory-holi-rhodei.config @@ -13,6 +13,4 @@ # You can check the .config file to verify that your configuration option is # being set as expected. # -CONFIG_CAMERA_FLASH_PWM=y -CONFIG_QCOM_I2C_NACK_ERR_WA=y -CONFIG_CAMERA_DISABLE_VSYNC_IRQ=y + diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-rhodei.config b/arch/arm64/configs/vendor/ext_config/moto-holi-rhodei.config index 6ba3b682bcc3..5380f47b7f25 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-rhodei.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-rhodei.config @@ -13,14 +13,12 @@ # You can check the .config file to verify that your configuration option is # being set as expected. # -CONFIG_RHODEP_DTB=y +CONFIG_RHODEI_DTB=y # CONFIG_NFC_QTI_I2C is not set CONFIG_FS_EPOLL_WAKEUP_DEBUG=y CONFIG_ZRAM_WRITEBACK=y # CONFIG_THERMAL_STATISTICS is not set # CONFIG_REGULATOR_QPNP_LCDB is not set +CONFIG_AF_NOISE_ELIMINATION=y CONFIG_AW882XX_STEREO_SMARTPA=y CONFIG_AW882XX_PARAMS_FROM_BIN=y -# CONFIG_MICRON_UFSHID is not set -CONFIG_QUP0_SE2_AP=y -CONFIG_CAMERA_FLASH_PWM=y \ No newline at end of file From 30f7d6785f91eb0ab505852dc0d8eab6821c30d1 Mon Sep 17 00:00:00 2001 From: Chuanchun Zhu Date: Sun, 6 Mar 2022 20:30:54 -0600 Subject: [PATCH 451/698] Revert "(CR) arm64/config: remove unnecessary configs" Mot-CRs-fixed: (CR) This reverts commit 1a13b7346498e3d6251d8f1eed2542a98d79458d. Change-Id: Ie124b37c71403889187eadbc53f79ed44afebf96 Reviewed-on: https://gerrit.mot.com/2208380 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi-milanf.config | 5 ----- 1 file changed, 5 deletions(-) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-milanf.config b/arch/arm64/configs/vendor/ext_config/moto-holi-milanf.config index bf9a38672d50..0eee60d019e7 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-milanf.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-milanf.config @@ -22,8 +22,3 @@ CONFIG_ZRAM_WRITEBACK=y # CONFIG_AW882XX_PARAMS_FROM_BIN is not set # CONFIG_UFSTW is not set CONFIG_CRYPTO_CHACHA20POLY1305=y - -# CONFIG_DEBUG_STACK_USAGE is not set -# CONFIG_DEBUG_MEMORY_INIT is not set -# CONFIG_LOCKUP_DETECTOR is not set -# CONFIG_SOFTLOCKUP_DETECTOR is not set From 114fd7f2f7ac9d9345eb0e5f4b0fd8aaeb620d00 Mon Sep 17 00:00:00 2001 From: wanggc6 Date: Thu, 10 Mar 2022 11:44:47 +0800 Subject: [PATCH 452/698] config:Disable CONFIG_QCOM_I2C_NACK_ERR_WA Disable CONFIG_QCOM_I2C_NACK_ERR_WA , because miami does not use wt6670 (deivers/i2c/busses/i2c-msm-geni.c). Change-Id: Ie7b48f925bc12e0766fbe9a36a2946e320db51d9 Signed-off-by: wanggc6 Reviewed-on: https://gerrit.mot.com/2212326 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Haijian Ma Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/factory-holi-miami.config | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm64/configs/vendor/ext_config/factory-holi-miami.config b/arch/arm64/configs/vendor/ext_config/factory-holi-miami.config index 1a235dd170f3..ebca30acfe4d 100644 --- a/arch/arm64/configs/vendor/ext_config/factory-holi-miami.config +++ b/arch/arm64/configs/vendor/ext_config/factory-holi-miami.config @@ -14,5 +14,4 @@ # being set as expected. # CONFIG_CAMERA_FLASH_PWM=y -CONFIG_QCOM_I2C_NACK_ERR_WA=y CONFIG_CAMERA_DISABLE_VSYNC_IRQ=y From c8bb17e9b8ada330fea3b62949950edfced5345a Mon Sep 17 00:00:00 2001 From: Yiqiang Feng Date: Fri, 11 Mar 2022 14:47:51 +0800 Subject: [PATCH 453/698] arm64/defconfig: remove unused novatek touch configs rhodei/defconfig: Bringup nova touchscreen,need to mask unused touch config. CONFIG_TOUCHSCREEN_NT36XXX, to avoid conflict with nova ko driver. Change-Id: I080c4bd8644ec406612dc3da931ab10cba9e6db4 Signed-off-by: Yiqiang Feng Reviewed-on: https://gerrit.mot.com/2213476 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Reviewed-by: Yeqing Wang Tested-by: Jira Key Reviewed-by: Hongshu Lou Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi-rhodei.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-rhodei.config b/arch/arm64/configs/vendor/ext_config/moto-holi-rhodei.config index 5380f47b7f25..fbc4e0a5b122 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-rhodei.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-rhodei.config @@ -22,3 +22,4 @@ CONFIG_ZRAM_WRITEBACK=y CONFIG_AF_NOISE_ELIMINATION=y CONFIG_AW882XX_STEREO_SMARTPA=y CONFIG_AW882XX_PARAMS_FROM_BIN=y +# CONFIG_TOUCHSCREEN_NT36XXX is not set From 45a4fa6351525a7627ef645dfb4f63b80481f0c2 Mon Sep 17 00:00:00 2001 From: mahj8 Date: Tue, 15 Mar 2022 11:11:03 +0800 Subject: [PATCH 454/698] arm/config: remove wt6670 ic for rhodep remove wt6670 ic for rhodep, because rhodep use sw solution. Change-Id: Ib79dd6aab13e3c9c2e68ba0591400b193c0e3b81 Signed-off-by: mahj8 Reviewed-on: https://gerrit.mot.com/2215964 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/factory-holi-rhodep.config | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm64/configs/vendor/ext_config/factory-holi-rhodep.config b/arch/arm64/configs/vendor/ext_config/factory-holi-rhodep.config index 1a235dd170f3..ebca30acfe4d 100644 --- a/arch/arm64/configs/vendor/ext_config/factory-holi-rhodep.config +++ b/arch/arm64/configs/vendor/ext_config/factory-holi-rhodep.config @@ -14,5 +14,4 @@ # being set as expected. # CONFIG_CAMERA_FLASH_PWM=y -CONFIG_QCOM_I2C_NACK_ERR_WA=y CONFIG_CAMERA_DISABLE_VSYNC_IRQ=y From e3a30068143352a733ddc289d4e3f2f624f323bb Mon Sep 17 00:00:00 2001 From: Chandana Kishori Chiluveru Date: Tue, 16 Nov 2021 19:28:44 -0800 Subject: [PATCH 455/698] serial: msm_geni_serial: Update QUP clock ON/OFF sequence This change is to update QUP clock ON/OFF sequence as per recommendations. Disable the divider before SE clk off and then enable it after SE clk ON. CRs-Fixed: 3071458 Mot-CRs-fixed: (CR) Change-Id: I5fd82be33d49de7a48159be969910097e88ab255 Signed-off-by: Chandana Kishori Chiluveru Reviewed-on: https://gerrit.mot.com/2216220 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Bin Liu Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- drivers/tty/serial/msm_geni_serial.c | 54 ++++++++++++++++++++++++---- 1 file changed, 47 insertions(+), 7 deletions(-) diff --git a/drivers/tty/serial/msm_geni_serial.c b/drivers/tty/serial/msm_geni_serial.c index 03dd04274462..5711de4c84d9 100644 --- a/drivers/tty/serial/msm_geni_serial.c +++ b/drivers/tty/serial/msm_geni_serial.c @@ -234,6 +234,7 @@ struct msm_geni_serial_port { bool pm_auto_suspend_disable; atomic_t is_clock_off; enum uart_error_code uart_error; + unsigned long ser_clk_cfg; }; static const struct uart_ops msm_geni_serial_pops; @@ -303,6 +304,28 @@ static void msm_geni_update_uart_error_code(struct msm_geni_serial_port *port, "%s: uart_error_code:%d\n", __func__, port->uart_error); } } + +/* + * The below API is used to enable and disable serial clock divider. + */ +static void msm_geni_update_se_clk_cfg(struct uart_port *uport, bool enable) +{ + struct msm_geni_serial_port *msm_port = GET_DEV_PORT(uport); + + IPC_LOG_MSG(msm_port->ipc_log_misc, "%s: enable:%d ser_clk_cfg:0x%x\n", + __func__, enable, msm_port->ser_clk_cfg); + + if (enable) { + geni_write_reg_nolog(msm_port->ser_clk_cfg, uport->membase, GENI_SER_M_CLK_CFG); + geni_write_reg_nolog(msm_port->ser_clk_cfg, uport->membase, GENI_SER_S_CLK_CFG); + geni_read_reg_nolog(uport->membase, GENI_SER_M_CLK_CFG); + } else { + geni_write_reg_nolog(0x1, uport->membase, GENI_SER_M_CLK_CFG); + geni_write_reg_nolog(0x1, uport->membase, GENI_SER_S_CLK_CFG); + geni_read_reg_nolog(uport->membase, GENI_SER_M_CLK_CFG); + } +} + /* * We are enabling the interrupts once the polling operations * is completed. @@ -2744,7 +2767,11 @@ static void msm_geni_serial_set_termios(struct uart_port *uport, clk_freq_diff, baud, clk_rate, clk_div); uport->uartclk = clk_rate; - clk_set_rate(port->serial_rsc.se_clk, clk_rate); + ret = clk_set_rate(port->serial_rsc.se_clk, clk_rate); + if (ret) { + dev_err(uport->dev, "Error setting clock rate\n"); + IPC_LOG_MSG(port->ipc_log_misc, "%s: SE clock set_rate error:%d\n", __func__, ret); + } ser_clk_cfg |= SER_CLK_EN; ser_clk_cfg |= (clk_div << CLK_DIV_SHFT); @@ -2753,10 +2780,12 @@ static void msm_geni_serial_set_termios(struct uart_port *uport, geni_write_reg_nolog(ser_clk_cfg, uport->membase, GENI_SER_M_CLK_CFG); geni_write_reg_nolog(ser_clk_cfg, uport->membase, GENI_SER_S_CLK_CFG); + port->ser_clk_cfg = ser_clk_cfg; geni_read_reg_nolog(uport->membase, GENI_SER_M_CLK_CFG); msm_geni_serial_termios_cfg(uport, termios); - IPC_LOG_MSG(port->ipc_log_misc, "%s: baud %d\n", __func__, baud); + IPC_LOG_MSG(port->ipc_log_misc, "%s: baud %d ser_clk_cfg:0x%x\n", + __func__, baud, port->ser_clk_cfg); exit_set_termios: msm_geni_serial_start_rx(uport); if (!uart_console(uport)) @@ -3016,10 +3045,12 @@ static void msm_geni_serial_cons_pm(struct uart_port *uport, if (new_state == UART_PM_STATE_ON && old_state == UART_PM_STATE_OFF) { se_geni_resources_on(&msm_port->serial_rsc); + msm_geni_update_se_clk_cfg(uport, true); atomic_set(&msm_port->is_clock_off, 0); } else if (new_state == UART_PM_STATE_OFF && old_state == UART_PM_STATE_ON) { atomic_set(&msm_port->is_clock_off, 1); + msm_geni_update_se_clk_cfg(uport, false); se_geni_resources_off(&msm_port->serial_rsc); } } @@ -3043,11 +3074,14 @@ static void msm_geni_serial_hs_pm(struct uart_port *uport, if (old_state == UART_PM_STATE_UNDEFINED) old_state = UART_PM_STATE_OFF; - if (new_state == UART_PM_STATE_ON && old_state == UART_PM_STATE_OFF) + if (new_state == UART_PM_STATE_ON && old_state == UART_PM_STATE_OFF) { se_geni_resources_on(&msm_port->serial_rsc); - else if (new_state == UART_PM_STATE_OFF && - old_state == UART_PM_STATE_ON) + msm_geni_update_se_clk_cfg(uport, true); + } else if (new_state == UART_PM_STATE_OFF && + old_state == UART_PM_STATE_ON) { + msm_geni_update_se_clk_cfg(uport, false); se_geni_resources_off(&msm_port->serial_rsc); + } } static const struct uart_ops msm_geni_console_pops = { @@ -3105,8 +3139,10 @@ static int msm_geni_serial_get_ver_info(struct uart_port *uport) struct msm_geni_serial_port *msm_port = GET_DEV_PORT(uport); /* clks_on/off only for HSUART, as console remains actve */ - if (!msm_port->is_console) + if (!msm_port->is_console) { se_geni_clks_on(&msm_port->serial_rsc); + msm_geni_update_se_clk_cfg(uport, true); + } /* Basic HW and FW info */ if (unlikely(get_se_proto(uport->membase) != UART)) { dev_err(uport->dev, "%s: Invalid FW %d loaded.\n", @@ -3136,8 +3172,10 @@ static int msm_geni_serial_get_ver_info(struct uart_port *uport) msm_geni_serial_enable_interrupts(uport); exit_ver_info: - if (!msm_port->is_console) + if (!msm_port->is_console) { + msm_geni_update_se_clk_cfg(uport, false); se_geni_clks_off(&msm_port->serial_rsc); + } return ret; } @@ -3602,6 +3640,7 @@ static int msm_geni_serial_runtime_suspend(struct device *dev) if (port->wakeup_byte && port->wakeup_irq) msm_geni_serial_allow_rx(port); + msm_geni_update_se_clk_cfg(&port->uport, false); ret = se_geni_resources_off(&port->serial_rsc); if (ret) { dev_err(dev, "%s: Error ret %d\n", __func__, ret); @@ -3646,6 +3685,7 @@ static int msm_geni_serial_runtime_resume(struct device *dev) __pm_relax(port->geni_wake); goto exit_runtime_resume; } + msm_geni_update_se_clk_cfg(&port->uport, true); start_rx_sequencer(&port->uport); /* Ensure that the Rx is running before enabling interrupts */ mb(); From 2153e67f78b2e72d1133cad6aa203f5e95a94732 Mon Sep 17 00:00:00 2001 From: louhs1 Date: Fri, 18 Mar 2022 13:44:13 +0800 Subject: [PATCH 456/698] miami: enable CONFIG_MIAMI_DTB remark: enable CONFIG_MIAMI_DTB for miami project Change-Id: I3badc03ff0b88e95a3c024e34c0b6144a238d9bc Signed-off-by: louhs1 Reviewed-on: https://gerrit.mot.com/2219968 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi-miami.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-miami.config b/arch/arm64/configs/vendor/ext_config/moto-holi-miami.config index 43df38789461..5b74a6e13271 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-miami.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-miami.config @@ -13,7 +13,7 @@ # You can check the .config file to verify that your configuration option is # being set as expected. # -CONFIG_RHODEP_DTB=y +CONFIG_MIAMI_DTB=y # CONFIG_NFC_QTI_I2C is not set CONFIG_FS_EPOLL_WAKEUP_DEBUG=y CONFIG_ZRAM_WRITEBACK=y From 1f4650c0ceac21b6d1f0afb8e08fff1a0a141198 Mon Sep 17 00:00:00 2001 From: xieqiong2 Date: Thu, 24 Mar 2022 11:07:04 +0800 Subject: [PATCH 457/698] charge:add bc12 detect channel definition. add bc12 charge type detect iio channel for bc1.2 protocol. Change-Id: I55577363ab6634547b8a4fb9244590d79c2c9ff7 Signed-off-by: xieqiong2 Reviewed-on: https://gerrit.mot.com/2224727 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Wei Xu Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- include/dt-bindings/iio/qti_power_supply_iio.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/dt-bindings/iio/qti_power_supply_iio.h b/include/dt-bindings/iio/qti_power_supply_iio.h index 5d90d48d39dd..112cf86ad924 100644 --- a/include/dt-bindings/iio/qti_power_supply_iio.h +++ b/include/dt-bindings/iio/qti_power_supply_iio.h @@ -179,4 +179,6 @@ #define PSY_IIO_QC3P_START_POLICY 0x111 #define PSY_IIO_QC3P_FIRMWARE_NUM 0x112 #define PSY_IIO_USB_TERMINATION_ENABLED 0x113 +#define PSY_IIO_START_BC12_DETECTION 0x114 +#define PSY_IIO_DETECTION_BC12_READY 0x115 #endif /* __QTI_POWER_SUPPLY_IIO_H__ */ From 49dcf205a6f0c63bbccc96fbe608e256f86afea0 Mon Sep 17 00:00:00 2001 From: chenlj26 Date: Thu, 17 Mar 2022 14:09:08 +0800 Subject: [PATCH 458/698] camera-kernel: miami: add miami config for front camera -add CONFIG_CAMERA_CCI_ADDR_SWITCH Change-Id: I8f351b15baeba582da115432739600ae722dd007 Signed-off-by: chenlj26 Reviewed-on: https://gerrit.mot.com/2218762 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Reviewed-by: Wang Liu Tested-by: Jira Key Reviewed-by: Shuo Wang Reviewed-by: Long Cheng Reviewed-by: Zhichao Chen Reviewed-by: Guobin Zhang Submit-Approved: Jira Key --- arch/arm64/Kconfig | 6 ++++++ arch/arm64/configs/vendor/ext_config/moto-holi-miami.config | 1 + 2 files changed, 7 insertions(+) diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 8b50654e0e29..e3872d311e40 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -1897,3 +1897,9 @@ config CAMERA_DISABLE_VSYNC_IRQ default n help Enable it to disable cam vsync irq. + +config CAMERA_CCI_ADDR_SWITCH + bool "For cam switch i2c address" + default n + help +Enable it to switch i2c address. \ No newline at end of file diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-miami.config b/arch/arm64/configs/vendor/ext_config/moto-holi-miami.config index 5b74a6e13271..3d5e0c1ed0b6 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-miami.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-miami.config @@ -25,3 +25,4 @@ CONFIG_AW882XX_PARAMS_FROM_BIN=y CONFIG_QUP0_SE2_AP=y CONFIG_CAMERA_FLASH_PWM=y CONFIG_CRYPTO_CHACHA20POLY1305=y +CONFIG_CAMERA_CCI_ADDR_SWITCH=y \ No newline at end of file From af15f14fb044798145abee376b16dcffa41935d3 Mon Sep 17 00:00:00 2001 From: xieqiong2 Date: Tue, 29 Mar 2022 17:03:01 +0800 Subject: [PATCH 459/698] power:add read usbin iio channel. Add the iio channel to read usbin voltage from charger protocol IC. Change-Id: Ifa1ac9eba4abb351387e0b1d54e283ac5fa73c38 Signed-off-by: xieqiong2 Reviewed-on: https://gerrit.mot.com/2228543 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Wei Xu Reviewed-by: Haijian Ma Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- include/dt-bindings/iio/qti_power_supply_iio.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/dt-bindings/iio/qti_power_supply_iio.h b/include/dt-bindings/iio/qti_power_supply_iio.h index 112cf86ad924..3da3be148931 100644 --- a/include/dt-bindings/iio/qti_power_supply_iio.h +++ b/include/dt-bindings/iio/qti_power_supply_iio.h @@ -181,4 +181,5 @@ #define PSY_IIO_USB_TERMINATION_ENABLED 0x113 #define PSY_IIO_START_BC12_DETECTION 0x114 #define PSY_IIO_DETECTION_BC12_READY 0x115 +#define PSY_IIO_READ_USBIN_VOLTAGE 0x116 #endif /* __QTI_POWER_SUPPLY_IIO_H__ */ From e09793dbe3a3e024ccc6a073b1aad8cdc75171f7 Mon Sep 17 00:00:00 2001 From: chenlj26 Date: Wed, 30 Mar 2022 07:28:03 -0500 Subject: [PATCH 460/698] Revert "(CR): camera-kernel: miami: add miami config for front camera" This reverts commit aefc1ffdaecc61c26bf03f4e61d2854611af31fe. Change-Id: I5059d5748cc88f156a68e798531f4629bfb66510 Reviewed-on: https://gerrit.mot.com/2229683 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Zhichao Chen Reviewed-by: Guobin Zhang Submit-Approved: Jira Key --- arch/arm64/Kconfig | 6 ------ arch/arm64/configs/vendor/ext_config/moto-holi-miami.config | 1 - 2 files changed, 7 deletions(-) diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index e3872d311e40..8b50654e0e29 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -1897,9 +1897,3 @@ config CAMERA_DISABLE_VSYNC_IRQ default n help Enable it to disable cam vsync irq. - -config CAMERA_CCI_ADDR_SWITCH - bool "For cam switch i2c address" - default n - help -Enable it to switch i2c address. \ No newline at end of file diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-miami.config b/arch/arm64/configs/vendor/ext_config/moto-holi-miami.config index 3d5e0c1ed0b6..5b74a6e13271 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-miami.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-miami.config @@ -25,4 +25,3 @@ CONFIG_AW882XX_PARAMS_FROM_BIN=y CONFIG_QUP0_SE2_AP=y CONFIG_CAMERA_FLASH_PWM=y CONFIG_CRYPTO_CHACHA20POLY1305=y -CONFIG_CAMERA_CCI_ADDR_SWITCH=y \ No newline at end of file From 58d21ba28ab4b22aa8b797c1cc013d042d9cd9e7 Mon Sep 17 00:00:00 2001 From: hansx3 Date: Mon, 28 Mar 2022 18:19:33 +0800 Subject: [PATCH 461/698] rhodei: Separate QUPAC configuration for rhodei TZ protect gpio45,46,56,57 for NFC SPI, but the four of them are used for camera sensor power supply. So we need to configure the QUPAC for TZ gpio protection removement. Change-Id: Idab704e62bcab80259d9e9495e4d4431dc2e6a9c Signed-off-by: hansx3 Reviewed-on: https://gerrit.mot.com/2227603 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Reviewed-by: XiaoFeng Wang Reviewed-by: Zhichao Chen Reviewed-by: Huosheng Liao Tested-by: Jira Key Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi-rhodei.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-rhodei.config b/arch/arm64/configs/vendor/ext_config/moto-holi-rhodei.config index fbc4e0a5b122..43ca144e22d4 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-rhodei.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-rhodei.config @@ -23,3 +23,4 @@ CONFIG_AF_NOISE_ELIMINATION=y CONFIG_AW882XX_STEREO_SMARTPA=y CONFIG_AW882XX_PARAMS_FROM_BIN=y # CONFIG_TOUCHSCREEN_NT36XXX is not set +CONFIG_QUP0_SE2_AP=y From 9b3f7b1f51aa2547b1fdf3df1ce420a7c1afe0c5 Mon Sep 17 00:00:00 2001 From: zhucc2 Date: Fri, 1 Apr 2022 20:02:23 +0800 Subject: [PATCH 462/698] arm64/config: disable SamSung TW and switch to WB On Android S, SamSung TW performance is abnormal, after write about 30GB data continually, the sequent write performance will drop from 450MB/s to 200MB/s. After switch to WB, the sequent write speed will keep 450MB/s. Change-Id: I9833411a5f0acb37c33b45fa4fb9de39fbe5f27e Reviewed-on: https://gerrit.mot.com/2232146 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/debug-holi-rhodep.config | 3 ++- arch/arm64/configs/vendor/ext_config/moto-holi-rhodep.config | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/arm64/configs/vendor/ext_config/debug-holi-rhodep.config b/arch/arm64/configs/vendor/ext_config/debug-holi-rhodep.config index 701c9f48cd63..f6674734aa68 100644 --- a/arch/arm64/configs/vendor/ext_config/debug-holi-rhodep.config +++ b/arch/arm64/configs/vendor/ext_config/debug-holi-rhodep.config @@ -23,4 +23,5 @@ # CONFIG_PROVE_LOCKING is not set # CONFIG_RCU_TORTURE_TEST is not set # CONFIG_TEST_USER_COPY is not set -CONFIG_CAMERA_FLASH_PWM=y \ No newline at end of file +CONFIG_CAMERA_FLASH_PWM=y +# CONFIG_UFSTW is not set diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-rhodep.config b/arch/arm64/configs/vendor/ext_config/moto-holi-rhodep.config index 43df38789461..11e135ebb908 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-rhodep.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-rhodep.config @@ -25,3 +25,4 @@ CONFIG_AW882XX_PARAMS_FROM_BIN=y CONFIG_QUP0_SE2_AP=y CONFIG_CAMERA_FLASH_PWM=y CONFIG_CRYPTO_CHACHA20POLY1305=y +# CONFIG_UFSTW is not set From 3777eba3b1dc4d691d8d23d3f963da56a95c2253 Mon Sep 17 00:00:00 2001 From: gaoyx9 Date: Wed, 6 Apr 2022 17:32:17 +0800 Subject: [PATCH 463/698] Revert "UPSTREAM: binder: fix the missing BR_FROZEN_REPLY in binder_return_strings" This reverts commit a4e84758f02959df24c67e0aabcefd42079c2d01. Change-Id: Ibe3b8e21f0d42086816e0cd18b08e42457414b1c Reviewed-on: https://gerrit.mot.com/2235002 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Submit-Approved: Jira Key Tested-by: Jira Key Reviewed-by: Lianlu Chen Reviewed-by: Xiaojun Ji --- drivers/android/binder.c | 3 +-- drivers/android/binder_internal.h | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/android/binder.c b/drivers/android/binder.c index 6e82ec9bdd69..5c9b17e41fc2 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -5969,8 +5969,7 @@ static const char * const binder_return_strings[] = { "BR_FINISHED", "BR_DEAD_BINDER", "BR_CLEAR_DEATH_NOTIFICATION_DONE", - "BR_FAILED_REPLY", - "BR_FROZEN_REPLY", + "BR_FAILED_REPLY" }; static const char * const binder_command_strings[] = { diff --git a/drivers/android/binder_internal.h b/drivers/android/binder_internal.h index 8af81a24b83d..68f4d7b5e7f3 100644 --- a/drivers/android/binder_internal.h +++ b/drivers/android/binder_internal.h @@ -155,7 +155,7 @@ enum binder_stat_types { }; struct binder_stats { - atomic_t br[_IOC_NR(BR_FROZEN_REPLY) + 1]; + atomic_t br[_IOC_NR(BR_FAILED_REPLY) + 1]; atomic_t bc[_IOC_NR(BC_REPLY_SG) + 1]; atomic_t obj_created[BINDER_STAT_COUNT]; atomic_t obj_deleted[BINDER_STAT_COUNT]; From 48d7fc4374efd7e00197a5512ff41f1a93022602 Mon Sep 17 00:00:00 2001 From: zhouwl Date: Wed, 6 Apr 2022 09:39:24 +0800 Subject: [PATCH 464/698] fsa4480: change io-channel-names Due to dtsi property name need to change according to iio-channels usage, change this name: typec_accessory_mode -> typec_accessory_mode. Change-Id: I67c220b7b34257bd74ee7536662fddfb7f71883b Signed-off-by: zhouwl Reviewed-on: https://gerrit.mot.com/2234591 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Lu Chai Reviewed-by: Hujun Liao Submit-Approved: Jira Key --- drivers/soc/qcom/fsa4480-i2c.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/soc/qcom/fsa4480-i2c.c b/drivers/soc/qcom/fsa4480-i2c.c index e263d671dc6c..a466133ac866 100644 --- a/drivers/soc/qcom/fsa4480-i2c.c +++ b/drivers/soc/qcom/fsa4480-i2c.c @@ -494,10 +494,10 @@ static int fsa4480_probe(struct i2c_client *i2c, goto err_data; } - fsa_priv->iio_ch = iio_channel_get(fsa_priv->dev, "typec_mode"); + fsa_priv->iio_ch = iio_channel_get(fsa_priv->dev, "typec_accessory_mode"); if (!fsa_priv->iio_ch) { dev_err(fsa_priv->dev, - "%s: iio_channel_get failed for typec_mode\n", + "%s: iio_channel_get failed for typec_accessory_mode\n", __func__); goto err_supply; } From 5935a56005eb902761172755a4dd9519e15f8074 Mon Sep 17 00:00:00 2001 From: chenlj26 Date: Wed, 13 Apr 2022 12:39:07 +0800 Subject: [PATCH 465/698] camera-kernel: sm6375/sm4350pro/sm4350: prevent read sensor id failure -add CONFIG_CAM_SENSOR_PROBE_RETRY to increase times of sensor id matching -relate product: corfu 5G/cyprus 5G/Cyprus 5G ip68/denver/ibiza-cmcc-extra /ibiza/miami/rhode 5G/rhode 5G India/rhode 5G+ Change-Id: I94621d96c39413f25d2dc68ba226fb43c99f35ce Signed-off-by: chenlj26 Reviewed-on: https://gerrit.mot.com/2240810 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Wang Liu Reviewed-by: Pengfei Qiao Reviewed-by: Reviewed-by: Zhichao Chen Reviewed-by: Zhuoran Xu Reviewed-by: Long Cheng Reviewed-by: Guobin Zhang Submit-Approved: Jira Key --- arch/arm64/Kconfig | 6 ++++++ .../arm64/configs/vendor/ext_config/moto-holi-corfur.config | 1 + arch/arm64/configs/vendor/ext_config/moto-holi-cypfq.config | 1 + arch/arm64/configs/vendor/ext_config/moto-holi-cypfr.config | 3 ++- .../arm64/configs/vendor/ext_config/moto-holi-denver.config | 1 + .../vendor/ext_config/moto-holi-ibiza-cmcc-extra.config | 1 + arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config | 1 + arch/arm64/configs/vendor/ext_config/moto-holi-miami.config | 1 + .../arm64/configs/vendor/ext_config/moto-holi-milanf.config | 1 + .../arm64/configs/vendor/ext_config/moto-holi-rhodec.config | 1 + .../arm64/configs/vendor/ext_config/moto-holi-rhodei.config | 1 + .../arm64/configs/vendor/ext_config/moto-holi-rhodep.config | 1 + 12 files changed, 18 insertions(+), 1 deletion(-) diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 8b50654e0e29..9735e490394c 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -1897,3 +1897,9 @@ config CAMERA_DISABLE_VSYNC_IRQ default n help Enable it to disable cam vsync irq. + +config CAM_SENSOR_PROBE_RETRY + bool "For sensor probe fail" + default n + help + Add retries for sensor id matching diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-corfur.config b/arch/arm64/configs/vendor/ext_config/moto-holi-corfur.config index 19b89fafefc0..b556bd07998d 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-corfur.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-corfur.config @@ -23,3 +23,4 @@ CONFIG_ZRAM_WRITEBACK=y CONFIG_AF_NOISE_ELIMINATION=y # CONFIG_TOUCHSCREEN_NT36XXX is not set # CONFIG_MICRON_UFSHID is not set +CONFIG_CAM_SENSOR_PROBE_RETRY=y diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-cypfq.config b/arch/arm64/configs/vendor/ext_config/moto-holi-cypfq.config index 4997380fc123..e8fab4e7c8b8 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-cypfq.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-cypfq.config @@ -21,3 +21,4 @@ CONFIG_ZRAM_WRITEBACK=y # CONFIG_REGULATOR_QPNP_LCDB is not set CONFIG_AF_NOISE_ELIMINATION=y # CONFIG_MICRON_UFSHID is not set +CONFIG_CAM_SENSOR_PROBE_RETRY=y diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-cypfr.config b/arch/arm64/configs/vendor/ext_config/moto-holi-cypfr.config index eb9f90b11d29..393c195abb51 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-cypfr.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-cypfr.config @@ -20,4 +20,5 @@ CONFIG_ZRAM_WRITEBACK=y # CONFIG_THERMAL_STATISTICS is not set CONFIG_AF_NOISE_ELIMINATION=y # CONFIG_MICRON_UFSHID is not set -CONFIG_FELICA_MOUNT_BLOCK=y \ No newline at end of file +CONFIG_FELICA_MOUNT_BLOCK=y +CONFIG_CAM_SENSOR_PROBE_RETRY=y \ No newline at end of file diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-denver.config b/arch/arm64/configs/vendor/ext_config/moto-holi-denver.config index 28291d3130d9..65d13ff498cc 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-denver.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-denver.config @@ -32,3 +32,4 @@ CONFIG_ZRAM_WRITEBACK=y # CONFIG_SCSI_SKHID is not set # CONFIG_MICRON_UFSHID is not set CONFIG_HZ_300=y +CONFIG_CAM_SENSOR_PROBE_RETRY=y diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza-cmcc-extra.config b/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza-cmcc-extra.config index 1c648ce6d55e..8bef06574d05 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza-cmcc-extra.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza-cmcc-extra.config @@ -3,3 +3,4 @@ CONFIG_ZRAM_WRITEBACK=y # CONFIG_UFSHID_POC is not set # CONFIG_SCSI_SKHID is not set # CONFIG_MICRON_UFSHID is not set +CONFIG_CAM_SENSOR_PROBE_RETRY=y diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config b/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config index e42aa2c2c499..8e110f97c053 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config @@ -31,3 +31,4 @@ CONFIG_ZRAM_WRITEBACK=y # CONFIG_MICRON_UFSHID is not set CONFIG_HZ_300=y CONFIG_PROCESS_RECLAIM=n +CONFIG_CAM_SENSOR_PROBE_RETRY=y diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-miami.config b/arch/arm64/configs/vendor/ext_config/moto-holi-miami.config index 5b74a6e13271..4f16766bd539 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-miami.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-miami.config @@ -25,3 +25,4 @@ CONFIG_AW882XX_PARAMS_FROM_BIN=y CONFIG_QUP0_SE2_AP=y CONFIG_CAMERA_FLASH_PWM=y CONFIG_CRYPTO_CHACHA20POLY1305=y +CONFIG_CAM_SENSOR_PROBE_RETRY=y diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-milanf.config b/arch/arm64/configs/vendor/ext_config/moto-holi-milanf.config index 0eee60d019e7..1b765d98d027 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-milanf.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-milanf.config @@ -22,3 +22,4 @@ CONFIG_ZRAM_WRITEBACK=y # CONFIG_AW882XX_PARAMS_FROM_BIN is not set # CONFIG_UFSTW is not set CONFIG_CRYPTO_CHACHA20POLY1305=y +CONFIG_CAM_SENSOR_PROBE_RETRY=y diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-rhodec.config b/arch/arm64/configs/vendor/ext_config/moto-holi-rhodec.config index 610de4886222..e31f185d35eb 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-rhodec.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-rhodec.config @@ -23,3 +23,4 @@ CONFIG_AF_NOISE_ELIMINATION=y CONFIG_AW882XX_STEREO_SMARTPA=y CONFIG_AW882XX_PARAMS_FROM_BIN=y CONFIG_CRYPTO_CHACHA20POLY1305=y +CONFIG_CAM_SENSOR_PROBE_RETRY=y diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-rhodei.config b/arch/arm64/configs/vendor/ext_config/moto-holi-rhodei.config index 43ca144e22d4..08fe4048a3ca 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-rhodei.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-rhodei.config @@ -24,3 +24,4 @@ CONFIG_AW882XX_STEREO_SMARTPA=y CONFIG_AW882XX_PARAMS_FROM_BIN=y # CONFIG_TOUCHSCREEN_NT36XXX is not set CONFIG_QUP0_SE2_AP=y +CONFIG_CAM_SENSOR_PROBE_RETRY=y diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-rhodep.config b/arch/arm64/configs/vendor/ext_config/moto-holi-rhodep.config index 11e135ebb908..51a7a99aa3c7 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-rhodep.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-rhodep.config @@ -26,3 +26,4 @@ CONFIG_QUP0_SE2_AP=y CONFIG_CAMERA_FLASH_PWM=y CONFIG_CRYPTO_CHACHA20POLY1305=y # CONFIG_UFSTW is not set +CONFIG_CAM_SENSOR_PROBE_RETRY=y From 5f1f1dd22344b1ccfba96aa3c01670905cc0d572 Mon Sep 17 00:00:00 2001 From: mahj8 Date: Wed, 13 Apr 2022 17:58:49 +0800 Subject: [PATCH 466/698] kernel: export some api for user version build As user version build error, so export some api for miami Change-Id: Icec594c6bde56e47baad6e482f486f8987761110 Signed-off-by: mahj8 Reviewed-on: https://gerrit.mot.com/2241288 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- android/abi_gki_aarch64_qcom | 3 +++ 1 file changed, 3 insertions(+) diff --git a/android/abi_gki_aarch64_qcom b/android/abi_gki_aarch64_qcom index e5c083e1bc2f..2009f6390cd2 100644 --- a/android/abi_gki_aarch64_qcom +++ b/android/abi_gki_aarch64_qcom @@ -1732,6 +1732,7 @@ param_get_int param_get_string param_get_ullong + param_get_uint param_ops_bool param_ops_byte param_ops_charp @@ -1744,6 +1745,7 @@ param_set_bool param_set_copystring param_set_int + param_set_uint passthru_features_check path_get path_put @@ -3000,6 +3002,7 @@ __wake_up_locked wake_up_process wakeup_source_add + wakeup_source_create wakeup_source_remove wakeup_source_register wakeup_source_unregister From 480c466493f949d2ed7dd2bff20833e47465cf51 Mon Sep 17 00:00:00 2001 From: sunyue5 Date: Sun, 17 Apr 2022 19:40:01 +0800 Subject: [PATCH 467/698] abi: Fix wlan module build error in GKI build qca_cld3_xxx.ko compile failure when make user build add whitelist ERROR: "init_task" [../../vendor/qcom/opensource/wlan/qcacld-3.0/.qca6390/wlan.ko] undefined! ERROR: "sock_from_file" [../../vendor/qcom/opensource/wlan/qcacld-3.0/.qca6390/wlan.ko] undefined! Change-Id: Icb2c09bf24325d243939bec6c69a9ca36abce4c8 Signed-off-by: sunyue5 Reviewed-on: https://gerrit.mot.com/2244333 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key (cherry picked from commit c284adb02295bb3957431144862ae19c96420a1e) Reviewed-on: https://gerrit.mot.com/2244347 Reviewed-by: Huosheng Liao --- android/abi_gki_aarch64_qcom | 2 ++ 1 file changed, 2 insertions(+) diff --git a/android/abi_gki_aarch64_qcom b/android/abi_gki_aarch64_qcom index 2009f6390cd2..cc85b5f663cd 100644 --- a/android/abi_gki_aarch64_qcom +++ b/android/abi_gki_aarch64_qcom @@ -1190,6 +1190,7 @@ in_group_p __init_rwsem init_srcu_struct + init_task init_timer_key init_uts_ns init_wait_entry @@ -2423,6 +2424,7 @@ sock_diag_save_cookie sock_diag_unregister sock_efree + sock_from_file sock_gettstamp sock_i_ino sock_init_data From 1fe500f6a47b749121c27e2c43fc1228ddb4f005 Mon Sep 17 00:00:00 2001 From: sunyue5 Date: Mon, 18 Apr 2022 17:37:35 +0800 Subject: [PATCH 468/698] remove "sock_from_file" symbol from qc white list As this symbol has still not been supported in the lastest GKI abi symbol manifest file, we have to implement this function by ourselves Change-Id: I1d898e0d3082815722c42d58ad22acf832379cbf Signed-off-by: sunyue5 Reviewed-on: https://gerrit.mot.com/2245023 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Daniel Finimundi Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key (cherry picked from commit 765bedbc5102b33d1f11a59b949b5f43d11e5172) Reviewed-on: https://gerrit.mot.com/2246086 Reviewed-by: Bin Liu Reviewed-by: Yue Sun Reviewed-by: Hujun Liao --- android/abi_gki_aarch64_qcom | 1 - 1 file changed, 1 deletion(-) diff --git a/android/abi_gki_aarch64_qcom b/android/abi_gki_aarch64_qcom index cc85b5f663cd..a0f66bbb8ad9 100644 --- a/android/abi_gki_aarch64_qcom +++ b/android/abi_gki_aarch64_qcom @@ -2424,7 +2424,6 @@ sock_diag_save_cookie sock_diag_unregister sock_efree - sock_from_file sock_gettstamp sock_i_ino sock_init_data From 614f40bfb82d595ec6e48801e9e90e3109d63208 Mon Sep 17 00:00:00 2001 From: chenlj26 Date: Tue, 19 Apr 2022 18:32:53 +0800 Subject: [PATCH 469/698] camera-kernel: miami: front camera ov32c4c and ov32b40 compatible details: add kernel macro CONFIG_CAMERA_CCI_ADDR_SWITCH=y for ov32c4c used front camera ov32c4c and ov32b40 compatible front camera ov32c4c bring up on 8350 baseline Change-Id: I92e2706e59edcf7914513d23ba774340e2024d3f Signed-off-by: chenlj26 Reviewed-on: https://gerrit.mot.com/2246391 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Wang Liu Reviewed-by: Shuo Wang Reviewed-by: Long Cheng Reviewed-by: Zhichao Chen Reviewed-by: Guobin Zhang Submit-Approved: Jira Key --- arch/arm64/Kconfig | 6 ++++++ arch/arm64/configs/vendor/ext_config/moto-holi-miami.config | 1 + 2 files changed, 7 insertions(+) diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 9735e490394c..0093666e1834 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -1903,3 +1903,9 @@ config CAM_SENSOR_PROBE_RETRY default n help Add retries for sensor id matching + +config CAMERA_CCI_ADDR_SWITCH + bool "For cam switch i2c address" + default n + help + Enable it to switch i2c address. \ No newline at end of file diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-miami.config b/arch/arm64/configs/vendor/ext_config/moto-holi-miami.config index 4f16766bd539..760c829d4879 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-miami.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-miami.config @@ -26,3 +26,4 @@ CONFIG_QUP0_SE2_AP=y CONFIG_CAMERA_FLASH_PWM=y CONFIG_CRYPTO_CHACHA20POLY1305=y CONFIG_CAM_SENSOR_PROBE_RETRY=y +CONFIG_CAMERA_CCI_ADDR_SWITCH=y \ No newline at end of file From 9cc8a19a740c213e63c1610cc186db5d063f81b9 Mon Sep 17 00:00:00 2001 From: zhucc2 Date: Sun, 24 Apr 2022 09:26:21 +0800 Subject: [PATCH 470/698] arm64/config: disable SamSung TW and switch to WB On Android S, SamSung TW performance is abnormal, after write about 30GB data continually, the sequent write performance will drop from 450MB/s to 200MB/s. After switch to WB, the sequent write speed will keep 450MB/s. Change-Id: Ib0eec3aa3d737b740fb6691c408ba98422affad0 Reviewed-on: https://gerrit.mot.com/2251000 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/debug-holi-miami.config | 3 ++- arch/arm64/configs/vendor/ext_config/moto-holi-miami.config | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/arm64/configs/vendor/ext_config/debug-holi-miami.config b/arch/arm64/configs/vendor/ext_config/debug-holi-miami.config index 701c9f48cd63..f6674734aa68 100644 --- a/arch/arm64/configs/vendor/ext_config/debug-holi-miami.config +++ b/arch/arm64/configs/vendor/ext_config/debug-holi-miami.config @@ -23,4 +23,5 @@ # CONFIG_PROVE_LOCKING is not set # CONFIG_RCU_TORTURE_TEST is not set # CONFIG_TEST_USER_COPY is not set -CONFIG_CAMERA_FLASH_PWM=y \ No newline at end of file +CONFIG_CAMERA_FLASH_PWM=y +# CONFIG_UFSTW is not set diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-miami.config b/arch/arm64/configs/vendor/ext_config/moto-holi-miami.config index 760c829d4879..9f6c87aacbfe 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-miami.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-miami.config @@ -22,8 +22,9 @@ CONFIG_ZRAM_WRITEBACK=y CONFIG_AW882XX_STEREO_SMARTPA=y CONFIG_AW882XX_PARAMS_FROM_BIN=y # CONFIG_MICRON_UFSHID is not set +# CONFIG_UFSTW is not set CONFIG_QUP0_SE2_AP=y CONFIG_CAMERA_FLASH_PWM=y CONFIG_CRYPTO_CHACHA20POLY1305=y CONFIG_CAM_SENSOR_PROBE_RETRY=y -CONFIG_CAMERA_CCI_ADDR_SWITCH=y \ No newline at end of file +CONFIG_CAMERA_CCI_ADDR_SWITCH=y From d18b44a46b2f3095fb715a6ae77e0d9ea53bf318 Mon Sep 17 00:00:00 2001 From: zhucc2 Date: Sun, 24 Apr 2022 09:35:50 +0800 Subject: [PATCH 471/698] arm64/config: enable Micron HID on miami. Miami have two Micron umcp, need enable HID function. 1.MT128GAXAU2U227Y 8+128 2.MT256GAXAU4U2281 8+256 Change-Id: Ic52a1f832e102c8870f5c4cd4b3351f6d7a901f0 Reviewed-on: https://gerrit.mot.com/2251006 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi-miami.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-miami.config b/arch/arm64/configs/vendor/ext_config/moto-holi-miami.config index 9f6c87aacbfe..2b99adf2b709 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-miami.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-miami.config @@ -21,7 +21,7 @@ CONFIG_ZRAM_WRITEBACK=y # CONFIG_REGULATOR_QPNP_LCDB is not set CONFIG_AW882XX_STEREO_SMARTPA=y CONFIG_AW882XX_PARAMS_FROM_BIN=y -# CONFIG_MICRON_UFSHID is not set +CONFIG_MICRON_UFSHID=y # CONFIG_UFSTW is not set CONFIG_QUP0_SE2_AP=y CONFIG_CAMERA_FLASH_PWM=y From f782bfe0979ba2135019aac6f33650455fe0719c Mon Sep 17 00:00:00 2001 From: mahj8 Date: Thu, 5 May 2022 12:46:58 +0800 Subject: [PATCH 472/698] kernel: add PD VDM VERIFY IIO channel add PD VDM VERIFY IIO channel for moto protocol verify Change-Id: Ieee4f7a4ae8d2f97ac7b08a7a96a126b5f191e77 Signed-off-by: mahj8 Reviewed-on: https://gerrit.mot.com/2259795 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- include/dt-bindings/iio/qti_power_supply_iio.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/dt-bindings/iio/qti_power_supply_iio.h b/include/dt-bindings/iio/qti_power_supply_iio.h index 3da3be148931..d93caa02a9d1 100644 --- a/include/dt-bindings/iio/qti_power_supply_iio.h +++ b/include/dt-bindings/iio/qti_power_supply_iio.h @@ -182,4 +182,6 @@ #define PSY_IIO_START_BC12_DETECTION 0x114 #define PSY_IIO_DETECTION_BC12_READY 0x115 #define PSY_IIO_READ_USBIN_VOLTAGE 0x116 + +#define PSY_IIO_MMI_PD_VDM_VERIFY 0x117 #endif /* __QTI_POWER_SUPPLY_IIO_H__ */ From 2bea5829da31bbaf3534a4ab3dc1e6982e27a46f Mon Sep 17 00:00:00 2001 From: xieqiong2 Date: Thu, 19 May 2022 14:57:11 +0800 Subject: [PATCH 473/698] iio:add bc12 type read iio. add bc12 type read iio seperately Change-Id: I72d0028ce0c58422671b5d6b5dc05f121df38752 Signed-off-by: xieqiong2 Reviewed-on: https://gerrit.mot.com/2273525 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Haijian Ma Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- include/dt-bindings/iio/qti_power_supply_iio.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/dt-bindings/iio/qti_power_supply_iio.h b/include/dt-bindings/iio/qti_power_supply_iio.h index d93caa02a9d1..bd20db8144cd 100644 --- a/include/dt-bindings/iio/qti_power_supply_iio.h +++ b/include/dt-bindings/iio/qti_power_supply_iio.h @@ -184,4 +184,5 @@ #define PSY_IIO_READ_USBIN_VOLTAGE 0x116 #define PSY_IIO_MMI_PD_VDM_VERIFY 0x117 +#define PSY_IIO_BC12_CHG_TYPE 0x118 #endif /* __QTI_POWER_SUPPLY_IIO_H__ */ From 143da9c58fb93ec66dbaa0fc3903d4b8dde4613c Mon Sep 17 00:00:00 2001 From: liaohj Date: Sat, 7 May 2022 14:22:57 +0800 Subject: [PATCH 474/698] configs/rhodep: config aw882xx mapsize 16k after aw882xx algo update to support get algo params from ram. need enlarge afe mapsize to 16k. Change-Id: I7079aaf7a2d239c90ce99d035f2d870e8b376ad7 Signed-off-by: liaohj Reviewed-on: https://gerrit.mot.com/2262544 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Wanlong Zhou Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- arch/arm64/Kconfig | 10 ++++++++-- .../configs/vendor/ext_config/moto-holi-rhodep.config | 1 + 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 0093666e1834..b0c563287c76 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -1884,7 +1884,13 @@ config AW882XX_STEREO_SMARTPA bool "aw dual smart pa" default n help - Enable it only for params of smartPA is stored in bin file. + Enable it only for dual smart pa. + +config AW882XX_MAPSIZE_16K + bool "aw afe mapsize 16k" + default n + help + Enable it only for use 16k mapsize. config CAMERA_FLASH_PWM bool "control flash" @@ -1908,4 +1914,4 @@ config CAMERA_CCI_ADDR_SWITCH bool "For cam switch i2c address" default n help - Enable it to switch i2c address. \ No newline at end of file + Enable it to switch i2c address. diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-rhodep.config b/arch/arm64/configs/vendor/ext_config/moto-holi-rhodep.config index 51a7a99aa3c7..8ad3bb171e47 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-rhodep.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-rhodep.config @@ -21,6 +21,7 @@ CONFIG_ZRAM_WRITEBACK=y # CONFIG_REGULATOR_QPNP_LCDB is not set CONFIG_AW882XX_STEREO_SMARTPA=y CONFIG_AW882XX_PARAMS_FROM_BIN=y +CONFIG_AW882XX_MAPSIZE_16K=y # CONFIG_MICRON_UFSHID is not set CONFIG_QUP0_SE2_AP=y CONFIG_CAMERA_FLASH_PWM=y From 91f373827697e65e2348c85c57688e854388e9b3 Mon Sep 17 00:00:00 2001 From: caoqian4 Date: Wed, 8 Jun 2022 16:06:40 +0800 Subject: [PATCH 475/698] configs: vendor/ext_config: init configuration for Penang to pass build Init config for new product penang Base on milanf Change-Id: I410d125be762d36c9947c83b6cba91eea194fd95 Signed-off-by: caoqian4 Reviewed-on: https://gerrit.mot.com/2291641 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao --- .../ext_config/debug-holi-penang.config | 26 +++++++++++++++++++ .../ext_config/factory-holi-penang.config | 16 ++++++++++++ .../vendor/ext_config/moto-holi-penang.config | 25 ++++++++++++++++++ drivers/soc/qcom/Kconfig | 8 ++++++ 4 files changed, 75 insertions(+) create mode 100644 arch/arm64/configs/vendor/ext_config/debug-holi-penang.config create mode 100644 arch/arm64/configs/vendor/ext_config/factory-holi-penang.config create mode 100644 arch/arm64/configs/vendor/ext_config/moto-holi-penang.config diff --git a/arch/arm64/configs/vendor/ext_config/debug-holi-penang.config b/arch/arm64/configs/vendor/ext_config/debug-holi-penang.config new file mode 100644 index 000000000000..018b945c19d3 --- /dev/null +++ b/arch/arm64/configs/vendor/ext_config/debug-holi-penang.config @@ -0,0 +1,26 @@ +# +# Please avoid changing the Qualcomm defconfig files and use this file to +# add any Motorola-specific configuration changes that are applicable to +# userdebug, eng, and user builds. +# +# After building, a list of all of the config files that are used can be found +# at the top of: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/mapphone_defconfig +# +# The actual output of the kernel configuration system can be found at: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/.config +# +# You can check the .config file to verify that your configuration option is +# being set as expected. +# + +# CONFIG_CGROUP_DEBUG is not set +# CONFIG_CLEANCACHE is not set +# CONFIG_CMA_ALLOW_WRITE_DEBUGFS is not set +# CONFIG_CMA_DEBUG is not set +# CONFIG_PREEMPTIRQ_EVENTS is not set +# CONFIG_PREEMPT_TRACER is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_TEST_USER_COPY is not set +# CONFIG_UFSTW is not set diff --git a/arch/arm64/configs/vendor/ext_config/factory-holi-penang.config b/arch/arm64/configs/vendor/ext_config/factory-holi-penang.config new file mode 100644 index 000000000000..cc7be9152bdd --- /dev/null +++ b/arch/arm64/configs/vendor/ext_config/factory-holi-penang.config @@ -0,0 +1,16 @@ +# +# Please avoid changing the Qualcomm defconfig files and use this file to +# add any Motorola-specific configuration changes that are applicable to +# userdebug, eng, and user builds. +# +# After building, a list of all of the config files that are used can be found +# at the top of: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/mapphone_defconfig +# +# The actual output of the kernel configuration system can be found at: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/.config +# +# You can check the .config file to verify that your configuration option is +# being set as expected. +# +CONFIG_CAMERA_DISABLE_VSYNC_IRQ=y diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-penang.config b/arch/arm64/configs/vendor/ext_config/moto-holi-penang.config new file mode 100644 index 000000000000..8679ae6cc00f --- /dev/null +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-penang.config @@ -0,0 +1,25 @@ +# +# Please avoid changing the Qualcomm defconfig files and use this file to +# add any Motorola-specific configuration changes that are applicable to +# userdebug, eng, and user builds. +# +# After building, a list of all of the config files that are used can be found +# at the top of: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/mapphone_defconfig +# +# The actual output of the kernel configuration system can be found at: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/.config +# +# You can check the .config file to verify that your configuration option is +# being set as expected. +# +CONFIG_PENANG_DTB=y +# CONFIG_NFC_QTI_I2C is not set +CONFIG_FS_EPOLL_WAKEUP_DEBUG=y +CONFIG_ZRAM_WRITEBACK=y +# CONFIG_THERMAL_STATISTICS is not set +# CONFIG_REGULATOR_QPNP_LCDB is not set +# CONFIG_AW882XX_PARAMS_FROM_BIN is not set +# CONFIG_UFSTW is not set +CONFIG_CRYPTO_CHACHA20POLY1305=y +CONFIG_CAM_SENSOR_PROBE_RETRY=y diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index 72e2ebc33b54..5b0e668de248 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -94,6 +94,14 @@ config MILANF_DTB Only include MILANF specific DTBs to limit the number that get built during kernel compilation. +config PENANG_DTB + depends on ARCH_QCOM + default n + bool "PENANG DTBs" + help + Only include PENANG specific DTBs to limit the number that + get built during kernel compilation. + config RHODEP_DTB depends on ARCH_QCOM default n From 7d796959be71471f77d92e18f44334ffe5576222 Mon Sep 17 00:00:00 2001 From: louhs1 Date: Wed, 8 Jun 2022 14:04:20 +0800 Subject: [PATCH 476/698] defconfig/rhodei: enable CHACHA20 crypto config enable CHACHA20 crypto config fix the CTS issue: CtsNetTestCases Change-Id: I6697ca597eaddcb661e5493b1ca6dcaa15a4f920 Signed-off-by: louhs1 Reviewed-on: https://gerrit.mot.com/2293157 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Yiqiang Feng Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi-rhodei.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-rhodei.config b/arch/arm64/configs/vendor/ext_config/moto-holi-rhodei.config index 08fe4048a3ca..6780d57d515d 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-rhodei.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-rhodei.config @@ -25,3 +25,4 @@ CONFIG_AW882XX_PARAMS_FROM_BIN=y # CONFIG_TOUCHSCREEN_NT36XXX is not set CONFIG_QUP0_SE2_AP=y CONFIG_CAM_SENSOR_PROBE_RETRY=y +CONFIG_CRYPTO_CHACHA20POLY1305=y From 7ffec8cda347c06a4bc6d5c8fb45ffb9b042c941 Mon Sep 17 00:00:00 2001 From: Alessio Balsini Date: Mon, 25 Jan 2021 16:58:50 +0000 Subject: [PATCH 477/698] FROMLIST: fs: Generic function to convert iocb to rw flags OverlayFS implements its own function to translate iocb flags into rw flags, so that they can be passed into another vfs call. With commit ce71bfea207b4 ("fs: align IOCB_* flags with RWF_* flags") Jens created a 1:1 matching between the iocb flags and rw flags, simplifying the conversion. Reduce the OverlayFS code by making the flag conversion function generic and reusable. Mot-CRs-fixed: (CR) Bug: 168023149 Link: https://lore.kernel.org/lkml/20210125153057.3623715-2-balsini@android.com/ Signed-off-by: Alessio Balsini Change-Id: I74aefeafd6ebbda2fbabee9024474dfe4cc6c2a7 Signed-off-by: Alessio Balsini Reviewed-on: https://gerrit.mot.com/2014516 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- fs/overlayfs/file.c | 23 ++++------------------- include/linux/fs.h | 5 +++++ 2 files changed, 9 insertions(+), 19 deletions(-) diff --git a/fs/overlayfs/file.c b/fs/overlayfs/file.c index d27bc5f9face..f59638448d55 100644 --- a/fs/overlayfs/file.c +++ b/fs/overlayfs/file.c @@ -14,6 +14,8 @@ #include #include "overlayfs.h" +#define OVL_IOCB_MASK (IOCB_DSYNC | IOCB_HIPRI | IOCB_NOWAIT | IOCB_SYNC) + static char ovl_whatisit(struct inode *inode, struct inode *realinode) { if (realinode != ovl_inode_upper(inode)) @@ -213,23 +215,6 @@ static void ovl_file_accessed(struct file *file) touch_atime(&file->f_path); } -static rwf_t ovl_iocb_to_rwf(struct kiocb *iocb) -{ - int ifl = iocb->ki_flags; - rwf_t flags = 0; - - if (ifl & IOCB_NOWAIT) - flags |= RWF_NOWAIT; - if (ifl & IOCB_HIPRI) - flags |= RWF_HIPRI; - if (ifl & IOCB_DSYNC) - flags |= RWF_DSYNC; - if (ifl & IOCB_SYNC) - flags |= RWF_SYNC; - - return flags; -} - static ssize_t ovl_read_iter(struct kiocb *iocb, struct iov_iter *iter) { struct file *file = iocb->ki_filp; @@ -246,7 +231,7 @@ static ssize_t ovl_read_iter(struct kiocb *iocb, struct iov_iter *iter) old_cred = ovl_override_creds(file_inode(file)->i_sb); ret = vfs_iter_read(real.file, iter, &iocb->ki_pos, - ovl_iocb_to_rwf(iocb)); + iocb_to_rw_flags(iocb->ki_flags, OVL_IOCB_MASK)); ovl_revert_creds(file_inode(file)->i_sb, old_cred); ovl_file_accessed(file); @@ -281,7 +266,7 @@ static ssize_t ovl_write_iter(struct kiocb *iocb, struct iov_iter *iter) old_cred = ovl_override_creds(file_inode(file)->i_sb); file_start_write(real.file); ret = vfs_iter_write(real.file, iter, &iocb->ki_pos, - ovl_iocb_to_rwf(iocb)); + iocb_to_rw_flags(iocb->ki_flags, OVL_IOCB_MASK)); file_end_write(real.file); ovl_revert_creds(file_inode(file)->i_sb, old_cred); diff --git a/include/linux/fs.h b/include/linux/fs.h index da4364318076..a362251bfaa6 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -3527,6 +3527,11 @@ static inline int kiocb_set_rw_flags(struct kiocb *ki, rwf_t flags) return 0; } +static inline rwf_t iocb_to_rw_flags(int ifl, int iocb_mask) +{ + return ifl & iocb_mask; +} + static inline ino_t parent_ino(struct dentry *dentry) { ino_t res; From 0ea440c499baa0a89aea735ed02af45856d9c22a Mon Sep 17 00:00:00 2001 From: Alessio Balsini Date: Mon, 25 Jan 2021 17:01:30 +0000 Subject: [PATCH 478/698] FROMLIST: fuse: 32-bit user space ioctl compat for fuse device With a 64-bit kernel build the FUSE device cannot handle ioctl requests coming from 32-bit user space. This is due to the ioctl command translation that generates different command identifiers that thus cannot be used for direct comparisons without proper manipulation. Explicitly extract type and number from the ioctl command to enable 32-bit user space compatibility on 64-bit kernel builds. Mot-CRs-fixed: (CR) Bug: 168023149 Link: https://lore.kernel.org/lkml/20210125153057.3623715-3-balsini@android.com/ Signed-off-by: Alessio Balsini Change-Id: I595517c54d551be70e83c7fcb4b62397a3615004 Signed-off-by: Alessio Balsini Reviewed-on: https://gerrit.mot.com/2014517 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- fs/fuse/dev.c | 29 ++++++++++++++++++----------- include/uapi/linux/fuse.h | 3 ++- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 4b95c83ef54a..832812817f75 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -2265,37 +2265,44 @@ static int fuse_device_clone(struct fuse_conn *fc, struct file *new) static long fuse_dev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - int err = -ENOTTY; + int res; + int oldfd; + struct fuse_dev *fud = NULL; - if (cmd == FUSE_DEV_IOC_CLONE) { - int oldfd; + if (_IOC_TYPE(cmd) != FUSE_DEV_IOC_MAGIC) + return -EINVAL; - err = -EFAULT; - if (!get_user(oldfd, (__u32 __user *) arg)) { + switch (_IOC_NR(cmd)) { + case _IOC_NR(FUSE_DEV_IOC_CLONE): + res = -EFAULT; + if (!get_user(oldfd, (__u32 __user *)arg)) { struct file *old = fget(oldfd); - err = -EINVAL; + res = -EINVAL; if (old) { - struct fuse_dev *fud = NULL; - /* * Check against file->f_op because CUSE * uses the same ioctl handler. */ if (old->f_op == file->f_op && - old->f_cred->user_ns == file->f_cred->user_ns) + old->f_cred->user_ns == + file->f_cred->user_ns) fud = fuse_get_dev(old); if (fud) { mutex_lock(&fuse_mutex); - err = fuse_device_clone(fud->fc, file); + res = fuse_device_clone(fud->fc, file); mutex_unlock(&fuse_mutex); } fput(old); } } + break; + default: + res = -ENOTTY; + break; } - return err; + return res; } const struct file_operations fuse_dev_operations = { diff --git a/include/uapi/linux/fuse.h b/include/uapi/linux/fuse.h index 0a88b2179fda..9eb4ea77197f 100644 --- a/include/uapi/linux/fuse.h +++ b/include/uapi/linux/fuse.h @@ -870,7 +870,8 @@ struct fuse_notify_retrieve_in { }; /* Device ioctls: */ -#define FUSE_DEV_IOC_CLONE _IOR(229, 0, uint32_t) +#define FUSE_DEV_IOC_MAGIC 229 +#define FUSE_DEV_IOC_CLONE _IOR(FUSE_DEV_IOC_MAGIC, 0, uint32_t) struct fuse_lseek_in { uint64_t fh; From 4e210ad39ef17c74a733c55a9a9045dcabca4c76 Mon Sep 17 00:00:00 2001 From: Alessio Balsini Date: Mon, 25 Jan 2021 17:02:28 +0000 Subject: [PATCH 479/698] FROMLIST: fuse: Definitions and ioctl for passthrough Expose the FUSE_PASSTHROUGH interface to user space and declare all the basic data structures and functions as the skeleton on top of which the FUSE passthrough functionality will be built. As part of this, introduce the new FUSE passthrough ioctl, which allows the FUSE daemon to specify a direct connection between a FUSE file and a lower file system file. Such ioctl requires user space to pass the file descriptor of one of its opened files through the fuse_passthrough_out data structure introduced in this patch. This structure includes extra fields for possible future extensions. Also, add the passthrough functions for the set-up and tear-down of the data structures and locks that will be used both when fuse_conns and fuse_files are created/deleted. Mot-CRs-fixed: (CR) Bug: 168023149 Link: https://lore.kernel.org/lkml/20210125153057.3623715-4-balsini@android.com/ Signed-off-by: Alessio Balsini Change-Id: I732532581348adadda5b5048a9346c2b0868d539 Signed-off-by: Alessio Balsini Reviewed-on: https://gerrit.mot.com/2014518 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- fs/fuse/Makefile | 1 + fs/fuse/dev.c | 12 ++++++++++++ fs/fuse/dir.c | 1 + fs/fuse/file.c | 4 +++- fs/fuse/fuse_i.h | 27 +++++++++++++++++++++++++++ fs/fuse/inode.c | 18 +++++++++++++++++- fs/fuse/passthrough.c | 21 +++++++++++++++++++++ include/uapi/linux/fuse.h | 11 ++++++++++- 8 files changed, 92 insertions(+), 3 deletions(-) create mode 100644 fs/fuse/passthrough.c diff --git a/fs/fuse/Makefile b/fs/fuse/Makefile index 3e8cebfb59b7..6971454a2bdf 100644 --- a/fs/fuse/Makefile +++ b/fs/fuse/Makefile @@ -8,4 +8,5 @@ obj-$(CONFIG_CUSE) += cuse.o obj-$(CONFIG_VIRTIO_FS) += virtiofs.o fuse-objs := dev.o dir.o file.o inode.o control.o xattr.o acl.o readdir.o +fuse-objs += passthrough.o virtiofs-y += virtio_fs.o diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 832812817f75..7d8ed4bc0b2d 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -2268,6 +2268,7 @@ static long fuse_dev_ioctl(struct file *file, unsigned int cmd, int res; int oldfd; struct fuse_dev *fud = NULL; + struct fuse_passthrough_out pto; if (_IOC_TYPE(cmd) != FUSE_DEV_IOC_MAGIC) return -EINVAL; @@ -2298,6 +2299,17 @@ static long fuse_dev_ioctl(struct file *file, unsigned int cmd, } } break; + case _IOC_NR(FUSE_DEV_IOC_PASSTHROUGH_OPEN): + res = -EFAULT; + if (!copy_from_user(&pto, + (struct fuse_passthrough_out __user *)arg, + sizeof(pto))) { + res = -EINVAL; + fud = fuse_get_dev(file); + if (fud) + res = fuse_passthrough_open(fud, &pto); + } + break; default: res = -ENOTTY; break; diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index eb9c853adf3a..0db1bb623dac 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -529,6 +529,7 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, ff->fh = outopen.fh; ff->nodeid = outentry.nodeid; ff->open_flags = outopen.open_flags; + fuse_passthrough_setup(fc, ff, &outopen); inode = fuse_iget(dir->i_sb, outentry.nodeid, outentry.generation, &outentry.attr, entry_attr_timeout(&outentry), 0); if (!inode) { diff --git a/fs/fuse/file.c b/fs/fuse/file.c index f6c499dbfd06..fa0536a2a1cb 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -151,7 +151,7 @@ int fuse_do_open(struct fuse_conn *fc, u64 nodeid, struct file *file, if (!err) { ff->fh = outarg.fh; ff->open_flags = outarg.open_flags; - + fuse_passthrough_setup(fc, ff, &outarg); } else if (err != -ENOSYS) { fuse_file_free(ff); return err; @@ -287,6 +287,8 @@ void fuse_release_common(struct file *file, bool isdir) struct fuse_release_args *ra = ff->release_args; int opcode = isdir ? FUSE_RELEASEDIR : FUSE_RELEASE; + fuse_passthrough_release(&ff->passthrough); + fuse_prepare_release(fi, ff, file->f_flags, opcode); if (ff->flock) { diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index 2d9aaf31e01f..b31ad31e5767 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -165,6 +165,14 @@ enum { struct fuse_conn; struct fuse_release_args; +/** + * Reference to lower filesystem file for read/write operations handled in + * passthrough mode + */ +struct fuse_passthrough { + struct file *filp; +}; + /** FUSE specific file data */ struct fuse_file { /** Fuse connection for this file */ @@ -210,6 +218,9 @@ struct fuse_file { } readdir; + /** Container for data related to the passthrough functionality */ + struct fuse_passthrough passthrough; + /** RB node to be linked on fuse_conn->polled_files */ struct rb_node polled_node; @@ -726,6 +737,9 @@ struct fuse_conn { /* Do not show mount options */ unsigned int no_mount_options:1; + /** Passthrough mode for read/write IO */ + unsigned int passthrough:1; + /** The number of requests waiting for completion */ atomic_t num_waiting; @@ -761,6 +775,12 @@ struct fuse_conn { /** List of device instances belonging to this connection */ struct list_head devices; + + /** IDR for passthrough requests */ + struct idr passthrough_req; + + /** Protects passthrough_req */ + spinlock_t passthrough_req_lock; }; static inline struct fuse_conn *get_fuse_conn_super(struct super_block *sb) @@ -1111,4 +1131,11 @@ unsigned int fuse_len_args(unsigned int numargs, struct fuse_arg *args); u64 fuse_get_unique(struct fuse_iqueue *fiq); void fuse_free_conn(struct fuse_conn *fc); +/* passthrough.c */ +int fuse_passthrough_open(struct fuse_dev *fud, + struct fuse_passthrough_out *pto); +int fuse_passthrough_setup(struct fuse_conn *fc, struct fuse_file *ff, + struct fuse_open_out *openarg); +void fuse_passthrough_release(struct fuse_passthrough *passthrough); + #endif /* _FS_FUSE_I_H */ diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index f3d712decb57..ba76f2029ba5 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -628,6 +628,7 @@ void fuse_conn_init(struct fuse_conn *fc, struct user_namespace *user_ns, memset(fc, 0, sizeof(*fc)); spin_lock_init(&fc->lock); spin_lock_init(&fc->bg_lock); + spin_lock_init(&fc->passthrough_req_lock); init_rwsem(&fc->killsb); refcount_set(&fc->count, 1); atomic_set(&fc->dev_count, 1); @@ -636,6 +637,7 @@ void fuse_conn_init(struct fuse_conn *fc, struct user_namespace *user_ns, INIT_LIST_HEAD(&fc->bg_queue); INIT_LIST_HEAD(&fc->entry); INIT_LIST_HEAD(&fc->devices); + idr_init(&fc->passthrough_req); atomic_set(&fc->num_waiting, 0); fc->max_background = FUSE_DEFAULT_MAX_BACKGROUND; fc->congestion_threshold = FUSE_DEFAULT_CONGESTION_THRESHOLD; @@ -972,6 +974,12 @@ static void process_init_reply(struct fuse_conn *fc, struct fuse_args *args, min_t(unsigned int, FUSE_MAX_MAX_PAGES, max_t(unsigned int, arg->max_pages, 1)); } + if (arg->flags & FUSE_PASSTHROUGH) { + fc->passthrough = 1; + /* Prevent further stacking */ + fc->sb->s_stack_depth = + FILESYSTEM_MAX_STACK_DEPTH; + } } else { ra_pages = fc->max_read / PAGE_SIZE; fc->no_lock = 1; @@ -1009,7 +1017,8 @@ void fuse_send_init(struct fuse_conn *fc) FUSE_WRITEBACK_CACHE | FUSE_NO_OPEN_SUPPORT | FUSE_PARALLEL_DIROPS | FUSE_HANDLE_KILLPRIV | FUSE_POSIX_ACL | FUSE_ABORT_ERROR | FUSE_MAX_PAGES | FUSE_CACHE_SYMLINKS | - FUSE_NO_OPENDIR_SUPPORT | FUSE_EXPLICIT_INVAL_DATA; + FUSE_NO_OPENDIR_SUPPORT | FUSE_EXPLICIT_INVAL_DATA | + FUSE_PASSTHROUGH; ia->args.opcode = FUSE_INIT; ia->args.in_numargs = 1; ia->args.in_args[0].size = sizeof(ia->in); @@ -1030,9 +1039,16 @@ void fuse_send_init(struct fuse_conn *fc) } EXPORT_SYMBOL_GPL(fuse_send_init); +static int free_fuse_passthrough(int id, void *p, void *data) +{ + return 0; +} + void fuse_free_conn(struct fuse_conn *fc) { WARN_ON(!list_empty(&fc->devices)); + idr_for_each(&fc->passthrough_req, free_fuse_passthrough, NULL); + idr_destroy(&fc->passthrough_req); kfree_rcu(fc, rcu); } EXPORT_SYMBOL_GPL(fuse_free_conn); diff --git a/fs/fuse/passthrough.c b/fs/fuse/passthrough.c new file mode 100644 index 000000000000..594060c654f8 --- /dev/null +++ b/fs/fuse/passthrough.c @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include "fuse_i.h" + +#include + +int fuse_passthrough_open(struct fuse_dev *fud, + struct fuse_passthrough_out *pto) +{ + return -EINVAL; +} + +int fuse_passthrough_setup(struct fuse_conn *fc, struct fuse_file *ff, + struct fuse_open_out *openarg) +{ + return -EINVAL; +} + +void fuse_passthrough_release(struct fuse_passthrough *passthrough) +{ +} diff --git a/include/uapi/linux/fuse.h b/include/uapi/linux/fuse.h index 9eb4ea77197f..f4b571de7f14 100644 --- a/include/uapi/linux/fuse.h +++ b/include/uapi/linux/fuse.h @@ -342,6 +342,7 @@ struct fuse_file_lock { #define FUSE_NO_OPENDIR_SUPPORT (1 << 24) #define FUSE_EXPLICIT_INVAL_DATA (1 << 25) #define FUSE_MAP_ALIGNMENT (1 << 26) +#define FUSE_PASSTHROUGH (1 << 31) /** * CUSE INIT request/reply flags @@ -592,7 +593,7 @@ struct fuse_create_in { struct fuse_open_out { uint64_t fh; uint32_t open_flags; - uint32_t padding; + uint32_t passthrough_fh; }; struct fuse_release_in { @@ -795,6 +796,13 @@ struct fuse_in_header { uint32_t padding; }; +struct fuse_passthrough_out { + uint32_t fd; + /* For future implementation */ + uint32_t len; + void *vec; +}; + struct fuse_out_header { uint32_t len; int32_t error; @@ -872,6 +880,7 @@ struct fuse_notify_retrieve_in { /* Device ioctls: */ #define FUSE_DEV_IOC_MAGIC 229 #define FUSE_DEV_IOC_CLONE _IOR(FUSE_DEV_IOC_MAGIC, 0, uint32_t) +#define FUSE_DEV_IOC_PASSTHROUGH_OPEN _IOW(FUSE_DEV_IOC_MAGIC, 1, struct fuse_passthrough_out) struct fuse_lseek_in { uint64_t fh; From 57f2f8db34b9faceb454f20692bf1a79eeaf007a Mon Sep 17 00:00:00 2001 From: Alessio Balsini Date: Mon, 25 Jan 2021 17:02:57 +0000 Subject: [PATCH 480/698] FROMLIST: fuse: Passthrough initialization and release Implement the FUSE passthrough ioctl that associates the lower (passthrough) file system file with the fuse_file. The file descriptor passed to the ioctl by the FUSE daemon is used to access the relative file pointer, that will be copied to the fuse_file data structure to consolidate the link between the FUSE and lower file system. To enable the passthrough mode, user space triggers the FUSE_DEV_IOC_PASSTHROUGH_OPEN ioctl and, if the call succeeds, receives back an identifier that will be used at open/create response time in the fuse_open_out field to associate the FUSE file to the lower file system file. The value returned by the ioctl to user space can be: - > 0: success, the identifier can be used as part of an open/create reply. - <= 0: an error occurred. The value 0 represents an error to preserve backward compatibility: the fuse_open_out field that is used to pass the passthrough_fh back to the kernel uses the same bits that were previously as struct padding, and is commonly zero-initialized (e.g., in the libfuse implementation). Removing 0 from the correct values fixes the ambiguity between the case in which 0 corresponds to a real passthrough_fh, a missing implementation of FUSE passthrough or a request for a normal FUSE file, simplifying the user space implementation. For the passthrough mode to be successfully activated, the lower file system file must implement both read_iter and write_iter file operations. This extra check avoids special pseudo files to be targeted for this feature. Passthrough comes with another limitation: no further file system stacking is allowed for those FUSE file systems using passthrough. Mot-CRs-fixed: (CR) Bug: 168023149 Link: https://lore.kernel.org/lkml/20210125153057.3623715-5-balsini@android.com/ Signed-off-by: Alessio Balsini Change-Id: I4d8290012302fb4547bce9bb261a03cc4f66b5aa Signed-off-by: Alessio Balsini Reviewed-on: https://gerrit.mot.com/2014519 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- fs/fuse/inode.c | 5 +++ fs/fuse/passthrough.c | 87 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 90 insertions(+), 2 deletions(-) diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index ba76f2029ba5..1c982cd43537 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -1041,6 +1041,11 @@ EXPORT_SYMBOL_GPL(fuse_send_init); static int free_fuse_passthrough(int id, void *p, void *data) { + struct fuse_passthrough *passthrough = (struct fuse_passthrough *)p; + + fuse_passthrough_release(passthrough); + kfree(p); + return 0; } diff --git a/fs/fuse/passthrough.c b/fs/fuse/passthrough.c index 594060c654f8..cf993e83803e 100644 --- a/fs/fuse/passthrough.c +++ b/fs/fuse/passthrough.c @@ -3,19 +3,102 @@ #include "fuse_i.h" #include +#include int fuse_passthrough_open(struct fuse_dev *fud, struct fuse_passthrough_out *pto) { - return -EINVAL; + int res; + struct file *passthrough_filp; + struct fuse_conn *fc = fud->fc; + struct inode *passthrough_inode; + struct super_block *passthrough_sb; + struct fuse_passthrough *passthrough; + + if (!fc->passthrough) + return -EPERM; + + /* This field is reserved for future implementation */ + if (pto->len != 0) + return -EINVAL; + + passthrough_filp = fget(pto->fd); + if (!passthrough_filp) { + pr_err("FUSE: invalid file descriptor for passthrough.\n"); + return -EBADF; + } + + if (!passthrough_filp->f_op->read_iter || + !passthrough_filp->f_op->write_iter) { + pr_err("FUSE: passthrough file misses file operations.\n"); + res = -EBADF; + goto err_free_file; + } + + passthrough_inode = file_inode(passthrough_filp); + passthrough_sb = passthrough_inode->i_sb; + if (passthrough_sb->s_stack_depth >= FILESYSTEM_MAX_STACK_DEPTH) { + pr_err("FUSE: fs stacking depth exceeded for passthrough\n"); + res = -EINVAL; + goto err_free_file; + } + + passthrough = kmalloc(sizeof(struct fuse_passthrough), GFP_KERNEL); + if (!passthrough) { + res = -ENOMEM; + goto err_free_file; + } + + passthrough->filp = passthrough_filp; + + idr_preload(GFP_KERNEL); + spin_lock(&fc->passthrough_req_lock); + res = idr_alloc(&fc->passthrough_req, passthrough, 1, 0, GFP_ATOMIC); + spin_unlock(&fc->passthrough_req_lock); + idr_preload_end(); + + if (res > 0) + return res; + + fuse_passthrough_release(passthrough); + kfree(passthrough); + +err_free_file: + fput(passthrough_filp); + + return res; } int fuse_passthrough_setup(struct fuse_conn *fc, struct fuse_file *ff, struct fuse_open_out *openarg) { - return -EINVAL; + struct fuse_passthrough *passthrough; + int passthrough_fh = openarg->passthrough_fh; + + if (!fc->passthrough) + return -EPERM; + + /* Default case, passthrough is not requested */ + if (passthrough_fh <= 0) + return -EINVAL; + + spin_lock(&fc->passthrough_req_lock); + passthrough = idr_remove(&fc->passthrough_req, passthrough_fh); + spin_unlock(&fc->passthrough_req_lock); + + if (!passthrough) + return -EINVAL; + + ff->passthrough = *passthrough; + kfree(passthrough); + + return 0; } void fuse_passthrough_release(struct fuse_passthrough *passthrough) { + if (passthrough->filp) { + fput(passthrough->filp); + passthrough->filp = NULL; + } } From ca9fac415fbb53190a19557d41d71c016ef899c2 Mon Sep 17 00:00:00 2001 From: Alessio Balsini Date: Mon, 25 Jan 2021 17:03:31 +0000 Subject: [PATCH 481/698] FROMLIST: fuse: Introduce synchronous read and write for passthrough All the read and write operations performed on fuse_files which have the passthrough feature enabled are forwarded to the associated lower file system file via VFS. Sending the request directly to the lower file system avoids the userspace round-trip that, because of possible context switches and additional operations might reduce the overall performance, especially in those cases where caching doesn't help, for example in reads at random offsets. Verifying if a fuse_file has a lower file system file associated with can be done by checking the validity of its passthrough_filp pointer. This pointer is not NULL only if passthrough has been successfully enabled via the appropriate ioctl(). When a read/write operation is requested for a FUSE file with passthrough enabled, a new equivalent VFS request is generated, which instead targets the lower file system file. The VFS layer performs additional checks that allow for safer operations but may cause the operation to fail if the process accessing the FUSE file system does not have access to the lower file system. This change only implements synchronous requests in passthrough, returning an error in the case of asynchronous operations, yet covering the majority of the use cases. Mot-CRs-fixed: (CR) Bug: 168023149 Link: https://lore.kernel.org/lkml/20210125153057.3623715-6-balsini@android.com/ Signed-off-by: Alessio Balsini Change-Id: Ifbe6a247fe7338f87d078fde923f0252eeaeb668 Signed-off-by: Alessio Balsini Reviewed-on: https://gerrit.mot.com/2014520 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- fs/fuse/file.c | 8 ++++-- fs/fuse/fuse_i.h | 2 ++ fs/fuse/passthrough.c | 57 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 65 insertions(+), 2 deletions(-) diff --git a/fs/fuse/file.c b/fs/fuse/file.c index fa0536a2a1cb..1421f34bfb94 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -1598,7 +1598,9 @@ static ssize_t fuse_file_read_iter(struct kiocb *iocb, struct iov_iter *to) if (fuse_is_bad(file_inode(file))) return -EIO; - if (!(ff->open_flags & FOPEN_DIRECT_IO)) + if (ff->passthrough.filp) + return fuse_passthrough_read_iter(iocb, to); + else if (!(ff->open_flags & FOPEN_DIRECT_IO)) return fuse_cache_read_iter(iocb, to); else return fuse_direct_read_iter(iocb, to); @@ -1612,7 +1614,9 @@ static ssize_t fuse_file_write_iter(struct kiocb *iocb, struct iov_iter *from) if (fuse_is_bad(file_inode(file))) return -EIO; - if (!(ff->open_flags & FOPEN_DIRECT_IO)) + if (ff->passthrough.filp) + return fuse_passthrough_write_iter(iocb, from); + else if (!(ff->open_flags & FOPEN_DIRECT_IO)) return fuse_cache_write_iter(iocb, from); else return fuse_direct_write_iter(iocb, from); diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index b31ad31e5767..abfede9483a3 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -1137,5 +1137,7 @@ int fuse_passthrough_open(struct fuse_dev *fud, int fuse_passthrough_setup(struct fuse_conn *fc, struct fuse_file *ff, struct fuse_open_out *openarg); void fuse_passthrough_release(struct fuse_passthrough *passthrough); +ssize_t fuse_passthrough_read_iter(struct kiocb *iocb, struct iov_iter *to); +ssize_t fuse_passthrough_write_iter(struct kiocb *iocb, struct iov_iter *from); #endif /* _FS_FUSE_I_H */ diff --git a/fs/fuse/passthrough.c b/fs/fuse/passthrough.c index cf993e83803e..d949ca07a83b 100644 --- a/fs/fuse/passthrough.c +++ b/fs/fuse/passthrough.c @@ -4,6 +4,63 @@ #include #include +#include + +#define PASSTHROUGH_IOCB_MASK \ + (IOCB_APPEND | IOCB_DSYNC | IOCB_HIPRI | IOCB_NOWAIT | IOCB_SYNC) + +static void fuse_copyattr(struct file *dst_file, struct file *src_file) +{ + struct inode *dst = file_inode(dst_file); + struct inode *src = file_inode(src_file); + + i_size_write(dst, i_size_read(src)); +} + +ssize_t fuse_passthrough_read_iter(struct kiocb *iocb_fuse, + struct iov_iter *iter) +{ + ssize_t ret; + struct file *fuse_filp = iocb_fuse->ki_filp; + struct fuse_file *ff = fuse_filp->private_data; + struct file *passthrough_filp = ff->passthrough.filp; + + if (!iov_iter_count(iter)) + return 0; + + ret = vfs_iter_read(passthrough_filp, iter, &iocb_fuse->ki_pos, + iocb_to_rw_flags(iocb_fuse->ki_flags, + PASSTHROUGH_IOCB_MASK)); + + return ret; +} + +ssize_t fuse_passthrough_write_iter(struct kiocb *iocb_fuse, + struct iov_iter *iter) +{ + ssize_t ret; + struct file *fuse_filp = iocb_fuse->ki_filp; + struct fuse_file *ff = fuse_filp->private_data; + struct inode *fuse_inode = file_inode(fuse_filp); + struct file *passthrough_filp = ff->passthrough.filp; + + if (!iov_iter_count(iter)) + return 0; + + inode_lock(fuse_inode); + + file_start_write(passthrough_filp); + ret = vfs_iter_write(passthrough_filp, iter, &iocb_fuse->ki_pos, + iocb_to_rw_flags(iocb_fuse->ki_flags, + PASSTHROUGH_IOCB_MASK)); + file_end_write(passthrough_filp); + if (ret > 0) + fuse_copyattr(fuse_filp, passthrough_filp); + + inode_unlock(fuse_inode); + + return ret; +} int fuse_passthrough_open(struct fuse_dev *fud, struct fuse_passthrough_out *pto) From 0c66e8e77110d21a9acca0a447c5568d7d14fedf Mon Sep 17 00:00:00 2001 From: Alessio Balsini Date: Mon, 25 Jan 2021 17:03:51 +0000 Subject: [PATCH 482/698] FROMLIST: fuse: Handle asynchronous read and write in passthrough Extend the passthrough feature by handling asynchronous IO both for read and write operations. When an AIO request is received, if the request targets a FUSE file with the passthrough functionality enabled, a new identical AIO request is created. The new request targets the lower file system file and gets assigned a special FUSE passthrough AIO completion callback. When the lower file system AIO request is completed, the FUSE passthrough AIO completion callback is executed and propagates the completion signal to the FUSE AIO request by triggering its completion callback as well. Mot-CRs-fixed: (CR) Bug: 168023149 Link: https://lore.kernel.org/lkml/20210125153057.3623715-7-balsini@android.com/ Signed-off-by: Alessio Balsini Change-Id: I47671ef36211102da6dd3ee8b2f226d1e6cd9d5c Signed-off-by: Alessio Balsini Reviewed-on: https://gerrit.mot.com/2014521 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- fs/fuse/passthrough.c | 99 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 89 insertions(+), 10 deletions(-) diff --git a/fs/fuse/passthrough.c b/fs/fuse/passthrough.c index d949ca07a83b..4ae0ed0ac4ea 100644 --- a/fs/fuse/passthrough.c +++ b/fs/fuse/passthrough.c @@ -9,6 +9,23 @@ #define PASSTHROUGH_IOCB_MASK \ (IOCB_APPEND | IOCB_DSYNC | IOCB_HIPRI | IOCB_NOWAIT | IOCB_SYNC) +struct fuse_aio_req { + struct kiocb iocb; + struct kiocb *iocb_fuse; +}; + +static inline void kiocb_clone(struct kiocb *kiocb, struct kiocb *kiocb_src, + struct file *filp) +{ + *kiocb = (struct kiocb){ + .ki_filp = filp, + .ki_flags = kiocb_src->ki_flags, + .ki_hint = kiocb_src->ki_hint, + .ki_ioprio = kiocb_src->ki_ioprio, + .ki_pos = kiocb_src->ki_pos, + }; +} + static void fuse_copyattr(struct file *dst_file, struct file *src_file) { struct inode *dst = file_inode(dst_file); @@ -17,6 +34,32 @@ static void fuse_copyattr(struct file *dst_file, struct file *src_file) i_size_write(dst, i_size_read(src)); } +static void fuse_aio_cleanup_handler(struct fuse_aio_req *aio_req) +{ + struct kiocb *iocb = &aio_req->iocb; + struct kiocb *iocb_fuse = aio_req->iocb_fuse; + + if (iocb->ki_flags & IOCB_WRITE) { + __sb_writers_acquired(file_inode(iocb->ki_filp)->i_sb, + SB_FREEZE_WRITE); + file_end_write(iocb->ki_filp); + fuse_copyattr(iocb_fuse->ki_filp, iocb->ki_filp); + } + + iocb_fuse->ki_pos = iocb->ki_pos; + kfree(aio_req); +} + +static void fuse_aio_rw_complete(struct kiocb *iocb, long res, long res2) +{ + struct fuse_aio_req *aio_req = + container_of(iocb, struct fuse_aio_req, iocb); + struct kiocb *iocb_fuse = aio_req->iocb_fuse; + + fuse_aio_cleanup_handler(aio_req); + iocb_fuse->ki_complete(iocb_fuse, res, res2); +} + ssize_t fuse_passthrough_read_iter(struct kiocb *iocb_fuse, struct iov_iter *iter) { @@ -28,9 +71,24 @@ ssize_t fuse_passthrough_read_iter(struct kiocb *iocb_fuse, if (!iov_iter_count(iter)) return 0; - ret = vfs_iter_read(passthrough_filp, iter, &iocb_fuse->ki_pos, - iocb_to_rw_flags(iocb_fuse->ki_flags, - PASSTHROUGH_IOCB_MASK)); + if (is_sync_kiocb(iocb_fuse)) { + ret = vfs_iter_read(passthrough_filp, iter, &iocb_fuse->ki_pos, + iocb_to_rw_flags(iocb_fuse->ki_flags, + PASSTHROUGH_IOCB_MASK)); + } else { + struct fuse_aio_req *aio_req; + + aio_req = kmalloc(sizeof(struct fuse_aio_req), GFP_KERNEL); + if (!aio_req) + return -ENOMEM; + + aio_req->iocb_fuse = iocb_fuse; + kiocb_clone(&aio_req->iocb, iocb_fuse, passthrough_filp); + aio_req->iocb.ki_complete = fuse_aio_rw_complete; + ret = call_read_iter(passthrough_filp, &aio_req->iocb, iter); + if (ret != -EIOCBQUEUED) + fuse_aio_cleanup_handler(aio_req); + } return ret; } @@ -43,20 +101,41 @@ ssize_t fuse_passthrough_write_iter(struct kiocb *iocb_fuse, struct fuse_file *ff = fuse_filp->private_data; struct inode *fuse_inode = file_inode(fuse_filp); struct file *passthrough_filp = ff->passthrough.filp; + struct inode *passthrough_inode = file_inode(passthrough_filp); if (!iov_iter_count(iter)) return 0; inode_lock(fuse_inode); - file_start_write(passthrough_filp); - ret = vfs_iter_write(passthrough_filp, iter, &iocb_fuse->ki_pos, - iocb_to_rw_flags(iocb_fuse->ki_flags, - PASSTHROUGH_IOCB_MASK)); - file_end_write(passthrough_filp); - if (ret > 0) - fuse_copyattr(fuse_filp, passthrough_filp); + if (is_sync_kiocb(iocb_fuse)) { + file_start_write(passthrough_filp); + ret = vfs_iter_write(passthrough_filp, iter, &iocb_fuse->ki_pos, + iocb_to_rw_flags(iocb_fuse->ki_flags, + PASSTHROUGH_IOCB_MASK)); + file_end_write(passthrough_filp); + if (ret > 0) + fuse_copyattr(fuse_filp, passthrough_filp); + } else { + struct fuse_aio_req *aio_req; + aio_req = kmalloc(sizeof(struct fuse_aio_req), GFP_KERNEL); + if (!aio_req) { + ret = -ENOMEM; + goto out; + } + + file_start_write(passthrough_filp); + __sb_writers_release(passthrough_inode->i_sb, SB_FREEZE_WRITE); + + aio_req->iocb_fuse = iocb_fuse; + kiocb_clone(&aio_req->iocb, iocb_fuse, passthrough_filp); + aio_req->iocb.ki_complete = fuse_aio_rw_complete; + ret = call_write_iter(passthrough_filp, &aio_req->iocb, iter); + if (ret != -EIOCBQUEUED) + fuse_aio_cleanup_handler(aio_req); + } +out: inode_unlock(fuse_inode); return ret; From 6296c14ca01f1fde0b2a996cb41f6d86802ee900 Mon Sep 17 00:00:00 2001 From: Alessio Balsini Date: Mon, 25 Jan 2021 17:04:38 +0000 Subject: [PATCH 483/698] FROMLIST: fuse: Use daemon creds in passthrough mode When using FUSE passthrough, read/write operations are directly forwarded to the lower file system file through VFS, but there is no guarantee that the process that is triggering the request has the right permissions to access the lower file system. This would cause the read/write access to fail. In passthrough file systems, where the FUSE daemon is responsible for the enforcement of the lower file system access policies, often happens that the process dealing with the FUSE file system doesn't have access to the lower file system. Being the FUSE daemon in charge of implementing the FUSE file operations, that in the case of read/write operations usually simply results in the copy of memory buffers from/to the lower file system respectively, these operations are executed with the FUSE daemon privileges. This patch adds a reference to the FUSE daemon credentials, referenced at FUSE_DEV_IOC_PASSTHROUGH_OPEN ioctl() time so that they can be used to temporarily raise the user credentials when accessing lower file system files in passthrough. The process accessing the FUSE file with passthrough enabled temporarily receives the privileges of the FUSE daemon while performing read/write operations. Similar behavior is implemented in overlayfs. These privileges will be reverted as soon as the IO operation completes. This feature does not provide any higher security privileges to those processes accessing the FUSE file system with passthrough enabled. This is because it is still the FUSE daemon responsible for enabling or not the passthrough feature at file open time, and should enable the feature only after appropriate access policy checks. Mot-CRs-fixed: (CR) Bug: 168023149 Link: https://lore.kernel.org/lkml/20210125153057.3623715-8-balsini@android.com/ Signed-off-by: Alessio Balsini Change-Id: Idb4f03a2ce7c536691e5eaf8fadadfcf002e1677 Signed-off-by: Alessio Balsini Reviewed-on: https://gerrit.mot.com/2014522 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- fs/fuse/fuse_i.h | 5 ++++- fs/fuse/passthrough.c | 11 +++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index abfede9483a3..e248948db9cf 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -167,10 +167,13 @@ struct fuse_release_args; /** * Reference to lower filesystem file for read/write operations handled in - * passthrough mode + * passthrough mode. + * This struct also tracks the credentials to be used for handling read/write + * operations. */ struct fuse_passthrough { struct file *filp; + struct cred *cred; }; /** FUSE specific file data */ diff --git a/fs/fuse/passthrough.c b/fs/fuse/passthrough.c index 4ae0ed0ac4ea..401d3e33f880 100644 --- a/fs/fuse/passthrough.c +++ b/fs/fuse/passthrough.c @@ -64,6 +64,7 @@ ssize_t fuse_passthrough_read_iter(struct kiocb *iocb_fuse, struct iov_iter *iter) { ssize_t ret; + const struct cred *old_cred; struct file *fuse_filp = iocb_fuse->ki_filp; struct fuse_file *ff = fuse_filp->private_data; struct file *passthrough_filp = ff->passthrough.filp; @@ -71,6 +72,7 @@ ssize_t fuse_passthrough_read_iter(struct kiocb *iocb_fuse, if (!iov_iter_count(iter)) return 0; + old_cred = override_creds(ff->passthrough.cred); if (is_sync_kiocb(iocb_fuse)) { ret = vfs_iter_read(passthrough_filp, iter, &iocb_fuse->ki_pos, iocb_to_rw_flags(iocb_fuse->ki_flags, @@ -89,6 +91,7 @@ ssize_t fuse_passthrough_read_iter(struct kiocb *iocb_fuse, if (ret != -EIOCBQUEUED) fuse_aio_cleanup_handler(aio_req); } + revert_creds(old_cred); return ret; } @@ -97,6 +100,7 @@ ssize_t fuse_passthrough_write_iter(struct kiocb *iocb_fuse, struct iov_iter *iter) { ssize_t ret; + const struct cred *old_cred; struct file *fuse_filp = iocb_fuse->ki_filp; struct fuse_file *ff = fuse_filp->private_data; struct inode *fuse_inode = file_inode(fuse_filp); @@ -108,6 +112,7 @@ ssize_t fuse_passthrough_write_iter(struct kiocb *iocb_fuse, inode_lock(fuse_inode); + old_cred = override_creds(ff->passthrough.cred); if (is_sync_kiocb(iocb_fuse)) { file_start_write(passthrough_filp); ret = vfs_iter_write(passthrough_filp, iter, &iocb_fuse->ki_pos, @@ -136,6 +141,7 @@ ssize_t fuse_passthrough_write_iter(struct kiocb *iocb_fuse, fuse_aio_cleanup_handler(aio_req); } out: + revert_creds(old_cred); inode_unlock(fuse_inode); return ret; @@ -186,6 +192,7 @@ int fuse_passthrough_open(struct fuse_dev *fud, } passthrough->filp = passthrough_filp; + passthrough->cred = prepare_creds(); idr_preload(GFP_KERNEL); spin_lock(&fc->passthrough_req_lock); @@ -237,4 +244,8 @@ void fuse_passthrough_release(struct fuse_passthrough *passthrough) fput(passthrough->filp); passthrough->filp = NULL; } + if (passthrough->cred) { + put_cred(passthrough->cred); + passthrough->cred = NULL; + } } From 7506f2d96bf302face73b37096108105ba1c74b4 Mon Sep 17 00:00:00 2001 From: Alessio Balsini Date: Mon, 25 Jan 2021 17:05:31 +0000 Subject: [PATCH 484/698] FROMLIST: fuse: Introduce passthrough for mmap Enabling FUSE passthrough for mmap-ed operations not only affects performance, but has also been shown as mandatory for the correct functioning of FUSE passthrough. yanwu noticed [1] that a FUSE file with passthrough enabled may suffer data inconsistencies if the same file is also accessed with mmap. What happens is that read/write operations are directly applied to the lower file system (and its cache), while mmap-ed operations are affecting the FUSE cache. Extend the FUSE passthrough implementation to also handle memory-mapped FUSE file, to both fix the cache inconsistencies and extend the passthrough performance benefits to mmap-ed operations. [1] https://lore.kernel.org/lkml/20210119110654.11817-1-wu-yan@tcl.com/ Mot-CRs-fixed: (CR) Bug: 168023149 Link: https://lore.kernel.org/lkml/20210125153057.3623715-9-balsini@android.com/ Signed-off-by: Alessio Balsini Change-Id: Ifad4698b0380f6e004c487940ac6907b9a9f2964 Signed-off-by: Alessio Balsini Reviewed-on: https://gerrit.mot.com/2014523 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- fs/fuse/file.c | 3 +++ fs/fuse/fuse_i.h | 1 + fs/fuse/passthrough.c | 41 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+) diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 1421f34bfb94..f9ccf4ac1678 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -2330,6 +2330,9 @@ static int fuse_file_mmap(struct file *file, struct vm_area_struct *vma) { struct fuse_file *ff = file->private_data; + if (ff->passthrough.filp) + return fuse_passthrough_mmap(file, vma); + if (ff->open_flags & FOPEN_DIRECT_IO) { /* Can't provide the coherency needed for MAP_SHARED */ if (vma->vm_flags & VM_MAYSHARE) diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index e248948db9cf..a6635b46a43e 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -1142,5 +1142,6 @@ int fuse_passthrough_setup(struct fuse_conn *fc, struct fuse_file *ff, void fuse_passthrough_release(struct fuse_passthrough *passthrough); ssize_t fuse_passthrough_read_iter(struct kiocb *iocb, struct iov_iter *to); ssize_t fuse_passthrough_write_iter(struct kiocb *iocb, struct iov_iter *from); +ssize_t fuse_passthrough_mmap(struct file *file, struct vm_area_struct *vma); #endif /* _FS_FUSE_I_H */ diff --git a/fs/fuse/passthrough.c b/fs/fuse/passthrough.c index 401d3e33f880..73131069a089 100644 --- a/fs/fuse/passthrough.c +++ b/fs/fuse/passthrough.c @@ -147,6 +147,47 @@ out: return ret; } +ssize_t fuse_passthrough_mmap(struct file *file, struct vm_area_struct *vma) +{ + int ret; + const struct cred *old_cred; + struct fuse_file *ff = file->private_data; + struct inode *fuse_inode = file_inode(file); + struct file *passthrough_filp = ff->passthrough.filp; + struct inode *passthrough_inode = file_inode(passthrough_filp); + + if (!passthrough_filp->f_op->mmap) + return -ENODEV; + + if (WARN_ON(file != vma->vm_file)) + return -EIO; + + vma->vm_file = get_file(passthrough_filp); + + old_cred = override_creds(ff->passthrough.cred); + ret = call_mmap(vma->vm_file, vma); + revert_creds(old_cred); + + if (ret) + fput(passthrough_filp); + else + fput(file); + + if (file->f_flags & O_NOATIME) + return ret; + + if ((!timespec64_equal(&fuse_inode->i_mtime, + &passthrough_inode->i_mtime) || + !timespec64_equal(&fuse_inode->i_ctime, + &passthrough_inode->i_ctime))) { + fuse_inode->i_mtime = passthrough_inode->i_mtime; + fuse_inode->i_ctime = passthrough_inode->i_ctime; + } + touch_atime(&file->f_path); + + return ret; +} + int fuse_passthrough_open(struct fuse_dev *fud, struct fuse_passthrough_out *pto) { From 201597f6c86ee75798353307ffa7f04c32909d7c Mon Sep 17 00:00:00 2001 From: Alessio Balsini Date: Fri, 5 Feb 2021 10:58:49 +0000 Subject: [PATCH 485/698] FROMLIST: fuse: Fix crediantials leak in passthrough read_iter If the system doesn't have enough memory when fuse_passthrough_read_iter is requested in asynchronous IO, an error is directly returned without restoring the caller's credentials. Fix by always ensuring credentials are restored. Mot-CRs-fixed: (CR) Fixes: 10b1e569ef010c240bfdaf1de1fb2360a4d08ead ("FROMLIST: fuse: Use daemon creds in passthrough mode") Link: https://lore.kernel.org/lkml/YB0qPHVORq7bJy6G@google.com/ Reported-by: Peng Tao Signed-off-by: Alessio Balsini Signed-off-by: Alessio Balsini Change-Id: I4aff43f5dd8ddab2cc8871cd9f81438963ead5b6 Reviewed-on: https://gerrit.mot.com/2014524 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- fs/fuse/passthrough.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/fs/fuse/passthrough.c b/fs/fuse/passthrough.c index 73131069a089..b5cc3d957451 100644 --- a/fs/fuse/passthrough.c +++ b/fs/fuse/passthrough.c @@ -81,8 +81,10 @@ ssize_t fuse_passthrough_read_iter(struct kiocb *iocb_fuse, struct fuse_aio_req *aio_req; aio_req = kmalloc(sizeof(struct fuse_aio_req), GFP_KERNEL); - if (!aio_req) - return -ENOMEM; + if (!aio_req) { + ret = -ENOMEM; + goto out; + } aio_req->iocb_fuse = iocb_fuse; kiocb_clone(&aio_req->iocb, iocb_fuse, passthrough_filp); @@ -91,6 +93,7 @@ ssize_t fuse_passthrough_read_iter(struct kiocb *iocb_fuse, if (ret != -EIOCBQUEUED) fuse_aio_cleanup_handler(aio_req); } +out: revert_creds(old_cred); return ret; From 1f784ca6da23d092353e1a8a45b9a4eaa2d2efa4 Mon Sep 17 00:00:00 2001 From: Alessio Balsini Date: Thu, 28 Jan 2021 19:48:23 +0000 Subject: [PATCH 486/698] FROMLIST: fuse: Allocate unl(CR) used ioctl number for passthrough V1 The current UAPI interface for FUSE passthrough is still under discussion upstream, thus we are reserving this ioctl number to avoid future conflicts with user space binaries. The user space implementation in Android will take care of doing all the checking to fall into the most appropriate ioctl number. Mot-CRs-fixed: (CR) Bug: 167695973 Link: https://lore.kernel.org/lkml/20210125153057.3623715-3-balsini@android.com/ Fixes: 9655e27a40d2 ("FROMLIST: fuse: Definitions and ioctl for passthrough") Test: manual test with additional printks Signed-off-by: Alessio Balsini Change-Id: I658c5ab2ebfe2b76d20685a099ac1b1fee3549cc Reviewed-on: https://gerrit.mot.com/2014525 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- include/uapi/linux/fuse.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/uapi/linux/fuse.h b/include/uapi/linux/fuse.h index f4b571de7f14..d1798775f954 100644 --- a/include/uapi/linux/fuse.h +++ b/include/uapi/linux/fuse.h @@ -796,6 +796,7 @@ struct fuse_in_header { uint32_t padding; }; +/* fuse_passthrough_out for passthrough V1 */ struct fuse_passthrough_out { uint32_t fd; /* For future implementation */ @@ -880,7 +881,8 @@ struct fuse_notify_retrieve_in { /* Device ioctls: */ #define FUSE_DEV_IOC_MAGIC 229 #define FUSE_DEV_IOC_CLONE _IOR(FUSE_DEV_IOC_MAGIC, 0, uint32_t) -#define FUSE_DEV_IOC_PASSTHROUGH_OPEN _IOW(FUSE_DEV_IOC_MAGIC, 1, struct fuse_passthrough_out) +/* 127 is reserved for the V1 interface implementation in Android */ +#define FUSE_DEV_IOC_PASSTHROUGH_OPEN _IOW(FUSE_DEV_IOC_MAGIC, 127, struct fuse_passthrough_out) struct fuse_lseek_in { uint64_t fh; From 3833d57eeabafcbf17b6e2fad793a2bf79847d3f Mon Sep 17 00:00:00 2001 From: Alessio Balsini Date: Thu, 13 May 2021 11:58:16 +0100 Subject: [PATCH 487/698] ANDROID: fuse/passthrough: API V2 with __u32 open argument The initial FUSE passthrough interface has the issue of introducing an ioctl which receives as a parameter a data structure containing a pointer. What happens is that, depending on the architecture, the size of this struct might change, and especially for 32-bit userspace running on 64-bit kernel, the size mismatch results into different a single ioctl the behavior of which depends on the data that is passed (e.g., with an enum). This is just a poor ioctl design as mentioned by Arnd Bergmann [1]. Introduce the new FUSE_PASSTHROUGH_OPEN ioctl which only gets the fd of the lower file system, which is a fixed-size __u32, dropping the confusing fuse_passthrough_out data structure. [1] https://lore.kernel.org/lkml/CAK8P3a2K2FzPvqBYL9W=Yut58SFXyetXwU4Fz50G5O3TsS0pPQ@mail.gmail.com/ Mot-CRs-fixed: (CR) Bug: 175195837 Signed-off-by: Alessio Balsini Change-Id: I486d71cbe20f3c0c87544fa75da4e2704fe57c7c Reviewed-on: https://gerrit.mot.com/2294434 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- fs/fuse/dev.c | 7 ++----- fs/fuse/fuse_i.h | 3 +-- fs/fuse/passthrough.c | 9 ++------- include/uapi/linux/fuse.h | 13 +++---------- 4 files changed, 8 insertions(+), 24 deletions(-) diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 7d8ed4bc0b2d..fdf74cbfc516 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -2268,7 +2268,6 @@ static long fuse_dev_ioctl(struct file *file, unsigned int cmd, int res; int oldfd; struct fuse_dev *fud = NULL; - struct fuse_passthrough_out pto; if (_IOC_TYPE(cmd) != FUSE_DEV_IOC_MAGIC) return -EINVAL; @@ -2301,13 +2300,11 @@ static long fuse_dev_ioctl(struct file *file, unsigned int cmd, break; case _IOC_NR(FUSE_DEV_IOC_PASSTHROUGH_OPEN): res = -EFAULT; - if (!copy_from_user(&pto, - (struct fuse_passthrough_out __user *)arg, - sizeof(pto))) { + if (!get_user(oldfd, (__u32 __user *)arg)) { res = -EINVAL; fud = fuse_get_dev(file); if (fud) - res = fuse_passthrough_open(fud, &pto); + res = fuse_passthrough_open(fud, oldfd); } break; default: diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index a6635b46a43e..cbee6796cec5 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -1135,8 +1135,7 @@ u64 fuse_get_unique(struct fuse_iqueue *fiq); void fuse_free_conn(struct fuse_conn *fc); /* passthrough.c */ -int fuse_passthrough_open(struct fuse_dev *fud, - struct fuse_passthrough_out *pto); +int fuse_passthrough_open(struct fuse_dev *fud, u32 lower_fd); int fuse_passthrough_setup(struct fuse_conn *fc, struct fuse_file *ff, struct fuse_open_out *openarg); void fuse_passthrough_release(struct fuse_passthrough *passthrough); diff --git a/fs/fuse/passthrough.c b/fs/fuse/passthrough.c index b5cc3d957451..e95494c25f92 100644 --- a/fs/fuse/passthrough.c +++ b/fs/fuse/passthrough.c @@ -191,8 +191,7 @@ ssize_t fuse_passthrough_mmap(struct file *file, struct vm_area_struct *vma) return ret; } -int fuse_passthrough_open(struct fuse_dev *fud, - struct fuse_passthrough_out *pto) +int fuse_passthrough_open(struct fuse_dev *fud, u32 lower_fd) { int res; struct file *passthrough_filp; @@ -204,11 +203,7 @@ int fuse_passthrough_open(struct fuse_dev *fud, if (!fc->passthrough) return -EPERM; - /* This field is reserved for future implementation */ - if (pto->len != 0) - return -EINVAL; - - passthrough_filp = fget(pto->fd); + passthrough_filp = fget(lower_fd); if (!passthrough_filp) { pr_err("FUSE: invalid file descriptor for passthrough.\n"); return -EBADF; diff --git a/include/uapi/linux/fuse.h b/include/uapi/linux/fuse.h index d1798775f954..a62498fbad3e 100644 --- a/include/uapi/linux/fuse.h +++ b/include/uapi/linux/fuse.h @@ -796,14 +796,6 @@ struct fuse_in_header { uint32_t padding; }; -/* fuse_passthrough_out for passthrough V1 */ -struct fuse_passthrough_out { - uint32_t fd; - /* For future implementation */ - uint32_t len; - void *vec; -}; - struct fuse_out_header { uint32_t len; int32_t error; @@ -881,8 +873,9 @@ struct fuse_notify_retrieve_in { /* Device ioctls: */ #define FUSE_DEV_IOC_MAGIC 229 #define FUSE_DEV_IOC_CLONE _IOR(FUSE_DEV_IOC_MAGIC, 0, uint32_t) -/* 127 is reserved for the V1 interface implementation in Android */ -#define FUSE_DEV_IOC_PASSTHROUGH_OPEN _IOW(FUSE_DEV_IOC_MAGIC, 127, struct fuse_passthrough_out) +/* 127 is reserved for the V1 interface implementation in Android (deprecated) */ +/* 126 is reserved for the V2 interface implementation in Android */ +#define FUSE_DEV_IOC_PASSTHROUGH_OPEN _IOW(FUSE_DEV_IOC_MAGIC, 126, __u32) struct fuse_lseek_in { uint64_t fh; From bb611b669fa6dd3363cde11fe2c078ec6627172d Mon Sep 17 00:00:00 2001 From: Alessio Balsini Date: Fri, 19 Mar 2021 15:05:14 +0000 Subject: [PATCH 488/698] UPSTREAM: fuse: fix matching of FUSE_DEV_IOC_CLONE command With commit f8425c939663 ("fuse: 32-bit user space ioctl compat for fuse device") the matching constraints for the FUSE_DEV_IOC_CLONE ioctl command are relaxed, limited to the testing of command type and number. As Arnd noticed, this is wrong as it wouldn't ensure the correctness of the data size or direction for the received FUSE device ioctl. Fix by bringing back the comparison of the ioctl received by the FUSE device to the originally generated FUSE_DEV_IOC_CLONE. Mot-CRs-fixed: (CR) Fixes: f8425c939663 ("fuse: 32-bit user space ioctl compat for fuse device") Reported-by: Arnd Bergmann Signed-off-by: Alessio Balsini Signed-off-by: M(CR) Szeredi Signed-off-by: Lee Jones Signed-off-by: Alessio Balsini Change-Id: I372d8399db6d603ba20ef50528acf6645e4d3c66 (cherry picked from commit 6076f5f341e612152879bfda99f0b76c1953bf0b) Reviewed-on: https://gerrit.mot.com/2294435 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- fs/fuse/dev.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index fdf74cbfc516..a4b663f50701 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -2269,11 +2269,8 @@ static long fuse_dev_ioctl(struct file *file, unsigned int cmd, int oldfd; struct fuse_dev *fud = NULL; - if (_IOC_TYPE(cmd) != FUSE_DEV_IOC_MAGIC) - return -EINVAL; - - switch (_IOC_NR(cmd)) { - case _IOC_NR(FUSE_DEV_IOC_CLONE): + switch (cmd) { + case FUSE_DEV_IOC_CLONE: res = -EFAULT; if (!get_user(oldfd, (__u32 __user *)arg)) { struct file *old = fget(oldfd); @@ -2298,7 +2295,7 @@ static long fuse_dev_ioctl(struct file *file, unsigned int cmd, } } break; - case _IOC_NR(FUSE_DEV_IOC_PASSTHROUGH_OPEN): + case FUSE_DEV_IOC_PASSTHROUGH_OPEN: res = -EFAULT; if (!get_user(oldfd, (__u32 __user *)arg)) { res = -EINVAL; From f2355025d773ed59ca3be81be56801cd2d71d6f3 Mon Sep 17 00:00:00 2001 From: Alessio Balsini Date: Thu, 23 Sep 2021 11:05:48 +0100 Subject: [PATCH 489/698] ANDROID: fs/fuse: Keep FUSE file times consistent with lower file When FUSE passthrough is used, the lower file system file is manipulated directly, but neither mtime, atime or ctime of the referencing FUSE file is updated. Fix by updating the file times when passthrough operations are performed. Mot-CRs-fixed: (CR) Bug: 200779468 Reported-by: Fengnan Chang Reported-by: Ed Tsai Signed-off-by: Alessio Balsini Change-Id: I35b72196b2cc1d79a9f62ddb32e2cfa934c3b6d3 Reviewed-on: https://gerrit.mot.com/2294436 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- fs/fuse/passthrough.c | 41 ++++++++++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/fs/fuse/passthrough.c b/fs/fuse/passthrough.c index e95494c25f92..95368ddfb53a 100644 --- a/fs/fuse/passthrough.c +++ b/fs/fuse/passthrough.c @@ -26,11 +26,34 @@ static inline void kiocb_clone(struct kiocb *kiocb, struct kiocb *kiocb_src, }; } +static void fuse_file_accessed(struct file *dst_file, struct file *src_file) +{ + struct inode *dst_inode; + struct inode *src_inode; + + if (dst_file->f_flags & O_NOATIME) + return; + + dst_inode = file_inode(dst_file); + src_inode = file_inode(src_file); + + if ((!timespec64_equal(&dst_inode->i_mtime, &src_inode->i_mtime) || + !timespec64_equal(&dst_inode->i_ctime, &src_inode->i_ctime))) { + dst_inode->i_mtime = src_inode->i_mtime; + dst_inode->i_ctime = src_inode->i_ctime; + } + + touch_atime(&dst_file->f_path); +} + static void fuse_copyattr(struct file *dst_file, struct file *src_file) { struct inode *dst = file_inode(dst_file); struct inode *src = file_inode(src_file); + dst->i_atime = src->i_atime; + dst->i_mtime = src->i_mtime; + dst->i_ctime = src->i_ctime; i_size_write(dst, i_size_read(src)); } @@ -96,6 +119,8 @@ ssize_t fuse_passthrough_read_iter(struct kiocb *iocb_fuse, out: revert_creds(old_cred); + fuse_file_accessed(fuse_filp, passthrough_filp); + return ret; } @@ -115,6 +140,8 @@ ssize_t fuse_passthrough_write_iter(struct kiocb *iocb_fuse, inode_lock(fuse_inode); + fuse_copyattr(fuse_filp, passthrough_filp); + old_cred = override_creds(ff->passthrough.cred); if (is_sync_kiocb(iocb_fuse)) { file_start_write(passthrough_filp); @@ -155,9 +182,7 @@ ssize_t fuse_passthrough_mmap(struct file *file, struct vm_area_struct *vma) int ret; const struct cred *old_cred; struct fuse_file *ff = file->private_data; - struct inode *fuse_inode = file_inode(file); struct file *passthrough_filp = ff->passthrough.filp; - struct inode *passthrough_inode = file_inode(passthrough_filp); if (!passthrough_filp->f_op->mmap) return -ENODEV; @@ -176,17 +201,7 @@ ssize_t fuse_passthrough_mmap(struct file *file, struct vm_area_struct *vma) else fput(file); - if (file->f_flags & O_NOATIME) - return ret; - - if ((!timespec64_equal(&fuse_inode->i_mtime, - &passthrough_inode->i_mtime) || - !timespec64_equal(&fuse_inode->i_ctime, - &passthrough_inode->i_ctime))) { - fuse_inode->i_mtime = passthrough_inode->i_mtime; - fuse_inode->i_ctime = passthrough_inode->i_ctime; - } - touch_atime(&file->f_path); + fuse_file_accessed(file, passthrough_filp); return ret; } From b8596af4007f34aca7da11e7fbbf2468cff03353 Mon Sep 17 00:00:00 2001 From: Yiqiang Feng Date: Sat, 11 Jun 2022 12:33:14 +0800 Subject: [PATCH 490/698] Miami/config: Bootup fail after flash GKI The micron HID macro defines the structure defined by Google,need to be removed from moto-holi-config. Change-Id: I1cf4ce67b0449658a87f6617f90119ef16122e0e Signed-off-by: Yiqiang Feng Reviewed-on: https://gerrit.mot.com/2297699 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Chuanchun Zhu Reviewed-by: Hongshu Lou Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi-miami.config | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-miami.config b/arch/arm64/configs/vendor/ext_config/moto-holi-miami.config index 2b99adf2b709..a231121fe78b 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-miami.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-miami.config @@ -21,7 +21,6 @@ CONFIG_ZRAM_WRITEBACK=y # CONFIG_REGULATOR_QPNP_LCDB is not set CONFIG_AW882XX_STEREO_SMARTPA=y CONFIG_AW882XX_PARAMS_FROM_BIN=y -CONFIG_MICRON_UFSHID=y # CONFIG_UFSTW is not set CONFIG_QUP0_SE2_AP=y CONFIG_CAMERA_FLASH_PWM=y From 308c0bf51601597d2f690451ac87ed48623aed29 Mon Sep 17 00:00:00 2001 From: duxu1 Date: Mon, 13 Jun 2022 17:33:54 +0800 Subject: [PATCH 491/698] Enable SPINLOCK and MUTEXES debug config Enable SPINLOCK and MUTEXES debug config in userdebug build to debug deadlock issue. CONFIG_DEBUG_SPINLOCK=y CONFIG_DEBUG_MUTEXES=y Change-Id: I2dee3eb1997b54ae18cba0c41fd8db32e68f3e3d Signed-off-by: duxu1 Reviewed-on: https://gerrit.mot.com/2298955 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Hongshu Lou Reviewed-by: Huosheng Liao Reviewed-by: Zhizhong Ge Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/debug-holi.config | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/configs/vendor/ext_config/debug-holi.config b/arch/arm64/configs/vendor/ext_config/debug-holi.config index 2aad8fa96812..c23f9114764a 100644 --- a/arch/arm64/configs/vendor/ext_config/debug-holi.config +++ b/arch/arm64/configs/vendor/ext_config/debug-holi.config @@ -54,8 +54,8 @@ CONFIG_CORESIGHT_TGU=y # CONFIG_DEBUG_KMEMLEAK is not set # CONFIG_DEBUG_VIRTUAL is not set # CONFIG_DEBUG_RT_MUTEXES is not set -# CONFIG_DEBUG_SPINLOCK is not set -# CONFIG_DEBUG_MUTEXES is not set +CONFIG_DEBUG_SPINLOCK=y +CONFIG_DEBUG_MUTEXES=y # CONFIG_DEBUG_LOCK_ALLOC is not set # CONFIG_DEBUG_LOCKDEP is not set # CONFIG_DEBUG_ATOMIC_SLEEP is not set From 3ce9097b984dedb4661880b0e8da42e9a0e14e37 Mon Sep 17 00:00:00 2001 From: zhouwl Date: Fri, 17 Jun 2022 18:14:34 +0800 Subject: [PATCH 492/698] defconfig: rhodec+rhodei: aw882xx mapsize after aw882xx algo update to support get algo params from RAM, need enlarge AFE mapsize to 16k. Change-Id: Id163b3078e338ffb54104a5dfd7f6a99b0f4bb22 Signed-off-by: zhouwl Reviewed-on: https://gerrit.mot.com/2304496 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Hujun Liao Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi-rhodec.config | 1 + arch/arm64/configs/vendor/ext_config/moto-holi-rhodei.config | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-rhodec.config b/arch/arm64/configs/vendor/ext_config/moto-holi-rhodec.config index e31f185d35eb..b47d0ac19b55 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-rhodec.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-rhodec.config @@ -22,5 +22,6 @@ CONFIG_ZRAM_WRITEBACK=y CONFIG_AF_NOISE_ELIMINATION=y CONFIG_AW882XX_STEREO_SMARTPA=y CONFIG_AW882XX_PARAMS_FROM_BIN=y +CONFIG_AW882XX_MAPSIZE_16K=y CONFIG_CRYPTO_CHACHA20POLY1305=y CONFIG_CAM_SENSOR_PROBE_RETRY=y diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-rhodei.config b/arch/arm64/configs/vendor/ext_config/moto-holi-rhodei.config index 6780d57d515d..4313d73778d7 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-rhodei.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-rhodei.config @@ -22,6 +22,7 @@ CONFIG_ZRAM_WRITEBACK=y CONFIG_AF_NOISE_ELIMINATION=y CONFIG_AW882XX_STEREO_SMARTPA=y CONFIG_AW882XX_PARAMS_FROM_BIN=y +CONFIG_AW882XX_MAPSIZE_16K=y # CONFIG_TOUCHSCREEN_NT36XXX is not set CONFIG_QUP0_SE2_AP=y CONFIG_CAM_SENSOR_PROBE_RETRY=y From 4868706096888e0eb8c252932e31fb381634fa82 Mon Sep 17 00:00:00 2001 From: zhouwl Date: Wed, 22 Jun 2022 14:16:57 +0800 Subject: [PATCH 493/698] defconfig: miami: aw882xx mapsize after aw882xx upgrade to get algorithm params for RAM, need to enlarge AFE mapsize to 16K. Change-Id: I927a5d8a1bf95810425ae08df73ecac4c9c8468b Signed-off-by: zhouwl Reviewed-on: https://gerrit.mot.com/2309236 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Hujun Liao Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi-miami.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-miami.config b/arch/arm64/configs/vendor/ext_config/moto-holi-miami.config index a231121fe78b..707291cdbab2 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-miami.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-miami.config @@ -21,6 +21,7 @@ CONFIG_ZRAM_WRITEBACK=y # CONFIG_REGULATOR_QPNP_LCDB is not set CONFIG_AW882XX_STEREO_SMARTPA=y CONFIG_AW882XX_PARAMS_FROM_BIN=y +CONFIG_AW882XX_MAPSIZE_16K=y # CONFIG_UFSTW is not set CONFIG_QUP0_SE2_AP=y CONFIG_CAMERA_FLASH_PWM=y From d9d23eca0e6c88387901cd7ce89d5cb81a601c50 Mon Sep 17 00:00:00 2001 From: zhouwl Date: Thu, 23 Jun 2022 16:44:29 +0800 Subject: [PATCH 494/698] fsa4480: optimize switch config flow - When headset is present and not plug-out, if USB PD mis-trigger recognize typec_accessory_device, this action will make fsa4480 change registers value, headset hardware signals will switch, then headset function becomes abnormal. Optimize fsa4480 workflow, if headset present state is not change, drop the update operation. - Enable debug log for analysis headset case. Change-Id: I40d3abc137db22ecdaf0cb74df081acbd4d2108d Signed-off-by: zhouwl Reviewed-on: https://gerrit.mot.com/2310806 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Hujun Liao Submit-Approved: Jira Key --- drivers/soc/qcom/fsa4480-i2c.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/soc/qcom/fsa4480-i2c.c b/drivers/soc/qcom/fsa4480-i2c.c index a466133ac866..61b0f25d4d68 100644 --- a/drivers/soc/qcom/fsa4480-i2c.c +++ b/drivers/soc/qcom/fsa4480-i2c.c @@ -67,6 +67,8 @@ static const struct fsa4480_reg_val fsa_reg_i2c_defaults[] = { {FSA4480_SWITCH_SETTINGS, 0x98}, }; +static bool fsa_reg_notifier; + static void fsa4480_usbc_update_settings(struct fsa4480_priv *fsa_priv, u32 switch_control, u32 switch_enable) { @@ -103,7 +105,7 @@ static int fsa4480_usbc_event_changed_psupply(struct fsa4480_priv *fsa_priv, dev = fsa_priv->dev; if (!dev) return -EINVAL; - dev_dbg(dev, "%s: queueing usbc_analog_work\n", + dev_info(dev, "%s: queueing usbc_analog_work\n", __func__); pm_stay_awake(fsa_priv->dev); queue_work(system_freezable_wq, &fsa_priv->usbc_analog_work); @@ -190,9 +192,14 @@ static int fsa4480_usbc_analog_setup_switches_psupply( goto done; } - dev_dbg(dev, "%s: setting GPIOs active = %d rcvd intval 0x%X\n", + dev_info(dev, "%s: setting GPIOs active = %d rcvd intval 0x%X\n", __func__, mode.intval != TYPEC_ACCESSORY_NONE, mode.intval); - atomic_set(&(fsa_priv->usbc_mode), mode.intval); + if ((atomic_read(&(fsa_priv->usbc_mode)) != mode.intval) || fsa_reg_notifier) { + atomic_set(&(fsa_priv->usbc_mode), mode.intval); + fsa_reg_notifier = false; + } else { + goto done; + } switch (mode.intval) { /* add all modes FSA should notify for in here */ @@ -308,8 +315,9 @@ int fsa4480_reg_notifier(struct notifier_block *nb, * as part of the init sequence check if there is a connected * USB C analog adapter */ - dev_dbg(fsa_priv->dev, "%s: verify if USB adapter is already inserted\n", + dev_info(fsa_priv->dev, "%s: verify if USB adapter is already inserted\n", __func__); + fsa_reg_notifier = true; rc = fsa4480_usbc_analog_setup_switches(fsa_priv); regmap_update_bits(fsa_priv->regmap, FSA4480_SWITCH_CONTROL, 0x07, fsa_priv->switch_control); From 5ae660d0139de5da269aacd4eb81d6b5b4e94c40 Mon Sep 17 00:00:00 2001 From: yaozm1 Date: Mon, 4 Jul 2022 15:27:37 +0800 Subject: [PATCH 495/698] kernal config:add CONFIG_SND_SOC_AW87XXX for penang add CONFIG_SND_SOC_AW87XXX; for awinic K PA. Change-Id: I3a8b54faae9fb2adde7d4b5c748aab2eb11dca0d Signed-off-by: yaozm1 Reviewed-on: https://gerrit.mot.com/2321817 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- arch/arm64/Kconfig | 6 ++++++ .../arm64/configs/vendor/ext_config/moto-holi-penang.config | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index b0c563287c76..bcb062773076 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -1892,6 +1892,12 @@ config AW882XX_MAPSIZE_16K help Enable it only for use 16k mapsize. +config SND_SOC_AW87XXX + tristate "SoC Audio for awinic AW87XXX Smart K PA" + depends on I2C + help + This option enables support for AW87XXX Smart K PA. + config CAMERA_FLASH_PWM bool "control flash" default n diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-penang.config b/arch/arm64/configs/vendor/ext_config/moto-holi-penang.config index 8679ae6cc00f..a93e0d0db1d0 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-penang.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-penang.config @@ -19,7 +19,7 @@ CONFIG_FS_EPOLL_WAKEUP_DEBUG=y CONFIG_ZRAM_WRITEBACK=y # CONFIG_THERMAL_STATISTICS is not set # CONFIG_REGULATOR_QPNP_LCDB is not set -# CONFIG_AW882XX_PARAMS_FROM_BIN is not set # CONFIG_UFSTW is not set CONFIG_CRYPTO_CHACHA20POLY1305=y CONFIG_CAM_SENSOR_PROBE_RETRY=y +# CONFIG_SND_SOC_AW87XXX is not set From 8c5f2d862141490750416260f9d037d6d3bdadae Mon Sep 17 00:00:00 2001 From: zhaoxp3 Date: Wed, 6 Jul 2022 09:44:10 +0800 Subject: [PATCH 496/698] penang: change reserved gpio TZ protect gpio45,46,56,57 for NFC SPI, but the four of them are used for other purpose so we need to saperate them from holi baseline Change-Id: Ia2d05a1c038706741a8b00ad923afa541026334c Signed-off-by: zhaoxp3 Reviewed-on: https://gerrit.mot.com/2323872 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Wang Wang Submit-Approved: Jira Key --- drivers/pinctrl/qcom/pinctrl-holi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pinctrl/qcom/pinctrl-holi.c b/drivers/pinctrl/qcom/pinctrl-holi.c index e0a5651d0c2e..7d8e48b1d644 100644 --- a/drivers/pinctrl/qcom/pinctrl-holi.c +++ b/drivers/pinctrl/qcom/pinctrl-holi.c @@ -1538,7 +1538,7 @@ static const struct msm_pingroup holi_groups[] = { }; static const int holi_reserved_gpios[] = { -#ifdef CONFIG_RHODEC_DTB +#if defined(CONFIG_RHODEC_DTB) || defined(CONFIG_PENANG_DTB) 13, 14, 15, 16, -1 #else 13, 14, 15, 16, 45, 46, 56, 57, -1 From 20dab1640112c82bad978209fd0b107a8665f0af Mon Sep 17 00:00:00 2001 From: chenlj26 Date: Wed, 6 Jul 2022 17:03:36 +0800 Subject: [PATCH 497/698] miami: Remove unused macros CONFIG_CAMERA_FLASH_PWM details: miami use i2c to control flash but PWM Change-Id: I4bd8032d54780eaf29470cd85bb8893954b041c9 Signed-off-by: chenlj26 Reviewed-on: https://gerrit.mot.com/2324313 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Wang Liu Reviewed-by: Reviewed-by: Long Cheng Reviewed-by: Zhichao Chen Reviewed-by: Guobin Zhang Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/debug-holi-miami.config | 2 +- arch/arm64/configs/vendor/ext_config/factory-holi-miami.config | 2 +- arch/arm64/configs/vendor/ext_config/moto-holi-miami.config | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm64/configs/vendor/ext_config/debug-holi-miami.config b/arch/arm64/configs/vendor/ext_config/debug-holi-miami.config index f6674734aa68..f7dfd271a2c2 100644 --- a/arch/arm64/configs/vendor/ext_config/debug-holi-miami.config +++ b/arch/arm64/configs/vendor/ext_config/debug-holi-miami.config @@ -23,5 +23,5 @@ # CONFIG_PROVE_LOCKING is not set # CONFIG_RCU_TORTURE_TEST is not set # CONFIG_TEST_USER_COPY is not set -CONFIG_CAMERA_FLASH_PWM=y +# CONFIG_CAMERA_FLASH_PWM is not set # CONFIG_UFSTW is not set diff --git a/arch/arm64/configs/vendor/ext_config/factory-holi-miami.config b/arch/arm64/configs/vendor/ext_config/factory-holi-miami.config index ebca30acfe4d..1a5f2dfdc5e6 100644 --- a/arch/arm64/configs/vendor/ext_config/factory-holi-miami.config +++ b/arch/arm64/configs/vendor/ext_config/factory-holi-miami.config @@ -13,5 +13,5 @@ # You can check the .config file to verify that your configuration option is # being set as expected. # -CONFIG_CAMERA_FLASH_PWM=y +# CONFIG_CAMERA_FLASH_PWM is not set CONFIG_CAMERA_DISABLE_VSYNC_IRQ=y diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-miami.config b/arch/arm64/configs/vendor/ext_config/moto-holi-miami.config index 707291cdbab2..8bceb5f1ae07 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-miami.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-miami.config @@ -24,7 +24,7 @@ CONFIG_AW882XX_PARAMS_FROM_BIN=y CONFIG_AW882XX_MAPSIZE_16K=y # CONFIG_UFSTW is not set CONFIG_QUP0_SE2_AP=y -CONFIG_CAMERA_FLASH_PWM=y +# CONFIG_CAMERA_FLASH_PWM is not set CONFIG_CRYPTO_CHACHA20POLY1305=y CONFIG_CAM_SENSOR_PROBE_RETRY=y CONFIG_CAMERA_CCI_ADDR_SWITCH=y From a22f74aebcede0147589a49b2b41f586879040fe Mon Sep 17 00:00:00 2001 From: marco Ballesio Date: Fri, 5 Nov 2021 18:09:22 +0530 Subject: [PATCH 498/698] binder: BINDER_FREEZE ioctl Frozen tasks can't process binder transactions, so a way is required to inform transmitting ends of communication failures due to the frozen state of their receiving counterparts. Additionally, races are possible between transitions to frozen state and binder transactions enqueued to a specific process. Implement BINDER_FREEZE ioctl for user space to inform the binder driver about the intention to freeze or unfreeze a process. When the ioctl is called, block the caller until any pending binder transactions toward the target process are flushed. Return an error to transactions to processes marked as frozen. Change-Id: I673f757a271574c4db50c4bafe143baf1bf7e490 Signed-off-by: Marco Ballesio Co-developed-by: Todd Kjos Signed-off-by: Todd Kjos Signed-off-by: Li Li Signed-off-by: Kanagarathina kalathi SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-on: https://gerrit.mot.com/2325560 Reviewed-by: Yonghui Jia Reviewed-by: Hongshu Lou Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- drivers/android/binder.c | 160 +++++++++++++++++++++++++--- drivers/android/binder_internal.h | 17 +++ include/uapi/linux/android/binder.h | 13 +++ 3 files changed, 178 insertions(+), 12 deletions(-) diff --git a/drivers/android/binder.c b/drivers/android/binder.c index 5c9b17e41fc2..abbe565e4b07 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -201,8 +201,25 @@ static struct binder_transaction_log_entry *binder_transaction_log_add( } enum binder_deferred_state { - BINDER_DEFERRED_FLUSH = 0x01, - BINDER_DEFERRED_RELEASE = 0x02, + BINDER_DEFERRED_PUT_FILES = 0x01, + BINDER_DEFERRED_FLUSH = 0x02, + BINDER_DEFERRED_RELEASE = 0x04, +}; + +/** + * struct binder_priority - scheduler policy and priority + * @sched_policy scheduler policy + * @prio [100..139] for SCHED_NORMAL, [0..99] for FIFO/RT + * + * The binder driver supports inheriting the following scheduler policies: + * SCHED_NORMAL + * SCHED_BATCH + * SCHED_FIFO + * SCHED_RR + */ +struct binder_priority { + unsigned int sched_policy; + int prio; }; enum { @@ -1700,6 +1717,12 @@ static void binder_free_transaction(struct binder_transaction *t) if (target_proc) { binder_inner_proc_lock(target_proc); + target_proc->outstanding_txns--; + if (target_proc->outstanding_txns < 0) + pr_warn("%s: Unexpected outstanding_txns %d\n", + __func__, target_proc->outstanding_txns); + if (!target_proc->outstanding_txns && target_proc->is_frozen) + wake_up_interruptible_all(&target_proc->freeze_wait); if (t->buffer) t->buffer->transaction = NULL; binder_inner_proc_unlock(target_proc); @@ -2810,10 +2833,11 @@ static int binder_fixup_parent(struct list_head *pf_head, * If the @thread parameter is not NULL, the transaction is always queued * to the waitlist of that specific thread. * - * Return: true if the transactions was successfully queued - * false if the target process or thread is dead + * Return: 0 if the transaction was successfully queued + * BR_DEAD_REPLY if the target process or thread is dead + * BR_FROZEN_REPLY if the target process or thread is frozen */ -static bool binder_proc_transaction(struct binder_transaction *t, +static int binder_proc_transaction(struct binder_transaction *t, struct binder_proc *proc, struct binder_thread *thread) { @@ -2835,10 +2859,11 @@ static bool binder_proc_transaction(struct binder_transaction *t, binder_inner_proc_lock(proc); - if (proc->is_dead || (thread && thread->is_dead)) { + if ((proc->is_frozen && !oneway) || proc->is_dead || + (thread && thread->is_dead)) { binder_inner_proc_unlock(proc); binder_node_unlock(node); - return false; + return proc->is_frozen ? BR_FROZEN_REPLY : BR_DEAD_REPLY; } if (!thread && !pending_async) @@ -2856,10 +2881,11 @@ static bool binder_proc_transaction(struct binder_transaction *t, if (!pending_async) binder_wakeup_thread_ilocked(proc, thread, !oneway /* sync */); + proc->outstanding_txns++; binder_inner_proc_unlock(proc); binder_node_unlock(node); - return true; + return 0; } /** @@ -3566,13 +3592,16 @@ static void binder_transaction(struct binder_proc *proc, if (reply) { binder_enqueue_thread_work(thread, tcomplete); binder_inner_proc_lock(target_proc); - if (target_thread->is_dead) { + if (target_thread->is_dead || target_proc->is_frozen) { + return_error = target_thread->is_dead ? + BR_DEAD_REPLY : BR_FROZEN_REPLY; binder_inner_proc_unlock(target_proc); goto err_dead_proc_or_thread; } BUG_ON(t->buffer->async_transaction != 0); binder_pop_transaction_ilocked(target_thread, in_reply_to); binder_enqueue_thread_work_ilocked(target_thread, &t->work); + target_proc->outstanding_txns++; binder_inner_proc_unlock(target_proc); if (in_reply_to->is_nested) { spin_lock(&thread->prio_lock); @@ -3599,7 +3628,9 @@ static void binder_transaction(struct binder_proc *proc, t->from_parent = thread->transaction_stack; thread->transaction_stack = t; binder_inner_proc_unlock(proc); - if (!binder_proc_transaction(t, target_proc, target_thread)) { + return_error = binder_proc_transaction(t, + target_proc, target_thread); + if (return_error) { binder_inner_proc_lock(proc); binder_pop_transaction_ilocked(thread, t); binder_inner_proc_unlock(proc); @@ -3609,7 +3640,8 @@ static void binder_transaction(struct binder_proc *proc, BUG_ON(target_node == NULL); BUG_ON(t->buffer->async_transaction != 1); binder_enqueue_thread_work(thread, tcomplete); - if (!binder_proc_transaction(t, target_proc, NULL)) + return_error = binder_proc_transaction(t, target_proc, NULL); + if (return_error) goto err_dead_proc_or_thread; } if (target_thread) @@ -3626,7 +3658,6 @@ static void binder_transaction(struct binder_proc *proc, return; err_dead_proc_or_thread: - return_error = BR_DEAD_REPLY; return_error_line = __LINE__; binder_dequeue_work(proc, tcomplete); err_translate_failed: @@ -4861,6 +4892,9 @@ static void binder_free_proc(struct binder_proc *proc) BUG_ON(!list_empty(&proc->todo)); BUG_ON(!list_empty(&proc->delivered_death)); + if (proc->outstanding_txns) + pr_warn("%s: Unexpected outstanding_txns %d\n", + __func__, proc->outstanding_txns); device = container_of(proc->context, struct binder_device, context); if (refcount_dec_and_test(&device->ref)) { kfree(proc->context->name); @@ -4924,6 +4958,7 @@ static int binder_thread_release(struct binder_proc *proc, (t->to_thread == thread) ? "in" : "out"); if (t->to_thread == thread) { + thread->proc->outstanding_txns--; t->to_proc = NULL; t->to_thread = NULL; if (t->buffer) { @@ -5171,6 +5206,45 @@ static int binder_ioctl_get_node_debug_info(struct binder_proc *proc, return 0; } +static int binder_ioctl_freeze(struct binder_freeze_info *info, + struct binder_proc *target_proc) +{ + int ret = 0; + + if (!info->enable) { + binder_inner_proc_lock(target_proc); + target_proc->is_frozen = false; + binder_inner_proc_unlock(target_proc); + return 0; + } + + /* + * Freezing the target. Prevent new transactions by + * setting frozen state. If timeout specified, wait + * for transactions to drain. + */ + binder_inner_proc_lock(target_proc); + target_proc->is_frozen = true; + binder_inner_proc_unlock(target_proc); + + if (info->timeout_ms > 0) + ret = wait_event_interruptible_timeout( + target_proc->freeze_wait, + (!target_proc->outstanding_txns), + msecs_to_jiffies(info->timeout_ms)); + + if (!ret && target_proc->outstanding_txns) + ret = -EAGAIN; + + if (ret < 0) { + binder_inner_proc_lock(target_proc); + target_proc->is_frozen = false; + binder_inner_proc_unlock(target_proc); + } + + return ret; +} + static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { int ret; @@ -5289,6 +5363,66 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) } break; } + case BINDER_FREEZE: { + struct binder_freeze_info info; + struct binder_proc **target_procs = NULL, *target_proc; + int target_procs_count = 0, i = 0; + + ret = 0; + + if (copy_from_user(&info, ubuf, sizeof(info))) { + ret = -EFAULT; + goto err; + } + + mutex_lock(&binder_procs_lock); + hlist_for_each_entry(target_proc, &binder_procs, proc_node) { + if (target_proc->pid == info.pid) + target_procs_count++; + } + + if (target_procs_count == 0) { + mutex_unlock(&binder_procs_lock); + ret = -EINVAL; + goto err; + } + + target_procs = kcalloc(target_procs_count, + sizeof(struct binder_proc *), + GFP_KERNEL); + + if (!target_procs) { + mutex_unlock(&binder_procs_lock); + ret = -ENOMEM; + goto err; + } + + hlist_for_each_entry(target_proc, &binder_procs, proc_node) { + if (target_proc->pid != info.pid) + continue; + + binder_inner_proc_lock(target_proc); + target_proc->tmp_ref++; + binder_inner_proc_unlock(target_proc); + + target_procs[i++] = target_proc; + } + mutex_unlock(&binder_procs_lock); + + for (i = 0; i < target_procs_count; i++) { + if (ret >= 0) + ret = binder_ioctl_freeze(&info, + target_procs[i]); + + binder_proc_dec_tmpref(target_procs[i]); + } + + kfree(target_procs); + + if (ret < 0) + goto err; + break; + } default: ret = -EINVAL; goto err; @@ -5398,6 +5532,7 @@ static int binder_open(struct inode *nodp, struct file *filp) proc->tsk = current->group_leader; eproc->cred = get_cred(filp->f_cred); INIT_LIST_HEAD(&proc->todo); + init_waitqueue_head(&proc->freeze_wait); if (binder_supported_policy(current->policy)) { proc->default_priority.sched_policy = current->policy; proc->default_priority.prio = current->normal_prio; @@ -5617,6 +5752,7 @@ static void binder_deferred_release(struct binder_proc *proc) proc->tmp_ref++; proc->is_dead = true; + proc->is_frozen = false; threads = 0; active_transactions = 0; while ((n = rb_first(&proc->threads))) { diff --git a/drivers/android/binder_internal.h b/drivers/android/binder_internal.h index 68f4d7b5e7f3..ab8aa6e6da3b 100644 --- a/drivers/android/binder_internal.h +++ b/drivers/android/binder_internal.h @@ -390,13 +390,25 @@ enum binder_prio_state { * (invariant after initialized) * @tsk task_struct for group_leader of process * (invariant after initialized) + * @files files_struct for process + * (protected by @files_lock) + * @files_lock mutex to protect @files * @deferred_work_node: element for binder_deferred_list * (protected by binder_deferred_lock) * @deferred_work: bitmap of deferred work to perform * (protected by binder_deferred_lock) + * @outstanding_txns: number of transactions to be transmitted before + * processes in freeze_wait are woken up + * (protected by @inner_lock) * @is_dead: process is dead and awaiting free * when outstanding transactions are cleaned up * (protected by @inner_lock) + * @is_frozen: process is frozen and unable to service + * binder transactions + * (protected by @inner_lock) + * @freeze_wait: waitqueue of processes waiting for all outstanding + * transactions to be processed + * (protected by @inner_lock) * @todo: list of work for this process * (protected by @inner_lock) * @stats: per-process binder statistics @@ -435,9 +447,14 @@ struct binder_proc { struct list_head waiting_threads; int pid; struct task_struct *tsk; + struct files_struct *files; + struct mutex files_lock; struct hlist_node deferred_work_node; int deferred_work; + int outstanding_txns; bool is_dead; + bool is_frozen; + wait_queue_head_t freeze_wait; struct list_head todo; struct binder_stats stats; diff --git a/include/uapi/linux/android/binder.h b/include/uapi/linux/android/binder.h index 25d12f7ab3f1..88c99a1abc5d 100644 --- a/include/uapi/linux/android/binder.h +++ b/include/uapi/linux/android/binder.h @@ -265,6 +265,12 @@ struct binder_node_info_for_ref { __u32 reserved3; }; +struct binder_freeze_info { + __u32 pid; + __u32 enable; + __u32 timeout_ms; +}; + #define BINDER_WRITE_READ _IOWR('b', 1, struct binder_write_read) #define BINDER_SET_IDLE_TIMEOUT _IOW('b', 3, __s64) #define BINDER_SET_MAX_THREADS _IOW('b', 5, __u32) @@ -275,6 +281,7 @@ struct binder_node_info_for_ref { #define BINDER_GET_NODE_DEBUG_INFO _IOWR('b', 11, struct binder_node_debug_info) #define BINDER_GET_NODE_INFO_FOR_REF _IOWR('b', 12, struct binder_node_info_for_ref) #define BINDER_SET_CONTEXT_MGR_EXT _IOW('b', 13, struct flat_binder_object) +#define BINDER_FREEZE _IOW('b', 14, struct binder_freeze_info) /* * NOTE: Two special error codes you should check for when calling @@ -456,6 +463,12 @@ enum binder_driver_return_protocol { * The the last transaction (either a bcTRANSACTION or * a bcATTEMPT_ACQUIRE) failed (e.g. out of memory). No parameters. */ + + BR_FROZEN_REPLY = _IO('r', 18), + /* + * The target of the last transaction (either a bcTRANSACTION or + * a bcATTEMPT_ACQUIRE) is frozen. No parameters. + */ }; enum binder_driver_command_protocol { From e816fb5085669bb1d3bcc232ecc2ffa7655e4c95 Mon Sep 17 00:00:00 2001 From: Marco Ballesio Date: Wed, 17 Nov 2021 14:35:07 +0530 Subject: [PATCH 499/698] FROMGIT: binder: BINDER_GET_FROZEN_INFO ioctl User space needs to know if binder transactions occurred to frozen processes. Introduce a new BINDER_GET_FROZEN ioctl and keep track of transactions occurring to frozen proceses. Bug: 180989544 (cherry picked from commit c55019c24b22d6770bd8e2f12fbddf3f83d37547 git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc.git char-misc-testing) Signed-off-by: Marco Ballesio Signed-off-by: Li Li Acked-by: Todd Kjos Link: https://lore.kernel.org/r/20210316011630.1121213-4-dualli@chromium.org Signed-off-by: Greg Kroah-Hartman Change-Id: If2fb07bc002940d27ec9ec060504940a71c654e4 Reviewed-on: https://gerrit.mot.com/2119046 Reviewed-by: Vijayakumar Gn Reviewed-by: Ling Jin SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Submit-Approved: Jira Key Signed-off-by: Murilo Alves Reviewed-on: https://gerrit.mot.com/2132252 Reviewed-by: Huosheng Liao Reviewed-on: https://gerrit.mot.com/2161796 Reviewed-by: Zhangqing Huang Reviewed-by: Xiangpo Zhao Reviewed-on: https://gerrit.mot.com/2325561 Reviewed-by: Yonghui Jia Reviewed-by: Hongshu Lou --- drivers/android/binder.c | 76 +++++++++++++++++++++-------- drivers/android/binder_internal.h | 6 +++ include/uapi/linux/android/binder.h | 7 +++ 3 files changed, 70 insertions(+), 19 deletions(-) diff --git a/drivers/android/binder.c b/drivers/android/binder.c index abbe565e4b07..73886d60749c 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -201,25 +201,8 @@ static struct binder_transaction_log_entry *binder_transaction_log_add( } enum binder_deferred_state { - BINDER_DEFERRED_PUT_FILES = 0x01, - BINDER_DEFERRED_FLUSH = 0x02, - BINDER_DEFERRED_RELEASE = 0x04, -}; - -/** - * struct binder_priority - scheduler policy and priority - * @sched_policy scheduler policy - * @prio [100..139] for SCHED_NORMAL, [0..99] for FIFO/RT - * - * The binder driver supports inheriting the following scheduler policies: - * SCHED_NORMAL - * SCHED_BATCH - * SCHED_FIFO - * SCHED_RR - */ -struct binder_priority { - unsigned int sched_policy; - int prio; + BINDER_DEFERRED_FLUSH = 0x01, + BINDER_DEFERRED_RELEASE = 0x02, }; enum { @@ -2858,6 +2841,10 @@ static int binder_proc_transaction(struct binder_transaction *t, } binder_inner_proc_lock(proc); + if (proc->is_frozen) { + proc->sync_recv |= !oneway; + proc->async_recv |= oneway; + } if ((proc->is_frozen && !oneway) || proc->is_dead || (thread && thread->is_dead)) { @@ -5213,6 +5200,8 @@ static int binder_ioctl_freeze(struct binder_freeze_info *info, if (!info->enable) { binder_inner_proc_lock(target_proc); + target_proc->sync_recv = false; + target_proc->async_recv = false; target_proc->is_frozen = false; binder_inner_proc_unlock(target_proc); return 0; @@ -5224,6 +5213,8 @@ static int binder_ioctl_freeze(struct binder_freeze_info *info, * for transactions to drain. */ binder_inner_proc_lock(target_proc); + target_proc->sync_recv = false; + target_proc->async_recv = false; target_proc->is_frozen = true; binder_inner_proc_unlock(target_proc); @@ -5245,6 +5236,33 @@ static int binder_ioctl_freeze(struct binder_freeze_info *info, return ret; } +static int binder_ioctl_get_freezer_info( + struct binder_frozen_status_info *info) +{ + struct binder_proc *target_proc; + bool found = false; + + info->sync_recv = 0; + info->async_recv = 0; + + mutex_lock(&binder_procs_lock); + hlist_for_each_entry(target_proc, &binder_procs, proc_node) { + if (target_proc->pid == info->pid) { + found = true; + binder_inner_proc_lock(target_proc); + info->sync_recv |= target_proc->sync_recv; + info->async_recv |= target_proc->async_recv; + binder_inner_proc_unlock(target_proc); + } + } + mutex_unlock(&binder_procs_lock); + + if (!found) + return -EINVAL; + + return 0; +} + static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { int ret; @@ -5423,6 +5441,24 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) goto err; break; } + case BINDER_GET_FROZEN_INFO: { + struct binder_frozen_status_info info; + + if (copy_from_user(&info, ubuf, sizeof(info))) { + ret = -EFAULT; + goto err; + } + + ret = binder_ioctl_get_freezer_info(&info); + if (ret < 0) + goto err; + + if (copy_to_user(ubuf, &info, sizeof(info))) { + ret = -EFAULT; + goto err; + } + break; + } default: ret = -EINVAL; goto err; @@ -5753,6 +5789,8 @@ static void binder_deferred_release(struct binder_proc *proc) proc->is_dead = true; proc->is_frozen = false; + proc->sync_recv = false; + proc->async_recv = false; threads = 0; active_transactions = 0; while ((n = rb_first(&proc->threads))) { diff --git a/drivers/android/binder_internal.h b/drivers/android/binder_internal.h index ab8aa6e6da3b..636d0f155d31 100644 --- a/drivers/android/binder_internal.h +++ b/drivers/android/binder_internal.h @@ -406,6 +406,10 @@ enum binder_prio_state { * @is_frozen: process is frozen and unable to service * binder transactions * (protected by @inner_lock) + * @sync_recv: process received sync transactions since last frozen + * (protected by @inner_lock) + * @async_recv: process received async transactions since last frozen + * (protected by @inner_lock) * @freeze_wait: waitqueue of processes waiting for all outstanding * transactions to be processed * (protected by @inner_lock) @@ -454,6 +458,8 @@ struct binder_proc { int outstanding_txns; bool is_dead; bool is_frozen; + bool sync_recv; + bool async_recv; wait_queue_head_t freeze_wait; struct list_head todo; diff --git a/include/uapi/linux/android/binder.h b/include/uapi/linux/android/binder.h index 88c99a1abc5d..926b05cf8e2c 100644 --- a/include/uapi/linux/android/binder.h +++ b/include/uapi/linux/android/binder.h @@ -271,6 +271,12 @@ struct binder_freeze_info { __u32 timeout_ms; }; +struct binder_frozen_status_info { + __u32 pid; + __u32 sync_recv; + __u32 async_recv; +}; + #define BINDER_WRITE_READ _IOWR('b', 1, struct binder_write_read) #define BINDER_SET_IDLE_TIMEOUT _IOW('b', 3, __s64) #define BINDER_SET_MAX_THREADS _IOW('b', 5, __u32) @@ -282,6 +288,7 @@ struct binder_freeze_info { #define BINDER_GET_NODE_INFO_FOR_REF _IOWR('b', 12, struct binder_node_info_for_ref) #define BINDER_SET_CONTEXT_MGR_EXT _IOW('b', 13, struct flat_binder_object) #define BINDER_FREEZE _IOW('b', 14, struct binder_freeze_info) +#define BINDER_GET_FROZEN_INFO _IOWR('b', 15, struct binder_frozen_status_info) /* * NOTE: Two special error codes you should check for when calling From 06a2ad3c313911b9d88741274c9cbf6210f90a95 Mon Sep 17 00:00:00 2001 From: Li Li Date: Tue, 7 Sep 2021 16:12:53 -0700 Subject: [PATCH 500/698] BACKPORT: FROMGIT: binder: fix freeze race Mot-CRs-fixed: (CR) Currently cgroup freezer is used to freeze the application threads, and BINDER_FREEZE is used to freeze the corresponding binder interface. There's already a mechanism in ioctl(BINDER_FREEZE) to wait for any existing transactions to drain out before actually freezing the binder interface. But freezing an app requires 2 steps, freezing the binder interface with ioctl(BINDER_FREEZE) and then freezing the application main threads with cgroupfs. This is not an atomic operation. The following race issue might happen. 1) Binder interface is frozen by ioctl(BINDER_FREEZE); 2) Main thread A initiates a new sync binder transaction to process B; 3) Main thread A is frozen by "echo 1 > cgroup.freeze"; 4) The response from process B reaches the frozen thread, which will unexpectedly fail. This patch provides a mechanism to check if there's any new pending transaction happening between ioctl(BINDER_FREEZE) and freezing the main thread. If there's any, the main thread freezing operation can be rolled back to finish the pending transaction. Furthermore, the response might reach the binder driver before the rollback actually happens. That will still cause failed transaction. As the other process doesn't wait for another response of the response, the response transaction failure can be fixed by treating the response transaction l(CR) an oneway/async one, allowing it to reach the frozen thread. And it will be consumed when the thread gets unfrozen later. NOTE: This patch reuses the existing definition of struct binder_frozen_status_info but expands the bit assignments of __u32 member sync_recv. To ensure backward compatibility, bit 0 of sync_recv still indicates there's an outstanding sync binder transaction. This patch adds new information to bit 1 of sync_recv, indicating the binder transaction happens exactly when there's a race. If an existing userspace app runs on a new kernel, a sync binder call will set bit 0 of sync_recv so ioctl(BINDER_GET_FROZEN_INFO) still return the expected value (true). The app just doesn't check bit 1 intentionally so it doesn't have the ability to tell if there's a race. This behavior is aligned with what happens on an old kernel which doesn't set bit 1 at all. A new userspace app can 1) check bit 0 to know if there's a sync binder transaction happened when being frozen - same as before; and 2) check bit 1 to know if that sync binder transaction happened exactly when there's a race - a new information for rollback decision. Fixes: 432ff1e91694 ("binder: BINDER_FREEZE ioctl") Acked-by: Todd Kjos Cc: stable Signed-off-by: Li Li Test: stress test with apps being frozen and initiating binder calls at the same time, confirmed the pending transactions succeeded. Link: https://lore.kernel.org/r/20210910164210.2282716-2-dualli@chromium.org Signed-off-by: Greg Kroah-Hartman Bug: 198493121 (cherry picked from commit b564171ade70570b7f335fa8ed17adb28409e3ac git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc.git char-misc-linus) Reviewed-on: https://gerrit.mot.com/2140525 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key Reviewed-on: https://gerrit.mot.com/2161797 Reviewed-by: Zhangqing Huang Reviewed-by: Xiangpo Zhao Change-Id: I2d3ac4dd1c11d7e0b4ba1c2fb97d183d4d3c7d6f Reviewed-on: https://gerrit.mot.com/2325573 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Reviewed-by: Yonghui Jia Reviewed-by: Hongshu Lou Reviewed-by: Huosheng Liao Tested-by: Jira Key Submit-Approved: Jira Key --- drivers/android/binder.c | 35 ++++++++++++++++++++++++----- drivers/android/binder_internal.h | 2 ++ include/uapi/linux/android/binder.h | 7 ++++++ 3 files changed, 38 insertions(+), 6 deletions(-) diff --git a/drivers/android/binder.c b/drivers/android/binder.c index 73886d60749c..77b06f304754 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -3579,9 +3579,8 @@ static void binder_transaction(struct binder_proc *proc, if (reply) { binder_enqueue_thread_work(thread, tcomplete); binder_inner_proc_lock(target_proc); - if (target_thread->is_dead || target_proc->is_frozen) { - return_error = target_thread->is_dead ? - BR_DEAD_REPLY : BR_FROZEN_REPLY; + if (target_thread->is_dead) { + return_error = BR_DEAD_REPLY; binder_inner_proc_unlock(target_proc); goto err_dead_proc_or_thread; } @@ -5193,6 +5192,22 @@ static int binder_ioctl_get_node_debug_info(struct binder_proc *proc, return 0; } +static bool binder_txns_pending_ilocked(struct binder_proc *proc) +{ + struct rb_node *n; + struct binder_thread *thread; + + if (proc->outstanding_txns > 0) + return true; + + for (n = rb_first(&proc->threads); n; n = rb_next(n)) { + thread = rb_entry(n, struct binder_thread, rb_node); + if (thread->transaction_stack) + return true; + } + return false; +} + static int binder_ioctl_freeze(struct binder_freeze_info *info, struct binder_proc *target_proc) { @@ -5224,8 +5239,13 @@ static int binder_ioctl_freeze(struct binder_freeze_info *info, (!target_proc->outstanding_txns), msecs_to_jiffies(info->timeout_ms)); - if (!ret && target_proc->outstanding_txns) - ret = -EAGAIN; + /* Check pending transactions that wait for reply */ + if (ret >= 0) { + binder_inner_proc_lock(target_proc); + if (binder_txns_pending_ilocked(target_proc)) + ret = -EAGAIN; + binder_inner_proc_unlock(target_proc); + } if (ret < 0) { binder_inner_proc_lock(target_proc); @@ -5241,6 +5261,7 @@ static int binder_ioctl_get_freezer_info( { struct binder_proc *target_proc; bool found = false; + __u32 txns_pending; info->sync_recv = 0; info->async_recv = 0; @@ -5250,7 +5271,9 @@ static int binder_ioctl_get_freezer_info( if (target_proc->pid == info->pid) { found = true; binder_inner_proc_lock(target_proc); - info->sync_recv |= target_proc->sync_recv; + txns_pending = binder_txns_pending_ilocked(target_proc); + info->sync_recv |= target_proc->sync_recv | + (txns_pending << 1); info->async_recv |= target_proc->async_recv; binder_inner_proc_unlock(target_proc); } diff --git a/drivers/android/binder_internal.h b/drivers/android/binder_internal.h index 636d0f155d31..9f4392458792 100644 --- a/drivers/android/binder_internal.h +++ b/drivers/android/binder_internal.h @@ -407,6 +407,8 @@ enum binder_prio_state { * binder transactions * (protected by @inner_lock) * @sync_recv: process received sync transactions since last frozen + * bit 0: received sync transaction after being frozen + * bit 1: new pending sync transaction during freezing * (protected by @inner_lock) * @async_recv: process received async transactions since last frozen * (protected by @inner_lock) diff --git a/include/uapi/linux/android/binder.h b/include/uapi/linux/android/binder.h index 926b05cf8e2c..14340b0267b7 100644 --- a/include/uapi/linux/android/binder.h +++ b/include/uapi/linux/android/binder.h @@ -273,7 +273,14 @@ struct binder_freeze_info { struct binder_frozen_status_info { __u32 pid; + + /* process received sync transactions since last frozen + * bit 0: received sync transaction after being frozen + * bit 1: new pending sync transaction during freezing + */ __u32 sync_recv; + + /* process received async transactions since last frozen */ __u32 async_recv; }; From 8e96178c997a667f50bd2458492d63de531ef878 Mon Sep 17 00:00:00 2001 From: duxu1 Date: Fri, 8 Jul 2022 17:30:08 +0800 Subject: [PATCH 501/698] Enable CONFIG_SLUB_DEBUG_ON on userdebug build Enable CONFIG_SLUB_DEBUG_ON on userdebug build to debug wlan tx timeout issue. CONFIG_SLUB_DEBUG_ON=y Change-Id: Ifa80d98e21c9649caf13f647027987f4a0c25d0f Signed-off-by: duxu1 Reviewed-on: https://gerrit.mot.com/2327322 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Hongshu Lou Reviewed-by: Zhizhong Ge Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/debug-holi.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/configs/vendor/ext_config/debug-holi.config b/arch/arm64/configs/vendor/ext_config/debug-holi.config index c23f9114764a..f7ee34778e71 100644 --- a/arch/arm64/configs/vendor/ext_config/debug-holi.config +++ b/arch/arm64/configs/vendor/ext_config/debug-holi.config @@ -16,7 +16,7 @@ CONFIG_DEBUG_FS=y CONFIG_CPU_FREQ_STAT=y # CONFIG_EDAC_KRYO_ARM64_PANIC_ON_CE is not set -# CONFIG_SLUB_DEBUG_ON is not set +CONFIG_SLUB_DEBUG_ON=y # CONFIG_SLUB_DEBUG_PANIC_ON is not set # CONFIG_CORESIGHT is not set # CONFIG_DEBUG_PAGEALLOC is not set From 05ea5309b7f9bda899df09a826409cc427e64662 Mon Sep 17 00:00:00 2001 From: yaozm1 Date: Thu, 14 Jul 2022 10:17:26 +0800 Subject: [PATCH 502/698] penang:kernel config:enable audio config enable awinic K pa config; for penang evb bringup. Change-Id: I29b26c8ae207e3ce71c6a7eed3f14e1723eee5b1 Signed-off-by: yaozm1 Reviewed-on: https://gerrit.mot.com/2333123 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Wang Wang Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi-penang.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-penang.config b/arch/arm64/configs/vendor/ext_config/moto-holi-penang.config index a93e0d0db1d0..9e00aaf4f414 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-penang.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-penang.config @@ -22,4 +22,4 @@ CONFIG_ZRAM_WRITEBACK=y # CONFIG_UFSTW is not set CONFIG_CRYPTO_CHACHA20POLY1305=y CONFIG_CAM_SENSOR_PROBE_RETRY=y -# CONFIG_SND_SOC_AW87XXX is not set +CONFIG_SND_SOC_AW87XXX=m From d3e91327229534aa5c966db56334cdf7cd0e405a Mon Sep 17 00:00:00 2001 From: zhangjun10 Date: Tue, 19 Jul 2022 14:49:03 +0800 Subject: [PATCH 503/698] : Enable nfc for Penang Enable nfc for pn557 on Penang Change-Id: Idd7bcd332a0fa5102bca7a6b6b97681b607ad478 Signed-off-by: zhangjun10 Reviewed-on: https://gerrit.mot.com/2337430 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi-penang.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-penang.config b/arch/arm64/configs/vendor/ext_config/moto-holi-penang.config index 9e00aaf4f414..e4cc6fb2a747 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-penang.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-penang.config @@ -23,3 +23,4 @@ CONFIG_ZRAM_WRITEBACK=y CONFIG_CRYPTO_CHACHA20POLY1305=y CONFIG_CAM_SENSOR_PROBE_RETRY=y CONFIG_SND_SOC_AW87XXX=m +CONFIG_NFC_QTI_I2C=m From 77cd16286f4b69587a7bd8d5252029bdf9c80388 Mon Sep 17 00:00:00 2001 From: "hq_yexiuyon.wb_tmp" Date: Thu, 4 Aug 2022 18:19:52 +0800 Subject: [PATCH 504/698] TP: The TP ft8057 close build kernel Modify: fix TP for ft8057 , add TP fix for factory Change-Id: I34aec889e04b44ab61b1dbb300391d4e02a41605 Signed-off-by: hq_yexiuyon.wb_tmp Reviewed-on: https://gerrit.mot.com/2354323 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Wei Deng Reviewed-by: Wang Wang Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi-penang.config | 1 + drivers/input/touchscreen/focaltech_touch/focaltech_core.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-penang.config b/arch/arm64/configs/vendor/ext_config/moto-holi-penang.config index e4cc6fb2a747..e5e3b88dd7ef 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-penang.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-penang.config @@ -24,3 +24,4 @@ CONFIG_CRYPTO_CHACHA20POLY1305=y CONFIG_CAM_SENSOR_PROBE_RETRY=y CONFIG_SND_SOC_AW87XXX=m CONFIG_NFC_QTI_I2C=m +# CONFIG_TOUCHSCREEN_FTS is not set diff --git a/drivers/input/touchscreen/focaltech_touch/focaltech_core.c b/drivers/input/touchscreen/focaltech_touch/focaltech_core.c index 823caa4fdc8e..c94a1a361795 100644 --- a/drivers/input/touchscreen/focaltech_touch/focaltech_core.c +++ b/drivers/input/touchscreen/focaltech_touch/focaltech_core.c @@ -70,7 +70,7 @@ /***************************************************************************** * Private constant and macro definitions using #define *****************************************************************************/ -#define FTS_DRIVER_NAME "fts_ts" +#define FTS_DRIVER_NAME "fts_tp" #define INTERVAL_READ_REG 200 /* unit:ms */ #define TIMEOUT_READ_REG 1000 /* unit:ms */ #if FTS_POWER_SOURCE_CUST_EN From 9b3bad04efa2228323b92aa1623a0dd76e067727 Mon Sep 17 00:00:00 2001 From: zhangjun10 Date: Mon, 22 Aug 2022 11:38:29 +0800 Subject: [PATCH 505/698] : penang : Enable NFC ESE SPI on TZ SPI on TZ need GPIO 45,46,56,57 need remove it for reserved list Change-Id: I3b7875573bd24f7ef8a5aad6140fdb044ad17def Signed-off-by: zhangjun10 Reviewed-on: https://gerrit.mot.com/2367734 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- drivers/pinctrl/qcom/pinctrl-holi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pinctrl/qcom/pinctrl-holi.c b/drivers/pinctrl/qcom/pinctrl-holi.c index 7d8e48b1d644..d8e65183092a 100644 --- a/drivers/pinctrl/qcom/pinctrl-holi.c +++ b/drivers/pinctrl/qcom/pinctrl-holi.c @@ -1538,7 +1538,7 @@ static const struct msm_pingroup holi_groups[] = { }; static const int holi_reserved_gpios[] = { -#if defined(CONFIG_RHODEC_DTB) || defined(CONFIG_PENANG_DTB) +#if defined(CONFIG_RHODEC_DTB) 13, 14, 15, 16, -1 #else 13, 14, 15, 16, 45, 46, 56, 57, -1 From 2be82f3e94f9bc5bb95f21571c828e3f8d451fa0 Mon Sep 17 00:00:00 2001 From: liujg6 Date: Fri, 5 Aug 2022 10:43:47 +0800 Subject: [PATCH 506/698] arm64/configs: add init configs for pnangn [Details] Add initial extra config files for penang5G NA Change-Id: I0c05fd818d88293161688fcb61c3c4bd72572f56 Reviewed-on: https://gerrit.mot.com/2355010 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Submit-Approved: Jira Key Tested-by: Jira Key Reviewed-by: Xianhong Li (cherry picked from commit f737e24a8dd2d127022789641f83045e9a8e68e0) Reviewed-on: https://gerrit.mot.com/2368040 Reviewed-by: Wang Wang --- .../ext_config/debug-holi-pnangn.config | 26 +++++++++++++++++++ .../ext_config/factory-holi-pnangn.config | 16 ++++++++++++ .../vendor/ext_config/moto-holi-pnangn.config | 26 +++++++++++++++++++ drivers/soc/qcom/Kconfig | 8 ++++++ 4 files changed, 76 insertions(+) create mode 100644 arch/arm64/configs/vendor/ext_config/debug-holi-pnangn.config create mode 100644 arch/arm64/configs/vendor/ext_config/factory-holi-pnangn.config create mode 100644 arch/arm64/configs/vendor/ext_config/moto-holi-pnangn.config diff --git a/arch/arm64/configs/vendor/ext_config/debug-holi-pnangn.config b/arch/arm64/configs/vendor/ext_config/debug-holi-pnangn.config new file mode 100644 index 000000000000..018b945c19d3 --- /dev/null +++ b/arch/arm64/configs/vendor/ext_config/debug-holi-pnangn.config @@ -0,0 +1,26 @@ +# +# Please avoid changing the Qualcomm defconfig files and use this file to +# add any Motorola-specific configuration changes that are applicable to +# userdebug, eng, and user builds. +# +# After building, a list of all of the config files that are used can be found +# at the top of: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/mapphone_defconfig +# +# The actual output of the kernel configuration system can be found at: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/.config +# +# You can check the .config file to verify that your configuration option is +# being set as expected. +# + +# CONFIG_CGROUP_DEBUG is not set +# CONFIG_CLEANCACHE is not set +# CONFIG_CMA_ALLOW_WRITE_DEBUGFS is not set +# CONFIG_CMA_DEBUG is not set +# CONFIG_PREEMPTIRQ_EVENTS is not set +# CONFIG_PREEMPT_TRACER is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_TEST_USER_COPY is not set +# CONFIG_UFSTW is not set diff --git a/arch/arm64/configs/vendor/ext_config/factory-holi-pnangn.config b/arch/arm64/configs/vendor/ext_config/factory-holi-pnangn.config new file mode 100644 index 000000000000..cc7be9152bdd --- /dev/null +++ b/arch/arm64/configs/vendor/ext_config/factory-holi-pnangn.config @@ -0,0 +1,16 @@ +# +# Please avoid changing the Qualcomm defconfig files and use this file to +# add any Motorola-specific configuration changes that are applicable to +# userdebug, eng, and user builds. +# +# After building, a list of all of the config files that are used can be found +# at the top of: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/mapphone_defconfig +# +# The actual output of the kernel configuration system can be found at: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/.config +# +# You can check the .config file to verify that your configuration option is +# being set as expected. +# +CONFIG_CAMERA_DISABLE_VSYNC_IRQ=y diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-pnangn.config b/arch/arm64/configs/vendor/ext_config/moto-holi-pnangn.config new file mode 100644 index 000000000000..b5a8186cd7be --- /dev/null +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-pnangn.config @@ -0,0 +1,26 @@ +# +# Please avoid changing the Qualcomm defconfig files and use this file to +# add any Motorola-specific configuration changes that are applicable to +# userdebug, eng, and user builds. +# +# After building, a list of all of the config files that are used can be found +# at the top of: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/mapphone_defconfig +# +# The actual output of the kernel configuration system can be found at: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/.config +# +# You can check the .config file to verify that your configuration option is +# being set as expected. +# +CONFIG_PNANGN_DTB=y +# CONFIG_NFC_QTI_I2C is not set +CONFIG_FS_EPOLL_WAKEUP_DEBUG=y +CONFIG_ZRAM_WRITEBACK=y +# CONFIG_THERMAL_STATISTICS is not set +# CONFIG_REGULATOR_QPNP_LCDB is not set +# CONFIG_UFSTW is not set +CONFIG_CRYPTO_CHACHA20POLY1305=y +CONFIG_CAM_SENSOR_PROBE_RETRY=y +CONFIG_SND_SOC_AW87XXX=m +CONFIG_NFC_QTI_I2C=m diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index 5b0e668de248..3f45409a5ef3 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -102,6 +102,14 @@ config PENANG_DTB Only include PENANG specific DTBs to limit the number that get built during kernel compilation. +config PNANGN_DTB + depends on ARCH_QCOM + default n + bool "PNANGN DTBs" + help + Only include PNANGN specific DTBs to limit the number that + get built during kernel compilation. + config RHODEP_DTB depends on ARCH_QCOM default n From a2bc7d6a71ca9eed72b1195de7bcb6b913eac9d1 Mon Sep 17 00:00:00 2001 From: guoyf2 Date: Tue, 23 Aug 2022 13:44:08 +0800 Subject: [PATCH 507/698] arm64/configs: use aw882xx for pnangn changes: pnangn use aw88261 smartpa Change-Id: I279449c0e26431d1bf3dbdc941ddeb03e1ce3bdc Signed-off-by: guoyf2 Reviewed-on: https://gerrit.mot.com/2368810 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Yunfei Guo Reviewed-by: Hujun Liao Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi-pnangn.config | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-pnangn.config b/arch/arm64/configs/vendor/ext_config/moto-holi-pnangn.config index b5a8186cd7be..847cefe1b0da 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-pnangn.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-pnangn.config @@ -22,5 +22,8 @@ CONFIG_ZRAM_WRITEBACK=y # CONFIG_UFSTW is not set CONFIG_CRYPTO_CHACHA20POLY1305=y CONFIG_CAM_SENSOR_PROBE_RETRY=y -CONFIG_SND_SOC_AW87XXX=m +# CONFIG_SND_SOC_AW87XXX is not set +CONFIG_AW882XX_STEREO_SMARTPA=y +CONFIG_AW882XX_PARAMS_FROM_BIN=y +CONFIG_AW882XX_MAPSIZE_16K=y CONFIG_NFC_QTI_I2C=m From cab90b27c838fd3f6a9ab881551e1848732068eb Mon Sep 17 00:00:00 2001 From: hujing3 Date: Tue, 23 Aug 2022 14:01:35 +0800 Subject: [PATCH 508/698] dts/pnangn: disable useless TP configs to avoid confict dts/pnangn: disable useless TP configs to avoid confict Change-Id: I6721695e98dbb66c48f14d017290f3b2d26bf236 Signed-off-by: hujing3 Reviewed-on: https://gerrit.mot.com/2368825 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Wang Wang Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi-pnangn.config | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-pnangn.config b/arch/arm64/configs/vendor/ext_config/moto-holi-pnangn.config index 847cefe1b0da..144ef69061ad 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-pnangn.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-pnangn.config @@ -19,6 +19,11 @@ CONFIG_FS_EPOLL_WAKEUP_DEBUG=y CONFIG_ZRAM_WRITEBACK=y # CONFIG_THERMAL_STATISTICS is not set # CONFIG_REGULATOR_QPNP_LCDB is not set +# CONFIG_TOUCHSCREEN_SYNAPTICS_TCM is not set +# CONFIG_TOUCHSCREEN_SYNAPTICS_DSX is not set +# CONFIG_TOUCHSCREEN_FTS is not set +# CONFIG_TOUCHSCREEN_FTS_DIRECTORY is not set +# CONFIG_TOUCHSCREEN_NT36XXX is not set # CONFIG_UFSTW is not set CONFIG_CRYPTO_CHACHA20POLY1305=y CONFIG_CAM_SENSOR_PROBE_RETRY=y From 54b29dd3e6fafff7ec7ac3d817fed99c958aebd7 Mon Sep 17 00:00:00 2001 From: zhangpei5 Date: Thu, 25 Aug 2022 10:44:48 +0800 Subject: [PATCH 509/698] disable CONFIG_SLUB_DEBUG_ON on penang disable config on penang debug Change-Id: I0ba52b88d47c3f296adc83fa3a7dedf9a9ea7360 Reviewed-on: https://gerrit.mot.com/2370806 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Guolin Wang Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/debug-holi-penang.config | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/configs/vendor/ext_config/debug-holi-penang.config b/arch/arm64/configs/vendor/ext_config/debug-holi-penang.config index 018b945c19d3..95c989c10a1b 100644 --- a/arch/arm64/configs/vendor/ext_config/debug-holi-penang.config +++ b/arch/arm64/configs/vendor/ext_config/debug-holi-penang.config @@ -24,3 +24,5 @@ # CONFIG_RCU_TORTURE_TEST is not set # CONFIG_TEST_USER_COPY is not set # CONFIG_UFSTW is not set + +# CONFIG_SLUB_DEBUG_ON is not set From 665a9f969ce9d3e9f4bacfd59f979d97108aa090 Mon Sep 17 00:00:00 2001 From: longc105 Date: Fri, 26 Aug 2022 00:53:16 +0800 Subject: [PATCH 510/698] driver-kernel: Penang5G NA: change reserved gpio for camera detials: change reserved gpio TZ protect gpio45,46,56,57 for NFC SPI, but the four of them are used for other purpose so we need to saperate them from holi baseline Change-Id: Id22587c488a7ef3e63ffd9c090cd56a85b61bf05 Signed-off-by: longc105 Reviewed-on: https://gerrit.mot.com/2371429 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Wang Liu Reviewed-by: Reviewed-by: Reviewed-by: Long Cheng Reviewed-by: Zhichao Chen Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- drivers/pinctrl/qcom/pinctrl-holi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pinctrl/qcom/pinctrl-holi.c b/drivers/pinctrl/qcom/pinctrl-holi.c index d8e65183092a..73f7eb9145b9 100644 --- a/drivers/pinctrl/qcom/pinctrl-holi.c +++ b/drivers/pinctrl/qcom/pinctrl-holi.c @@ -1538,7 +1538,7 @@ static const struct msm_pingroup holi_groups[] = { }; static const int holi_reserved_gpios[] = { -#if defined(CONFIG_RHODEC_DTB) +#if defined(CONFIG_RHODEC_DTB)||defined(CONFIG_PNANGN_DTB) 13, 14, 15, 16, -1 #else 13, 14, 15, 16, 45, 46, 56, 57, -1 From c1a407aadac5732088366c2149aad1dbd01e734b Mon Sep 17 00:00:00 2001 From: xiewen3 Date: Mon, 5 Sep 2022 14:32:04 +0800 Subject: [PATCH 511/698] enable CONFIG_MSM_TZ_QSEE_LOG for penang debug feature: enable CONFIG_MSM_TZ_QSEE_LOG for penang Change-Id: Ia122789a496aaff9f7e2a6a5be0def514e1a0670 Signed-off-by: xiewen3 Reviewed-on: https://gerrit.mot.com/2378109 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi-penang.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-penang.config b/arch/arm64/configs/vendor/ext_config/moto-holi-penang.config index e5e3b88dd7ef..b862bded89b8 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-penang.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-penang.config @@ -24,4 +24,5 @@ CONFIG_CRYPTO_CHACHA20POLY1305=y CONFIG_CAM_SENSOR_PROBE_RETRY=y CONFIG_SND_SOC_AW87XXX=m CONFIG_NFC_QTI_I2C=m +CONFIG_MSM_TZ_QSEE_LOG=y # CONFIG_TOUCHSCREEN_FTS is not set From 5a9376b14530e549c4382e46abc38abf312b113c Mon Sep 17 00:00:00 2001 From: xiewen3 Date: Mon, 5 Sep 2022 14:30:17 +0800 Subject: [PATCH 512/698] print qseelog to kernel buffer debug feature: Print qseelog to kernel buffer when debug cmdl is programmed. Change-Id: Ib8ebc5e60dd0b4b7b7c082a9d4537ed73a1ac992 Signed-off-by: xiewen3 Reviewed-on: https://gerrit.mot.com/2378108 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- drivers/firmware/qcom/Kconfig | 5 + drivers/firmware/qcom/tz_log.c | 298 ++++++++++++++++++++++++++++++++- 2 files changed, 302 insertions(+), 1 deletion(-) diff --git a/drivers/firmware/qcom/Kconfig b/drivers/firmware/qcom/Kconfig index 4cab380c8b07..b24d680cd618 100644 --- a/drivers/firmware/qcom/Kconfig +++ b/drivers/firmware/qcom/Kconfig @@ -5,3 +5,8 @@ config QTI_TZ_LOG This option enables a driver with a debugfs interface for messages produced by the Secure code (Trust zone). These messages provide diagnostic information about TZ operation. +config MSM_TZ_QSEE_LOG + bool "enable print QSEE log to kernel log" + depends on QTI_TZ_LOG + help + Set to enable print MSM Trust Zone (TZ) QSEE log to kernel log \ No newline at end of file diff --git a/drivers/firmware/qcom/tz_log.c b/drivers/firmware/qcom/tz_log.c index 53b8ad35d5f0..f98e09cb0d5b 100644 --- a/drivers/firmware/qcom/tz_log.c +++ b/drivers/firmware/qcom/tz_log.c @@ -19,6 +19,9 @@ #include #include #include +#ifdef CONFIG_MSM_TZ_QSEE_LOG +#include +#endif #ifndef CONFIG_DEBUG_FS #include @@ -388,7 +391,16 @@ struct tzdbg_stat { char *name; char *data; }; - +//print qsee log to kernel log +#ifdef CONFIG_MSM_TZ_QSEE_LOG +#ifdef CONFIG_DEBUG_FS +static bool enable_printk_qseelog = false; +#else +static bool enable_printk_qseelog = false; +#endif +#define PRINTK_LIMIT 1024 +static char *b_str = NULL; +#endif struct tzdbg { void __iomem *virt_iobase; void __iomem *hyp_virt_iobase; @@ -402,6 +414,10 @@ struct tzdbg { uint32_t tz_version; bool is_encrypted_log_enabled; bool is_enlarged_buf; +#ifdef CONFIG_MSM_TZ_QSEE_LOG + struct workqueue_struct *heartbeat_work_q; + struct work_struct heartbeat_work; +#endif }; struct tzbsp_encr_log_t { @@ -1532,6 +1548,263 @@ static void tzdbg_query_encrypted_log(void) } } +#ifdef CONFIG_MSM_TZ_QSEE_LOG +static int splitline_printk(const char *str, int len) +{ + int cnt = 0; + char *s = "\n"; + char *b_str_tmp = NULL; + char *buf = NULL; + + if (b_str == NULL && debug_rw_buf_size >0 ) { + b_str = (char *)vmalloc(debug_rw_buf_size +1); + } + if(len> debug_rw_buf_size) { + pr_err("[TEE-AP]:log is more than max len. trancate \n"); + len = debug_rw_buf_size; + } + b_str_tmp = b_str; + memcpy(b_str_tmp, str, len); + b_str_tmp[len] = 0; + + + buf = strstr(b_str_tmp, s); + + while (buf != NULL) { + cnt++; + buf[0] = '\0'; + pr_err("[TEE]: %s \n",b_str_tmp); + b_str_tmp = buf + strlen(s); + buf = strstr(b_str_tmp, s); + } + + return 0; +} + +static int _print_qsee_log_stats(struct tzdbg_log_t *log, + struct tzdbg_log_pos_t *log_start, uint32_t log_len + ) +{ + uint32_t wrap_start; + uint32_t wrap_end; + uint32_t wrap_cnt; + int max_len; + int len = 0; + int i = 0; + + wrap_start = log_start->wrap; + wrap_end = log->log_pos.wrap; + + /* Calculate difference in # of buffer wrap-arounds */ + if (wrap_end >= wrap_start) { + wrap_cnt = wrap_end - wrap_start; + } else { + /* wrap counter has wrapped around, invalidate start position */ + wrap_cnt = 2; + } + + if (wrap_cnt > 1) { + /* end position has wrapped around more than once, */ + /* current start no longer valid */ + log_start->wrap = log->log_pos.wrap - 1; + log_start->offset = (log->log_pos.offset + 1) % log_len; + } else if ((wrap_cnt == 1) && + (log->log_pos.offset > log_start->offset)) { + /* end position has overwritten start */ + log_start->offset = (log->log_pos.offset + 1) % log_len; + } + while (log_start->offset == log->log_pos.offset) { + /* + * No data in ring buffer, + * so we'll hang around until something happens + */ + unsigned long t = msleep_interruptible(50); + + if (t != 0) { + /* Some event woke us up, so let's quit */ + return 0; + } + } + + max_len = debug_rw_buf_size; + + /* + * Read from ring buff while there is data and space in return buff + */ + while ((log_start->offset != log->log_pos.offset) && (len < max_len)) { + tzdbg.disp_buf[i++] = log->log_buf[log_start->offset]; + log_start->offset = (log_start->offset + 1) % log_len; + if (log_start->offset == 0) + ++log_start->wrap; + ++len; + } + + /* + * return buffer to caller + */ + tzdbg.stat[TZDBG_QSEE_LOG].data = tzdbg.disp_buf; + /* + * print the display buffer + */ + splitline_printk(tzdbg.stat[TZDBG_QSEE_LOG].data,len); + return len; +} + +static int _print_qsee_log_v2_stats(struct tzdbg_log_v2_t *log, + struct tzdbg_log_pos_v2_t *log_start, uint32_t log_len) +{ + uint32_t wrap_start; + uint32_t wrap_end; + uint32_t wrap_cnt; + int max_len; + int len = 0; + int i = 0; + + wrap_start = log_start->wrap; + wrap_end = log->log_pos.wrap; + + /* Calculate difference in # of buffer wrap-arounds */ + if (wrap_end >= wrap_start) + wrap_cnt = wrap_end - wrap_start; + else { + /* wrap counter has wrapped around, invalidate start position */ + wrap_cnt = 2; +} + + if (wrap_cnt > 1) { + /* end position has wrapped around more than once, */ + /* current start no longer valid */ + log_start->wrap = log->log_pos.wrap - 1; + log_start->offset = (log->log_pos.offset + 1) % log_len; + } else if ((wrap_cnt == 1) && + (log->log_pos.offset > log_start->offset)) { + /* end position has overwritten start */ + log_start->offset = (log->log_pos.offset + 1) % log_len; + } + pr_debug("diag_buf wrap = %u, offset = %u\n", + log->log_pos.wrap, log->log_pos.offset); + + while (log_start->offset == log->log_pos.offset) { + /* + * No data in ring buffer, + * so we'll hang around until something happens + */ + unsigned long t = msleep_interruptible(50); + + if (t != 0) { + /* Some event woke us up, so let's quit */ + return 0; + } + } + + max_len = debug_rw_buf_size; + + pr_debug("diag_buf wrap = %u, offset = %u\n", + log->log_pos.wrap, log->log_pos.offset); + + /* + * Read from ring buff while there is data and space in return buff + */ + while ((log_start->offset != log->log_pos.offset) && (len < max_len)) { + tzdbg.disp_buf[i++] = log->log_buf[log_start->offset]; + log_start->offset = (log_start->offset + 1) % log_len; + if (log_start->offset == 0) + ++log_start->wrap; + ++len; + } + + /* + * return buffer to caller + */ + tzdbg.stat[TZDBG_QSEE_LOG].data = tzdbg.disp_buf; + /* + * print the display buffer + */ + splitline_printk(tzdbg.stat[TZDBG_QSEE_LOG].data,len); + return len; +} +static _print_encrpted_qsee_log_stats(struct encrypted_log_info *enc_log_info) +{ + int ret = 0, len = 0; + struct tzbsp_encr_log_t *encr_log_head; + uint32_t size = 0; + + ret = qcom_scm_request_encrypted_log(enc_log_info->paddr, + enc_log_info->size, ENCRYPTED_QSEE_LOG_ID); + if (ret) + return 0; + encr_log_head = (struct tzbsp_encr_log_t *)(enc_log_info->vaddr); + pr_debug("display_buf_size = %d, encr_log_buff_size = %d\n", + display_buf_size, encr_log_head->encr_log_buff_size); + size = encr_log_head->encr_log_buff_size; + + len += scnprintf(tzdbg.disp_buf + len, + (display_buf_size - 1) - len, + "\n-------- New Encrypted QSEE Log --------\n"); + + len += scnprintf(tzdbg.disp_buf + len, + (display_buf_size - 1) - len, + "\nMagic_Num :\n0x%x\n" + "\nVerion :\n%d\n" + "\nEncr_Log_Buff_Size :\n%d\n" + "\nWrap_Count :\n%d\n", + encr_log_head->magic_num, + encr_log_head->version, + encr_log_head->encr_log_buff_size, + encr_log_head->wrap_count); + + len += print_text("\nKey : ", encr_log_head->key, + TZBSP_AES_256_ENCRYPTED_KEY_SIZE, + tzdbg.disp_buf + len, display_buf_size); + len += print_text("\nNonce : ", encr_log_head->nonce, + TZBSP_NONCE_LEN, + tzdbg.disp_buf + len, display_buf_size - len); + len += print_text("\nTag : ", encr_log_head->tag, + TZBSP_TAG_LEN, + tzdbg.disp_buf + len, display_buf_size - len); + + if (len > display_buf_size - size) + pr_warn("Cannot fit all info into the buffer\n"); + + pr_debug("encrypted log size %d, disply buffer size %d, used len %d\n", + size, display_buf_size, len); + + len += print_text("\nLog : ", encr_log_head->log_buf, size, + tzdbg.disp_buf + len, display_buf_size - len); + memset(enc_log_info->vaddr, 0, enc_log_info->size); + tzdbg.stat[TZDBG_QSEE_LOG].data = tzdbg.disp_buf; + /* + * print the display buffer + */ + splitline_printk(tzdbg.stat[TZDBG_QSEE_LOG].data,len); + return len; +} + +static void tzdbg_heartbeat_work(struct work_struct *work) +{ + static struct tzdbg_log_pos_t log_start = {0}; + static struct tzdbg_log_pos_v2_t log_start_v2 = {0}; + if(enable_printk_qseelog) { + pr_debug("[TEE] qsee log -------------begin---\n"); + if (!tzdbg.is_encrypted_log_enabled) { + if (!tzdbg.is_enlarged_buf) + _print_qsee_log_stats(g_qsee_log, &log_start, + QSEE_LOG_BUF_SIZE - sizeof(struct tzdbg_log_pos_t)); + else + _print_qsee_log_v2_stats(g_qsee_log_v2, &log_start_v2, + QSEE_LOG_BUF_SIZE_V2 - sizeof(struct tzdbg_log_pos_v2_t)); + }else{ + _print_encrpted_qsee_log_stats(&enc_qseelog_info); + } + + pr_debug("[TEE] qsee log -------------end---\n"); + + queue_work(tzdbg.heartbeat_work_q , + &tzdbg.heartbeat_work + ); + } +} +#endif /* * Driver functions */ @@ -1649,6 +1922,15 @@ static int tz_log_probe(struct platform_device *pdev) if (tzdbgfs_init(pdev)) goto exit_free_disp_buf; +#ifdef CONFIG_MSM_TZ_QSEE_LOG + if(enable_printk_qseelog) { + tzdbg.heartbeat_work_q = create_singlethread_workqueue("tz_heartbeat"); + INIT_WORK(&tzdbg.heartbeat_work, + tzdbg_heartbeat_work); + queue_work(tzdbg.heartbeat_work_q, &tzdbg.heartbeat_work); + dev_err(&pdev->dev, "%s: enable_printk_qseelog is set, is_enlarged=%d is_encrypted=%d\n", __func__,tzdbg.is_enlarged_buf,tzdbg.is_encrypted_log_enabled); + } +#endif return 0; exit_free_disp_buf: @@ -1666,6 +1948,12 @@ exit_free_diag_buf: static int tz_log_remove(struct platform_device *pdev) { +#ifdef CONFIG_MSM_TZ_QSEE_LOG + if(enable_printk_qseelog) { + enable_printk_qseelog = false; + flush_work(&tzdbg.heartbeat_work); + } +#endif tzdbgfs_exit(pdev); dma_free_coherent(&pdev->dev, display_buf_size, (void *)tzdbg.disp_buf, disp_buf_paddr); @@ -1692,6 +1980,14 @@ static struct platform_driver tz_log_driver = { }; module_platform_driver(tz_log_driver); +#ifdef CONFIG_MSM_TZ_QSEE_LOG +static int __init setup_enable_printk_qseelog(char *buf) +{ + enable_printk_qseelog = true; + return 0; +} +early_param("printk_qseelog", setup_enable_printk_qseelog); +#endif MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("TZ Log driver"); From fa3b0b74bbcf5a0ec20be524615ba02c6ee022d8 Mon Sep 17 00:00:00 2001 From: William Liu Date: Thu, 8 Sep 2022 19:32:29 +0800 Subject: [PATCH 513/698] fs:EROFS:Porting 5.10 erofs to 5.4 Porting erfos changes from 5.10 common kernel And some glue code to make it pass build on 5.4 be3f6035831a erofs: fix unsafe pagevec reuse of hooked pclusters 6c1ad56b2d78 erofs: remove the occupied parameter from z_erofs_pagevec_enqueue() ee75174f6ab9 erofs: don't trigger WARN() when decompression fails 8326be9e5121 erofs: fix up erofs_lookup tracepoint ca9ee53cea1f18edf318a01a19653ae3847474a9 UPSTREAM: erofs: fix deadlock when shrink erofs slab b943d328889d25cdb1aa397880c079b7d55a0901 UPSTREAM: erofs: fix unsafe pagevec reuse of hooked pclusters 028f7128c4fbb75ba113824f8600ca9a7097a0ed UPSTREAM: erofs: remove the occupied parameter from z_erofs_pagevec_enqueue() ee75174f6ab93611e1623f0ae5590beda008aef5 erofs: don't trigger WARN() when decompression fail dcd77f0b7453 UPSTREAM: erofs: fix 1 lcluster-sized pcluster for big pcluster e085d3f0d0dc UPSTREAM: erofs: enable big pcluster feature ed0607cc5256 UPSTREAM: erofs: support decompress big pcluster for lz4 backend d34cb6cdc044 UPSTREAM: erofs: support parsing big pcluster compact indexes 051d76b899bd UPSTREAM: erofs: support parsing big pcluster compress indexes d14993160141 UPSTREAM: erofs: adjust per-CPU buffers according to max_pclusterblks 95a1d5df840a UPSTREAM: erofs: add big physical cluster definition 8043aaed1dad UPSTREAM: erofs: fix up inplace I/O pointer for big pcluster 6ad2f8f1699c UPSTREAM: erofs: introduce physical cluster slab pools 432f58b100f0 UPSTREAM: erofs: introduce multipage per-CPU buffers 571c9a0bd334 UPSTREAM: erofs: remove a void EROFS_VERSION macro set in Makefile 431d73396dad UPSTREAM: erofs: reserve physical_clusterbits[] 89dbc6246a86 UPSTREAM: erofs: Clean up spelling mistakes found in fs/erofs ac1f14e9d5a8 UPSTREAM: erofs: add on-disk compression configurations cd21e62366bb UPSTREAM: erofs: introduce on-disk lz4 fs configurations e17fd2ac9dfc UPSTREAM: erofs: introduce erofs_sb_has_xxx() helpers ba1a3d1fb2db UPSTREAM: erofs: don't use erofs_map_blocks() any more 384b2cdaf83e UPSTREAM: erofs: complete a missing case for inplace I/O 8326be9e51218d23ebe52c8d4c2d7c23302f6e44 erofs: fix up erofs_lookup tracepoint 51c19f4a62129bca096df760c7690833958ce9cf erofs: fix error return code in erofs_read_superblock() 06229c49eb7f UPSTREAM: erofs: support adjust lz4 history window size 0a24d25f0882 UPSTREAM: erofs: use sync decompression for atomic contexts only 0ca4eafb3928 UPSTREAM: erofs: use workqueue decompression for atomic contexts only 4ae1c8a4d06a UPSTREAM: erofs: force inplace I/O under low memory scenario 46a00756cbf8 UPSTREAM: erofs: insert to managed cache after adding to pcl b1c757466f42 UPSTREAM: erofs: get rid of magical Z_EROFS_MAPPING_STAGING Change-Id: Ibc0d16af7424aa02806ec35b431d4faa28a126cd Signed-off-by: William Liu Reviewed-on: https://gerrit.mot.com/2379154 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- fs/erofs/Kconfig | 15 +- fs/erofs/Makefile | 7 +- fs/erofs/compress.h | 62 +++- fs/erofs/data.c | 23 +- fs/erofs/decompressor.c | 291 ++++++++++------ fs/erofs/dir.c | 2 +- fs/erofs/erofs_fs.h | 56 ++- fs/erofs/inode.c | 8 +- fs/erofs/internal.h | 130 ++++--- fs/erofs/namei.c | 4 +- fs/erofs/pcpubuf.c | 148 ++++++++ fs/erofs/super.c | 455 +++++++++++++++--------- fs/erofs/utils.c | 148 +++----- fs/erofs/xattr.c | 6 +- fs/erofs/xattr.h | 26 +- fs/erofs/zdata.c | 744 +++++++++++++++++++++------------------- fs/erofs/zdata.h | 25 +- fs/erofs/zmap.c | 213 +++++++++--- fs/erofs/zpvec.h | 2 +- 19 files changed, 1457 insertions(+), 908 deletions(-) create mode 100644 fs/erofs/pcpubuf.c diff --git a/fs/erofs/Kconfig b/fs/erofs/Kconfig index 9d634d3a1845..858b3339f381 100644 --- a/fs/erofs/Kconfig +++ b/fs/erofs/Kconfig @@ -3,6 +3,7 @@ config EROFS_FS tristate "EROFS filesystem support" depends on BLOCK + select LIBCRC32C help EROFS (Enhanced Read-Only File System) is a lightweight read-only file system with modern designs (eg. page-sized @@ -75,17 +76,3 @@ config EROFS_FS_ZIP If you don't want to enable compression feature, say N. -config EROFS_FS_CLUSTER_PAGE_LIMIT - int "EROFS Cluster Pages Hard Limit" - depends on EROFS_FS_ZIP - range 1 256 - default "1" - help - Indicates maximum # of pages of a compressed - physical cluster. - - For example, if files in a image were compressed - into 8k-unit, hard limit should not be configured - less than 2. Otherwise, the image will be refused - to mount on this kernel. - diff --git a/fs/erofs/Makefile b/fs/erofs/Makefile index 46f2aa4ba46c..1f9aced49070 100644 --- a/fs/erofs/Makefile +++ b/fs/erofs/Makefile @@ -1,11 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only -EROFS_VERSION = "1.0" - -ccflags-y += -DEROFS_VERSION=\"$(EROFS_VERSION)\" - obj-$(CONFIG_EROFS_FS) += erofs.o -erofs-objs := super.o inode.o data.o namei.o dir.o utils.o +erofs-objs := super.o inode.o data.o namei.o dir.o utils.o pcpubuf.o erofs-$(CONFIG_EROFS_FS_XATTR) += xattr.o erofs-$(CONFIG_EROFS_FS_ZIP) += decompressor.o zmap.o zdata.o - diff --git a/fs/erofs/compress.h b/fs/erofs/compress.h index 07d279fd5d67..aea129ddda74 100644 --- a/fs/erofs/compress.h +++ b/fs/erofs/compress.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (C) 2019 HUAWEI, Inc. - * http://www.huawei.com/ + * https://www.huawei.com/ * Created by Gao Xiang */ #ifndef __EROFS_FS_COMPRESS_H @@ -26,30 +26,58 @@ struct z_erofs_decompress_req { bool inplace_io, partial_decoding; }; +/* some special page->private (unsigned long, see below) */ +#define Z_EROFS_SHORTLIVED_PAGE (-1UL << 2) +#define Z_EROFS_PREALLOCATED_PAGE (-2UL << 2) + /* - * - 0x5A110C8D ('sallocated', Z_EROFS_MAPPING_STAGING) - - * used to mark temporary allocated pages from other - * file/cached pages and NULL mapping pages. + * For all pages in a pcluster, page->private should be one of + * Type Last 2bits page->private + * short-lived page 00 Z_EROFS_SHORTLIVED_PAGE + * preallocated page (tryalloc) 00 Z_EROFS_PREALLOCATED_PAGE + * cached/managed page 00 pointer to z_erofs_pcluster + * online page (file-backed, 01/10/11 sub-index << 2 | count + * some pages can be used for inplace I/O) + * + * page->mapping should be one of + * Type page->mapping + * short-lived page NULL + * preallocated page NULL + * cached/managed page non-NULL or NULL (invalidated/truncated page) + * online page non-NULL + * + * For all managed pages, PG_private should be set with 1 extra refcount, + * which is used for page reclaim / migration. */ -#define Z_EROFS_MAPPING_STAGING ((void *)0x5A110C8D) -/* check if a page is marked as staging */ -static inline bool z_erofs_page_is_staging(struct page *page) +/* + * short-lived pages are pages directly from buddy system with specific + * page->private (no need to set PagePrivate since these are non-LRU / + * non-movable pages and bypass reclaim / migration code). + */ +static inline bool z_erofs_is_shortlived_page(struct page *page) { - return page->mapping == Z_EROFS_MAPPING_STAGING; -} - -static inline bool z_erofs_put_stagingpage(struct list_head *pagepool, - struct page *page) -{ - if (!z_erofs_page_is_staging(page)) + if (page->private != Z_EROFS_SHORTLIVED_PAGE) return false; - /* staging pages should not be used by others at the same time */ - if (page_ref_count(page) > 1) + DBG_BUGON(page->mapping); + return true; +} + +static inline bool z_erofs_put_shortlivedpage(struct list_head *pagepool, + struct page *page) +{ + if (!z_erofs_is_shortlived_page(page)) + return false; + + /* short-lived pages should not be used by others at the same time */ + if (page_ref_count(page) > 1) { put_page(page); - else + } else { + /* follow the pcluster rule above. */ + set_page_private(page, 0); list_add(&page->lru, pagepool); + } return true; } diff --git a/fs/erofs/data.c b/fs/erofs/data.c index b22a08ac53a2..b336a6201bca 100644 --- a/fs/erofs/data.c +++ b/fs/erofs/data.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2017-2018 HUAWEI, Inc. - * http://www.huawei.com/ + * https://www.huawei.com/ * Created by Gao Xiang */ #include "internal.h" @@ -109,21 +109,6 @@ err_out: return err; } -int erofs_map_blocks(struct inode *inode, - struct erofs_map_blocks *map, int flags) -{ - if (erofs_inode_is_data_compressed(EROFS_I(inode)->datalayout)) { - int err = z_erofs_map_blocks_iter(inode, map, flags); - - if (map->mpage) { - put_page(map->mpage); - map->mpage = NULL; - } - return err; - } - return erofs_map_blocks_flatmode(inode, map, flags); -} - static inline struct bio *erofs_read_raw_page(struct bio *bio, struct address_space *mapping, struct page *page, @@ -159,7 +144,7 @@ submit_bio_retry: erofs_blk_t blknr; unsigned int blkoff; - err = erofs_map_blocks(inode, &map, EROFS_GET_BLOCKS_RAW); + err = erofs_map_blocks_flatmode(inode, &map, EROFS_GET_BLOCKS_RAW); if (err) goto err_out; @@ -224,7 +209,7 @@ submit_bio_retry: bio_set_dev(bio, sb->s_bdev); bio->bi_iter.bi_sector = (sector_t)blknr << LOG_SECTORS_PER_BLOCK; - bio->bi_opf = REQ_OP_READ; + bio->bi_opf = REQ_OP_READ | (ra ? REQ_RAHEAD : 0); } err = bio_add_page(bio, page, PAGE_SIZE, 0); @@ -337,7 +322,7 @@ static sector_t erofs_bmap(struct address_space *mapping, sector_t block) return 0; } - if (!erofs_map_blocks(inode, &map, EROFS_GET_BLOCKS_RAW)) + if (!erofs_map_blocks_flatmode(inode, &map, EROFS_GET_BLOCKS_RAW)) return erofs_blknr(map.m_pa); return 0; diff --git a/fs/erofs/decompressor.c b/fs/erofs/decompressor.c index 38eeec5e3032..6f6e3d0af2fd 100644 --- a/fs/erofs/decompressor.c +++ b/fs/erofs/decompressor.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2019 HUAWEI, Inc. - * http://www.huawei.com/ + * https://www.huawei.com/ * Created by Gao Xiang */ #include "compress.h" @@ -28,6 +28,42 @@ struct z_erofs_decompressor { char *name; }; +int z_erofs_load_lz4_config(struct super_block *sb, + struct erofs_super_block *dsb, + struct z_erofs_lz4_cfgs *lz4, int size) +{ + struct erofs_sb_info *sbi = EROFS_SB(sb); + u16 distance; + + if (lz4) { + if (size < sizeof(struct z_erofs_lz4_cfgs)) { + erofs_err(sb, "invalid lz4 cfgs, size=%u", size); + return -EINVAL; + } + distance = le16_to_cpu(lz4->max_distance); + + sbi->lz4.max_pclusterblks = le16_to_cpu(lz4->max_pclusterblks); + if (!sbi->lz4.max_pclusterblks) { + sbi->lz4.max_pclusterblks = 1; /* reserved case */ + } else if (sbi->lz4.max_pclusterblks > + Z_EROFS_PCLUSTER_MAX_SIZE / EROFS_BLKSIZ) { + erofs_err(sb, "too large lz4 pclusterblks %u", + sbi->lz4.max_pclusterblks); + return -EINVAL; + } else if (sbi->lz4.max_pclusterblks >= 2) { + erofs_info(sb, "EXPERIMENTAL big pcluster feature in use. Use at your own risk!"); + } + } else { + distance = le16_to_cpu(dsb->u1.lz4_max_distance); + sbi->lz4.max_pclusterblks = 1; + } + + sbi->lz4.max_distance_pages = distance ? + DIV_ROUND_UP(distance, PAGE_SIZE) + 1 : + LZ4_MAX_DISTANCE_PAGES; + return erofs_pcpubuf_growsize(sbi->lz4.max_pclusterblks); +} + static int z_erofs_lz4_prepare_destpages(struct z_erofs_decompress_req *rq, struct list_head *pagepool) { @@ -36,6 +72,8 @@ static int z_erofs_lz4_prepare_destpages(struct z_erofs_decompress_req *rq, struct page *availables[LZ4_MAX_DISTANCE_PAGES] = { NULL }; unsigned long bounced[DIV_ROUND_UP(LZ4_MAX_DISTANCE_PAGES, BITS_PER_LONG)] = { 0 }; + unsigned int lz4_max_distance_pages = + EROFS_SB(rq->sb)->lz4.max_distance_pages; void *kaddr = NULL; unsigned int i, j, top; @@ -44,14 +82,14 @@ static int z_erofs_lz4_prepare_destpages(struct z_erofs_decompress_req *rq, struct page *const page = rq->out[i]; struct page *victim; - if (j >= LZ4_MAX_DISTANCE_PAGES) + if (j >= lz4_max_distance_pages) j = 0; /* 'valid' bounced can only be tested after a complete round */ if (test_bit(j, bounced)) { - DBG_BUGON(i < LZ4_MAX_DISTANCE_PAGES); - DBG_BUGON(top >= LZ4_MAX_DISTANCE_PAGES); - availables[top++] = rq->out[i - LZ4_MAX_DISTANCE_PAGES]; + DBG_BUGON(i < lz4_max_distance_pages); + DBG_BUGON(top >= lz4_max_distance_pages); + availables[top++] = rq->out[i - lz4_max_distance_pages]; } if (page) { @@ -77,108 +115,149 @@ static int z_erofs_lz4_prepare_destpages(struct z_erofs_decompress_req *rq, victim = availables[--top]; get_page(victim); } else { - victim = erofs_allocpage(pagepool, GFP_KERNEL, false); - if (!victim) - return -ENOMEM; - victim->mapping = Z_EROFS_MAPPING_STAGING; + victim = erofs_allocpage(pagepool, + GFP_KERNEL | __GFP_NOFAIL); + set_page_private(victim, Z_EROFS_SHORTLIVED_PAGE); } rq->out[i] = victim; } return kaddr ? 1 : 0; } -static void *generic_copy_inplace_data(struct z_erofs_decompress_req *rq, - u8 *src, unsigned int pageofs_in) +static void *z_erofs_handle_inplace_io(struct z_erofs_decompress_req *rq, + void *inpage, unsigned int *inputmargin, int *maptype, + bool support_0padding) { - /* - * if in-place decompression is ongoing, those decompressed - * pages should be copied in order to avoid being overlapped. - */ - struct page **in = rq->in; - u8 *const tmp = erofs_get_pcpubuf(0); - u8 *tmpp = tmp; - unsigned int inlen = rq->inputsize - pageofs_in; - unsigned int count = min_t(uint, inlen, PAGE_SIZE - pageofs_in); + unsigned int nrpages_in, nrpages_out; + unsigned int ofull, oend, inputsize, total, i, j; + struct page **in; + void *src, *tmp; - while (tmpp < tmp + inlen) { - if (!src) - src = kmap_atomic(*in); - memcpy(tmpp, src + pageofs_in, count); - kunmap_atomic(src); - src = NULL; - tmpp += count; - pageofs_in = 0; - count = PAGE_SIZE; - ++in; + inputsize = rq->inputsize; + nrpages_in = PAGE_ALIGN(inputsize) >> PAGE_SHIFT; + oend = rq->pageofs_out + rq->outputsize; + ofull = PAGE_ALIGN(oend); + nrpages_out = ofull >> PAGE_SHIFT; + + if (rq->inplace_io) { + if (rq->partial_decoding || !support_0padding || + ofull - oend < LZ4_DECOMPRESS_INPLACE_MARGIN(inputsize)) + goto docopy; + + for (i = 0; i < nrpages_in; ++i) { + DBG_BUGON(rq->in[i] == NULL); + for (j = 0; j < nrpages_out - nrpages_in + i; ++j) + if (rq->out[j] == rq->in[i]) + goto docopy; + } } - return tmp; + + if (nrpages_in <= 1) { + *maptype = 0; + return inpage; + } + kunmap_atomic(inpage); + might_sleep(); + src = erofs_vm_map_ram(rq->in, nrpages_in); + if (!src) + return ERR_PTR(-ENOMEM); + *maptype = 1; + return src; + +docopy: + /* Or copy compressed data which can be overlapped to per-CPU buffer */ + in = rq->in; + src = erofs_get_pcpubuf(nrpages_in); + if (!src) { + DBG_BUGON(1); + kunmap_atomic(inpage); + return ERR_PTR(-EFAULT); + } + + tmp = src; + total = rq->inputsize; + while (total) { + unsigned int page_copycnt = + min_t(unsigned int, total, PAGE_SIZE - *inputmargin); + + if (!inpage) + inpage = kmap_atomic(*in); + memcpy(tmp, inpage + *inputmargin, page_copycnt); + kunmap_atomic(inpage); + inpage = NULL; + tmp += page_copycnt; + total -= page_copycnt; + ++in; + *inputmargin = 0; + } + *maptype = 2; + return src; } static int z_erofs_lz4_decompress(struct z_erofs_decompress_req *rq, u8 *out) { - unsigned int inputmargin, inlen; - u8 *src; - bool copied, support_0padding; - int ret; + unsigned int inputmargin; + u8 *headpage, *src; + bool support_0padding; + int ret, maptype; - if (rq->inputsize > PAGE_SIZE) - return -EOPNOTSUPP; - - src = kmap_atomic(*rq->in); + DBG_BUGON(*rq->in == NULL); + headpage = kmap_atomic(*rq->in); inputmargin = 0; support_0padding = false; /* decompression inplace is only safe when 0padding is enabled */ - if (EROFS_SB(rq->sb)->feature_incompat & - EROFS_FEATURE_INCOMPAT_LZ4_0PADDING) { + if (erofs_sb_has_lz4_0padding(EROFS_SB(rq->sb))) { support_0padding = true; - while (!src[inputmargin & ~PAGE_MASK]) + while (!headpage[inputmargin & ~PAGE_MASK]) if (!(++inputmargin & ~PAGE_MASK)) break; if (inputmargin >= rq->inputsize) { - kunmap_atomic(src); + kunmap_atomic(headpage); return -EIO; } } - copied = false; - inlen = rq->inputsize - inputmargin; - if (rq->inplace_io) { - const uint oend = (rq->pageofs_out + - rq->outputsize) & ~PAGE_MASK; - const uint nr = PAGE_ALIGN(rq->pageofs_out + - rq->outputsize) >> PAGE_SHIFT; + rq->inputsize -= inputmargin; + src = z_erofs_handle_inplace_io(rq, headpage, &inputmargin, &maptype, + support_0padding); + if (IS_ERR(src)) + return PTR_ERR(src); - if (rq->partial_decoding || !support_0padding || - rq->out[nr - 1] != rq->in[0] || - rq->inputsize - oend < - LZ4_DECOMPRESS_INPLACE_MARGIN(inlen)) { - src = generic_copy_inplace_data(rq, src, inputmargin); - inputmargin = 0; - copied = true; - } - } + /* legacy format could compress extra data in a pcluster. */ + if (rq->partial_decoding || !support_0padding) + ret = LZ4_decompress_safe_partial(src + inputmargin, out, + rq->inputsize, rq->outputsize, rq->outputsize); + else + ret = LZ4_decompress_safe(src + inputmargin, out, + rq->inputsize, rq->outputsize); + + if (ret != rq->outputsize) { + erofs_err(rq->sb, "failed to decompress %d in[%u, %u] out[%u]", + ret, rq->inputsize, inputmargin, rq->outputsize); - ret = LZ4_decompress_safe_partial(src + inputmargin, out, - inlen, rq->outputsize, - rq->outputsize); - if (ret < 0) { - erofs_err(rq->sb, "failed to decompress, in[%u, %u] out[%u]", - inlen, inputmargin, rq->outputsize); - WARN_ON(1); print_hex_dump(KERN_DEBUG, "[ in]: ", DUMP_PREFIX_OFFSET, - 16, 1, src + inputmargin, inlen, true); + 16, 1, src + inputmargin, rq->inputsize, true); print_hex_dump(KERN_DEBUG, "[out]: ", DUMP_PREFIX_OFFSET, 16, 1, out, rq->outputsize, true); + + if (ret >= 0) + memset(out + ret, 0, rq->outputsize - ret); ret = -EIO; } - if (copied) - erofs_put_pcpubuf(src); - else + if (maptype == 0) { kunmap_atomic(src); + } else if (maptype == 1) { + vm_unmap_ram(src, PAGE_ALIGN(rq->inputsize) >> PAGE_SHIFT); + } else if (maptype == 2) { + erofs_put_pcpubuf(src); + } else { + DBG_BUGON(1); + return -EFAULT; + } return ret; } @@ -228,57 +307,51 @@ static int z_erofs_decompress_generic(struct z_erofs_decompress_req *rq, const struct z_erofs_decompressor *alg = decompressors + rq->alg; unsigned int dst_maptype; void *dst; - int ret, i; + int ret; - if (nrpages_out == 1 && !rq->inplace_io) { - DBG_BUGON(!*rq->out); - dst = kmap_atomic(*rq->out); - dst_maptype = 0; - goto dstmap_out; - } - - /* - * For the case of small output size (especially much less - * than PAGE_SIZE), memcpy the decompressed data rather than - * compressed data is preferred. - */ - if (rq->outputsize <= PAGE_SIZE * 7 / 8) { - dst = erofs_get_pcpubuf(0); - if (IS_ERR(dst)) - return PTR_ERR(dst); - - rq->inplace_io = false; - ret = alg->decompress(rq, dst); - if (!ret) - copy_from_pcpubuf(rq->out, dst, rq->pageofs_out, - rq->outputsize); - - erofs_put_pcpubuf(dst); - return ret; + /* two optimized fast paths only for non bigpcluster cases yet */ + if (rq->inputsize <= PAGE_SIZE) { + if (nrpages_out == 1 && !rq->inplace_io) { + DBG_BUGON(!*rq->out); + dst = kmap_atomic(*rq->out); + dst_maptype = 0; + goto dstmap_out; + } + + /* + * For the case of small output size (especially much less + * than PAGE_SIZE), memcpy the decompressed data rather than + * compressed data is preferred. + */ + if (rq->outputsize <= PAGE_SIZE * 7 / 8) { + dst = erofs_get_pcpubuf(1); + if (IS_ERR(dst)) + return PTR_ERR(dst); + + rq->inplace_io = false; + ret = alg->decompress(rq, dst); + if (!ret) + copy_from_pcpubuf(rq->out, dst, rq->pageofs_out, + rq->outputsize); + + erofs_put_pcpubuf(dst); + return ret; + } } + /* general decoding path which can be used for all cases */ ret = alg->prepare_destpages(rq, pagepool); - if (ret < 0) { + if (ret < 0) return ret; - } else if (ret) { + if (ret) { dst = page_address(*rq->out); dst_maptype = 1; goto dstmap_out; } - i = 0; - while (1) { - dst = vm_map_ram(rq->out, nrpages_out, -1, PAGE_KERNEL); - - /* retry two more times (totally 3 times) */ - if (dst || ++i >= 3) - break; - vm_unmap_aliases(); - } - + dst = erofs_vm_map_ram(rq->out, nrpages_out); if (!dst) return -ENOMEM; - dst_maptype = 2; dstmap_out: diff --git a/fs/erofs/dir.c b/fs/erofs/dir.c index d28c623dfef9..2776bb832127 100644 --- a/fs/erofs/dir.c +++ b/fs/erofs/dir.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2017-2018 HUAWEI, Inc. - * http://www.huawei.com/ + * https://www.huawei.com/ * Created by Gao Xiang */ #include "internal.h" diff --git a/fs/erofs/erofs_fs.h b/fs/erofs/erofs_fs.h index 52ab96154467..8739d3adf51f 100644 --- a/fs/erofs/erofs_fs.h +++ b/fs/erofs/erofs_fs.h @@ -3,7 +3,7 @@ * EROFS (Enhanced ROM File System) on-disk format definition * * Copyright (C) 2017-2018 HUAWEI, Inc. - * http://www.huawei.com/ + * https://www.huawei.com/ * Created by Gao Xiang */ #ifndef __EROFS_FS_H @@ -11,20 +11,29 @@ #define EROFS_SUPER_OFFSET 1024 +#define EROFS_FEATURE_COMPAT_SB_CHKSUM 0x00000001 + /* * Any bits that aren't in EROFS_ALL_FEATURE_INCOMPAT should * be incompatible with this kernel version. */ #define EROFS_FEATURE_INCOMPAT_LZ4_0PADDING 0x00000001 -#define EROFS_ALL_FEATURE_INCOMPAT EROFS_FEATURE_INCOMPAT_LZ4_0PADDING +#define EROFS_FEATURE_INCOMPAT_COMPR_CFGS 0x00000002 +#define EROFS_FEATURE_INCOMPAT_BIG_PCLUSTER 0x00000002 +#define EROFS_ALL_FEATURE_INCOMPAT \ + (EROFS_FEATURE_INCOMPAT_LZ4_0PADDING | \ + EROFS_FEATURE_INCOMPAT_COMPR_CFGS | \ + EROFS_FEATURE_INCOMPAT_BIG_PCLUSTER) -/* 128-byte erofs on-disk super block */ +#define EROFS_SB_EXTSLOT_SIZE 16 + +/* erofs on-disk super block (currently 128 bytes) */ struct erofs_super_block { __le32 magic; /* file system magic number */ __le32 checksum; /* crc32c(super_block) */ __le32 feature_compat; __u8 blkszbits; /* support block_size == PAGE_SIZE only */ - __u8 reserved; + __u8 sb_extslots; /* superblock size = 128 + sb_extslots * 16 */ __le16 root_nid; /* nid of root directory */ __le64 inos; /* total valid ino # (== f_files - f_favail) */ @@ -37,8 +46,13 @@ struct erofs_super_block { __u8 uuid[16]; /* 128-bit uuid for volume */ __u8 volume_name[16]; /* volume name */ __le32 feature_incompat; - - __u8 reserved2[44]; + union { + /* bitmap for available compression algorithms */ + __le16 available_compr_algs; + /* customized sliding window size instead of 64k by default */ + __le16 lz4_max_distance; + } __packed u1; + __u8 reserved2[42]; }; /* @@ -191,20 +205,33 @@ static inline unsigned int erofs_xattr_entry_size(struct erofs_xattr_entry *e) e->e_name_len + le16_to_cpu(e->e_value_size)); } +/* maximum supported size of a physical compression cluster */ +#define Z_EROFS_PCLUSTER_MAX_SIZE (1024 * 1024) + /* available compression algorithm types (for h_algorithmtype) */ enum { Z_EROFS_COMPRESSION_LZ4 = 0, Z_EROFS_COMPRESSION_MAX }; +#define Z_EROFS_ALL_COMPR_ALGS (1 << (Z_EROFS_COMPRESSION_MAX - 1)) + +/* 14 bytes (+ length field = 16 bytes) */ +struct z_erofs_lz4_cfgs { + __le16 max_distance; + __le16 max_pclusterblks; + u8 reserved[10]; +} __packed; /* * bit 0 : COMPACTED_2B indexes (0 - off; 1 - on) * e.g. for 4k logical cluster size, 4B if compacted 2B is off; * (4B) + 2B + (4B) if compacted 2B is on. + * bit 1 : HEAD1 big pcluster (0 - off; 1 - on) + * bit 2 : HEAD2 big pcluster (0 - off; 1 - on) */ -#define Z_EROFS_ADVISE_COMPACTED_2B_BIT 0 - -#define Z_EROFS_ADVISE_COMPACTED_2B (1 << Z_EROFS_ADVISE_COMPACTED_2B_BIT) +#define Z_EROFS_ADVISE_COMPACTED_2B 0x0001 +#define Z_EROFS_ADVISE_BIG_PCLUSTER_1 0x0002 +#define Z_EROFS_ADVISE_BIG_PCLUSTER_2 0x0004 struct z_erofs_map_header { __le32 h_reserved1; @@ -216,9 +243,7 @@ struct z_erofs_map_header { __u8 h_algorithmtype; /* * bit 0-2 : logical cluster bits - 12, e.g. 0 for 4096; - * bit 3-4 : (physical - logical) cluster bits of head 1: - * For example, if logical clustersize = 4096, 1 for 8192. - * bit 5-7 : (physical - logical) cluster bits of head 2. + * bit 3-7 : reserved. */ __u8 h_clusterbits; }; @@ -261,6 +286,13 @@ enum { #define Z_EROFS_VLE_DI_CLUSTER_TYPE_BITS 2 #define Z_EROFS_VLE_DI_CLUSTER_TYPE_BIT 0 +/* + * D0_CBLKCNT will be marked _only_ at the 1st non-head lcluster to store the + * compressed block count of a compressed extent (in logical clusters, aka. + * block count of a pcluster). + */ +#define Z_EROFS_VLE_DI_D0_CBLKCNT (1 << 11) + struct z_erofs_vle_decompressed_index { __le16 di_advise; /* where to decompress in the head cluster */ diff --git a/fs/erofs/inode.c b/fs/erofs/inode.c index 0dbeaf68e1d6..0a94a52a119f 100644 --- a/fs/erofs/inode.c +++ b/fs/erofs/inode.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2017-2018 HUAWEI, Inc. - * http://www.huawei.com/ + * https://www.huawei.com/ * Created by Gao Xiang */ #include "xattr.h" @@ -356,27 +356,21 @@ int erofs_getattr(const struct path *path, struct kstat *stat, const struct inode_operations erofs_generic_iops = { .getattr = erofs_getattr, -#ifdef CONFIG_EROFS_FS_XATTR .listxattr = erofs_listxattr, -#endif .get_acl = erofs_get_acl, }; const struct inode_operations erofs_symlink_iops = { .get_link = page_get_link, .getattr = erofs_getattr, -#ifdef CONFIG_EROFS_FS_XATTR .listxattr = erofs_listxattr, -#endif .get_acl = erofs_get_acl, }; const struct inode_operations erofs_fast_symlink_iops = { .get_link = simple_get_link, .getattr = erofs_getattr, -#ifdef CONFIG_EROFS_FS_XATTR .listxattr = erofs_listxattr, -#endif .get_acl = erofs_get_acl, }; diff --git a/fs/erofs/internal.h b/fs/erofs/internal.h index cc7a42682814..c18b0553cb98 100644 --- a/fs/erofs/internal.h +++ b/fs/erofs/internal.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (C) 2017-2018 HUAWEI, Inc. - * http://www.huawei.com/ + * https://www.huawei.com/ * Created by Gao Xiang */ #ifndef __EROFS_INTERNAL_H @@ -46,25 +46,43 @@ typedef u64 erofs_off_t; /* data type for filesystem-wide blocks number */ typedef u32 erofs_blk_t; +struct erofs_fs_context { +#ifdef CONFIG_EROFS_FS_ZIP + /* current strategy of how to use managed cache */ + unsigned char cache_strategy; + /* strategy of sync decompression (false - auto, true - force on) */ + bool readahead_sync_decompress; + + /* threshold for decompression synchronously */ + unsigned int max_sync_decompress_pages; +#endif + unsigned int mount_opt; +}; + +/* all filesystem-wide lz4 configurations */ +struct erofs_sb_lz4_info { + /* # of pages needed for EROFS lz4 rolling decompression */ + u16 max_distance_pages; + /* maximum possible blocks for pclusters in the filesystem */ + u16 max_pclusterblks; +}; + struct erofs_sb_info { #ifdef CONFIG_EROFS_FS_ZIP /* list for all registered superblocks, mainly for shrinker */ struct list_head list; struct mutex umount_mutex; - /* the dedicated workstation for compression */ - struct radix_tree_root workstn_tree; - - /* threshold for decompression synchronously */ - unsigned int max_sync_decompress_pages; + /* managed XArray arranged in physical block number */ + struct xarray managed_pslots; unsigned int shrinker_run_no; - - /* current strategy of how to use managed cache */ - unsigned char cache_strategy; + u16 available_compr_algs; /* pseudo inode to manage cached pages */ struct inode *managed_cache; + + struct erofs_sb_lz4_info lz4; #endif /* CONFIG_EROFS_FS_ZIP */ u32 blocks; u32 meta_blkaddr; @@ -75,6 +93,7 @@ struct erofs_sb_info { /* inode slot unit size in bit shift */ unsigned char islotbits; + u32 sb_size; /* total superblock size */ u32 build_time_nsec; u64 build_time; @@ -85,9 +104,10 @@ struct erofs_sb_info { u8 uuid[16]; /* 128-bit uuid for volume */ u8 volume_name[16]; /* volume name */ + u32 feature_compat; u32 feature_incompat; - unsigned int mount_opt; + struct erofs_fs_context ctx; /* options */ }; #define EROFS_SB(sb) ((struct erofs_sb_info *)(sb)->s_fs_info) @@ -97,17 +117,17 @@ struct erofs_sb_info { #define EROFS_MOUNT_XATTR_USER 0x00000010 #define EROFS_MOUNT_POSIX_ACL 0x00000020 -#define clear_opt(sbi, option) ((sbi)->mount_opt &= ~EROFS_MOUNT_##option) -#define set_opt(sbi, option) ((sbi)->mount_opt |= EROFS_MOUNT_##option) -#define test_opt(sbi, option) ((sbi)->mount_opt & EROFS_MOUNT_##option) +#define clear_opt(ctx, option) ((ctx)->mount_opt &= ~EROFS_MOUNT_##option) +#define set_opt(ctx, option) ((ctx)->mount_opt |= EROFS_MOUNT_##option) +#define test_opt(ctx, option) ((ctx)->mount_opt & EROFS_MOUNT_##option) -#ifdef CONFIG_EROFS_FS_ZIP enum { EROFS_ZIP_CACHE_DISABLED, EROFS_ZIP_CACHE_READAHEAD, EROFS_ZIP_CACHE_READAROUND }; +#ifdef CONFIG_EROFS_FS_ZIP #define EROFS_LOCKED_MAGIC (INT_MIN | 0xE0F510CCL) /* basic unit of the workstation of a super_block */ @@ -176,12 +196,6 @@ static inline int erofs_wait_on_workgroup_freezed(struct erofs_workgroup *grp) return v; } #endif /* !CONFIG_SMP */ - -/* hard limit of pages per compressed cluster */ -#define Z_EROFS_CLUSTER_MAX_PAGES (CONFIG_EROFS_FS_CLUSTER_PAGE_LIMIT) -#define EROFS_PCPUBUF_NR_PAGES Z_EROFS_CLUSTER_MAX_PAGES -#else -#define EROFS_PCPUBUF_NR_PAGES 0 #endif /* !CONFIG_EROFS_FS_ZIP */ /* we strictly follow PAGE_SIZE and no buffer head yet */ @@ -210,6 +224,17 @@ static inline erofs_off_t iloc(struct erofs_sb_info *sbi, erofs_nid_t nid) return blknr_to_addr(sbi->meta_blkaddr) + (nid << sbi->islotbits); } +#define EROFS_FEATURE_FUNCS(name, compat, feature) \ +static inline bool erofs_sb_has_##name(struct erofs_sb_info *sbi) \ +{ \ + return sbi->feature_##compat & EROFS_FEATURE_##feature; \ +} + +EROFS_FEATURE_FUNCS(lz4_0padding, incompat, INCOMPAT_LZ4_0PADDING) +EROFS_FEATURE_FUNCS(compr_cfgs, incompat, INCOMPAT_COMPR_CFGS) +EROFS_FEATURE_FUNCS(big_pcluster, incompat, INCOMPAT_BIG_PCLUSTER) +EROFS_FEATURE_FUNCS(sb_chksum, compat, COMPAT_SB_CHKSUM) + /* atomic flag definitions */ #define EROFS_I_EA_INITED_BIT 0 #define EROFS_I_Z_INITED_BIT 1 @@ -238,7 +263,6 @@ struct erofs_inode { unsigned short z_advise; unsigned char z_algorithmtype[2]; unsigned char z_logical_clusterbits; - unsigned char z_physical_clusterbits[2]; }; #endif /* CONFIG_EROFS_FS_ZIP */ }; @@ -278,12 +302,10 @@ static inline unsigned int erofs_inode_datalayout(unsigned int value) extern const struct super_operations erofs_sops; extern const struct address_space_operations erofs_raw_access_aops; -#ifdef CONFIG_EROFS_FS_ZIP -extern const struct address_space_operations z_erofs_vle_normalaccess_aops; -#endif +extern const struct address_space_operations z_erofs_aops; /* - * Logical to physical block mapping, used by erofs_map_blocks() + * Logical to physical block mapping * * Different with other file systems, it is used for 2 access modes: * @@ -330,7 +352,7 @@ struct erofs_map_blocks { struct page *mpage; }; -/* Flags used by erofs_map_blocks() */ +/* Flags used by erofs_map_blocks_flatmode() */ #define EROFS_GET_BLOCKS_RAW 0x0001 /* zmap.c */ @@ -352,8 +374,6 @@ static inline int z_erofs_map_blocks_iter(struct inode *inode, /* data.c */ struct page *erofs_get_meta_page(struct super_block *sb, erofs_blk_t blkaddr); -int erofs_map_blocks(struct inode *, struct erofs_map_blocks *, int); - /* inode.c */ static inline unsigned long erofs_inode_hash(erofs_nid_t nid) { @@ -381,30 +401,37 @@ int erofs_namei(struct inode *dir, struct qstr *name, /* dir.c */ extern const struct file_operations erofs_dir_fops; -/* utils.c / zdata.c */ -struct page *erofs_allocpage(struct list_head *pool, gfp_t gfp, bool nofail); - -#if (EROFS_PCPUBUF_NR_PAGES > 0) -void *erofs_get_pcpubuf(unsigned int pagenr); -#define erofs_put_pcpubuf(buf) do { \ - (void)&(buf); \ - preempt_enable(); \ -} while (0) -#else -static inline void *erofs_get_pcpubuf(unsigned int pagenr) +static inline void *erofs_vm_map_ram(struct page **pages, unsigned int count) { - return ERR_PTR(-EOPNOTSUPP); + int retried = 0; + + while (1) { + void *p = vm_map_ram(pages, count, -1, PAGE_KERNEL); + + /* retry two more times (totally 3 times) */ + if (p || ++retried >= 3) + return p; + vm_unmap_aliases(); + } + return NULL; } -#define erofs_put_pcpubuf(buf) do {} while (0) -#endif +/* pcpubuf.c */ +void *erofs_get_pcpubuf(unsigned int requiredpages); +void erofs_put_pcpubuf(void *ptr); +int erofs_pcpubuf_growsize(unsigned int nrpages); +void erofs_pcpubuf_init(void); +void erofs_pcpubuf_exit(void); + +/* utils.c / zdata.c */ +struct page *erofs_allocpage(struct list_head *pool, gfp_t gfp); #ifdef CONFIG_EROFS_FS_ZIP int erofs_workgroup_put(struct erofs_workgroup *grp); struct erofs_workgroup *erofs_find_workgroup(struct super_block *sb, - pgoff_t index, bool *tag); -int erofs_register_workgroup(struct super_block *sb, - struct erofs_workgroup *grp, bool tag); + pgoff_t index); +struct erofs_workgroup *erofs_insert_workgroup(struct super_block *sb, + struct erofs_workgroup *grp); void erofs_workgroup_free_rcu(struct erofs_workgroup *grp); void erofs_shrinker_register(struct super_block *sb); void erofs_shrinker_unregister(struct super_block *sb); @@ -416,6 +443,9 @@ int erofs_try_to_free_all_cached_pages(struct erofs_sb_info *sbi, struct erofs_workgroup *egrp); int erofs_try_to_free_cached_page(struct address_space *mapping, struct page *page); +int z_erofs_load_lz4_config(struct super_block *sb, + struct erofs_super_block *dsb, + struct z_erofs_lz4_cfgs *lz4, int len); #else static inline void erofs_shrinker_register(struct super_block *sb) {} static inline void erofs_shrinker_unregister(struct super_block *sb) {} @@ -423,6 +453,16 @@ static inline int erofs_init_shrinker(void) { return 0; } static inline void erofs_exit_shrinker(void) {} static inline int z_erofs_init_zip_subsystem(void) { return 0; } static inline void z_erofs_exit_zip_subsystem(void) {} +static inline int z_erofs_load_lz4_config(struct super_block *sb, + struct erofs_super_block *dsb, + struct z_erofs_lz4_cfgs *lz4, int len) +{ + if (lz4 || dsb->u1.lz4_max_distance) { + erofs_err(sb, "lz4 algorithm isn't enabled"); + return -EINVAL; + } + return 0; +} #endif /* !CONFIG_EROFS_FS_ZIP */ #define EFSCORRUPTED EUCLEAN /* Filesystem is corrupted */ diff --git a/fs/erofs/namei.c b/fs/erofs/namei.c index 3abbecbf73de..5f8cc7346c69 100644 --- a/fs/erofs/namei.c +++ b/fs/erofs/namei.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2017-2018 HUAWEI, Inc. - * http://www.huawei.com/ + * https://www.huawei.com/ * Created by Gao Xiang */ #include "xattr.h" @@ -244,9 +244,7 @@ static struct dentry *erofs_lookup(struct inode *dir, const struct inode_operations erofs_dir_iops = { .lookup = erofs_lookup, .getattr = erofs_getattr, -#ifdef CONFIG_EROFS_FS_XATTR .listxattr = erofs_listxattr, -#endif .get_acl = erofs_get_acl, }; diff --git a/fs/erofs/pcpubuf.c b/fs/erofs/pcpubuf.c new file mode 100644 index 000000000000..6c885575128a --- /dev/null +++ b/fs/erofs/pcpubuf.c @@ -0,0 +1,148 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) Gao Xiang + * + * For low-latency decompression algorithms (e.g. lz4), reserve consecutive + * per-CPU virtual memory (in pages) in advance to store such inplace I/O + * data if inplace decompression is failed (due to unmet inplace margin for + * example). + */ +#include "internal.h" + +struct erofs_pcpubuf { + raw_spinlock_t lock; + void *ptr; + struct page **pages; + unsigned int nrpages; +}; + +static DEFINE_PER_CPU(struct erofs_pcpubuf, erofs_pcb); + +void *erofs_get_pcpubuf(unsigned int requiredpages) + __acquires(pcb->lock) +{ + struct erofs_pcpubuf *pcb = &get_cpu_var(erofs_pcb); + + raw_spin_lock(&pcb->lock); + /* check if the per-CPU buffer is too small */ + if (requiredpages > pcb->nrpages) { + raw_spin_unlock(&pcb->lock); + put_cpu_var(erofs_pcb); + /* (for sparse checker) pretend pcb->lock is still taken */ + __acquire(pcb->lock); + return NULL; + } + return pcb->ptr; +} + +void erofs_put_pcpubuf(void *ptr) __releases(pcb->lock) +{ + struct erofs_pcpubuf *pcb = &per_cpu(erofs_pcb, smp_processor_id()); + + DBG_BUGON(pcb->ptr != ptr); + raw_spin_unlock(&pcb->lock); + put_cpu_var(erofs_pcb); +} + +/* the next step: support per-CPU page buffers hotplug */ +int erofs_pcpubuf_growsize(unsigned int nrpages) +{ + static DEFINE_MUTEX(pcb_resize_mutex); + static unsigned int pcb_nrpages; + LIST_HEAD(pagepool); + int delta, cpu, ret, i; + + mutex_lock(&pcb_resize_mutex); + delta = nrpages - pcb_nrpages; + ret = 0; + /* avoid shrinking pcpubuf, since no idea how many fses rely on */ + if (delta <= 0) + goto out; + + for_each_possible_cpu(cpu) { + struct erofs_pcpubuf *pcb = &per_cpu(erofs_pcb, cpu); + struct page **pages, **oldpages; + void *ptr, *old_ptr; + + pages = kmalloc_array(nrpages, sizeof(*pages), GFP_KERNEL); + if (!pages) { + ret = -ENOMEM; + break; + } + + for (i = 0; i < nrpages; ++i) { + pages[i] = erofs_allocpage(&pagepool, GFP_KERNEL); + if (!pages[i]) { + ret = -ENOMEM; + oldpages = pages; + goto free_pagearray; + } + } + ptr = vmap(pages, nrpages, VM_MAP, PAGE_KERNEL); + if (!ptr) { + ret = -ENOMEM; + oldpages = pages; + goto free_pagearray; + } + raw_spin_lock(&pcb->lock); + old_ptr = pcb->ptr; + pcb->ptr = ptr; + oldpages = pcb->pages; + pcb->pages = pages; + i = pcb->nrpages; + pcb->nrpages = nrpages; + raw_spin_unlock(&pcb->lock); + + if (!oldpages) { + DBG_BUGON(old_ptr); + continue; + } + + if (old_ptr) + vunmap(old_ptr); +free_pagearray: + while (i) + list_add(&oldpages[--i]->lru, &pagepool); + kfree(oldpages); + if (ret) + break; + } + pcb_nrpages = nrpages; + put_pages_list(&pagepool); +out: + mutex_unlock(&pcb_resize_mutex); + return ret; +} + +void erofs_pcpubuf_init(void) +{ + int cpu; + + for_each_possible_cpu(cpu) { + struct erofs_pcpubuf *pcb = &per_cpu(erofs_pcb, cpu); + + raw_spin_lock_init(&pcb->lock); + } +} + +void erofs_pcpubuf_exit(void) +{ + int cpu, i; + + for_each_possible_cpu(cpu) { + struct erofs_pcpubuf *pcb = &per_cpu(erofs_pcb, cpu); + + if (pcb->ptr) { + vunmap(pcb->ptr); + pcb->ptr = NULL; + } + if (!pcb->pages) + continue; + + for (i = 0; i < pcb->nrpages; ++i) + if (pcb->pages[i]) + put_page(pcb->pages[i]); + kfree(pcb->pages); + pcb->pages = NULL; + } +} diff --git a/fs/erofs/super.c b/fs/erofs/super.c index 22e059b4f745..975c8a18f0ed 100644 --- a/fs/erofs/super.c +++ b/fs/erofs/super.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2017-2018 HUAWEI, Inc. - * http://www.huawei.com/ + * https://www.huawei.com/ * Created by Gao Xiang */ #include @@ -9,6 +9,9 @@ #include #include #include +#include +#include +#include #include "xattr.h" #define CREATE_TRACE_POINTS @@ -46,6 +49,30 @@ void _erofs_info(struct super_block *sb, const char *function, va_end(args); } +static int erofs_superblock_csum_verify(struct super_block *sb, void *sbdata) +{ + struct erofs_super_block *dsb; + u32 expected_crc, crc; + + dsb = kmemdup(sbdata + EROFS_SUPER_OFFSET, + EROFS_BLKSIZ - EROFS_SUPER_OFFSET, GFP_KERNEL); + if (!dsb) + return -ENOMEM; + + expected_crc = le32_to_cpu(dsb->checksum); + dsb->checksum = 0; + /* to allow for x86 boot sectors and other oddities. */ + crc = crc32c(~0, dsb, EROFS_BLKSIZ - EROFS_SUPER_OFFSET); + kfree(dsb); + + if (crc != expected_crc) { + erofs_err(sb, "invalid checksum 0x%08x, 0x%08x expected", + crc, expected_crc); + return -EBADMSG; + } + return 0; +} + static void erofs_inode_init_once(void *ptr) { struct erofs_inode *vi = ptr; @@ -95,6 +122,136 @@ static bool check_layout_compatibility(struct super_block *sb, return true; } +#ifdef CONFIG_EROFS_FS_ZIP +/* read variable-sized metadata, offset will be aligned by 4-byte */ +static void *erofs_read_metadata(struct super_block *sb, struct page **pagep, + erofs_off_t *offset, int *lengthp) +{ + struct page *page = *pagep; + u8 *buffer, *ptr; + int len, i, cnt; + erofs_blk_t blk; + + *offset = round_up(*offset, 4); + blk = erofs_blknr(*offset); + + if (!page || page->index != blk) { + if (page) { + unlock_page(page); + put_page(page); + } + page = erofs_get_meta_page(sb, blk); + if (IS_ERR(page)) + goto err_nullpage; + } + + ptr = kmap(page); + len = le16_to_cpu(*(__le16 *)&ptr[erofs_blkoff(*offset)]); + if (!len) + len = U16_MAX + 1; + buffer = kmalloc(len, GFP_KERNEL); + if (!buffer) { + buffer = ERR_PTR(-ENOMEM); + goto out; + } + *offset += sizeof(__le16); + *lengthp = len; + + for (i = 0; i < len; i += cnt) { + cnt = min(EROFS_BLKSIZ - (int)erofs_blkoff(*offset), len - i); + blk = erofs_blknr(*offset); + + if (!page || page->index != blk) { + if (page) { + kunmap(page); + unlock_page(page); + put_page(page); + } + page = erofs_get_meta_page(sb, blk); + if (IS_ERR(page)) { + kfree(buffer); + goto err_nullpage; + } + ptr = kmap(page); + } + memcpy(buffer + i, ptr + erofs_blkoff(*offset), cnt); + *offset += cnt; + } +out: + kunmap(page); + *pagep = page; + return buffer; +err_nullpage: + *pagep = NULL; + return page; +} + +static int erofs_load_compr_cfgs(struct super_block *sb, + struct erofs_super_block *dsb) +{ + struct erofs_sb_info *sbi; + struct page *page; + unsigned int algs, alg; + erofs_off_t offset; + int size, ret; + + sbi = EROFS_SB(sb); + sbi->available_compr_algs = le16_to_cpu(dsb->u1.available_compr_algs); + + if (sbi->available_compr_algs & ~Z_EROFS_ALL_COMPR_ALGS) { + erofs_err(sb, "try to load compressed fs with unsupported algorithms %x", + sbi->available_compr_algs & ~Z_EROFS_ALL_COMPR_ALGS); + return -EINVAL; + } + + offset = EROFS_SUPER_OFFSET + sbi->sb_size; + page = NULL; + alg = 0; + ret = 0; + + for (algs = sbi->available_compr_algs; algs; algs >>= 1, ++alg) { + void *data; + + if (!(algs & 1)) + continue; + + data = erofs_read_metadata(sb, &page, &offset, &size); + if (IS_ERR(data)) { + ret = PTR_ERR(data); + goto err; + } + + switch (alg) { + case Z_EROFS_COMPRESSION_LZ4: + ret = z_erofs_load_lz4_config(sb, dsb, data, size); + break; + default: + DBG_BUGON(1); + ret = -EFAULT; + } + kfree(data); + if (ret) + goto err; + } +err: + if (page) { + unlock_page(page); + put_page(page); + } + return ret; +} +#else +static int erofs_load_compr_cfgs(struct super_block *sb, + struct erofs_super_block *dsb) +{ + if (dsb->u1.available_compr_algs) { + erofs_err(sb, "try to load compressed fs when compression is disabled"); + return -EINVAL; + } + return 0; +} +#endif + static int erofs_read_superblock(struct super_block *sb) { struct erofs_sb_info *sbi; @@ -112,7 +269,7 @@ static int erofs_read_superblock(struct super_block *sb) sbi = EROFS_SB(sb); - data = kmap_atomic(page); + data = kmap(page); dsb = (struct erofs_super_block *)(data + EROFS_SUPER_OFFSET); ret = -EINVAL; @@ -121,6 +278,14 @@ static int erofs_read_superblock(struct super_block *sb) goto out; } + sbi->feature_compat = le32_to_cpu(dsb->feature_compat); + if (erofs_sb_has_sb_chksum(sbi)) { + ret = erofs_superblock_csum_verify(sb, data); + if (ret) + goto out; + } + + ret = -EINVAL; blkszbits = dsb->blkszbits; /* 9(512 bytes) + LOG_SECTORS_PER_BLOCK == LOG_BLOCK_SIZE */ if (blkszbits != LOG_BLOCK_SIZE) { @@ -132,6 +297,12 @@ static int erofs_read_superblock(struct super_block *sb) if (!check_layout_compatibility(sb, dsb)) goto out; + sbi->sb_size = 128 + dsb->sb_extslots * EROFS_SB_EXTSLOT_SIZE; + if (sbi->sb_size > EROFS_BLKSIZ) { + erofs_err(sb, "invalid sb_extslots %u (more than a fs block)", + sbi->sb_size); + goto out; + } sbi->blocks = le32_to_cpu(dsb->blocks); sbi->meta_blkaddr = le32_to_cpu(dsb->meta_blkaddr); #ifdef CONFIG_EROFS_FS_XATTR @@ -153,139 +324,101 @@ static int erofs_read_superblock(struct super_block *sb) ret = -EFSCORRUPTED; goto out; } - ret = 0; + + /* parse on-disk compression configurations */ + if (erofs_sb_has_compr_cfgs(sbi)) + ret = erofs_load_compr_cfgs(sb, dsb); + else + ret = z_erofs_load_lz4_config(sb, dsb, NULL, 0); out: - kunmap_atomic(data); + kunmap(page); put_page(page); return ret; } -#ifdef CONFIG_EROFS_FS_ZIP -static int erofs_build_cache_strategy(struct super_block *sb, - substring_t *args) -{ - struct erofs_sb_info *sbi = EROFS_SB(sb); - const char *cs = match_strdup(args); - int err = 0; - - if (!cs) { - erofs_err(sb, "Not enough memory to store cache strategy"); - return -ENOMEM; - } - - if (!strcmp(cs, "disabled")) { - sbi->cache_strategy = EROFS_ZIP_CACHE_DISABLED; - } else if (!strcmp(cs, "readahead")) { - sbi->cache_strategy = EROFS_ZIP_CACHE_READAHEAD; - } else if (!strcmp(cs, "readaround")) { - sbi->cache_strategy = EROFS_ZIP_CACHE_READAROUND; - } else { - erofs_err(sb, "Unrecognized cache strategy \"%s\"", cs); - err = -EINVAL; - } - kfree(cs); - return err; -} -#else -static int erofs_build_cache_strategy(struct super_block *sb, - substring_t *args) -{ - erofs_info(sb, "EROFS compression is disabled, so cache strategy is ignored"); - return 0; -} -#endif - /* set up default EROFS parameters */ -static void erofs_default_options(struct erofs_sb_info *sbi) +static void erofs_default_options(struct erofs_fs_context *ctx) { #ifdef CONFIG_EROFS_FS_ZIP - sbi->cache_strategy = EROFS_ZIP_CACHE_READAROUND; - sbi->max_sync_decompress_pages = 3; + ctx->cache_strategy = EROFS_ZIP_CACHE_READAROUND; + ctx->max_sync_decompress_pages = 3; + ctx->readahead_sync_decompress = false; #endif #ifdef CONFIG_EROFS_FS_XATTR - set_opt(sbi, XATTR_USER); + set_opt(ctx, XATTR_USER); #endif #ifdef CONFIG_EROFS_FS_POSIX_ACL - set_opt(sbi, POSIX_ACL); + set_opt(ctx, POSIX_ACL); #endif } enum { Opt_user_xattr, - Opt_nouser_xattr, Opt_acl, - Opt_noacl, Opt_cache_strategy, Opt_err }; -static match_table_t erofs_tokens = { - {Opt_user_xattr, "user_xattr"}, - {Opt_nouser_xattr, "nouser_xattr"}, - {Opt_acl, "acl"}, - {Opt_noacl, "noacl"}, - {Opt_cache_strategy, "cache_strategy=%s"}, - {Opt_err, NULL} +static const struct fs_parameter_enum erofs_param_cache_strategy[] ={ + {Opt_cache_strategy, "disabled", EROFS_ZIP_CACHE_DISABLED}, + {Opt_cache_strategy, "readahead", EROFS_ZIP_CACHE_READAHEAD}, + {Opt_cache_strategy, "readaround", EROFS_ZIP_CACHE_READAROUND}, + {} }; -static int erofs_parse_options(struct super_block *sb, char *options) +static const struct fs_parameter_spec erofs_fs_param_specs[] = { + fsparam_flag_no("user_xattr", Opt_user_xattr), + fsparam_flag_no("acl", Opt_acl), + fsparam_enum("cache_strategy", Opt_cache_strategy), + {} +}; +const struct fs_parameter_description erofs_fs_parameters = { + .name = "erofs", + .specs = erofs_fs_param_specs, + .enums = erofs_param_cache_strategy, +}; + +static int erofs_fc_parse_param(struct fs_context *fc, + struct fs_parameter *param) { - substring_t args[MAX_OPT_ARGS]; - char *p; - int err; + struct erofs_fs_context *ctx __maybe_unused = fc->fs_private; + struct fs_parse_result result; + int opt; - if (!options) - return 0; + opt = fs_parse(fc, &erofs_fs_parameters, param, &result); + if (opt < 0) + return opt; - while ((p = strsep(&options, ","))) { - int token; - - if (!*p) - continue; - - args[0].to = args[0].from = NULL; - token = match_token(p, erofs_tokens, args); - - switch (token) { + switch (opt) { + case Opt_user_xattr: #ifdef CONFIG_EROFS_FS_XATTR - case Opt_user_xattr: - set_opt(EROFS_SB(sb), XATTR_USER); - break; - case Opt_nouser_xattr: - clear_opt(EROFS_SB(sb), XATTR_USER); - break; + if (result.boolean) + set_opt(ctx, XATTR_USER); + else + clear_opt(ctx, XATTR_USER); #else - case Opt_user_xattr: - erofs_info(sb, "user_xattr options not supported"); - break; - case Opt_nouser_xattr: - erofs_info(sb, "nouser_xattr options not supported"); - break; + errorfc(fc, "{,no}user_xattr options not supported"); #endif + break; + case Opt_acl: #ifdef CONFIG_EROFS_FS_POSIX_ACL - case Opt_acl: - set_opt(EROFS_SB(sb), POSIX_ACL); - break; - case Opt_noacl: - clear_opt(EROFS_SB(sb), POSIX_ACL); - break; + if (result.boolean) + set_opt(ctx, POSIX_ACL); + else + clear_opt(ctx, POSIX_ACL); #else - case Opt_acl: - erofs_info(sb, "acl options not supported"); - break; - case Opt_noacl: - erofs_info(sb, "noacl options not supported"); - break; + errorfc(fc, "{,no}acl options not supported"); #endif - case Opt_cache_strategy: - err = erofs_build_cache_strategy(sb, args); - if (err) - return err; - break; - default: - erofs_err(sb, "Unrecognized mount option \"%s\" or missing value", p); - return -EINVAL; - } + break; + case Opt_cache_strategy: +#ifdef CONFIG_EROFS_FS_ZIP + ctx->cache_strategy = result.uint_32; +#else + errorfc(fc, "compression not supported, cache_strategy ignored"); +#endif + break; + default: + return -ENOPARAM; } return 0; } @@ -349,10 +482,11 @@ static int erofs_init_managed_cache(struct super_block *sb) static int erofs_init_managed_cache(struct super_block *sb) { return 0; } #endif -static int erofs_fill_super(struct super_block *sb, void *data, int silent) +static int erofs_fc_fill_super(struct super_block *sb, struct fs_context *fc) { struct inode *inode; struct erofs_sb_info *sbi; + struct erofs_fs_context *ctx = fc->fs_private; int err; sb->s_magic = EROFS_SUPER_MAGIC; @@ -376,24 +510,17 @@ static int erofs_fill_super(struct super_block *sb, void *data, int silent) sb->s_time_gran = 1; sb->s_op = &erofs_sops; - -#ifdef CONFIG_EROFS_FS_XATTR sb->s_xattr = erofs_xattr_handlers; -#endif - /* set erofs default mount options */ - erofs_default_options(sbi); - err = erofs_parse_options(sb, data); - if (err) - return err; - - if (test_opt(sbi, POSIX_ACL)) + if (test_opt(ctx, POSIX_ACL)) sb->s_flags |= SB_POSIXACL; else sb->s_flags &= ~SB_POSIXACL; + sbi->ctx = *ctx; + #ifdef CONFIG_EROFS_FS_ZIP - INIT_RADIX_TREE(&sbi->workstn_tree, GFP_ATOMIC); + xa_init(&sbi->managed_pslots); #endif /* get the root inode */ @@ -418,15 +545,58 @@ static int erofs_fill_super(struct super_block *sb, void *data, int silent) if (err) return err; - erofs_info(sb, "mounted with opts: %s, root inode @ nid %llu.", - (char *)data, ROOT_NID(sbi)); + erofs_info(sb, "mounted with root inode @ nid %llu.", ROOT_NID(sbi)); return 0; } -static struct dentry *erofs_mount(struct file_system_type *fs_type, int flags, - const char *dev_name, void *data) +static int erofs_fc_get_tree(struct fs_context *fc) { - return mount_bdev(fs_type, flags, dev_name, data, erofs_fill_super); + return get_tree_bdev(fc, erofs_fc_fill_super); +} + +static int erofs_fc_reconfigure(struct fs_context *fc) +{ + struct super_block *sb = fc->root->d_sb; + struct erofs_sb_info *sbi = EROFS_SB(sb); + struct erofs_fs_context *ctx = fc->fs_private; + + DBG_BUGON(!sb_rdonly(sb)); + + if (test_opt(ctx, POSIX_ACL)) + fc->sb_flags |= SB_POSIXACL; + else + fc->sb_flags &= ~SB_POSIXACL; + + sbi->ctx = *ctx; + + fc->sb_flags |= SB_RDONLY; + return 0; +} + +static void erofs_fc_free(struct fs_context *fc) +{ + kfree(fc->fs_private); +} + +static const struct fs_context_operations erofs_context_ops = { + .parse_param = erofs_fc_parse_param, + .get_tree = erofs_fc_get_tree, + .reconfigure = erofs_fc_reconfigure, + .free = erofs_fc_free, +}; + +static int erofs_init_fs_context(struct fs_context *fc) +{ + fc->fs_private = kzalloc(sizeof(struct erofs_fs_context), GFP_KERNEL); + if (!fc->fs_private) + return -ENOMEM; + + /* set default mount options */ + erofs_default_options(fc->fs_private); + + fc->ops = &erofs_context_ops; + + return 0; } /* @@ -465,7 +635,7 @@ static void erofs_put_super(struct super_block *sb) static struct file_system_type erofs_fs_type = { .owner = THIS_MODULE, .name = "erofs", - .mount = erofs_mount, + .init_fs_context = erofs_init_fs_context, .kill_sb = erofs_kill_sb, .fs_flags = FS_REQUIRES_DEV, }; @@ -490,6 +660,7 @@ static int __init erofs_module_init(void) if (err) goto shrinker_err; + erofs_pcpubuf_init(); err = z_erofs_init_zip_subsystem(); if (err) goto zip_err; @@ -519,6 +690,7 @@ static void __exit erofs_module_exit(void) /* Ensure all RCU free inodes are safe before cache is destroyed. */ rcu_barrier(); kmem_cache_destroy(erofs_inode_cachep); + erofs_pcpubuf_exit(); } /* get filesystem statistics */ @@ -538,72 +710,44 @@ static int erofs_statfs(struct dentry *dentry, struct kstatfs *buf) buf->f_namelen = EROFS_NAME_LEN; - buf->f_fsid.val[0] = (u32)id; - buf->f_fsid.val[1] = (u32)(id >> 32); + buf->f_fsid = u64_to_fsid(id); return 0; } static int erofs_show_options(struct seq_file *seq, struct dentry *root) { struct erofs_sb_info *sbi __maybe_unused = EROFS_SB(root->d_sb); + struct erofs_fs_context *ctx __maybe_unused = &sbi->ctx; #ifdef CONFIG_EROFS_FS_XATTR - if (test_opt(sbi, XATTR_USER)) + if (test_opt(ctx, XATTR_USER)) seq_puts(seq, ",user_xattr"); else seq_puts(seq, ",nouser_xattr"); #endif #ifdef CONFIG_EROFS_FS_POSIX_ACL - if (test_opt(sbi, POSIX_ACL)) + if (test_opt(ctx, POSIX_ACL)) seq_puts(seq, ",acl"); else seq_puts(seq, ",noacl"); #endif #ifdef CONFIG_EROFS_FS_ZIP - if (sbi->cache_strategy == EROFS_ZIP_CACHE_DISABLED) { + if (ctx->cache_strategy == EROFS_ZIP_CACHE_DISABLED) seq_puts(seq, ",cache_strategy=disabled"); - } else if (sbi->cache_strategy == EROFS_ZIP_CACHE_READAHEAD) { + else if (ctx->cache_strategy == EROFS_ZIP_CACHE_READAHEAD) seq_puts(seq, ",cache_strategy=readahead"); - } else if (sbi->cache_strategy == EROFS_ZIP_CACHE_READAROUND) { + else if (ctx->cache_strategy == EROFS_ZIP_CACHE_READAROUND) seq_puts(seq, ",cache_strategy=readaround"); - } else { - seq_puts(seq, ",cache_strategy=(unknown)"); - DBG_BUGON(1); - } #endif return 0; } -static int erofs_remount(struct super_block *sb, int *flags, char *data) -{ - struct erofs_sb_info *sbi = EROFS_SB(sb); - unsigned int org_mnt_opt = sbi->mount_opt; - int err; - - DBG_BUGON(!sb_rdonly(sb)); - err = erofs_parse_options(sb, data); - if (err) - goto out; - - if (test_opt(sbi, POSIX_ACL)) - sb->s_flags |= SB_POSIXACL; - else - sb->s_flags &= ~SB_POSIXACL; - - *flags |= SB_RDONLY; - return 0; -out: - sbi->mount_opt = org_mnt_opt; - return err; -} - const struct super_operations erofs_sops = { .put_super = erofs_put_super, .alloc_inode = erofs_alloc_inode, .free_inode = erofs_free_inode, .statfs = erofs_statfs, .show_options = erofs_show_options, - .remount_fs = erofs_remount, }; module_init(erofs_module_init); @@ -612,4 +756,5 @@ module_exit(erofs_module_exit); MODULE_DESCRIPTION("Enhanced ROM File System"); MODULE_AUTHOR("Gao Xiang, Chao Yu, Miao Xie, CONSUMER BG, HUAWEI Inc."); MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS(ANDROID_GKI_VFS_EXPORT_ONLY); diff --git a/fs/erofs/utils.c b/fs/erofs/utils.c index 3e28fd082df0..9d9c2c73bebd 100644 --- a/fs/erofs/utils.c +++ b/fs/erofs/utils.c @@ -1,13 +1,13 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2018 HUAWEI, Inc. - * http://www.huawei.com/ + * https://www.huawei.com/ * Created by Gao Xiang */ #include "internal.h" #include -struct page *erofs_allocpage(struct list_head *pool, gfp_t gfp, bool nofail) +struct page *erofs_allocpage(struct list_head *pool, gfp_t gfp) { struct page *page; @@ -16,30 +16,15 @@ struct page *erofs_allocpage(struct list_head *pool, gfp_t gfp, bool nofail) DBG_BUGON(page_ref_count(page) != 1); list_del(&page->lru); } else { - page = alloc_pages(gfp | (nofail ? __GFP_NOFAIL : 0), 0); + page = alloc_page(gfp); } return page; } -#if (EROFS_PCPUBUF_NR_PAGES > 0) -static struct { - u8 data[PAGE_SIZE * EROFS_PCPUBUF_NR_PAGES]; -} ____cacheline_aligned_in_smp erofs_pcpubuf[NR_CPUS]; - -void *erofs_get_pcpubuf(unsigned int pagenr) -{ - preempt_disable(); - return &erofs_pcpubuf[smp_processor_id()].data[pagenr * PAGE_SIZE]; -} -#endif - #ifdef CONFIG_EROFS_FS_ZIP /* global shrink count (for all mounted EROFS instances) */ static atomic_long_t erofs_global_shrink_cnt; -#define __erofs_workgroup_get(grp) atomic_inc(&(grp)->refcount) -#define __erofs_workgroup_put(grp) atomic_dec(&(grp)->refcount) - static int erofs_workgroup_get(struct erofs_workgroup *grp) { int o; @@ -59,18 +44,15 @@ repeat: } struct erofs_workgroup *erofs_find_workgroup(struct super_block *sb, - pgoff_t index, bool *tag) + pgoff_t index) { struct erofs_sb_info *sbi = EROFS_SB(sb); struct erofs_workgroup *grp; repeat: rcu_read_lock(); - grp = radix_tree_lookup(&sbi->workstn_tree, index); + grp = xa_load(&sbi->managed_pslots, index); if (grp) { - *tag = xa_pointer_tag(grp); - grp = xa_untag_pointer(grp); - if (erofs_workgroup_get(grp)) { /* prefer to relax rcu read side */ rcu_read_unlock(); @@ -83,46 +65,37 @@ repeat: return grp; } -int erofs_register_workgroup(struct super_block *sb, - struct erofs_workgroup *grp, - bool tag) +struct erofs_workgroup *erofs_insert_workgroup(struct super_block *sb, + struct erofs_workgroup *grp) { - struct erofs_sb_info *sbi; - int err; - - /* grp shouldn't be broken or used before */ - if (atomic_read(&grp->refcount) != 1) { - DBG_BUGON(1); - return -EINVAL; - } - - err = radix_tree_preload(GFP_NOFS); - if (err) - return err; - - sbi = EROFS_SB(sb); - xa_lock(&sbi->workstn_tree); - - grp = xa_tag_pointer(grp, tag); + struct erofs_sb_info *const sbi = EROFS_SB(sb); + struct erofs_workgroup *pre; /* - * Bump up reference count before making this workgroup - * visible to other users in order to avoid potential UAF - * without serialized by workstn_lock. + * Bump up a reference count before making this visible + * to others for the XArray in order to avoid potential + * UAF without serialized by xa_lock. */ - __erofs_workgroup_get(grp); + atomic_inc(&grp->refcount); - err = radix_tree_insert(&sbi->workstn_tree, grp->index, grp); - if (err) - /* - * it's safe to decrease since the workgroup isn't visible - * and refcount >= 2 (cannot be freezed). - */ - __erofs_workgroup_put(grp); - - xa_unlock(&sbi->workstn_tree); - radix_tree_preload_end(); - return err; +repeat: + xa_lock(&sbi->managed_pslots); + pre = __xa_cmpxchg(&sbi->managed_pslots, grp->index, + NULL, grp, GFP_NOFS); + if (pre) { + if (xa_is_err(pre)) { + pre = ERR_PTR(xa_err(pre)); + } else if (erofs_workgroup_get(pre)) { + /* try to legitimize the current in-tree one */ + xa_unlock(&sbi->managed_pslots); + cond_resched(); + goto repeat; + } + atomic_dec(&grp->refcount); + grp = pre; + } + xa_unlock(&sbi->managed_pslots); + return grp; } static void __erofs_workgroup_free(struct erofs_workgroup *grp) @@ -142,15 +115,8 @@ int erofs_workgroup_put(struct erofs_workgroup *grp) return count; } -static void erofs_workgroup_unfreeze_final(struct erofs_workgroup *grp) -{ - erofs_workgroup_unfreeze(grp, 0); - __erofs_workgroup_free(grp); -} - static bool erofs_try_to_release_workgroup(struct erofs_sb_info *sbi, - struct erofs_workgroup *grp, - bool cleanup) + struct erofs_workgroup *grp) { /* * If managed cache is on, refcount of workgroups @@ -162,7 +128,7 @@ static bool erofs_try_to_release_workgroup(struct erofs_sb_info *sbi, /* * Note that all cached pages should be unattached - * before deleted from the radix tree. Otherwise some + * before deleted from the XArray. Otherwise some * cached pages could be still attached to the orphan * old workgroup when the new one is available in the tree. */ @@ -176,49 +142,34 @@ static bool erofs_try_to_release_workgroup(struct erofs_sb_info *sbi, * however in order to avoid some race conditions, add a * DBG_BUGON to observe this in advance. */ - DBG_BUGON(xa_untag_pointer(radix_tree_delete(&sbi->workstn_tree, - grp->index)) != grp); + DBG_BUGON(__xa_erase(&sbi->managed_pslots, grp->index) != grp); - /* - * If managed cache is on, last refcount should indicate - * the related workstation. - */ - erofs_workgroup_unfreeze_final(grp); + /* last refcount should be connected with its managed pslot. */ + erofs_workgroup_unfreeze(grp, 0); + __erofs_workgroup_free(grp); return true; } static unsigned long erofs_shrink_workstation(struct erofs_sb_info *sbi, - unsigned long nr_shrink, - bool cleanup) + unsigned long nr_shrink) { - pgoff_t first_index = 0; - void *batch[PAGEVEC_SIZE]; + struct erofs_workgroup *grp; unsigned int freed = 0; + unsigned long index; - int i, found; -repeat: - xa_lock(&sbi->workstn_tree); - - found = radix_tree_gang_lookup(&sbi->workstn_tree, - batch, first_index, PAGEVEC_SIZE); - - for (i = 0; i < found; ++i) { - struct erofs_workgroup *grp = xa_untag_pointer(batch[i]); - - first_index = grp->index + 1; - + xa_lock(&sbi->managed_pslots); + xa_for_each(&sbi->managed_pslots, index, grp) { /* try to shrink each valid workgroup */ - if (!erofs_try_to_release_workgroup(sbi, grp, cleanup)) + if (!erofs_try_to_release_workgroup(sbi, grp)) continue; + xa_unlock(&sbi->managed_pslots); ++freed; if (!--nr_shrink) - break; + return freed; + xa_lock(&sbi->managed_pslots); } - xa_unlock(&sbi->workstn_tree); - - if (i && nr_shrink) - goto repeat; + xa_unlock(&sbi->managed_pslots); return freed; } @@ -245,7 +196,8 @@ void erofs_shrinker_unregister(struct super_block *sb) struct erofs_sb_info *const sbi = EROFS_SB(sb); mutex_lock(&sbi->umount_mutex); - erofs_shrink_workstation(sbi, ~0UL, true); + /* clean up all remaining workgroups in memory */ + erofs_shrink_workstation(sbi, ~0UL); spin_lock(&erofs_sb_list_lock); list_del(&sbi->list); @@ -294,7 +246,7 @@ static unsigned long erofs_shrink_scan(struct shrinker *shrink, spin_unlock(&erofs_sb_list_lock); sbi->shrinker_run_no = run_no; - freed += erofs_shrink_workstation(sbi, nr - freed, false); + freed += erofs_shrink_workstation(sbi, nr - freed); spin_lock(&erofs_sb_list_lock); /* Get the next list element before we move this one */ diff --git a/fs/erofs/xattr.c b/fs/erofs/xattr.c index 7d6e38116254..6330bca9d91d 100644 --- a/fs/erofs/xattr.c +++ b/fs/erofs/xattr.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2017-2018 HUAWEI, Inc. - * http://www.huawei.com/ + * https://www.huawei.com/ * Created by Gao Xiang */ #include @@ -430,7 +430,7 @@ static int shared_getxattr(struct inode *inode, struct getxattr_iter *it) static bool erofs_xattr_user_list(struct dentry *dentry) { - return test_opt(EROFS_SB(dentry->d_sb), XATTR_USER); + return test_opt(&EROFS_SB(dentry->d_sb)->ctx, XATTR_USER); } static bool erofs_xattr_trusted_list(struct dentry *dentry) @@ -478,7 +478,7 @@ static int erofs_xattr_generic_get(const struct xattr_handler *handler, switch (handler->flags) { case EROFS_XATTR_INDEX_USER: - if (!test_opt(sbi, XATTR_USER)) + if (!test_opt(&sbi->ctx, XATTR_USER)) return -EOPNOTSUPP; break; case EROFS_XATTR_INDEX_TRUSTED: diff --git a/fs/erofs/xattr.h b/fs/erofs/xattr.h index 3585b84d2f20..815304bd335f 100644 --- a/fs/erofs/xattr.h +++ b/fs/erofs/xattr.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (C) 2017-2018 HUAWEI, Inc. - * http://www.huawei.com/ + * https://www.huawei.com/ * Created by Gao Xiang */ #ifndef __EROFS_XATTR_H @@ -46,18 +46,19 @@ extern const struct xattr_handler erofs_xattr_security_handler; static inline const struct xattr_handler *erofs_xattr_handler(unsigned int idx) { -static const struct xattr_handler *xattr_handler_map[] = { - [EROFS_XATTR_INDEX_USER] = &erofs_xattr_user_handler, + static const struct xattr_handler *xattr_handler_map[] = { + [EROFS_XATTR_INDEX_USER] = &erofs_xattr_user_handler, #ifdef CONFIG_EROFS_FS_POSIX_ACL - [EROFS_XATTR_INDEX_POSIX_ACL_ACCESS] = &posix_acl_access_xattr_handler, - [EROFS_XATTR_INDEX_POSIX_ACL_DEFAULT] = - &posix_acl_default_xattr_handler, + [EROFS_XATTR_INDEX_POSIX_ACL_ACCESS] = + &posix_acl_access_xattr_handler, + [EROFS_XATTR_INDEX_POSIX_ACL_DEFAULT] = + &posix_acl_default_xattr_handler, #endif - [EROFS_XATTR_INDEX_TRUSTED] = &erofs_xattr_trusted_handler, + [EROFS_XATTR_INDEX_TRUSTED] = &erofs_xattr_trusted_handler, #ifdef CONFIG_EROFS_FS_SECURITY - [EROFS_XATTR_INDEX_SECURITY] = &erofs_xattr_security_handler, + [EROFS_XATTR_INDEX_SECURITY] = &erofs_xattr_security_handler, #endif -}; + }; return idx && idx < ARRAY_SIZE(xattr_handler_map) ? xattr_handler_map[idx] : NULL; @@ -75,11 +76,8 @@ static inline int erofs_getxattr(struct inode *inode, int index, return -EOPNOTSUPP; } -static inline ssize_t erofs_listxattr(struct dentry *dentry, - char *buffer, size_t buffer_size) -{ - return -EOPNOTSUPP; -} +#define erofs_listxattr (NULL) +#define erofs_xattr_handlers (NULL) #endif /* !CONFIG_EROFS_FS_XATTR */ #ifdef CONFIG_EROFS_FS_POSIX_ACL diff --git a/fs/erofs/zdata.c b/fs/erofs/zdata.c index fb718c3e3ebd..15e03d0f60a0 100644 --- a/fs/erofs/zdata.c +++ b/fs/erofs/zdata.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2018 HUAWEI, Inc. - * http://www.huawei.com/ + * https://www.huawei.com/ * Created by Gao Xiang */ #include "zdata.h" @@ -10,6 +10,93 @@ #include +/* + * since pclustersize is variable for big pcluster feature, introduce slab + * pools implementation for different pcluster sizes. + */ +struct z_erofs_pcluster_slab { + struct kmem_cache *slab; + unsigned int maxpages; + char name[48]; +}; + +#define _PCLP(n) { .maxpages = n } + +static struct z_erofs_pcluster_slab pcluster_pool[] __read_mostly = { + _PCLP(1), _PCLP(4), _PCLP(16), _PCLP(64), _PCLP(128), + _PCLP(Z_EROFS_PCLUSTER_MAX_PAGES) +}; + +static void z_erofs_destroy_pcluster_pool(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(pcluster_pool); ++i) { + if (!pcluster_pool[i].slab) + continue; + kmem_cache_destroy(pcluster_pool[i].slab); + pcluster_pool[i].slab = NULL; + } +} + +static int z_erofs_create_pcluster_pool(void) +{ + struct z_erofs_pcluster_slab *pcs; + struct z_erofs_pcluster *a; + unsigned int size; + + for (pcs = pcluster_pool; + pcs < pcluster_pool + ARRAY_SIZE(pcluster_pool); ++pcs) { + size = struct_size(a, compressed_pages, pcs->maxpages); + + sprintf(pcs->name, "erofs_pcluster-%u", pcs->maxpages); + pcs->slab = kmem_cache_create(pcs->name, size, 0, + SLAB_RECLAIM_ACCOUNT, NULL); + if (pcs->slab) + continue; + + z_erofs_destroy_pcluster_pool(); + return -ENOMEM; + } + return 0; +} + +static struct z_erofs_pcluster *z_erofs_alloc_pcluster(unsigned int nrpages) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(pcluster_pool); ++i) { + struct z_erofs_pcluster_slab *pcs = pcluster_pool + i; + struct z_erofs_pcluster *pcl; + + if (nrpages > pcs->maxpages) + continue; + + pcl = kmem_cache_zalloc(pcs->slab, GFP_NOFS); + if (!pcl) + return ERR_PTR(-ENOMEM); + pcl->pclusterpages = nrpages; + return pcl; + } + return ERR_PTR(-EINVAL); +} + +static void z_erofs_free_pcluster(struct z_erofs_pcluster *pcl) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(pcluster_pool); ++i) { + struct z_erofs_pcluster_slab *pcs = pcluster_pool + i; + + if (pcl->pclusterpages > pcs->maxpages) + continue; + + kmem_cache_free(pcs->slab, pcl); + return; + } + DBG_BUGON(1); +} + /* * a compressed_pages[] placeholder in order to avoid * being filled with file pages for in-place decompression. @@ -20,6 +107,11 @@ enum z_erofs_cache_alloctype { DONTALLOC, /* don't allocate any cached pages */ DELAYEDALLOC, /* delayed allocation (at the time of submitting io) */ + /* + * try to use cached I/O if page allocation succeeds or fallback + * to in-place I/O instead to avoid any direct reclaim. + */ + TRYALLOC, }; /* @@ -32,64 +124,37 @@ typedef tagptr1_t compressed_page_t; tagptr_fold(compressed_page_t, page, 1) static struct workqueue_struct *z_erofs_workqueue __read_mostly; -static struct kmem_cache *pcluster_cachep __read_mostly; void z_erofs_exit_zip_subsystem(void) { destroy_workqueue(z_erofs_workqueue); - kmem_cache_destroy(pcluster_cachep); + z_erofs_destroy_pcluster_pool(); } static inline int z_erofs_init_workqueue(void) { const unsigned int onlinecpus = num_possible_cpus(); - const unsigned int flags = WQ_UNBOUND | WQ_HIGHPRI | WQ_CPU_INTENSIVE; /* * no need to spawn too many threads, limiting threads could minimum * scheduling overhead, perhaps per-CPU threads should be better? */ - z_erofs_workqueue = alloc_workqueue("erofs_unzipd", flags, + z_erofs_workqueue = alloc_workqueue("erofs_unzipd", + WQ_UNBOUND | WQ_HIGHPRI, onlinecpus + onlinecpus / 4); return z_erofs_workqueue ? 0 : -ENOMEM; } -static void z_erofs_pcluster_init_once(void *ptr) -{ - struct z_erofs_pcluster *pcl = ptr; - struct z_erofs_collection *cl = z_erofs_primarycollection(pcl); - unsigned int i; - - mutex_init(&cl->lock); - cl->nr_pages = 0; - cl->vcnt = 0; - for (i = 0; i < Z_EROFS_CLUSTER_MAX_PAGES; ++i) - pcl->compressed_pages[i] = NULL; -} - -static void z_erofs_pcluster_init_always(struct z_erofs_pcluster *pcl) -{ - struct z_erofs_collection *cl = z_erofs_primarycollection(pcl); - - atomic_set(&pcl->obj.refcount, 1); - - DBG_BUGON(cl->nr_pages); - DBG_BUGON(cl->vcnt); -} - int __init z_erofs_init_zip_subsystem(void) { - pcluster_cachep = kmem_cache_create("erofs_compress", - Z_EROFS_WORKGROUP_SIZE, 0, - SLAB_RECLAIM_ACCOUNT, - z_erofs_pcluster_init_once); - if (pcluster_cachep) { - if (!z_erofs_init_workqueue()) - return 0; + int err = z_erofs_create_pcluster_pool(); - kmem_cache_destroy(pcluster_cachep); - } - return -ENOMEM; + if (err) + return err; + err = z_erofs_init_workqueue(); + if (err) + z_erofs_destroy_pcluster_pool(); + return err; } enum z_erofs_collectmode { @@ -109,6 +174,12 @@ enum z_erofs_collectmode { * |_______PRIMARY_FOLLOWED_______|________PRIMARY_HOOKED___________| */ COLLECT_PRIMARY_HOOKED, + /* + * a weak form of COLLECT_PRIMARY_FOLLOWED, the difference is that it + * could be dispatched into bypass queue later due to uptodated managed + * pages. All related online pages cannot be reused for inplace I/O (or + * pagevec) since it can be directly decoded without I/O submission. + */ COLLECT_PRIMARY_FOLLOWED_NOINPLACE, /* * The current collection has been linked with the owned chain, and @@ -133,7 +204,8 @@ struct z_erofs_collector { struct z_erofs_pcluster *pcl, *tailpcl; struct z_erofs_collection *cl; - struct page **compressedpages; + /* a pointer used to pick up inplace I/O pages */ + struct page **icpage_ptr; z_erofs_next_pcluster_t owned_head; enum z_erofs_collectmode mode; @@ -145,6 +217,7 @@ struct z_erofs_decompress_frontend { struct z_erofs_collector clt; struct erofs_map_blocks map; + bool readahead; /* used for applying cache strategy on the fly */ bool backmost; erofs_off_t headoffset; @@ -166,18 +239,22 @@ static void preload_compressed_pages(struct z_erofs_collector *clt, enum z_erofs_cache_alloctype type, struct list_head *pagepool) { - const struct z_erofs_pcluster *pcl = clt->pcl; - const unsigned int clusterpages = BIT(pcl->clusterbits); - struct page **pages = clt->compressedpages; - pgoff_t index = pcl->obj.index + (pages - pcl->compressed_pages); + struct z_erofs_pcluster *pcl = clt->pcl; bool standalone = true; + gfp_t gfp = (mapping_gfp_mask(mc) & ~__GFP_DIRECT_RECLAIM) | + __GFP_NOMEMALLOC | __GFP_NORETRY | __GFP_NOWARN; + struct page **pages; + pgoff_t index; if (clt->mode < COLLECT_PRIMARY_FOLLOWED) return; - for (; pages < pcl->compressed_pages + clusterpages; ++pages) { + pages = pcl->compressed_pages; + index = pcl->obj.index; + for (; index < pcl->obj.index + pcl->pclusterpages; ++index, ++pages) { struct page *page; compressed_page_t t; + struct page *newpage = NULL; /* the compressed page was loaded before */ if (READ_ONCE(*pages)) @@ -187,23 +264,43 @@ static void preload_compressed_pages(struct z_erofs_collector *clt, if (page) { t = tag_compressed_page_justfound(page); - } else if (type == DELAYEDALLOC) { - t = tagptr_init(compressed_page_t, PAGE_UNALLOCATED); - } else { /* DONTALLOC */ - if (standalone) - clt->compressedpages = pages; + } else { + /* I/O is needed, no possible to decompress directly */ standalone = false; - continue; + switch (type) { + case DELAYEDALLOC: + t = tagptr_init(compressed_page_t, + PAGE_UNALLOCATED); + break; + case TRYALLOC: + newpage = erofs_allocpage(pagepool, gfp); + if (!newpage) + continue; + set_page_private(newpage, + Z_EROFS_PREALLOCATED_PAGE); + t = tag_compressed_page_justfound(newpage); + break; + default: /* DONTALLOC */ + continue; + } } if (!cmpxchg_relaxed(pages, NULL, tagptr_cast_ptr(t))) continue; - if (page) + if (page) { put_page(page); + } else if (newpage) { + set_page_private(newpage, 0); + list_add(&newpage->lru, pagepool); + } } - if (standalone) /* downgrade to PRIMARY_FOLLOWED_NOINPLACE */ + /* + * don't do inplace I/O if all compressed pages are available in + * managed cache since it can be moved to the bypass queue instead. + */ + if (standalone) clt->mode = COLLECT_PRIMARY_FOLLOWED_NOINPLACE; } @@ -214,14 +311,13 @@ int erofs_try_to_free_all_cached_pages(struct erofs_sb_info *sbi, struct z_erofs_pcluster *const pcl = container_of(grp, struct z_erofs_pcluster, obj); struct address_space *const mapping = MNGD_MAPPING(sbi); - const unsigned int clusterpages = BIT(pcl->clusterbits); int i; /* * refcount of workgroup is now freezed as 1, * therefore no need to worry about available decompression users. */ - for (i = 0; i < clusterpages; ++i) { + for (i = 0; i < pcl->pclusterpages; ++i) { struct page *page = pcl->compressed_pages[i]; if (!page) @@ -236,11 +332,8 @@ int erofs_try_to_free_all_cached_pages(struct erofs_sb_info *sbi, /* barrier is implied in the following 'unlock_page' */ WRITE_ONCE(pcl->compressed_pages[i], NULL); - set_page_private(page, 0); - ClearPagePrivate(page); - + detach_page_private(page); unlock_page(page); - put_page(page); } return 0; } @@ -249,13 +342,12 @@ int erofs_try_to_free_cached_page(struct address_space *mapping, struct page *page) { struct z_erofs_pcluster *const pcl = (void *)page_private(page); - const unsigned int clusterpages = BIT(pcl->clusterbits); int ret = 0; /* 0 - busy */ if (erofs_workgroup_try_to_freeze(&pcl->obj, 1)) { unsigned int i; - for (i = 0; i < clusterpages; ++i) { + for (i = 0; i < pcl->pclusterpages; ++i) { if (pcl->compressed_pages[i] == page) { WRITE_ONCE(pcl->compressed_pages[i], NULL); ret = 1; @@ -264,25 +356,21 @@ int erofs_try_to_free_cached_page(struct address_space *mapping, } erofs_workgroup_unfreeze(&pcl->obj, 1); - if (ret) { - ClearPagePrivate(page); - put_page(page); - } + if (ret) + detach_page_private(page); } return ret; } /* page_type must be Z_EROFS_PAGE_TYPE_EXCLUSIVE */ -static inline bool z_erofs_try_inplace_io(struct z_erofs_collector *clt, - struct page *page) +static bool z_erofs_try_inplace_io(struct z_erofs_collector *clt, + struct page *page) { struct z_erofs_pcluster *const pcl = clt->pcl; - const unsigned int clusterpages = BIT(pcl->clusterbits); - while (clt->compressedpages < pcl->compressed_pages + clusterpages) { - if (!cmpxchg(clt->compressedpages++, NULL, page)) + while (clt->icpage_ptr > pcl->compressed_pages) + if (!cmpxchg(--clt->icpage_ptr, NULL, page)) return true; - } return false; } @@ -335,40 +423,31 @@ retry: return COLLECT_PRIMARY; /* :( better luck next time */ } -static struct z_erofs_collection *cllookup(struct z_erofs_collector *clt, - struct inode *inode, - struct erofs_map_blocks *map) +static int z_erofs_lookup_collection(struct z_erofs_collector *clt, + struct inode *inode, + struct erofs_map_blocks *map) { - struct erofs_workgroup *grp; - struct z_erofs_pcluster *pcl; + struct z_erofs_pcluster *pcl = clt->pcl; struct z_erofs_collection *cl; unsigned int length; - bool tag; - grp = erofs_find_workgroup(inode->i_sb, map->m_pa >> PAGE_SHIFT, &tag); - if (!grp) - return NULL; - - pcl = container_of(grp, struct z_erofs_pcluster, obj); + /* to avoid unexpected loop formed by corrupted images */ if (clt->owned_head == &pcl->next || pcl == clt->tailpcl) { DBG_BUGON(1); - erofs_workgroup_put(grp); - return ERR_PTR(-EFSCORRUPTED); + return -EFSCORRUPTED; } cl = z_erofs_primarycollection(pcl); if (cl->pageofs != (map->m_la & ~PAGE_MASK)) { DBG_BUGON(1); - erofs_workgroup_put(grp); - return ERR_PTR(-EFSCORRUPTED); + return -EFSCORRUPTED; } length = READ_ONCE(pcl->length); if (length & Z_EROFS_PCLUSTER_FULL_LENGTH) { if ((map->m_llen << Z_EROFS_PCLUSTER_LENGTH_BIT) > length) { DBG_BUGON(1); - erofs_workgroup_put(grp); - return ERR_PTR(-EFSCORRUPTED); + return -EFSCORRUPTED; } } else { unsigned int llen = map->m_llen << Z_EROFS_PCLUSTER_LENGTH_BIT; @@ -390,25 +469,25 @@ static struct z_erofs_collection *cllookup(struct z_erofs_collector *clt, /* clean tailpcl if the current owned_head is Z_EROFS_PCLUSTER_TAIL */ if (clt->owned_head == Z_EROFS_PCLUSTER_TAIL) clt->tailpcl = NULL; - clt->pcl = pcl; clt->cl = cl; - return cl; + return 0; } -static struct z_erofs_collection *clregister(struct z_erofs_collector *clt, - struct inode *inode, - struct erofs_map_blocks *map) +static int z_erofs_register_collection(struct z_erofs_collector *clt, + struct inode *inode, + struct erofs_map_blocks *map) { struct z_erofs_pcluster *pcl; struct z_erofs_collection *cl; + struct erofs_workgroup *grp; int err; - /* no available workgroup, let's allocate one */ - pcl = kmem_cache_alloc(pcluster_cachep, GFP_NOFS); - if (!pcl) - return ERR_PTR(-ENOMEM); + /* no available pcluster, let's allocate one */ + pcl = z_erofs_alloc_pcluster(map->m_plen >> PAGE_SHIFT); + if (IS_ERR(pcl)) + return PTR_ERR(pcl); - z_erofs_pcluster_init_always(pcl); + atomic_set(&pcl->obj.refcount, 1); pcl->obj.index = map->m_pa >> PAGE_SHIFT; pcl->length = (map->m_llen << Z_EROFS_PCLUSTER_LENGTH_BIT) | @@ -420,9 +499,6 @@ static struct z_erofs_collection *clregister(struct z_erofs_collector *clt, else pcl->algorithmformat = Z_EROFS_COMPRESSION_SHIFTED; - pcl->clusterbits = EROFS_I(inode)->z_physical_clusterbits[0]; - pcl->clusterbits -= PAGE_SHIFT; - /* new pclusters should be claimed as type 1, primary and followed */ pcl->next = clt->owned_head; clt->mode = COLLECT_PRIMARY_FOLLOWED; @@ -434,13 +510,19 @@ static struct z_erofs_collection *clregister(struct z_erofs_collector *clt, * lock all primary followed works before visible to others * and mutex_trylock *never* fails for a new pcluster. */ - mutex_trylock(&cl->lock); + mutex_init(&cl->lock); + DBG_BUGON(!mutex_trylock(&cl->lock)); - err = erofs_register_workgroup(inode->i_sb, &pcl->obj, 0); - if (err) { - mutex_unlock(&cl->lock); - kmem_cache_free(pcluster_cachep, pcl); - return ERR_PTR(-EAGAIN); + grp = erofs_insert_workgroup(inode->i_sb, &pcl->obj); + if (IS_ERR(grp)) { + err = PTR_ERR(grp); + goto err_out; + } + + if (grp != &pcl->obj) { + clt->pcl = container_of(grp, struct z_erofs_pcluster, obj); + err = -EEXIST; + goto err_out; } /* used to check tail merging loop due to corrupted images */ if (clt->owned_head == Z_EROFS_PCLUSTER_TAIL) @@ -448,14 +530,20 @@ static struct z_erofs_collection *clregister(struct z_erofs_collector *clt, clt->owned_head = &pcl->next; clt->pcl = pcl; clt->cl = cl; - return cl; + return 0; + +err_out: + mutex_unlock(&cl->lock); + z_erofs_free_pcluster(pcl); + return err; } static int z_erofs_collector_begin(struct z_erofs_collector *clt, struct inode *inode, struct erofs_map_blocks *map) { - struct z_erofs_collection *cl; + struct erofs_workgroup *grp; + int ret; DBG_BUGON(clt->cl); @@ -468,24 +556,30 @@ static int z_erofs_collector_begin(struct z_erofs_collector *clt, return -EINVAL; } -repeat: - cl = cllookup(clt, inode, map); - if (!cl) { - cl = clregister(clt, inode, map); + grp = erofs_find_workgroup(inode->i_sb, map->m_pa >> PAGE_SHIFT); + if (grp) { + clt->pcl = container_of(grp, struct z_erofs_pcluster, obj); + } else { + ret = z_erofs_register_collection(clt, inode, map); - if (cl == ERR_PTR(-EAGAIN)) - goto repeat; + if (!ret) + goto out; + if (ret != -EEXIST) + return ret; } - if (IS_ERR(cl)) - return PTR_ERR(cl); + ret = z_erofs_lookup_collection(clt, inode, map); + if (ret) { + erofs_workgroup_put(&clt->pcl->obj); + return ret; + } +out: z_erofs_pagevec_ctor_init(&clt->vector, Z_EROFS_NR_INLINE_PAGEVECS, - cl->pagevec, cl->vcnt); + clt->cl->pagevec, clt->cl->vcnt); - clt->compressedpages = clt->pcl->compressed_pages; - if (clt->mode <= COLLECT_PRIMARY) /* cannot do in-place I/O */ - clt->compressedpages += Z_EROFS_CLUSTER_MAX_PAGES; + /* since file-backed online pages are traversed in reverse order */ + clt->icpage_ptr = clt->pcl->compressed_pages + clt->pcl->pclusterpages; return 0; } @@ -498,9 +592,8 @@ static void z_erofs_rcu_callback(struct rcu_head *head) struct z_erofs_collection *const cl = container_of(head, struct z_erofs_collection, rcu); - kmem_cache_free(pcluster_cachep, - container_of(cl, struct z_erofs_pcluster, - primary_collection)); + z_erofs_free_pcluster(container_of(cl, struct z_erofs_pcluster, + primary_collection)); } void erofs_workgroup_free_rcu(struct erofs_workgroup *grp) @@ -541,15 +634,6 @@ static bool z_erofs_collector_end(struct z_erofs_collector *clt) return true; } -static inline struct page *__stagingpage_alloc(struct list_head *pagepool, - gfp_t gfp) -{ - struct page *page = erofs_allocpage(pagepool, gfp, true); - - page->mapping = Z_EROFS_MAPPING_STAGING; - return page; -} - static bool should_alloc_managed_pages(struct z_erofs_decompress_frontend *fe, unsigned int cachestrategy, erofs_off_t la) @@ -565,11 +649,10 @@ static bool should_alloc_managed_pages(struct z_erofs_decompress_frontend *fe, } static int z_erofs_do_read_page(struct z_erofs_decompress_frontend *fe, - struct page *page, - struct list_head *pagepool) + struct page *page, struct list_head *pagepool) { struct inode *const inode = fe->inode; - struct erofs_sb_info *const sbi __maybe_unused = EROFS_I_SB(inode); + struct erofs_sb_info *const sbi = EROFS_I_SB(inode); struct erofs_map_blocks *const map = &fe->map; struct z_erofs_collector *const clt = &fe->clt; const loff_t offset = page_offset(page); @@ -618,8 +701,8 @@ restart_now: goto err_out; /* preload all compressed pages (maybe downgrade role if necessary) */ - if (should_alloc_managed_pages(fe, sbi->cache_strategy, map->m_la)) - cache_strategy = DELAYEDALLOC; + if (should_alloc_managed_pages(fe, sbi->ctx.cache_strategy, map->m_la)) + cache_strategy = TRYALLOC; else cache_strategy = DONTALLOC; @@ -659,8 +742,9 @@ retry: /* should allocate an additional staging page for pagevec */ if (err == -EAGAIN) { struct page *const newpage = - __stagingpage_alloc(pagepool, GFP_NOFS); + alloc_page(GFP_NOFS | __GFP_NOFAIL); + set_page_private(newpage, Z_EROFS_SHORTLIVED_PAGE); err = z_erofs_attach_page(clt, newpage, Z_EROFS_PAGE_TYPE_EXCLUSIVE, true); if (!err) @@ -699,13 +783,14 @@ err_out: goto out; } -static void z_erofs_vle_unzip_kickoff(void *ptr, int bios) +static void z_erofs_decompressqueue_work(struct work_struct *work); +static void z_erofs_decompress_kickoff(struct z_erofs_decompressqueue *io, + bool sync, int bios) { - tagptr1_t t = tagptr_init(tagptr1_t, ptr); - struct z_erofs_unzip_io *io = tagptr_unfold_ptr(t); - bool background = tagptr_unfold_tags(t); + struct erofs_sb_info *const sbi = EROFS_SB(io->sb); - if (!background) { + /* wake up the caller thread for sync decompression */ + if (sync) { unsigned long flags; spin_lock_irqsave(&io->u.wait.lock, flags); @@ -715,41 +800,46 @@ static void z_erofs_vle_unzip_kickoff(void *ptr, int bios) return; } - if (!atomic_add_return(bios, &io->pending_bios)) + if (atomic_add_return(bios, &io->pending_bios)) + return; + /* Use workqueue and sync decompression for atomic contexts only */ + if (in_atomic() || irqs_disabled()) { queue_work(z_erofs_workqueue, &io->u.work); + sbi->ctx.readahead_sync_decompress = true; + return; + } + z_erofs_decompressqueue_work(&io->u.work); } -static inline void z_erofs_vle_read_endio(struct bio *bio) +static bool z_erofs_page_is_invalidated(struct page *page) { - struct erofs_sb_info *sbi = NULL; + return !page->mapping && !z_erofs_is_shortlived_page(page); +} + +static void z_erofs_decompressqueue_endio(struct bio *bio) +{ + tagptr1_t t = tagptr_init(tagptr1_t, bio->bi_private); + struct z_erofs_decompressqueue *q = tagptr_unfold_ptr(t); blk_status_t err = bio->bi_status; struct bio_vec *bvec; struct bvec_iter_all iter_all; bio_for_each_segment_all(bvec, bio, iter_all) { struct page *page = bvec->bv_page; - bool cachemngd = false; DBG_BUGON(PageUptodate(page)); - DBG_BUGON(!page->mapping); - - if (!sbi && !z_erofs_page_is_staging(page)) - sbi = EROFS_SB(page->mapping->host->i_sb); - - /* sbi should already be gotten if the page is managed */ - if (sbi) - cachemngd = erofs_page_is_managed(sbi, page); + DBG_BUGON(z_erofs_page_is_invalidated(page)); if (err) SetPageError(page); - else if (cachemngd) - SetPageUptodate(page); - if (cachemngd) + if (erofs_page_is_managed(EROFS_SB(q->sb), page)) { + if (!err) + SetPageUptodate(page); unlock_page(page); + } } - - z_erofs_vle_unzip_kickoff(bio->bi_private, -1); + z_erofs_decompress_kickoff(q, tagptr_unfold_tags(t), -1); bio_put(bio); } @@ -758,9 +848,8 @@ static int z_erofs_decompress_pcluster(struct super_block *sb, struct list_head *pagepool) { struct erofs_sb_info *const sbi = EROFS_SB(sb); - const unsigned int clusterpages = BIT(pcl->clusterbits); struct z_erofs_pagevec_ctor ctor; - unsigned int i, outputsize, llen, nr_pages; + unsigned int i, inputsize, outputsize, llen, nr_pages; struct page *pages_onstack[Z_EROFS_VMAP_ONSTACK_PAGES]; struct page **pages, **compressed_pages, *page; @@ -811,9 +900,9 @@ static int z_erofs_decompress_pcluster(struct super_block *sb, /* all pages in pagevec ought to be valid */ DBG_BUGON(!page); - DBG_BUGON(!page->mapping); + DBG_BUGON(z_erofs_page_is_invalidated(page)); - if (z_erofs_put_stagingpage(pagepool, page)) + if (z_erofs_put_shortlivedpage(pagepool, page)) continue; if (page_type == Z_EROFS_VLE_PAGE_TYPE_HEAD) @@ -840,16 +929,16 @@ static int z_erofs_decompress_pcluster(struct super_block *sb, overlapped = false; compressed_pages = pcl->compressed_pages; - for (i = 0; i < clusterpages; ++i) { + for (i = 0; i < pcl->pclusterpages; ++i) { unsigned int pagenr; page = compressed_pages[i]; /* all compressed pages ought to be valid */ DBG_BUGON(!page); - DBG_BUGON(!page->mapping); + DBG_BUGON(z_erofs_page_is_invalidated(page)); - if (!z_erofs_page_is_staging(page)) { + if (!z_erofs_is_shortlived_page(page)) { if (erofs_page_is_managed(sbi, page)) { if (!PageUptodate(page)) err = -EIO; @@ -874,7 +963,7 @@ static int z_erofs_decompress_pcluster(struct super_block *sb, overlapped = true; } - /* PG_error needs checking for inplaced and staging pages */ + /* PG_error needs checking for all non-managed pages */ if (PageError(page)) { DBG_BUGON(PageUptodate(page)); err = -EIO; @@ -893,12 +982,13 @@ static int z_erofs_decompress_pcluster(struct super_block *sb, partial = true; } + inputsize = pcl->pclusterpages * PAGE_SIZE; err = z_erofs_decompress(&(struct z_erofs_decompress_req) { .sb = sb, .in = compressed_pages, .out = pages, .pageofs_out = cl->pageofs, - .inputsize = PAGE_SIZE, + .inputsize = inputsize, .outputsize = outputsize, .alg = pcl->algorithmformat, .inplace_io = overlapped, @@ -906,15 +996,15 @@ static int z_erofs_decompress_pcluster(struct super_block *sb, }, pagepool); out: - /* must handle all compressed pages before endding pages */ - for (i = 0; i < clusterpages; ++i) { + /* must handle all compressed pages before ending pages */ + for (i = 0; i < pcl->pclusterpages; ++i) { page = compressed_pages[i]; if (erofs_page_is_managed(sbi, page)) continue; - /* recycle all individual staging pages */ - (void)z_erofs_put_stagingpage(pagepool, page); + /* recycle all individual short-lived pages */ + (void)z_erofs_put_shortlivedpage(pagepool, page); WRITE_ONCE(compressed_pages[i], NULL); } @@ -924,10 +1014,10 @@ out: if (!page) continue; - DBG_BUGON(!page->mapping); + DBG_BUGON(z_erofs_page_is_invalidated(page)); - /* recycle all individual staging pages */ - if (z_erofs_put_stagingpage(pagepool, page)) + /* recycle all individual short-lived pages */ + if (z_erofs_put_shortlivedpage(pagepool, page)) continue; if (err < 0) @@ -954,9 +1044,8 @@ out: return err; } -static void z_erofs_vle_unzip_all(struct super_block *sb, - struct z_erofs_unzip_io *io, - struct list_head *pagepool) +static void z_erofs_decompress_queue(const struct z_erofs_decompressqueue *io, + struct list_head *pagepool) { z_erofs_next_pcluster_t owned = io->head; @@ -972,21 +1061,21 @@ static void z_erofs_vle_unzip_all(struct super_block *sb, pcl = container_of(owned, struct z_erofs_pcluster, next); owned = READ_ONCE(pcl->next); - z_erofs_decompress_pcluster(sb, pcl, pagepool); + z_erofs_decompress_pcluster(io->sb, pcl, pagepool); } } -static void z_erofs_vle_unzip_wq(struct work_struct *work) +static void z_erofs_decompressqueue_work(struct work_struct *work) { - struct z_erofs_unzip_io_sb *iosb = - container_of(work, struct z_erofs_unzip_io_sb, io.u.work); + struct z_erofs_decompressqueue *bgq = + container_of(work, struct z_erofs_decompressqueue, u.work); LIST_HEAD(pagepool); - DBG_BUGON(iosb->io.head == Z_EROFS_PCLUSTER_TAIL_CLOSED); - z_erofs_vle_unzip_all(iosb->sb, &iosb->io, &pagepool); + DBG_BUGON(bgq->head == Z_EROFS_PCLUSTER_TAIL_CLOSED); + z_erofs_decompress_queue(bgq, &pagepool); put_pages_list(&pagepool); - kvfree(iosb); + kvfree(bgq); } static struct page *pickup_page_for_submission(struct z_erofs_pcluster *pcl, @@ -995,8 +1084,6 @@ static struct page *pickup_page_for_submission(struct z_erofs_pcluster *pcl, struct address_space *mc, gfp_t gfp) { - /* determined at compile time to avoid too many #ifdefs */ - const bool nocache = __builtin_constant_p(mc) ? !mc : false; const pgoff_t index = pcl->obj.index; bool tocache = false; @@ -1017,7 +1104,7 @@ repeat: * the cached page has not been allocated and * an placeholder is out there, prepare it now. */ - if (!nocache && page == PAGE_UNALLOCATED) { + if (page == PAGE_UNALLOCATED) { tocache = true; goto out_allocpage; } @@ -1027,31 +1114,30 @@ repeat: justfound = tagptr_unfold_tags(t); page = tagptr_unfold_ptr(t); + /* + * preallocated cached pages, which is used to avoid direct reclaim + * otherwise, it will go inplace I/O path instead. + */ + if (page->private == Z_EROFS_PREALLOCATED_PAGE) { + WRITE_ONCE(pcl->compressed_pages[nr], page); + set_page_private(page, 0); + tocache = true; + goto out_tocache; + } mapping = READ_ONCE(page->mapping); /* - * if managed cache is disabled, it's no way to - * get such a cached-like page. - */ - if (nocache) { - /* if managed cache is disabled, it is impossible `justfound' */ - DBG_BUGON(justfound); - - /* and it should be locked, not uptodate, and not truncated */ - DBG_BUGON(!PageLocked(page)); - DBG_BUGON(PageUptodate(page)); - DBG_BUGON(!mapping); - goto out; - } - - /* - * unmanaged (file) pages are all locked solidly, + * file-backed online pages in plcuster are all locked steady, * therefore it is impossible for `mapping' to be NULL. */ if (mapping && mapping != mc) /* ought to be unmanaged pages */ goto out; + /* directly return for shortlived page as well */ + if (z_erofs_is_shortlived_page(page)) + goto out; + lock_page(page); /* only true if page reclaim goes wrong, should never happen */ @@ -1094,50 +1180,48 @@ repeat: unlock_page(page); put_page(page); out_allocpage: - page = __stagingpage_alloc(pagepool, gfp); + page = erofs_allocpage(pagepool, gfp | __GFP_NOFAIL); if (oldpage != cmpxchg(&pcl->compressed_pages[nr], oldpage, page)) { list_add(&page->lru, pagepool); - cpu_relax(); + cond_resched(); goto repeat; } - if (nocache || !tocache) - goto out; - if (add_to_page_cache_lru(page, mc, index + nr, gfp)) { - page->mapping = Z_EROFS_MAPPING_STAGING; +out_tocache: + if (!tocache || add_to_page_cache_lru(page, mc, index + nr, gfp)) { + /* turn into temporary page if fails (1 ref) */ + set_page_private(page, Z_EROFS_SHORTLIVED_PAGE); goto out; } + attach_page_private(page, pcl); + /* drop a refcount added by allocpage (then we have 2 refs here) */ + put_page(page); - set_page_private(page, (unsigned long)pcl); - SetPagePrivate(page); out: /* the only exit (for tracing and debugging) */ return page; } -static struct z_erofs_unzip_io *jobqueue_init(struct super_block *sb, - struct z_erofs_unzip_io *io, - bool foreground) +static struct z_erofs_decompressqueue * +jobqueue_init(struct super_block *sb, + struct z_erofs_decompressqueue *fgq, bool *fg) { - struct z_erofs_unzip_io_sb *iosb; + struct z_erofs_decompressqueue *q; - if (foreground) { - /* waitqueue available for foreground io */ - DBG_BUGON(!io); - - init_waitqueue_head(&io->u.wait); - atomic_set(&io->pending_bios, 0); - goto out; + if (fg && !*fg) { + q = kvzalloc(sizeof(*q), GFP_KERNEL | __GFP_NOWARN); + if (!q) { + *fg = true; + goto fg_out; + } + INIT_WORK(&q->u.work, z_erofs_decompressqueue_work); + } else { +fg_out: + q = fgq; + init_waitqueue_head(&fgq->u.wait); + atomic_set(&fgq->pending_bios, 0); } - - iosb = kvzalloc(sizeof(*iosb), GFP_KERNEL | __GFP_NOFAIL); - DBG_BUGON(!iosb); - - /* initialize fields in the allocated descriptor */ - io = &iosb->io; - iosb->sb = sb; - INIT_WORK(&io->u.work, z_erofs_vle_unzip_wq); -out: - io->head = Z_EROFS_PCLUSTER_TAIL_CLOSED; - return io; + q->sb = sb; + q->head = Z_EROFS_PCLUSTER_TAIL_CLOSED; + return q; } /* define decompression jobqueue types */ @@ -1148,22 +1232,17 @@ enum { }; static void *jobqueueset_init(struct super_block *sb, - z_erofs_next_pcluster_t qtail[], - struct z_erofs_unzip_io *q[], - struct z_erofs_unzip_io *fgq, - bool forcefg) + struct z_erofs_decompressqueue *q[], + struct z_erofs_decompressqueue *fgq, bool *fg) { /* * if managed cache is enabled, bypass jobqueue is needed, * no need to read from device for all pclusters in this queue. */ - q[JQ_BYPASS] = jobqueue_init(sb, fgq + JQ_BYPASS, true); - qtail[JQ_BYPASS] = &q[JQ_BYPASS]->head; + q[JQ_BYPASS] = jobqueue_init(sb, fgq + JQ_BYPASS, NULL); + q[JQ_SUBMIT] = jobqueue_init(sb, fgq + JQ_SUBMIT, fg); - q[JQ_SUBMIT] = jobqueue_init(sb, fgq + JQ_SUBMIT, forcefg); - qtail[JQ_SUBMIT] = &q[JQ_SUBMIT]->head; - - return tagptr_cast_ptr(tagptr_fold(tagptr1_t, q[JQ_SUBMIT], !forcefg)); + return tagptr_cast_ptr(tagptr_fold(tagptr1_t, q[JQ_SUBMIT], *fg)); } static void move_to_bypass_jobqueue(struct z_erofs_pcluster *pcl, @@ -1185,55 +1264,34 @@ static void move_to_bypass_jobqueue(struct z_erofs_pcluster *pcl, qtail[JQ_BYPASS] = &pcl->next; } -static bool postsubmit_is_all_bypassed(struct z_erofs_unzip_io *q[], - unsigned int nr_bios, - bool force_fg) +static void z_erofs_submit_queue(struct super_block *sb, + struct z_erofs_decompress_frontend *f, + struct list_head *pagepool, + struct z_erofs_decompressqueue *fgq, + bool *force_fg) { - /* - * although background is preferred, no one is pending for submission. - * don't issue workqueue for decompression but drop it directly instead. - */ - if (force_fg || nr_bios) - return false; - - kvfree(container_of(q[JQ_SUBMIT], struct z_erofs_unzip_io_sb, io)); - return true; -} - -static bool z_erofs_vle_submit_all(struct super_block *sb, - z_erofs_next_pcluster_t owned_head, - struct list_head *pagepool, - struct z_erofs_unzip_io *fgq, - bool force_fg) -{ - struct erofs_sb_info *const sbi __maybe_unused = EROFS_SB(sb); + struct erofs_sb_info *const sbi = EROFS_SB(sb); z_erofs_next_pcluster_t qtail[NR_JOBQUEUES]; - struct z_erofs_unzip_io *q[NR_JOBQUEUES]; - struct bio *bio; + struct z_erofs_decompressqueue *q[NR_JOBQUEUES]; void *bi_private; + z_erofs_next_pcluster_t owned_head = f->clt.owned_head; /* since bio will be NULL, no need to initialize last_index */ - pgoff_t uninitialized_var(last_index); - bool force_submit = false; - unsigned int nr_bios; + pgoff_t last_index; + unsigned int nr_bios = 0; + struct bio *bio = NULL; - if (owned_head == Z_EROFS_PCLUSTER_TAIL) - return false; - - force_submit = false; - bio = NULL; - nr_bios = 0; - bi_private = jobqueueset_init(sb, qtail, q, fgq, force_fg); + bi_private = jobqueueset_init(sb, q, fgq, force_fg); + qtail[JQ_BYPASS] = &q[JQ_BYPASS]->head; + qtail[JQ_SUBMIT] = &q[JQ_SUBMIT]->head; /* by default, all need io submission */ q[JQ_SUBMIT]->head = owned_head; do { struct z_erofs_pcluster *pcl; - unsigned int clusterpages; - pgoff_t first_index; - struct page *page; - unsigned int i = 0, bypass = 0; - int err; + pgoff_t cur, end; + unsigned int i = 0; + bool bypass = true; /* no possible 'owned_head' equals the following */ DBG_BUGON(owned_head == Z_EROFS_PCLUSTER_TAIL_CLOSED); @@ -1241,55 +1299,50 @@ static bool z_erofs_vle_submit_all(struct super_block *sb, pcl = container_of(owned_head, struct z_erofs_pcluster, next); - clusterpages = BIT(pcl->clusterbits); + cur = pcl->obj.index; + end = cur + pcl->pclusterpages; /* close the main owned chain at first */ owned_head = cmpxchg(&pcl->next, Z_EROFS_PCLUSTER_TAIL, Z_EROFS_PCLUSTER_TAIL_CLOSED); - first_index = pcl->obj.index; - force_submit |= (first_index != last_index + 1); + do { + struct page *page; -repeat: - page = pickup_page_for_submission(pcl, i, pagepool, - MNGD_MAPPING(sbi), - GFP_NOFS); - if (!page) { - force_submit = true; - ++bypass; - goto skippage; - } + page = pickup_page_for_submission(pcl, i++, pagepool, + MNGD_MAPPING(sbi), + GFP_NOFS); + if (!page) + continue; - if (bio && force_submit) { + if (bio && cur != last_index + 1) { submit_bio_retry: - submit_bio(bio); - bio = NULL; - } + submit_bio(bio); + bio = NULL; + } - if (!bio) { - bio = bio_alloc(GFP_NOIO, BIO_MAX_PAGES); + if (!bio) { + bio = bio_alloc(GFP_NOIO, BIO_MAX_PAGES); - bio->bi_end_io = z_erofs_vle_read_endio; - bio_set_dev(bio, sb->s_bdev); - bio->bi_iter.bi_sector = (sector_t)(first_index + i) << - LOG_SECTORS_PER_BLOCK; - bio->bi_private = bi_private; - bio->bi_opf = REQ_OP_READ; + bio->bi_end_io = z_erofs_decompressqueue_endio; + bio_set_dev(bio, sb->s_bdev); + bio->bi_iter.bi_sector = (sector_t)cur << + LOG_SECTORS_PER_BLOCK; + bio->bi_private = bi_private; + bio->bi_opf = REQ_OP_READ; + if (f->readahead) + bio->bi_opf |= REQ_RAHEAD; + ++nr_bios; + } - ++nr_bios; - } + if (bio_add_page(bio, page, PAGE_SIZE, 0) < PAGE_SIZE) + goto submit_bio_retry; - err = bio_add_page(bio, page, PAGE_SIZE, 0); - if (err < PAGE_SIZE) - goto submit_bio_retry; + last_index = cur; + bypass = false; + } while (++cur < end); - force_submit = false; - last_index = first_index + i; -skippage: - if (++i < clusterpages) - goto repeat; - - if (bypass < clusterpages) + if (!bypass) qtail[JQ_SUBMIT] = &pcl->next; else move_to_bypass_jobqueue(pcl, qtail, owned_head); @@ -1298,40 +1351,42 @@ skippage: if (bio) submit_bio(bio); - if (postsubmit_is_all_bypassed(q, nr_bios, force_fg)) - return true; - - z_erofs_vle_unzip_kickoff(bi_private, nr_bios); - return true; + /* + * although background is preferred, no one is pending for submission. + * don't issue workqueue for decompression but drop it directly instead. + */ + if (!*force_fg && !nr_bios) { + kvfree(q[JQ_SUBMIT]); + return; + } + z_erofs_decompress_kickoff(q[JQ_SUBMIT], *force_fg, nr_bios); } -static void z_erofs_submit_and_unzip(struct super_block *sb, - struct z_erofs_collector *clt, - struct list_head *pagepool, - bool force_fg) +static void z_erofs_runqueue(struct super_block *sb, + struct z_erofs_decompress_frontend *f, + struct list_head *pagepool, bool force_fg) { - struct z_erofs_unzip_io io[NR_JOBQUEUES]; + struct z_erofs_decompressqueue io[NR_JOBQUEUES]; - if (!z_erofs_vle_submit_all(sb, clt->owned_head, - pagepool, io, force_fg)) + if (f->clt.owned_head == Z_EROFS_PCLUSTER_TAIL) return; + z_erofs_submit_queue(sb, f, pagepool, io, &force_fg); - /* decompress no I/O pclusters immediately */ - z_erofs_vle_unzip_all(sb, &io[JQ_BYPASS], pagepool); + /* handle bypass queue (no i/o pclusters) immediately */ + z_erofs_decompress_queue(&io[JQ_BYPASS], pagepool); if (!force_fg) return; /* wait until all bios are completed */ - wait_event(io[JQ_SUBMIT].u.wait, - !atomic_read(&io[JQ_SUBMIT].pending_bios)); + io_wait_event(io[JQ_SUBMIT].u.wait, + !atomic_read(&io[JQ_SUBMIT].pending_bios)); - /* let's synchronous decompression */ - z_erofs_vle_unzip_all(sb, &io[JQ_SUBMIT], pagepool); + /* handle synchronous decompress queue in the caller context */ + z_erofs_decompress_queue(&io[JQ_SUBMIT], pagepool); } -static int z_erofs_vle_normalaccess_readpage(struct file *file, - struct page *page) +static int z_erofs_readpage(struct file *file, struct page *page) { struct inode *const inode = page->mapping->host; struct z_erofs_decompress_frontend f = DECOMPRESS_FRONTEND_INIT(inode); @@ -1346,7 +1401,7 @@ static int z_erofs_vle_normalaccess_readpage(struct file *file, (void)z_erofs_collector_end(&f.clt); /* if some compressed cluster ready, need submit them anyway */ - z_erofs_submit_and_unzip(inode->i_sb, &f.clt, &pagepool, true); + z_erofs_runqueue(inode->i_sb, &f, &pagepool, true); if (err) erofs_err(inode->i_sb, "failed to read, err [%d]", err); @@ -1362,7 +1417,7 @@ static int z_erofs_vle_normalaccess_readpage(struct file *file, static bool should_decompress_synchronously(struct erofs_sb_info *sbi, unsigned int nr) { - return nr <= sbi->max_sync_decompress_pages; + return nr <= 3; } static int z_erofs_vle_normalaccess_readpages(struct file *filp, @@ -1423,7 +1478,7 @@ static int z_erofs_vle_normalaccess_readpages(struct file *filp, (void)z_erofs_collector_end(&f.clt); - z_erofs_submit_and_unzip(inode->i_sb, &f.clt, &pagepool, sync); + z_erofs_runqueue(inode->i_sb, &f, &pagepool, sync); if (f.map.mpage) put_page(f.map.mpage); @@ -1433,8 +1488,9 @@ static int z_erofs_vle_normalaccess_readpages(struct file *filp, return 0; } -const struct address_space_operations z_erofs_vle_normalaccess_aops = { - .readpage = z_erofs_vle_normalaccess_readpage, + +const struct address_space_operations z_erofs_aops = { + .readpage = z_erofs_readpage, .readpages = z_erofs_vle_normalaccess_readpages, }; diff --git a/fs/erofs/zdata.h b/fs/erofs/zdata.h index 568d5a493876..942ee69dff6a 100644 --- a/fs/erofs/zdata.h +++ b/fs/erofs/zdata.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (C) 2018 HUAWEI, Inc. - * http://www.huawei.com/ + * https://www.huawei.com/ * Created by Gao Xiang */ #ifndef __EROFS_FS_ZDATA_H @@ -10,6 +10,7 @@ #include "internal.h" #include "zpvec.h" +#define Z_EROFS_PCLUSTER_MAX_PAGES (Z_EROFS_PCLUSTER_MAX_SIZE / PAGE_SIZE) #define Z_EROFS_NR_INLINE_PAGEVECS 3 /* @@ -59,16 +60,17 @@ struct z_erofs_pcluster { /* A: point to next chained pcluster or TAILs */ z_erofs_next_pcluster_t next; - /* A: compressed pages (including multi-usage pages) */ - struct page *compressed_pages[Z_EROFS_CLUSTER_MAX_PAGES]; - /* A: lower limit of decompressed length and if full length or not */ unsigned int length; + /* I: physical cluster size in pages */ + unsigned short pclusterpages; + /* I: compression algorithm format */ unsigned char algorithmformat; - /* I: bit shift of physical cluster size */ - unsigned char clusterbits; + + /* A: compressed pages (can be cached or inplaced pages) */ + struct page *compressed_pages[]; }; #define z_erofs_primarycollection(pcluster) (&(pcluster)->primary_collection) @@ -82,9 +84,8 @@ struct z_erofs_pcluster { #define Z_EROFS_PCLUSTER_NIL (NULL) -#define Z_EROFS_WORKGROUP_SIZE sizeof(struct z_erofs_pcluster) - -struct z_erofs_unzip_io { +struct z_erofs_decompressqueue { + struct super_block *sb; atomic_t pending_bios; z_erofs_next_pcluster_t head; @@ -94,11 +95,6 @@ struct z_erofs_unzip_io { } u; }; -struct z_erofs_unzip_io_sb { - struct z_erofs_unzip_io io; - struct super_block *sb; -}; - #define MNGD_MAPPING(sbi) ((sbi)->managed_cache->i_mapping) static inline bool erofs_page_is_managed(const struct erofs_sb_info *sbi, struct page *page) @@ -177,6 +173,7 @@ static inline void z_erofs_onlinepage_endio(struct page *page) v = atomic_dec_return(u.o); if (!(v & Z_EROFS_ONLINEPAGE_COUNT_MASK)) { + set_page_private(page, 0); ClearPagePrivate(page); if (!PageError(page)) SetPageUptodate(page); diff --git a/fs/erofs/zmap.c b/fs/erofs/zmap.c index 6553f58fb289..adc4b4bcf51e 100644 --- a/fs/erofs/zmap.c +++ b/fs/erofs/zmap.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2018-2019 HUAWEI, Inc. - * http://www.huawei.com/ + * https://www.huawei.com/ * Created by Gao Xiang */ #include "internal.h" @@ -11,22 +11,21 @@ int z_erofs_fill_inode(struct inode *inode) { struct erofs_inode *const vi = EROFS_I(inode); + struct erofs_sb_info *sbi = EROFS_SB(inode->i_sb); - if (vi->datalayout == EROFS_INODE_FLAT_COMPRESSION_LEGACY) { + if (!erofs_sb_has_big_pcluster(sbi) && + vi->datalayout == EROFS_INODE_FLAT_COMPRESSION_LEGACY) { vi->z_advise = 0; vi->z_algorithmtype[0] = 0; vi->z_algorithmtype[1] = 0; vi->z_logical_clusterbits = LOG_BLOCK_SIZE; - vi->z_physical_clusterbits[0] = vi->z_logical_clusterbits; - vi->z_physical_clusterbits[1] = vi->z_logical_clusterbits; set_bit(EROFS_I_Z_INITED_BIT, &vi->flags); } - - inode->i_mapping->a_ops = &z_erofs_vle_normalaccess_aops; + inode->i_mapping->a_ops = &z_erofs_aops; return 0; } -static int fill_inode_lazy(struct inode *inode) +static int z_erofs_fill_inode_lazy(struct inode *inode) { struct erofs_inode *const vi = EROFS_I(inode); struct super_block *const sb = inode->i_sb; @@ -52,7 +51,8 @@ static int fill_inode_lazy(struct inode *inode) if (test_bit(EROFS_I_Z_INITED_BIT, &vi->flags)) goto out_unlock; - DBG_BUGON(vi->datalayout == EROFS_INODE_FLAT_COMPRESSION_LEGACY); + DBG_BUGON(!erofs_sb_has_big_pcluster(EROFS_SB(sb)) && + vi->datalayout == EROFS_INODE_FLAT_COMPRESSION_LEGACY); pos = ALIGN(iloc(EROFS_SB(sb), vi->nid) + vi->inode_isize + vi->xattr_isize, 8); @@ -77,18 +77,22 @@ static int fill_inode_lazy(struct inode *inode) } vi->z_logical_clusterbits = LOG_BLOCK_SIZE + (h->h_clusterbits & 7); - vi->z_physical_clusterbits[0] = vi->z_logical_clusterbits + - ((h->h_clusterbits >> 3) & 3); - - if (vi->z_physical_clusterbits[0] != LOG_BLOCK_SIZE) { - erofs_err(sb, "unsupported physical clusterbits %u for nid %llu, please upgrade kernel", - vi->z_physical_clusterbits[0], vi->nid); - err = -EOPNOTSUPP; + if (!erofs_sb_has_big_pcluster(EROFS_SB(sb)) && + vi->z_advise & (Z_EROFS_ADVISE_BIG_PCLUSTER_1 | + Z_EROFS_ADVISE_BIG_PCLUSTER_2)) { + erofs_err(sb, "per-inode big pcluster without sb feature for nid %llu", + vi->nid); + err = -EFSCORRUPTED; + goto unmap_done; + } + if (vi->datalayout == EROFS_INODE_FLAT_COMPRESSION && + !(vi->z_advise & Z_EROFS_ADVISE_BIG_PCLUSTER_1) ^ + !(vi->z_advise & Z_EROFS_ADVISE_BIG_PCLUSTER_2)) { + erofs_err(sb, "big pcluster head1/2 of compact indexes should be consistent for nid %llu", + vi->nid); + err = -EFSCORRUPTED; goto unmap_done; } - - vi->z_physical_clusterbits[1] = vi->z_logical_clusterbits + - ((h->h_clusterbits >> 5) & 7); /* paired with smp_mb() at the beginning of the function */ smp_mb(); set_bit(EROFS_I_Z_INITED_BIT, &vi->flags); @@ -111,7 +115,7 @@ struct z_erofs_maprecorder { u8 type; u16 clusterofs; u16 delta[2]; - erofs_blk_t pblk; + erofs_blk_t pblk, compressedlcs; }; static int z_erofs_reload_indexes(struct z_erofs_maprecorder *m, @@ -146,8 +150,8 @@ static int z_erofs_reload_indexes(struct z_erofs_maprecorder *m, return 0; } -static int vle_legacy_load_cluster_from_disk(struct z_erofs_maprecorder *m, - unsigned long lcn) +static int legacy_load_cluster_from_disk(struct z_erofs_maprecorder *m, + unsigned long lcn) { struct inode *const inode = m->inode; struct erofs_inode *const vi = EROFS_I(inode); @@ -174,6 +178,15 @@ static int vle_legacy_load_cluster_from_disk(struct z_erofs_maprecorder *m, case Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD: m->clusterofs = 1 << vi->z_logical_clusterbits; m->delta[0] = le16_to_cpu(di->di_u.delta[0]); + if (m->delta[0] & Z_EROFS_VLE_DI_D0_CBLKCNT) { + if (!(vi->z_advise & Z_EROFS_ADVISE_BIG_PCLUSTER_1)) { + DBG_BUGON(1); + return -EFSCORRUPTED; + } + m->compressedlcs = m->delta[0] & + ~Z_EROFS_VLE_DI_D0_CBLKCNT; + m->delta[0] = 1; + } m->delta[1] = le16_to_cpu(di->di_u.delta[1]); break; case Z_EROFS_VLE_CLUSTER_TYPE_PLAIN: @@ -214,6 +227,7 @@ static int unpack_compacted_index(struct z_erofs_maprecorder *m, unsigned int vcnt, base, lo, encodebits, nblk; int i; u8 *in, type; + bool big_pcluster; if (1 << amortizedshift == 4 && lclusterbits <= 14) vcnt = 2; @@ -222,6 +236,7 @@ static int unpack_compacted_index(struct z_erofs_maprecorder *m, else return -EOPNOTSUPP; + big_pcluster = vi->z_advise & Z_EROFS_ADVISE_BIG_PCLUSTER_1; encodebits = ((vcnt << amortizedshift) - sizeof(__le32)) * 8 / vcnt; base = round_down(eofs, vcnt << amortizedshift); in = m->kaddr + base; @@ -233,7 +248,15 @@ static int unpack_compacted_index(struct z_erofs_maprecorder *m, m->type = type; if (type == Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD) { m->clusterofs = 1 << lclusterbits; - if (i + 1 != vcnt) { + if (lo & Z_EROFS_VLE_DI_D0_CBLKCNT) { + if (!big_pcluster) { + DBG_BUGON(1); + return -EFSCORRUPTED; + } + m->compressedlcs = lo & ~Z_EROFS_VLE_DI_D0_CBLKCNT; + m->delta[0] = 1; + return 0; + } else if (i + 1 != (int)vcnt) { m->delta[0] = lo; return 0; } @@ -246,22 +269,48 @@ static int unpack_compacted_index(struct z_erofs_maprecorder *m, in, encodebits * (i - 1), &type); if (type != Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD) lo = 0; + else if (lo & Z_EROFS_VLE_DI_D0_CBLKCNT) + lo = 1; m->delta[0] = lo + 1; return 0; } m->clusterofs = lo; m->delta[0] = 0; /* figout out blkaddr (pblk) for HEAD lclusters */ - nblk = 1; - while (i > 0) { - --i; - lo = decode_compactedbits(lclusterbits, lomask, - in, encodebits * i, &type); - if (type == Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD) - i -= lo; + if (!big_pcluster) { + nblk = 1; + while (i > 0) { + --i; + lo = decode_compactedbits(lclusterbits, lomask, + in, encodebits * i, &type); + if (type == Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD) + i -= lo; - if (i >= 0) + if (i >= 0) + ++nblk; + } + } else { + nblk = 0; + while (i > 0) { + --i; + lo = decode_compactedbits(lclusterbits, lomask, + in, encodebits * i, &type); + if (type == Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD) { + if (lo & Z_EROFS_VLE_DI_D0_CBLKCNT) { + --i; + nblk += lo & ~Z_EROFS_VLE_DI_D0_CBLKCNT; + continue; + } + /* bigpcluster shouldn't have plain d0 == 1 */ + if (lo <= 1) { + DBG_BUGON(1); + return -EFSCORRUPTED; + } + i -= lo - 2; + continue; + } ++nblk; + } } in += (vcnt << amortizedshift) - sizeof(__le32); m->pblk = le32_to_cpu(*(__le32 *)in) + nblk; @@ -319,13 +368,13 @@ out: return unpack_compacted_index(m, amortizedshift, erofs_blkoff(pos)); } -static int vle_load_cluster_from_disk(struct z_erofs_maprecorder *m, - unsigned int lcn) +static int z_erofs_load_cluster_from_disk(struct z_erofs_maprecorder *m, + unsigned int lcn) { const unsigned int datamode = EROFS_I(m->inode)->datalayout; if (datamode == EROFS_INODE_FLAT_COMPRESSION_LEGACY) - return vle_legacy_load_cluster_from_disk(m, lcn); + return legacy_load_cluster_from_disk(m, lcn); if (datamode == EROFS_INODE_FLAT_COMPRESSION) return compacted_load_cluster_from_disk(m, lcn); @@ -333,8 +382,8 @@ static int vle_load_cluster_from_disk(struct z_erofs_maprecorder *m, return -EINVAL; } -static int vle_extent_lookback(struct z_erofs_maprecorder *m, - unsigned int lookback_distance) +static int z_erofs_extent_lookback(struct z_erofs_maprecorder *m, + unsigned int lookback_distance) { struct erofs_inode *const vi = EROFS_I(m->inode); struct erofs_map_blocks *const map = m->map; @@ -351,7 +400,7 @@ static int vle_extent_lookback(struct z_erofs_maprecorder *m, /* load extent head logical cluster if needed */ lcn -= lookback_distance; - err = vle_load_cluster_from_disk(m, lcn); + err = z_erofs_load_cluster_from_disk(m, lcn); if (err) return err; @@ -364,10 +413,10 @@ static int vle_extent_lookback(struct z_erofs_maprecorder *m, DBG_BUGON(1); return -EFSCORRUPTED; } - return vle_extent_lookback(m, m->delta[0]); + return z_erofs_extent_lookback(m, m->delta[0]); case Z_EROFS_VLE_CLUSTER_TYPE_PLAIN: map->m_flags &= ~EROFS_MAP_ZIPPED; - /* fallthrough */ + fallthrough; case Z_EROFS_VLE_CLUSTER_TYPE_HEAD: map->m_la = (lcn << lclusterbits) | m->clusterofs; break; @@ -381,6 +430,75 @@ static int vle_extent_lookback(struct z_erofs_maprecorder *m, return 0; } +static int z_erofs_get_extent_compressedlen(struct z_erofs_maprecorder *m, + unsigned int initial_lcn) +{ + struct erofs_inode *const vi = EROFS_I(m->inode); + struct erofs_map_blocks *const map = m->map; + const unsigned int lclusterbits = vi->z_logical_clusterbits; + unsigned long lcn; + int err; + + DBG_BUGON(m->type != Z_EROFS_VLE_CLUSTER_TYPE_PLAIN && + m->type != Z_EROFS_VLE_CLUSTER_TYPE_HEAD); + if (!(map->m_flags & EROFS_MAP_ZIPPED) || + !(vi->z_advise & Z_EROFS_ADVISE_BIG_PCLUSTER_1)) { + map->m_plen = 1 << lclusterbits; + return 0; + } + + lcn = m->lcn + 1; + if (m->compressedlcs) + goto out; + + err = z_erofs_load_cluster_from_disk(m, lcn); + if (err) + return err; + + /* + * If the 1st NONHEAD lcluster has already been handled initially w/o + * valid compressedlcs, which means at least it mustn't be CBLKCNT, or + * an internal implemenatation error is detected. + * + * The following code can also handle it properly anyway, but let's + * BUG_ON in the debugging mode only for developers to notice that. + */ + DBG_BUGON(lcn == initial_lcn && + m->type == Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD); + + switch (m->type) { + case Z_EROFS_VLE_CLUSTER_TYPE_PLAIN: + case Z_EROFS_VLE_CLUSTER_TYPE_HEAD: + /* + * if the 1st NONHEAD lcluster is actually PLAIN or HEAD type + * rather than CBLKCNT, it's a 1 lcluster-sized pcluster. + */ + m->compressedlcs = 1; + break; + case Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD: + if (m->delta[0] != 1) + goto err_bonus_cblkcnt; + if (m->compressedlcs) + break; + fallthrough; + default: + erofs_err(m->inode->i_sb, + "cannot found CBLKCNT @ lcn %lu of nid %llu", + lcn, vi->nid); + DBG_BUGON(1); + return -EFSCORRUPTED; + } +out: + map->m_plen = m->compressedlcs << lclusterbits; + return 0; +err_bonus_cblkcnt: + erofs_err(m->inode->i_sb, + "bogus CBLKCNT @ lcn %lu of nid %llu", + lcn, vi->nid); + DBG_BUGON(1); + return -EFSCORRUPTED; +} + int z_erofs_map_blocks_iter(struct inode *inode, struct erofs_map_blocks *map, int flags) @@ -392,6 +510,7 @@ int z_erofs_map_blocks_iter(struct inode *inode, }; int err = 0; unsigned int lclusterbits, endoff; + unsigned long initial_lcn; unsigned long long ofs, end; trace_z_erofs_map_blocks_iter_enter(inode, map, flags); @@ -404,16 +523,16 @@ int z_erofs_map_blocks_iter(struct inode *inode, goto out; } - err = fill_inode_lazy(inode); + err = z_erofs_fill_inode_lazy(inode); if (err) goto out; lclusterbits = vi->z_logical_clusterbits; ofs = map->m_la; - m.lcn = ofs >> lclusterbits; + initial_lcn = ofs >> lclusterbits; endoff = ofs & ((1 << lclusterbits) - 1); - err = vle_load_cluster_from_disk(&m, m.lcn); + err = z_erofs_load_cluster_from_disk(&m, initial_lcn); if (err) goto unmap_out; @@ -424,7 +543,7 @@ int z_erofs_map_blocks_iter(struct inode *inode, case Z_EROFS_VLE_CLUSTER_TYPE_PLAIN: if (endoff >= m.clusterofs) map->m_flags &= ~EROFS_MAP_ZIPPED; - /* fallthrough */ + fallthrough; case Z_EROFS_VLE_CLUSTER_TYPE_HEAD: if (endoff >= m.clusterofs) { map->m_la = (m.lcn << lclusterbits) | m.clusterofs; @@ -441,10 +560,10 @@ int z_erofs_map_blocks_iter(struct inode *inode, end = (m.lcn << lclusterbits) | m.clusterofs; map->m_flags |= EROFS_MAP_FULL_MAPPED; m.delta[0] = 1; - /* fallthrough */ + fallthrough; case Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD: - /* get the correspoinding first chunk */ - err = vle_extent_lookback(&m, m.delta[0]); + /* get the corresponding first chunk */ + err = z_erofs_extent_lookback(&m, m.delta[0]); if (err) goto unmap_out; break; @@ -457,10 +576,12 @@ int z_erofs_map_blocks_iter(struct inode *inode, } map->m_llen = end - map->m_la; - map->m_plen = 1 << lclusterbits; map->m_pa = blknr_to_addr(m.pblk); map->m_flags |= EROFS_MAP_MAPPED; + err = z_erofs_get_extent_compressedlen(&m, initial_lcn); + if (err) + goto out; unmap_out: if (m.kaddr) kunmap_atomic(m.kaddr); diff --git a/fs/erofs/zpvec.h b/fs/erofs/zpvec.h index 6a20b2c3a24c..52898176ef31 100644 --- a/fs/erofs/zpvec.h +++ b/fs/erofs/zpvec.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (C) 2018 HUAWEI, Inc. - * http://www.huawei.com/ + * https://www.huawei.com/ * Created by Gao Xiang */ #ifndef __EROFS_FS_ZPVEC_H From be4fac7c66ab5e538012c866278b9f7da77afbda Mon Sep 17 00:00:00 2001 From: Guoqing Jiang Date: Thu, 8 Sep 2022 19:53:16 +0800 Subject: [PATCH 514/698] include/linux/pagemap.h: introduce attach/detach_page_private MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Patch series "Introduce attach/detach_page_private to cleanup code". This patch (of 10): The logic in attach_page_buffers and __clear_page_buffers are quite paired, but 1. they are located in different files. 2. attach_page_buffers is implemented in buffer_head.h, so it could be used by other files. But __clear_page_buffers is static function in buffer.c and other potential users can't call the function, md-bitmap even copied the function. So, introduce the new attach/detach_page_private to replace them. With the new pair of function, we will remove the usage of attach_page_buffers and __clear_page_buffers in next patches. Thanks for suggestions about the function name from Alexander Viro, Andreas Grünbacher, Christoph Hellwig and Matthew Wilcox. Suggested-by: Matthew Wilcox Signed-off-by: Guoqing Jiang Signed-off-by: Andrew Morton Reviewed-by: Andrew Morton Cc: "Darrick J. Wong" Cc: William Kucharski Cc: "Kirill A. Shutemov" Cc: Andreas Gruenbacher Cc: Yang Shi Cc: Yafang Shao Cc: Song Liu Cc: Chris Mason Cc: Josef Bac(CR) Cc: David Sterba Cc: Alexander Viro Cc: Jaegeuk Kim Cc: Chao Yu Cc: Christoph Hellwig Cc: Anton Altaparmakov Cc: M(CR)e Marshall Cc: Martin Brandenburg Cc: Thomas Gleixner Cc: Sebastian Andrzej Siewior Cc: Roman Gushchin Cc: Andreas Dilger Cc: Chao Yu Cc: Dave Chinner Link: http://lkml.kernel.org/r/20200517214718.468-1-guoqing.jiang@cloud.ionos.com Link: http://lkml.kernel.org/r/20200517214718.468-2-guoqing.jiang@cloud.ionos.com Signed-off-by: Linus Torvalds Moto-CRs-Fixed:(CR) Change-Id: Id4bbb98c9a658b834988f37843d09f065e246668 Signed-off-by: William Liu Reviewed-on: https://gerrit.mot.com/2380691 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- include/linux/pagemap.h | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h index eabb6b91a15e..5ccb6baf050f 100644 --- a/include/linux/pagemap.h +++ b/include/linux/pagemap.h @@ -207,6 +207,43 @@ static inline int page_cache_add_speculative(struct page *page, int count) return __page_cache_add_speculative(page, count); } +/** + * attach_page_private - Attach private data to a page. + * @page: Page to attach data to. + * @data: Data to attach to page. + * + * Attaching private data to a page increments the page's reference count. + * The data must be detached before the page will be freed. + */ +static inline void attach_page_private(struct page *page, void *data) +{ + get_page(page); + set_page_private(page, (unsigned long)data); + SetPagePrivate(page); +} + +/** + * detach_page_private - Detach private data from a page. + * @page: Page to detach data from. + * + * Removes the data that was previously attached to the page and decrements + * the refcount on the page. + * + * Return: Data that was attached to the page. + */ +static inline void *detach_page_private(struct page *page) +{ + void *data = (void *)page_private(page); + + if (!PagePrivate(page)) + return NULL; + ClearPagePrivate(page); + set_page_private(page, 0); + put_page(page); + + return data; +} + #ifdef CONFIG_NUMA extern struct page *__page_cache_alloc(gfp_t gfp); #else From 84a58d6dd0a683c13a1245e54279ddb833e15bf3 Mon Sep 17 00:00:00 2001 From: William Liu Date: Thu, 8 Sep 2022 19:57:13 +0800 Subject: [PATCH 515/698] include:statfs.h:reduce boilerplate in fsid handling Get rid of boilerplate in most of ->statfs() instances... Change-Id: I630d57a8016013d7d4a2854e2c2c43b1563c27ef Signed-off-by: William Liu Reviewed-on: https://gerrit.mot.com/2380706 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- include/linux/statfs.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/linux/statfs.h b/include/linux/statfs.h index 9bc69edb8f18..20f695b90aab 100644 --- a/include/linux/statfs.h +++ b/include/linux/statfs.h @@ -40,8 +40,14 @@ struct kstatfs { #define ST_NOATIME 0x0400 /* do not update access times */ #define ST_NODIRATIME 0x0800 /* do not update directory access times */ #define ST_RELATIME 0x1000 /* update atime relative to mtime/ctime */ +#define ST_NOSYMFOLLOW 0x2000 /* do not follow symlinks */ struct dentry; extern int vfs_get_fsid(struct dentry *dentry, __kernel_fsid_t *fsid); +static inline __kernel_fsid_t u64_to_fsid(u64 v) +{ + return (__kernel_fsid_t){.val = {(u32)v, (u32)(v>>32)}}; +} + #endif From 38414b7380db33ef4fd5b097806f6b3d8a173930 Mon Sep 17 00:00:00 2001 From: liujg6 Date: Wed, 14 Sep 2022 10:41:22 +0800 Subject: [PATCH 516/698] disable CONFIG_SLUB_DEBUG_ON on pnangn Performance on pnangn is worse due to CONFIG_SLUB_DEBUG_ON is enabled. Disable it to optimize performance on userdebug build. Change-Id: I3c46ffc87d95271a4ceef73914c7a13ee052e11e Reviewed-on: https://gerrit.mot.com/2383580 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Wang Wang Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/debug-holi-pnangn.config | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/configs/vendor/ext_config/debug-holi-pnangn.config b/arch/arm64/configs/vendor/ext_config/debug-holi-pnangn.config index 018b945c19d3..95c989c10a1b 100644 --- a/arch/arm64/configs/vendor/ext_config/debug-holi-pnangn.config +++ b/arch/arm64/configs/vendor/ext_config/debug-holi-pnangn.config @@ -24,3 +24,5 @@ # CONFIG_RCU_TORTURE_TEST is not set # CONFIG_TEST_USER_COPY is not set # CONFIG_UFSTW is not set + +# CONFIG_SLUB_DEBUG_ON is not set From 42d17b391076b62ee19eeb5d1f2fece6797756c6 Mon Sep 17 00:00:00 2001 From: HQ Cam LiJunyu Date: Fri, 16 Sep 2022 18:36:47 +0800 Subject: [PATCH 517/698] penang: Adjust actuator noise reduction details: Add drive node Modify the motor voltage value Change-Id: I2cd674e7df7a2e02829c6afe5889c61a9e835e29 Signed-off-by: HQ Cam LiJunyu Reviewed-on: https://gerrit.mot.com/2385577 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Pengfei Qiao Reviewed-by: Reviewed-by: Reviewed-by: Shuo Wang Reviewed-by: Wang Liu Reviewed-by: Long Cheng Reviewed-by: Zhichao Chen Reviewed-by: Guobin Zhang Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi-penang.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-penang.config b/arch/arm64/configs/vendor/ext_config/moto-holi-penang.config index b862bded89b8..a837d08e2e86 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-penang.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-penang.config @@ -25,4 +25,5 @@ CONFIG_CAM_SENSOR_PROBE_RETRY=y CONFIG_SND_SOC_AW87XXX=m CONFIG_NFC_QTI_I2C=m CONFIG_MSM_TZ_QSEE_LOG=y +CONFIG_AF_NOISE_ELIMINATION=y # CONFIG_TOUCHSCREEN_FTS is not set From f536ebe9fcccb97a4761b2a662802098d0c42a06 Mon Sep 17 00:00:00 2001 From: YangYi Date: Mon, 10 Oct 2022 16:39:27 +0800 Subject: [PATCH 518/698] Penang: fix for device suspend tests fail. [1/2] Penang: Fix for device suspend tests fail. qcom cr number: 3243388, 3208991. Change-Id: Idedf1825a3237cd85cf463ec459f6d5a31662c8d Signed-off-by: YangYi Reviewed-on: https://gerrit.mot.com/2400062 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Yuchang Guo Reviewed-by: Jiacheng Ou Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- net/qrtr/mhi.c | 2 +- net/qrtr/ns.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/net/qrtr/mhi.c b/net/qrtr/mhi.c index c9377d28d890..ae9c3e0f3fc3 100644 --- a/net/qrtr/mhi.c +++ b/net/qrtr/mhi.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only -/* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. */ +/* Copyright (c) 2018-2021, The Linux Foundation. All rights reserved. */ #include #include diff --git a/net/qrtr/ns.c b/net/qrtr/ns.c index 845f21c8e1d0..28516cdeffb4 100644 --- a/net/qrtr/ns.c +++ b/net/qrtr/ns.c @@ -104,7 +104,7 @@ unsigned int qrtr_get_service_id(unsigned int node_id, unsigned int port_id) struct qrtr_node *node; unsigned long index; - node = node_get(node_id); + node = xa_load(&nodes, node_id); if (!node) return 0; From 7ea59341763bb0c1a010a939f236bb1081d00f32 Mon Sep 17 00:00:00 2001 From: liujg6 Date: Fri, 21 Oct 2022 17:07:05 +0800 Subject: [PATCH 519/698] arm64/configs: disable NFC on pnangn [Details] Penang5G NA does not support NFC, disable NFC config which inheritted from Penang ROW. Change-Id: I785a3234df733f4ce5d548ebdc04bbc3675b09d8 Reviewed-on: https://gerrit.mot.com/2411025 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Wang Wang Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi-pnangn.config | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-pnangn.config b/arch/arm64/configs/vendor/ext_config/moto-holi-pnangn.config index 144ef69061ad..7ac0f38ab785 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-pnangn.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-pnangn.config @@ -31,4 +31,3 @@ CONFIG_CAM_SENSOR_PROBE_RETRY=y CONFIG_AW882XX_STEREO_SMARTPA=y CONFIG_AW882XX_PARAMS_FROM_BIN=y CONFIG_AW882XX_MAPSIZE_16K=y -CONFIG_NFC_QTI_I2C=m From a65aa65ad1c1520ebb405b1bd5ae8d5d3986f2d0 Mon Sep 17 00:00:00 2001 From: YangYi Date: Wed, 26 Oct 2022 11:27:31 +0800 Subject: [PATCH 520/698] Penang: resolve kasan panic Penang: KASAN: slab-out-of-bounds in qrtr_endpoint_register Change-Id: I7542a0f2af0ceb0fdd04291b86795ba942ffe8d7 Signed-off-by: YangYi Reviewed-on: https://gerrit.mot.com/2413704 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Yuchang Guo Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- net/qrtr/qrtr.c | 20 +++++++++++++++----- net/qrtr/qrtr.h | 14 +++++++++++++- net/qrtr/smd.c | 16 ++++++++++------ 3 files changed, 38 insertions(+), 12 deletions(-) diff --git a/net/qrtr/qrtr.c b/net/qrtr/qrtr.c index fd1591c3fbcf..30584254f785 100644 --- a/net/qrtr/qrtr.c +++ b/net/qrtr/qrtr.c @@ -193,6 +193,7 @@ struct qrtr_node { void *ilc; u32 nonwake_svc[MAX_NON_WAKE_SVC_LEN]; + struct qrtr_array no_wake_svc; }; struct qrtr_tx_flow_waiter { @@ -421,6 +422,7 @@ static void __qrtr_node_release(struct kref *kref) kthread_stop(node->task); skb_queue_purge(&node->rx_queue); + kfree(node->no_wake_svc.arr); kfree(node); } @@ -944,8 +946,12 @@ int qrtr_endpoint_post(struct qrtr_endpoint *ep, const void *data, size_t len) if (svc_id > 0) { for (i = 0; i < MAX_NON_WAKE_SVC_LEN; i++) { if (svc_id == node->nonwake_svc[i]) { - wake = false; - break; + for (i = 0; i < node->no_wake_svc.size; i++) { + if (svc_id == node->no_wake_svc.arr[i]) { + wake = false; + break; + } + } } } } @@ -964,7 +970,6 @@ int qrtr_endpoint_post(struct qrtr_endpoint *ep, const void *data, size_t len) qrtr_port_put(ipc); } - return 0; err: @@ -1170,7 +1175,7 @@ static void qrtr_hello_work(struct kthread_work *work) * The specified endpoint must have the xmit function pointer set on call. */ int qrtr_endpoint_register(struct qrtr_endpoint *ep, unsigned int net_id, - bool rt, u32 *svc_arr) + bool rt, struct qrtr_array *svc_arr) { struct qrtr_node *node; struct sched_param param = {.sched_priority = 1}; @@ -1203,7 +1208,12 @@ int qrtr_endpoint_register(struct qrtr_endpoint *ep, unsigned int net_id, if (svc_arr) memcpy(node->nonwake_svc, svc_arr, MAX_NON_WAKE_SVC_LEN * sizeof(int)); - + if(svc_arr && svc_arr->size) { + node->no_wake_svc.arr = kmalloc_array(svc_arr->size, sizeof(u32), GFP_KERNEL); + memcpy((void *)node->no_wake_svc.arr, (void *)svc_arr->arr, + svc_arr->size * sizeof(u32)); + node->no_wake_svc.size = svc_arr->size; + } mutex_init(&node->qrtr_tx_lock); INIT_RADIX_TREE(&node->qrtr_tx_flow, GFP_KERNEL); init_waitqueue_head(&node->resume_tx); diff --git a/net/qrtr/qrtr.h b/net/qrtr/qrtr.h index 449028c2ec93..f58117d6fb03 100644 --- a/net/qrtr/qrtr.h +++ b/net/qrtr/qrtr.h @@ -28,8 +28,20 @@ struct qrtr_endpoint { struct qrtr_node *node; }; +/** + * struct qrtr_array - array with size + * @arr: elements in the array + * @size: number of elements + * + * An array with its size provided. + */ +struct qrtr_array { + u32 *arr; + size_t size; +}; + int qrtr_endpoint_register(struct qrtr_endpoint *ep, unsigned int net_id, - bool rt, u32 *svc_arr); + bool rt, struct qrtr_array *svc_arr); void qrtr_endpoint_unregister(struct qrtr_endpoint *ep); diff --git a/net/qrtr/smd.c b/net/qrtr/smd.c index 705e6523e1b2..1939bc1c98bb 100644 --- a/net/qrtr/smd.c +++ b/net/qrtr/smd.c @@ -64,8 +64,9 @@ static int qcom_smd_qrtr_probe(struct rpmsg_device *rpdev) struct qrtr_smd_dev *qdev; u32 net_id; bool rt; - int rc, size; - u32 *svc_arr = NULL; + int rc; + size_t size; + struct qrtr_array svc_arr = {NULL, 0}; pr_info("%s:Entered\n", __func__); qdev = devm_kzalloc(&rpdev->dev, sizeof(*qdev), GFP_KERNEL); @@ -87,13 +88,16 @@ static int qcom_smd_qrtr_probe(struct rpmsg_device *rpdev) if (size > 0) { if (size > MAX_NON_WAKE_SVC_LEN) size = MAX_NON_WAKE_SVC_LEN; - svc_arr = kmalloc_array(size, sizeof(u32), GFP_KERNEL); + svc_arr.size = size; + svc_arr.arr = kmalloc_array(size, sizeof(u32), GFP_KERNEL); + if (!svc_arr.arr) + return -ENOMEM; of_property_read_u32_array(rpdev->dev.of_node, "qcom,non-wake-svc", - svc_arr, size); + svc_arr.arr, size); } - rc = qrtr_endpoint_register(&qdev->ep, net_id, rt, svc_arr); - kfree(svc_arr); + rc = qrtr_endpoint_register(&qdev->ep, net_id, rt, &svc_arr); + kfree(svc_arr.arr); if (rc) return rc; From 0ab43c2ab514f765cb0e023fa955fc3c9bca841e Mon Sep 17 00:00:00 2001 From: YangYi Date: Tue, 1 Nov 2022 11:12:14 +0800 Subject: [PATCH 521/698] Penang: kasan panic Penang: resolve kasan panic. Change-Id: I69112a4f4717c8f8c8bf958316ae9a0516dad945 Signed-off-by: YangYi Reviewed-on: https://gerrit.mot.com/2417581 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Yuchang Guo Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- net/qrtr/qrtr.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/net/qrtr/qrtr.c b/net/qrtr/qrtr.c index 30584254f785..81a87bc224eb 100644 --- a/net/qrtr/qrtr.c +++ b/net/qrtr/qrtr.c @@ -956,16 +956,14 @@ int qrtr_endpoint_post(struct qrtr_endpoint *ep, const void *data, size_t len) } } } - if (sock_queue_rcv_skb(&ipc->sk, skb)) goto err; - /** * Force wakeup for all packets except for sensors and blacklisted services * from adsp side */ if ((node->nid != 9 && node->nid != 5) || - (node->nid == 5 && wake)) + (node->nid == 5 && wake)) pm_wakeup_ws_event(node->ws, qrtr_wakeup_ms, true); qrtr_port_put(ipc); From 485bfce7488fd22eb8e777d51eb94a027b514e20 Mon Sep 17 00:00:00 2001 From: YangYi Date: Wed, 9 Nov 2022 16:45:47 +0800 Subject: [PATCH 522/698] penang: device suspend tests fail Penang: fix the problem of device suspend tests fail. Change-Id: I2477d57440b40dcf930fff27631554c2024ec444 Signed-off-by: YangYi Reviewed-on: https://gerrit.mot.com/2424757 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Yuchang Guo Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- net/qrtr/qrtr.c | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/net/qrtr/qrtr.c b/net/qrtr/qrtr.c index 81a87bc224eb..0b4873903143 100644 --- a/net/qrtr/qrtr.c +++ b/net/qrtr/qrtr.c @@ -192,7 +192,6 @@ struct qrtr_node { struct wakeup_source *ws; void *ilc; - u32 nonwake_svc[MAX_NON_WAKE_SVC_LEN]; struct qrtr_array no_wake_svc; }; @@ -943,15 +942,11 @@ int qrtr_endpoint_post(struct qrtr_endpoint *ep, const void *data, size_t len) if (node->nid == 5) { svc_id = qrtr_get_service_id(cb->src_node, cb->src_port); - if (svc_id > 0) { - for (i = 0; i < MAX_NON_WAKE_SVC_LEN; i++) { - if (svc_id == node->nonwake_svc[i]) { - for (i = 0; i < node->no_wake_svc.size; i++) { - if (svc_id == node->no_wake_svc.arr[i]) { - wake = false; - break; - } - } + if (svc_id > 0){ + for (i = 0; i < node->no_wake_svc.size; i++) { + if (svc_id == node->no_wake_svc.arr[i]) { + wake = false; + break; } } } @@ -1204,8 +1199,6 @@ int qrtr_endpoint_register(struct qrtr_endpoint *ep, unsigned int net_id, if (rt) sched_setscheduler(node->task, SCHED_FIFO, ¶m); - if (svc_arr) - memcpy(node->nonwake_svc, svc_arr, MAX_NON_WAKE_SVC_LEN * sizeof(int)); if(svc_arr && svc_arr->size) { node->no_wake_svc.arr = kmalloc_array(svc_arr->size, sizeof(u32), GFP_KERNEL); memcpy((void *)node->no_wake_svc.arr, (void *)svc_arr->arr, From e819d7d240a30c3fd32d9e4474207c879c285bea Mon Sep 17 00:00:00 2001 From: Yunxian He Date: Fri, 11 Nov 2022 14:59:44 +0800 Subject: [PATCH 523/698] update btfm enable ch delay when freq 48000 ch 0 main changes: btfm_slim.c Change-Id: I6c38d3956da85b13a8946cb5db7bad312320bba5 Signed-off-by: Yunxian He Reviewed-on: https://gerrit.mot.com/2427412 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- drivers/bluetooth/btfm_slim.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/bluetooth/btfm_slim.c b/drivers/bluetooth/btfm_slim.c index 46202a5ef1c0..086f20699c27 100644 --- a/drivers/bluetooth/btfm_slim.c +++ b/drivers/bluetooth/btfm_slim.c @@ -145,7 +145,7 @@ int btfm_slim_enable_ch(struct btfmslim *btfmslim, struct btfmslim_ch *ch, if (!btfmslim || !ch) return -EINVAL; - BTFMSLIM_DBG("port: %d ch: %d", ch->port, ch->ch); + BTFMSLIM_INFO("port: %d ch: %d rxport: %d", ch->port, ch->ch, rxport); /* Define the channel with below parameters */ prop.prot = ((rates == 44100) || (rates == 88200)) ? @@ -162,6 +162,7 @@ int btfm_slim_enable_ch(struct btfmslim *btfmslim, struct btfmslim_ch *ch, * 2. 44.1k, 88.2k rxports */ if (((rates == 8000 && btfm_feedback_ch_setting && rxport == 0) || + (rates == 48000 && rxport == 0) || (rxport == 1 && (rates == 44100 || rates == 88200))) && btfm_slim_is_sb_reset_needed(chipset_ver)) { From 9d8582cf76bb9fae3f343d095de29cc8981d1429 Mon Sep 17 00:00:00 2001 From: Yunxian He Date: Mon, 14 Nov 2022 09:49:22 +0800 Subject: [PATCH 524/698] no need btfm enable delay when freq 48000 rxport 0 main change: when freq 48000, rxport 0, btfm enable no need delay. revert change in (CR) Change-Id: I1dec2ada86501b6690b08718c038e465c14b2029 Signed-off-by: Yunxian He Reviewed-on: https://gerrit.mot.com/2428502 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Wang Wang Submit-Approved: Jira Key --- drivers/bluetooth/btfm_slim.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/bluetooth/btfm_slim.c b/drivers/bluetooth/btfm_slim.c index 086f20699c27..3ada61a65f9c 100644 --- a/drivers/bluetooth/btfm_slim.c +++ b/drivers/bluetooth/btfm_slim.c @@ -145,7 +145,7 @@ int btfm_slim_enable_ch(struct btfmslim *btfmslim, struct btfmslim_ch *ch, if (!btfmslim || !ch) return -EINVAL; - BTFMSLIM_INFO("port: %d ch: %d rxport: %d", ch->port, ch->ch, rxport); + BTFMSLIM_INFO("port: %d ch: %d", ch->port, ch->ch); /* Define the channel with below parameters */ prop.prot = ((rates == 44100) || (rates == 88200)) ? @@ -162,7 +162,6 @@ int btfm_slim_enable_ch(struct btfmslim *btfmslim, struct btfmslim_ch *ch, * 2. 44.1k, 88.2k rxports */ if (((rates == 8000 && btfm_feedback_ch_setting && rxport == 0) || - (rates == 48000 && rxport == 0) || (rxport == 1 && (rates == 44100 || rates == 88200))) && btfm_slim_is_sb_reset_needed(chipset_ver)) { From 4bcc5f37695e9d18bdb28f2b23f9740fa04c5a65 Mon Sep 17 00:00:00 2001 From: xiewen3 Date: Mon, 14 Nov 2022 14:16:54 +0800 Subject: [PATCH 525/698] arm64/configs: Enable CONFIG_FELICA_MOUNT_BLOCK for penang 5G. Enable CONFIG_FELICA_MOUNT_BLOCK to block mount in the root environment. Change-Id: Ia9c71f44ac00bced7a374bca70ffd0b4dbd4ee01 Signed-off-by: xiewen3 Reviewed-on: https://gerrit.mot.com/2428915 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Wang Wang Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi-penang.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-penang.config b/arch/arm64/configs/vendor/ext_config/moto-holi-penang.config index a837d08e2e86..7d93354b67d7 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-penang.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-penang.config @@ -27,3 +27,4 @@ CONFIG_NFC_QTI_I2C=m CONFIG_MSM_TZ_QSEE_LOG=y CONFIG_AF_NOISE_ELIMINATION=y # CONFIG_TOUCHSCREEN_FTS is not set +CONFIG_FELICA_MOUNT_BLOCK=y From 40b836f15d78ad4db8ceed824045748bdb19d45e Mon Sep 17 00:00:00 2001 From: tanhua1 Date: Thu, 24 Nov 2022 16:44:54 +0800 Subject: [PATCH 526/698] disable HPB in penang5g Disable the HPB in penang5G To follow the product family decision Change-Id: I1eac669c626f26f26c365626df97086e816343e7 Signed-off-by: tanhua1 Reviewed-on: https://gerrit.mot.com/2438990 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi-penang.config | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-penang.config b/arch/arm64/configs/vendor/ext_config/moto-holi-penang.config index 7d93354b67d7..c4315a1195cf 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-penang.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-penang.config @@ -28,3 +28,7 @@ CONFIG_MSM_TZ_QSEE_LOG=y CONFIG_AF_NOISE_ELIMINATION=y # CONFIG_TOUCHSCREEN_FTS is not set CONFIG_FELICA_MOUNT_BLOCK=y +# CONFIG_UFSFEATURE is not set +# CONFIG_UFSHPB is not set +# CONFIG_UFSTW is not set +# CONFIG_SCSI_SKHPB is not set From c318647637604cde844ea0b508dbb3b554878b6e Mon Sep 17 00:00:00 2001 From: panzh2 Date: Fri, 3 Feb 2023 16:28:53 +0800 Subject: [PATCH 527/698] [PnangNA][configs] disable HPB in pnang 5G NA Disable the HPB in penang5G NA follow the product family decision Change-Id: I07daa682ddd5675263763befe1965851f37cbee7 Signed-off-by: panzh2 Reviewed-on: https://gerrit.mot.com/2501716 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Jianguo Liu Reviewed-by: Wang Wang Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi-pnangn.config | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-pnangn.config b/arch/arm64/configs/vendor/ext_config/moto-holi-pnangn.config index 7ac0f38ab785..c13ef95eb93d 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-pnangn.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-pnangn.config @@ -31,3 +31,7 @@ CONFIG_CAM_SENSOR_PROBE_RETRY=y CONFIG_AW882XX_STEREO_SMARTPA=y CONFIG_AW882XX_PARAMS_FROM_BIN=y CONFIG_AW882XX_MAPSIZE_16K=y +# CONFIG_UFSFEATURE is not set +# CONFIG_UFSHPB is not set +# CONFIG_UFSTW is not set +# CONFIG_SCSI_SKHPB is not set From b6b62eb330e6d6cb12c1c4850baeb77e0668bf67 Mon Sep 17 00:00:00 2001 From: tongkun1 Date: Wed, 15 Feb 2023 11:05:51 +0800 Subject: [PATCH 528/698] configs: vendor/ext_config: init configuration for Bangkk to pass build Change-Id: Ic8f6e1e5b651da856ae2f294ebc57edc1e8171d2 Reviewed-on: https://gerrit.mot.com/2513550 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Submit-Approved: Jira Key Tested-by: Jira Key Reviewed-by: Hao Li (cherry picked from commit ce397efc28e4e9e45e15180dd8630a2c66166978) Reviewed-on: https://gerrit.mot.com/2532084 Reviewed-by: Xiangpo Zhao Submit-Approved: tongkun1 --- .../ext_config/debug-holi-bangkk.config | 28 +++++++++++++++ .../ext_config/factory-holi-bangkk.config | 16 +++++++++ .../vendor/ext_config/moto-holi-bangkk.config | 34 +++++++++++++++++++ drivers/soc/qcom/Kconfig | 8 +++++ 4 files changed, 86 insertions(+) create mode 100644 arch/arm64/configs/vendor/ext_config/debug-holi-bangkk.config create mode 100644 arch/arm64/configs/vendor/ext_config/factory-holi-bangkk.config create mode 100644 arch/arm64/configs/vendor/ext_config/moto-holi-bangkk.config diff --git a/arch/arm64/configs/vendor/ext_config/debug-holi-bangkk.config b/arch/arm64/configs/vendor/ext_config/debug-holi-bangkk.config new file mode 100644 index 000000000000..95c989c10a1b --- /dev/null +++ b/arch/arm64/configs/vendor/ext_config/debug-holi-bangkk.config @@ -0,0 +1,28 @@ +# +# Please avoid changing the Qualcomm defconfig files and use this file to +# add any Motorola-specific configuration changes that are applicable to +# userdebug, eng, and user builds. +# +# After building, a list of all of the config files that are used can be found +# at the top of: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/mapphone_defconfig +# +# The actual output of the kernel configuration system can be found at: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/.config +# +# You can check the .config file to verify that your configuration option is +# being set as expected. +# + +# CONFIG_CGROUP_DEBUG is not set +# CONFIG_CLEANCACHE is not set +# CONFIG_CMA_ALLOW_WRITE_DEBUGFS is not set +# CONFIG_CMA_DEBUG is not set +# CONFIG_PREEMPTIRQ_EVENTS is not set +# CONFIG_PREEMPT_TRACER is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_TEST_USER_COPY is not set +# CONFIG_UFSTW is not set + +# CONFIG_SLUB_DEBUG_ON is not set diff --git a/arch/arm64/configs/vendor/ext_config/factory-holi-bangkk.config b/arch/arm64/configs/vendor/ext_config/factory-holi-bangkk.config new file mode 100644 index 000000000000..cc7be9152bdd --- /dev/null +++ b/arch/arm64/configs/vendor/ext_config/factory-holi-bangkk.config @@ -0,0 +1,16 @@ +# +# Please avoid changing the Qualcomm defconfig files and use this file to +# add any Motorola-specific configuration changes that are applicable to +# userdebug, eng, and user builds. +# +# After building, a list of all of the config files that are used can be found +# at the top of: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/mapphone_defconfig +# +# The actual output of the kernel configuration system can be found at: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/.config +# +# You can check the .config file to verify that your configuration option is +# being set as expected. +# +CONFIG_CAMERA_DISABLE_VSYNC_IRQ=y diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-bangkk.config b/arch/arm64/configs/vendor/ext_config/moto-holi-bangkk.config new file mode 100644 index 000000000000..c4315a1195cf --- /dev/null +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-bangkk.config @@ -0,0 +1,34 @@ +# +# Please avoid changing the Qualcomm defconfig files and use this file to +# add any Motorola-specific configuration changes that are applicable to +# userdebug, eng, and user builds. +# +# After building, a list of all of the config files that are used can be found +# at the top of: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/mapphone_defconfig +# +# The actual output of the kernel configuration system can be found at: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/.config +# +# You can check the .config file to verify that your configuration option is +# being set as expected. +# +CONFIG_PENANG_DTB=y +# CONFIG_NFC_QTI_I2C is not set +CONFIG_FS_EPOLL_WAKEUP_DEBUG=y +CONFIG_ZRAM_WRITEBACK=y +# CONFIG_THERMAL_STATISTICS is not set +# CONFIG_REGULATOR_QPNP_LCDB is not set +# CONFIG_UFSTW is not set +CONFIG_CRYPTO_CHACHA20POLY1305=y +CONFIG_CAM_SENSOR_PROBE_RETRY=y +CONFIG_SND_SOC_AW87XXX=m +CONFIG_NFC_QTI_I2C=m +CONFIG_MSM_TZ_QSEE_LOG=y +CONFIG_AF_NOISE_ELIMINATION=y +# CONFIG_TOUCHSCREEN_FTS is not set +CONFIG_FELICA_MOUNT_BLOCK=y +# CONFIG_UFSFEATURE is not set +# CONFIG_UFSHPB is not set +# CONFIG_UFSTW is not set +# CONFIG_SCSI_SKHPB is not set diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index 3f45409a5ef3..6a28b609ffe0 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -110,6 +110,14 @@ config PNANGN_DTB Only include PNANGN specific DTBs to limit the number that get built during kernel compilation. +config BANGKK_DTB + depends on ARCH_QCOM + default n + bool "BANGKK DTBs" + help + Only include PENANG specific DTBs to limit the number that + get built during kernel compilation. + config RHODEP_DTB depends on ARCH_QCOM default n From 53ad4b3fb9fdf6ccb2f451b6e9374483f951946f Mon Sep 17 00:00:00 2001 From: Yunxian He Date: Tue, 14 Mar 2023 15:21:13 +0800 Subject: [PATCH 529/698] Enable samsung RN4V NFC driver integrate samsung RN4V NFC driver this driver support RN4V and SN4V Change-Id: I022f009eb7db4ad3e0bc96ca0fa9aad8b9f5003b Signed-off-by: Yunxian He Reviewed-on: https://gerrit.mot.com/2538504 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- .../arm64/configs/vendor/ext_config/moto-holi-bangkk.config | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-bangkk.config b/arch/arm64/configs/vendor/ext_config/moto-holi-bangkk.config index c4315a1195cf..5124e86dc97c 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-bangkk.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-bangkk.config @@ -23,7 +23,7 @@ CONFIG_ZRAM_WRITEBACK=y CONFIG_CRYPTO_CHACHA20POLY1305=y CONFIG_CAM_SENSOR_PROBE_RETRY=y CONFIG_SND_SOC_AW87XXX=m -CONFIG_NFC_QTI_I2C=m +#CONFIG_NFC_QTI_I2C=m CONFIG_MSM_TZ_QSEE_LOG=y CONFIG_AF_NOISE_ELIMINATION=y # CONFIG_TOUCHSCREEN_FTS is not set @@ -32,3 +32,7 @@ CONFIG_FELICA_MOUNT_BLOCK=y # CONFIG_UFSHPB is not set # CONFIG_UFSTW is not set # CONFIG_SCSI_SKHPB is not set +CONFIG_NFC=y +CONFIG_SEC_NFC_PRODUCT_N5=y +CONFIG_SEC_NFC=m +CONFIG_SEC_NFC_IF_I2C=y From bf8cede7f65571f131f7d439b33685c3a533cad2 Mon Sep 17 00:00:00 2001 From: Yunxian He Date: Thu, 9 Mar 2023 11:24:38 +0800 Subject: [PATCH 530/698] integrate samsung RN4V NFC driver integrate samsung RN4V NFC driver this driver support RN4V and SN4V Change-Id: Ibea9dcded110f0d058fcbc84516912a1be9d1915 Signed-off-by: Yunxian He Reviewed-on: https://gerrit.mot.com/2533690 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- drivers/nfc/Kconfig | 1 + drivers/nfc/Makefile | 1 + drivers/nfc/samsung/Kconfig | 67 ++ drivers/nfc/samsung/Makefile | 7 + drivers/nfc/samsung/sec_nfc.c | 1154 +++++++++++++++++++++++++++++++++ drivers/nfc/samsung/sec_nfc.h | 142 ++++ 6 files changed, 1372 insertions(+) create mode 100644 drivers/nfc/samsung/Kconfig create mode 100644 drivers/nfc/samsung/Makefile create mode 100644 drivers/nfc/samsung/sec_nfc.c create mode 100644 drivers/nfc/samsung/sec_nfc.h diff --git a/drivers/nfc/Kconfig b/drivers/nfc/Kconfig index 36d414f63dbf..2ab2e795295e 100644 --- a/drivers/nfc/Kconfig +++ b/drivers/nfc/Kconfig @@ -59,6 +59,7 @@ source "drivers/nfc/st-nci/Kconfig" source "drivers/nfc/nxp-nci/Kconfig" source "drivers/nfc/s3fwrn5/Kconfig" source "drivers/nfc/st95hf/Kconfig" +source "drivers/nfc/samsung/Kconfig" endmenu config NFC_QTI_I2C diff --git a/drivers/nfc/Makefile b/drivers/nfc/Makefile index 7aa7c077b4a0..9c5c77308bc5 100644 --- a/drivers/nfc/Makefile +++ b/drivers/nfc/Makefile @@ -17,4 +17,5 @@ obj-$(CONFIG_NFC_ST_NCI) += st-nci/ obj-$(CONFIG_NFC_NXP_NCI) += nxp-nci/ obj-$(CONFIG_NFC_S3FWRN5) += s3fwrn5/ obj-$(CONFIG_NFC_ST95HF) += st95hf/ +obj-$(CONFIG_SEC_NFC) += samsung/ obj-y += qti/ diff --git a/drivers/nfc/samsung/Kconfig b/drivers/nfc/samsung/Kconfig new file mode 100644 index 000000000000..3c66f3b24baf --- /dev/null +++ b/drivers/nfc/samsung/Kconfig @@ -0,0 +1,67 @@ +# +# Near Field Communication (NFC) devices +# + +menu "Near Field Communication (NFC) devices" + depends on NFC + +config SEC_NFC + tristate "Samsung NFC driver" + default m + help + SAMSUNG NFC Driver. + This driver provides support for SAMSUNG NFC products. + You should select your NFC product and interface. + + Say Y here to compile support for SAMSUNG NFC driver into the + kernel. + +choice + prompt "SEC NFC Products" + depends on SEC_NFC + default SEC_NFC_PRODUCT_N5 +config SEC_NFC_PRODUCT_N3 + bool "RN3" +config SEC_NFC_PRODUCT_N5 + bool "RN5/RNx" +endchoice +choice + prompt "SEC NFC Interface" + depends on SEC_NFC + default SEC_NFC_IF_I2C +config SEC_NFC_IF_UART + bool "UART" +config SEC_NFC_IF_I2C + bool "I2C" +config SEC_NFC_IF_I2C_GPIO + bool "I2C-GPIO (S/W-I2C)" + select I2C_CHARDEV + select I2C_MUX + select I2C_MUX_GPIO + select I2C_ARB_GPIO_CHALLENGE + select I2C_ALGOBIT + select I2C_GPIO +endchoice +config SEC_NFC_GPIO_CLK + bool "SEC NFC GPIO CLK" + default n + help + SAMSUNG NFC CLR REQ feature. + This feature provides support for SAMSUNG NFC products. + You should select this feature if your NFC product uses AP CLK. + + Say Y here to compile support for SAMSUNG NFC CLK REQ feature into the + kernel. +config SEC_NFC_DEDICATED_CLK + tristate "SEC NFC DEDICATED CLK" + default m +config SEC_NFC_LDO_EN + tristate "SEC NFC LDO" + default m +config SEC_NFC_PMIC_LDO + tristate "SEC NFC PMIC LDO" + default m +config SEC_ESE_COLDRESET + tristate "eSE Cold reset" + default m +endmenu diff --git a/drivers/nfc/samsung/Makefile b/drivers/nfc/samsung/Makefile new file mode 100644 index 000000000000..950cde363a53 --- /dev/null +++ b/drivers/nfc/samsung/Makefile @@ -0,0 +1,7 @@ +# +# Makefile for Samsung NRNx NFC driver +# + +obj-$(CONFIG_SEC_NFC) += sec_nfc.o + +ccflags-$(CONFIG_NFC_DEBUG) := -DDEBUG diff --git a/drivers/nfc/samsung/sec_nfc.c b/drivers/nfc/samsung/sec_nfc.c new file mode 100644 index 000000000000..fc5206ad333e --- /dev/null +++ b/drivers/nfc/samsung/sec_nfc.c @@ -0,0 +1,1154 @@ +/* + * SAMSUNG NFC Controller + * + * Copyright (C) 2013 Samsung Electronics Co.Ltd + * Author: Woonki Lee + * Heejae Kim + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program + * + */ +#ifdef CONFIG_SEC_NFC_IF_I2C_GPIO +#define CONFIG_SEC_NFC_IF_I2C +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_SEC_NFC_GPIO_CLK +#include +#endif +#ifdef CONFIG_SEC_NFC_WAKE_LOCK +#include +#endif +#include +#include + +#ifndef CONFIG_SEC_NFC_IF_I2C +struct sec_nfc_i2c_info {}; +#define sec_nfc_read NULL +#define sec_nfc_write NULL +#define sec_nfc_poll NULL +#define sec_nfc_i2c_irq_clear(x) + +#define SEC_NFC_GET_INFO(dev) platform_get_drvdata(to_platform_device(dev)) + +#else /* CONFIG_SEC_NFC_IF_I2C */ +#include +#include +#include +#include +#include "sec_nfc.h" + +#define SEC_NFC_GET_INFO(dev) i2c_get_clientdata(to_i2c_client(dev)) +enum sec_nfc_irq { + SEC_NFC_SKIP = -1, + SEC_NFC_NONE, + SEC_NFC_INT, + SEC_NFC_READ_TIMES, +}; + +struct sec_nfc_i2c_info { + struct i2c_client *i2c_dev; + struct mutex read_mutex; + enum sec_nfc_irq read_irq; + wait_queue_head_t read_wait; + size_t buflen; + u8 *buf; +}; +#endif + +struct sec_nfc_info { + struct miscdevice miscdev; + struct mutex mutex; + enum sec_nfc_mode mode; + struct device *dev; + struct sec_nfc_platform_data *pdata; + struct sec_nfc_i2c_info i2c_info; +#ifdef CONFIG_SEC_NFC_WAKE_LOCK + struct wake_lock nfc_wake_lock; +#endif +#ifdef CONFIG_SEC_NFC_GPIO_CLK + bool clk_ctl; + bool clk_state; +#endif +#ifdef CONFIG_SEC_NFC_DEDICATED_CLK + void __iomem *clkctrl; +#endif +}; + +#ifdef CONFIG_SEC_ESE_COLDRESET +struct mutex coldreset_mutex; +struct mutex sleep_wake_mutex; +bool sleep_wakeup_state[2]; +u8 disable_combo_reset_cmd[4] = {0x2F, 0x30, 0x01, 0x00}; +bool is_shutdown = false; +enum sec_nfc_mode cur_mode; +#endif + +#ifdef CONFIG_SEC_NFC_IF_I2C +static irqreturn_t sec_nfc_irq_thread_fn(int irq, void *dev_id) +{ + struct sec_nfc_info *info = dev_id; + struct sec_nfc_platform_data *pdata = info->pdata; + + dev_dbg(info->dev, "[NFC] Read Interrupt is occurred!\n"); + + if (gpio_get_value(pdata->irq) == 0) { + dev_err(info->dev, "[NFC] Warning,irq-gpio state is low!\n"); + return IRQ_HANDLED; + } + + mutex_lock(&info->i2c_info.read_mutex); + /* Skip interrupt during power switching + * It is released after first write */ + if (info->i2c_info.read_irq == SEC_NFC_SKIP) { + dev_dbg(info->dev, "%s: Now power swiching. Skip this IRQ\n", __func__); + mutex_unlock(&info->i2c_info.read_mutex); + return IRQ_HANDLED; + } + + info->i2c_info.read_irq += SEC_NFC_READ_TIMES; + mutex_unlock(&info->i2c_info.read_mutex); + + wake_up_interruptible(&info->i2c_info.read_wait); +#ifdef CONFIG_SEC_NFC_WAKE_LOCK + wake_lock_timeout(&info->nfc_wake_lock, 2 * HZ); +#endif + + return IRQ_HANDLED; +} + +static ssize_t sec_nfc_read(struct file *file, char __user *buf, + size_t count, loff_t *ppos) +{ + struct sec_nfc_info *info = container_of(file->private_data, + struct sec_nfc_info, miscdev); + enum sec_nfc_irq irq; + int ret = 0; + + dev_dbg(info->dev, "%s: info: %p, count: %zu\n", __func__, + info, count); + + mutex_lock(&info->mutex); + if (info->mode == SEC_NFC_MODE_OFF) { + dev_err(info->dev, "sec_nfc is not enabled\n"); + ret = -ENODEV; + goto out; + } + + mutex_lock(&info->i2c_info.read_mutex); + if (count == 0) { + if (info->i2c_info.read_irq >= SEC_NFC_INT) + info->i2c_info.read_irq--; + mutex_unlock(&info->i2c_info.read_mutex); + goto out; + } + + irq = info->i2c_info.read_irq; + mutex_unlock(&info->i2c_info.read_mutex); + if (irq == SEC_NFC_NONE) { + if (file->f_flags & O_NONBLOCK) { + dev_err(info->dev, "it is nonblock\n"); + ret = -EAGAIN; + goto out; + } + } + + /* i2c recv */ + if (count > info->i2c_info.buflen) + count = info->i2c_info.buflen; + + if (count > SEC_NFC_MSG_MAX_SIZE) { + dev_err(info->dev, "user required wrong size :%d\n", (u32)count); + ret = -EINVAL; + goto out; + } + + mutex_lock(&info->i2c_info.read_mutex); + memset(info->i2c_info.buf, 0, count); + ret = i2c_master_recv(info->i2c_info.i2c_dev, info->i2c_info.buf, (u32)count); + dev_dbg(info->dev, "recv size : %d\n", ret); + + if (ret == -EREMOTEIO) { + ret = -ERESTART; + goto read_error; + } else if (ret != count) { + dev_err(info->dev, "read failed: return: %d count: %d\n", + ret, (u32)count); + /* ret = -EREMOTEIO; */ + goto read_error; + } + + if (info->i2c_info.read_irq >= SEC_NFC_INT) + info->i2c_info.read_irq--; + + if (info->i2c_info.read_irq == SEC_NFC_READ_TIMES) + wake_up_interruptible(&info->i2c_info.read_wait); + + mutex_unlock(&info->i2c_info.read_mutex); + + if (copy_to_user(buf, info->i2c_info.buf, ret)) { + dev_err(info->dev, "copy failed to user\n"); + ret = -EFAULT; + } + + goto out; + +read_error: + info->i2c_info.read_irq = SEC_NFC_NONE; + mutex_unlock(&info->i2c_info.read_mutex); +out: + mutex_unlock(&info->mutex); + + return ret; +} + +static ssize_t sec_nfc_write(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) +{ + struct sec_nfc_info *info = container_of(file->private_data, + struct sec_nfc_info, miscdev); + int ret = 0; + + dev_dbg(info->dev, "%s: info: %p, count %d\n", __func__, + info, (u32)count); + + mutex_lock(&info->mutex); + + if (info->mode == SEC_NFC_MODE_OFF) { + dev_err(info->dev, "sec_nfc is not enabled\n"); + ret = -ENODEV; + goto out; + } + + if (count > info->i2c_info.buflen) + count = info->i2c_info.buflen; + + if (count > SEC_NFC_MSG_MAX_SIZE) { + dev_err(info->dev, "user required wrong size :%d\n", (u32)count); + ret = -EINVAL; + goto out; + } + + if (copy_from_user(info->i2c_info.buf, buf, count)) { + dev_err(info->dev, "copy failed from user\n"); + ret = -EFAULT; + goto out; + } + + /* Skip interrupt during power switching + * It is released after first write + */ + mutex_lock(&info->i2c_info.read_mutex); + ret = i2c_master_send(info->i2c_info.i2c_dev, info->i2c_info.buf, count); + if (info->i2c_info.read_irq == SEC_NFC_SKIP) + info->i2c_info.read_irq = SEC_NFC_NONE; + mutex_unlock(&info->i2c_info.read_mutex); + + if (ret == -EREMOTEIO) { + dev_err(info->dev, "send failed: return: %d count: %d\n", + ret, (u32)count); + ret = -ERESTART; + goto out; + } + + if (ret != count) { + dev_err(info->dev, "send failed: return: %d count: %d\n", + ret, (u32)count); + ret = -EREMOTEIO; + } + +out: + mutex_unlock(&info->mutex); + + return ret; +} + +static unsigned int sec_nfc_poll(struct file *file, poll_table *wait) +{ + struct sec_nfc_info *info = container_of(file->private_data, + struct sec_nfc_info, miscdev); + enum sec_nfc_irq irq; + + int ret = 0; + + dev_dbg(info->dev, "%s: info: %p\n", __func__, info); + + mutex_lock(&info->mutex); + + if (info->mode == SEC_NFC_MODE_OFF) { + dev_err(info->dev, "sec_nfc is not enabled\n"); + ret = -ENODEV; + goto out; + } + + poll_wait(file, &info->i2c_info.read_wait, wait); + + mutex_lock(&info->i2c_info.read_mutex); + irq = info->i2c_info.read_irq; + if (irq == SEC_NFC_READ_TIMES) + ret = (POLLIN | POLLRDNORM); + mutex_unlock(&info->i2c_info.read_mutex); + +out: + mutex_unlock(&info->mutex); + + return ret; +} + +void sec_nfc_i2c_irq_clear(struct sec_nfc_info *info) +{ + /* clear interrupt. Interrupt will be occurred at power off */ + mutex_lock(&info->i2c_info.read_mutex); + info->i2c_info.read_irq = SEC_NFC_NONE; + mutex_unlock(&info->i2c_info.read_mutex); +} + +int sec_nfc_i2c_probe(struct i2c_client *client) +{ + struct device *dev = &client->dev; + struct sec_nfc_info *info = dev_get_drvdata(dev); + struct sec_nfc_platform_data *pdata = info->pdata; + int ret; + + pr_info("%s: start: %p\n", __func__, info); + + info->i2c_info.buflen = SEC_NFC_MAX_BUFFER_SIZE; + info->i2c_info.buf = kzalloc(SEC_NFC_MAX_BUFFER_SIZE, GFP_KERNEL); + if (!info->i2c_info.buf) { + dev_err(dev, "failed to allocate memory for sec_nfc_info->buf\n"); + return -ENOMEM; + } + info->i2c_info.i2c_dev = client; + info->i2c_info.read_irq = SEC_NFC_NONE; + mutex_init(&info->i2c_info.read_mutex); + init_waitqueue_head(&info->i2c_info.read_wait); + i2c_set_clientdata(client, info); + + info->dev = dev; + + ret = gpio_request(pdata->irq, "nfc_int"); + if (ret) { + pr_err("GPIO request is failed to register IRQ\n"); + goto err_irq_req; + } + client->irq = gpio_to_irq(pdata->irq); + pr_info("%s: push interrupt no = %d\n", __func__, client->irq); + + ret = request_threaded_irq(client->irq, NULL, sec_nfc_irq_thread_fn, + IRQF_TRIGGER_RISING | IRQF_ONESHOT, SEC_NFC_DRIVER_NAME, + info); + if (ret < 0) { + pr_err("failed to register IRQ handler\n"); + kfree(info->i2c_info.buf); + return ret; + } + + pr_info("%s success\n", __func__); + return 0; + +err_irq_req: + return ret; +} + +void sec_nfc_i2c_remove(struct device *dev) +{ + struct sec_nfc_info *info = dev_get_drvdata(dev); + struct i2c_client *client = info->i2c_info.i2c_dev; + struct sec_nfc_platform_data *pdata = info->pdata; + free_irq(client->irq, info); + gpio_free(pdata->irq); +} +#endif /* CONFIG_SEC_NFC_IF_I2C */ + +#ifdef CONFIG_SEC_NFC_GPIO_CLK +static irqreturn_t sec_nfc_clk_irq_thread(int irq, void *dev_id) +{ + struct sec_nfc_info *info = dev_id; + struct sec_nfc_platform_data *pdata = info->pdata; + bool value; + + dev_dbg(info->dev, "[NFC]Clock Interrupt is occurred!\n"); + value = gpio_get_value(pdata->clk_req) > 0 ? true : false; + + if (value == info->clk_state) + return IRQ_HANDLED; + + if (value) + clk_prepare_enable(pdata->clk); + else + clk_disable_unprepare(pdata->clk); + + info->clk_state = value; + + return IRQ_HANDLED; +} + +void sec_nfc_clk_ctl_enable(struct sec_nfc_info *info) +{ + struct sec_nfc_platform_data *pdata = info->pdata; + unsigned int irq; + int ret; + + irq = gpio_to_irq(pdata->clk_req); + + if (info->clk_ctl) + return; + + info->clk_state = false; + ret = request_threaded_irq(irq, NULL, sec_nfc_clk_irq_thread, + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + SEC_NFC_DRIVER_NAME, info); + if (ret < 0) + dev_err(info->dev, "failed to register CLK REQ IRQ handler\n"); + + info->clk_ctl = true; +} + +void sec_nfc_clk_ctl_disable(struct sec_nfc_info *info) +{ + struct sec_nfc_platform_data *pdata = info->pdata; + unsigned int irq; + + if (pdata->clk_req) + irq = gpio_to_irq(pdata->clk_req); + else + return; + + if (!info->clk_ctl) + return; + + free_irq(irq, info); + if (info->clk_state) + clk_disable_unprepare(pdata->clk); + info->clk_state = false; + info->clk_ctl = false; +} +#else +#define sec_nfc_clk_ctl_enable(x) +#define sec_nfc_clk_ctl_disable(x) +#endif /* CONFIG_SEC_NFC_GPIO_CLK */ + +static void sec_nfc_set_mode(struct sec_nfc_info *info, + enum sec_nfc_mode mode) +{ + struct sec_nfc_platform_data *pdata = info->pdata; +#ifdef CONFIG_SEC_ESE_COLDRESET + int alreadFirmHigh = 0; + int ret ; + enum sec_nfc_mode oldmode = info->mode; +#endif +#ifdef CONFIG_SEC_NFC_DEDICATED_CLK + unsigned int val = readl(info->clkctrl); +#endif + + /* intfo lock is aleady gotten before calling this function */ + if (info->mode == mode) { + pr_err("Power mode is already %d", mode); + return; + } + info->mode = mode; + +#ifdef CONFIG_SEC_NFC_IF_I2C + /* Skip interrupt during power switching + * It is released after first write */ + mutex_lock(&info->i2c_info.read_mutex); +#ifdef CONFIG_SEC_ESE_COLDRESET + cur_mode = mode; + memset(sleep_wakeup_state, false, sizeof(sleep_wakeup_state)); + if (oldmode == SEC_NFC_MODE_OFF) { + if (gpio_get_value(pdata->firm) == 1) { + alreadFirmHigh = 1; + pr_err("Firm is already high; do not anything"); + } else { /*Firm pin is low*/ + gpio_set_value(pdata->firm, SEC_NFC_FW_ON); + msleep(SEC_NFC_VEN_WAIT_TIME); + } + + if (gpio_get_value(pdata->ven) == SEC_NFC_PW_ON) { + ret = i2c_master_send(info->i2c_info.i2c_dev, disable_combo_reset_cmd, + sizeof(disable_combo_reset_cmd)/sizeof(u8)); + pr_err("disable combo_reset_command ret: %d", ret); + } else { + pr_err("skip disable combo_reset_command"); + } + + if (alreadFirmHigh == 1) { + pr_err("Firm is already high; do not anything2"); + } else { /*Firm pin is low*/ + mdelay(3); /*wait for FW*/ + gpio_set_value(pdata->firm, SEC_NFC_FW_OFF); + } + } +#endif + info->i2c_info.read_irq = SEC_NFC_SKIP; + mutex_unlock(&info->i2c_info.read_mutex); +#endif + +#ifdef CONFIG_SEC_ESE_COLDRESET + mdelay(1); + pr_err("FIRMWARE_GUARD_TIME(+1ms) in PW_OFF(total:4ms)\n"); +#endif + + gpio_set_value(pdata->ven, SEC_NFC_PW_OFF); + if (pdata->firm) + gpio_set_value(pdata->firm, SEC_NFC_FW_OFF); + + if (mode == SEC_NFC_MODE_BOOTLOADER) + if (pdata->firm) + gpio_set_value(pdata->firm, SEC_NFC_FW_ON); + + if (mode != SEC_NFC_MODE_OFF) { + msleep(SEC_NFC_VEN_WAIT_TIME); + sec_nfc_clk_ctl_enable(info); + gpio_set_value(pdata->ven, SEC_NFC_PW_ON); +#ifdef CONFIG_SEC_NFC_DEDICATED_CLK + val |= 0xC0000000; + writel(val, info->clkctrl); +#endif +#ifdef CONFIG_SEC_NFC_IF_I2C + enable_irq_wake(info->i2c_info.i2c_dev->irq); +#endif + msleep(SEC_NFC_VEN_WAIT_TIME/2); + } else { +#ifdef CONFIG_SEC_ESE_COLDRESET + int PW_OFF_DURATION = 20; + struct timespec t0, t1; + getnstimeofday(&t0); + mdelay(PW_OFF_DURATION); + + if (is_shutdown == false) + gpio_set_value(pdata->ven, SEC_NFC_PW_ON); + + getnstimeofday(&t1); + pr_err("DeepStby: PW_OFF duration (%d)ms, real PW_OFF duration is (%ld-%ld)ms\n", + PW_OFF_DURATION ,t0.tv_nsec*1000, t1.tv_nsec*1000); + pr_err("DeepStby: enter DeepStby(PW_ON)\n"); +#endif + sec_nfc_clk_ctl_disable(info); +#ifdef CONFIG_SEC_NFC_DEDICATED_CLK + val &= ~0xC0000000; + writel(val, info->clkctrl); +#endif +#ifdef CONFIG_SEC_NFC_IF_I2C + disable_irq_wake(info->i2c_info.i2c_dev->irq); +#endif + } + +#ifdef CONFIG_SEC_NFC_WAKE_LOCK + if (wake_lock_active(&info->nfc_wake_lock)) + wake_unlock(&info->nfc_wake_lock); +#endif + + pr_info("%s NFC mode is : %d\n", __func__, mode); +} + +#ifdef CONFIG_SEC_ESE_COLDRESET +struct cold_reset_gpio { + int firm_gpio; + int coldreset_gpio; +}; + +struct cold_reset_gpio cold_reset_gpio_data; + +void init_coldreset_mutex(void) +{ + mutex_init(&coldreset_mutex); +} + +void init_sleep_wake_mutex(void) +{ + mutex_init(&sleep_wake_mutex); +} + +void check_and_sleep_nfc(unsigned int gpio, int value) { + if (sleep_wakeup_state[IDX_SLEEP_WAKEUP_NFC] == true || + sleep_wakeup_state[IDX_SLEEP_WAKEUP_ESE] == true) { + pr_info("%s keep wake up state\n", __func__); + return; + } + gpio_set_value(gpio, value); +} + +int trig_cold_reset_id(int id) +{ + int wakeup_delay = 20; + int duration = 18; + struct timespec t0, t1, t2; + int isFirmHigh = 0; + + if (id == ESE_ID) + mutex_lock(&coldreset_mutex); + + getnstimeofday(&t0); + if (gpio_get_value(cold_reset_gpio_data.firm_gpio) == 1) { + isFirmHigh = 1; + } else { + gpio_set_value(cold_reset_gpio_data.firm_gpio, SEC_NFC_FW_ON); + mdelay(wakeup_delay); + } + + getnstimeofday(&t1); + gpio_set_value(cold_reset_gpio_data.coldreset_gpio, SEC_NFC_COLDRESET_ON); + mdelay(duration); + gpio_set_value(cold_reset_gpio_data.coldreset_gpio, SEC_NFC_COLDRESET_OFF); + getnstimeofday(&t2); + + if (isFirmHigh == 1) + pr_err("COLDRESET: FW_PIN already high, do not FW_OFF\n"); + else + gpio_set_value(cold_reset_gpio_data.firm_gpio, SEC_NFC_FW_OFF); + + pr_err("COLDRESET: FW_ON time (%ld-%ld)\n", t0.tv_nsec*1000, t1.tv_nsec*1000); + pr_err("COLDRESET: GPIO3 ON time (%ld-%ld)\n", t1.tv_nsec*1000, t2.tv_nsec*1000); + + if (id == ESE_ID) + mutex_unlock(&coldreset_mutex); + + pr_err("COLDRESET: exit"); + return 0; +} + +extern int trig_cold_reset(void) // Called from eSE driver +{ + pr_info("%s trig_cold_reset\n", __func__); + return trig_cold_reset_id(ESE_ID); +} +EXPORT_SYMBOL(trig_cold_reset); + +extern int trig_nfc_wakeup(void) +{ + pr_info("%s trig_nfc_wakeup\n", __func__); + + if (cur_mode == SEC_NFC_MODE_OFF || cur_mode == SEC_NFC_MODE_BOOTLOADER) { + pr_err("nfc mode not support to wake up"); + return -EPERM;; + } + mutex_lock(&sleep_wake_mutex); + gpio_set_value(cold_reset_gpio_data.firm_gpio, SEC_NFC_WAKE_UP); + sleep_wakeup_state[IDX_SLEEP_WAKEUP_ESE] = true; + mutex_unlock(&sleep_wake_mutex); + return 0; +} +EXPORT_SYMBOL(trig_nfc_wakeup); + +extern int trig_nfc_sleep(void) +{ + pr_info("%s trig_nfc_sleep\n", __func__); + if (cur_mode == SEC_NFC_MODE_OFF || cur_mode == SEC_NFC_MODE_BOOTLOADER) { + pr_err("nfc mode not support to sleep"); + return -EPERM;; + } + mutex_lock(&sleep_wake_mutex); + sleep_wakeup_state[IDX_SLEEP_WAKEUP_ESE] = false; + check_and_sleep_nfc(cold_reset_gpio_data.firm_gpio, SEC_NFC_WAKE_SLEEP); + mutex_unlock(&sleep_wake_mutex); + return 0; +} +EXPORT_SYMBOL(trig_nfc_sleep); +#endif + +static long sec_nfc_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + struct sec_nfc_info *info = container_of(file->private_data, + struct sec_nfc_info, miscdev); + struct sec_nfc_platform_data *pdata = info->pdata; + unsigned int new = (unsigned int)arg; + int ret = 0; + + dev_dbg(info->dev, "%s: info: %p, cmd: 0x%x\n", + __func__, info, cmd); + + mutex_lock(&info->mutex); +#ifdef CONFIG_SEC_ESE_COLDRESET + mutex_lock(&coldreset_mutex); +#endif + + switch (cmd) { + case SEC_NFC_SET_MODE: + if (info->mode == new) + break; + + if (new >= SEC_NFC_MODE_COUNT) { + dev_err(info->dev, "wrong mode (%d)\n", new); + ret = -EFAULT; + break; + } + sec_nfc_set_mode(info, new); + break; + +#if defined(CONFIG_SEC_NFC_PRODUCT_N3) + case SEC_NFC_SLEEP: + case SEC_NFC_WAKEUP: + break; + +#elif defined(CONFIG_SEC_NFC_PRODUCT_N5) || defined(CONFIG_SEC_NFC_PRODUCT_N7) + case SEC_NFC_SLEEP: + if (info->mode != SEC_NFC_MODE_BOOTLOADER) { +#ifdef CONFIG_SEC_NFC_WAKE_LOCK + if (wake_lock_active(&info->nfc_wake_lock)) + wake_unlock(&info->nfc_wake_lock); +#endif +#ifdef CONFIG_SEC_ESE_COLDRESET + mutex_lock(&sleep_wake_mutex); + sleep_wakeup_state[IDX_SLEEP_WAKEUP_NFC] = false; + check_and_sleep_nfc(pdata->wake, SEC_NFC_WAKE_SLEEP); + mutex_unlock(&sleep_wake_mutex); +#else + gpio_set_value(pdata->wake, SEC_NFC_WAKE_SLEEP); +#endif + } + break; + + case SEC_NFC_WAKEUP: + if (info->mode != SEC_NFC_MODE_BOOTLOADER) { + gpio_set_value(pdata->wake, SEC_NFC_WAKE_UP); +#ifdef CONFIG_SEC_ESE_COLDRESET + sleep_wakeup_state[IDX_SLEEP_WAKEUP_NFC] = true; +#endif +#ifdef CONFIG_SEC_NFC_WAKE_LOCK + if (!wake_lock_active(&info->nfc_wake_lock)) + wake_lock(&info->nfc_wake_lock); +#endif + } + break; +#endif +#ifdef CONFIG_SEC_ESE_COLDRESET + case SEC_NFC_COLD_RESET: + trig_cold_reset_id(DEVICEHOST_ID); + break; + case SEC_NFC_SHUTDOWN: + is_shutdown = true; + break; +#endif + default: + dev_err(info->dev, "Unknown ioctl 0x%x\n", cmd); + ret = -ENOIOCTLCMD; + break; + } + +#ifdef CONFIG_SEC_ESE_COLDRESET + mutex_unlock(&coldreset_mutex); +#endif + mutex_unlock(&info->mutex); + + return ret; +} + +static int sec_nfc_open(struct inode *inode, struct file *file) +{ + struct sec_nfc_info *info = container_of(file->private_data, + struct sec_nfc_info, miscdev); + int ret = 0; + + pr_info("%s info : %p\n", __func__, info); + + mutex_lock(&info->mutex); + if (info->mode != SEC_NFC_MODE_OFF) { + dev_err(info->dev, "sec_nfc is busy\n"); + ret = -EBUSY; + goto out; + } + + sec_nfc_set_mode(info, SEC_NFC_MODE_OFF); + +out: + mutex_unlock(&info->mutex); + return ret; +} + +static int sec_nfc_close(struct inode *inode, struct file *file) +{ + struct sec_nfc_info *info = container_of(file->private_data, + struct sec_nfc_info, miscdev); + + pr_info("%s: info : %p\n", __func__, info); + + mutex_lock(&info->mutex); + sec_nfc_set_mode(info, SEC_NFC_MODE_OFF); + mutex_unlock(&info->mutex); + + return 0; +} + +static const struct file_operations sec_nfc_fops = { + .owner = THIS_MODULE, + .read = sec_nfc_read, + .write = sec_nfc_write, + .poll = sec_nfc_poll, + .open = sec_nfc_open, + .release = sec_nfc_close, + .unlocked_ioctl = sec_nfc_ioctl, +}; + +#ifdef CONFIG_PM +static int sec_nfc_suspend(struct device *dev) +{ + struct sec_nfc_info *info = SEC_NFC_GET_INFO(dev); + struct sec_nfc_platform_data *pdata = info->pdata; + int ret = 0; + int value = 0; + + mutex_lock(&info->mutex); + + if (info->mode == SEC_NFC_MODE_BOOTLOADER) + ret = -EPERM; + + value = gpio_get_value(pdata->wake); + if(value > 0){ + pr_info("%s: hal is still active, block suspend.\n", __func__); + ret = -EPERM; + } + mutex_unlock(&info->mutex); + + return ret; +} + +static int sec_nfc_resume(struct device *dev) +{ + return 0; +} + +static SIMPLE_DEV_PM_OPS(sec_nfc_pm_ops, sec_nfc_suspend, sec_nfc_resume); +#endif + +#ifdef CONFIG_OF +/*device tree parsing*/ +static int sec_nfc_parse_dt(struct device *dev, + struct sec_nfc_platform_data *pdata) +{ + struct device_node *np = dev->of_node; + + pdata->ven = of_get_named_gpio(np, "sec-nfc,ven-gpio", 0); + pdata->firm = of_get_named_gpio(np, "sec-nfc,firm-gpio", 0); + pdata->wake = pdata->firm; +#ifdef CONFIG_SEC_NFC_IF_I2C + pdata->irq = of_get_named_gpio(np, "sec-nfc,irq-gpio", 0); +#endif + +#ifdef CONFIG_SEC_ESE_COLDRESET + pdata->coldreset = of_get_named_gpio(np, "sec-nfc,coldreset-gpio",0); + cold_reset_gpio_data.firm_gpio = pdata->firm; + cold_reset_gpio_data.coldreset_gpio = pdata->coldreset; +#endif + +#ifdef CONFIG_SEC_NFC_LDO_EN + pdata->pvdd_en = of_get_named_gpio(np, "sec-nfc,ldo_en",0); +#endif +#ifdef CONFIG_SEC_NFC_PMIC_LDO + if (of_property_read_string(np, "sec-nfc,pmic-ldo", &pdata->pvdd_regulator_name)) + pr_err("%s: Failed to get %s regulator.\n", __func__, pdata->pvdd_regulator_name); +#endif + +#ifdef CONFIG_SEC_NFC_DEDICATED_CLK + if(of_property_read_u32(np, "clkctrl-reg", (u32 *)&pdata->clkctrl_addr)) + return -EINVAL; +#endif +#ifdef CONFIG_SEC_NFC_GPIO_CLK + pdata->clk_req = of_get_named_gpio(np, "sec-nfc,clk_req-gpio", 0); + pdata->clk = clk_get(dev, "OSC_NFC"); +#endif + + pr_info("%s: irq : %d, ven : %d, firm : %d\n", + __func__, pdata->irq, pdata->ven, pdata->firm); + return 0; +} +#else /* CONFIG_OF */ +static int sec_nfc_parse_dt(struct device *dev, + struct sec_nfc_platform_data *pdata) +{ + return -ENODEV; +} +#endif + +static int __sec_nfc_probe(struct device *dev) +{ + struct sec_nfc_info *info; + struct sec_nfc_platform_data *pdata = NULL; + int ret = 0; + + pr_info("%s : start\n", __func__); + if (dev->of_node) { + pdata = devm_kzalloc(dev, sizeof(struct sec_nfc_platform_data), GFP_KERNEL); + if (!pdata) + return -ENOMEM; + + ret = sec_nfc_parse_dt(dev, pdata); + if (ret) + return ret; + } else { + pdata = dev->platform_data; + } + + if (!pdata) { + dev_err(dev, "No platform data\n"); + ret = -ENOMEM; + goto err_pdata; + } + + info = kzalloc(sizeof(struct sec_nfc_info), GFP_KERNEL); + if (!info) { + ret = -ENOMEM; + goto err_info_alloc; + } + info->dev = dev; + info->pdata = pdata; + info->mode = SEC_NFC_MODE_OFF; + + mutex_init(&info->mutex); + dev_set_drvdata(dev, info); + + info->miscdev.minor = MISC_DYNAMIC_MINOR; + info->miscdev.name = SEC_NFC_DRIVER_NAME; + info->miscdev.fops = &sec_nfc_fops; + info->miscdev.parent = dev; + ret = misc_register(&info->miscdev); + if (ret < 0) { + dev_err(dev, "failed to register Device\n"); + goto err_dev_reg; + } + +#ifdef CONFIG_SEC_NFC_DEDICATED_CLK + if (pdata->clkctrl_addr != 0) { + info->clkctrl = ioremap_nocache(pdata->clkctrl_addr, 0x80); + if (!info->clkctrl) { + dev_err(dev, "cannot remap nfc clock register\n"); + ret = -ENXIO; + goto err_iomap; + } + } +#endif +#ifdef CONFIG_SEC_NFC_LDO_EN + { + ret = gpio_request(pdata->pvdd_en, "ldo_en"); + if (ret < 0) { + pr_err("failed to request about pvdd_en pin\n"); + goto err_dev_reg; + } + if (!is_charging_mode) + gpio_direction_output(pdata->pvdd_en, NFC_I2C_LDO_ON); + pr_info("pvdd en: %d\n", gpio_get_value(pdata->pvdd_en)); + } +#endif +#ifdef CONFIG_SEC_NFC_PMIC_LDO + if (!is_charging_mode) { + pdata->pvdd_regulator = regulator_get(NULL, pdata->pvdd_regulator_name); + if (IS_ERR(pdata->pvdd_regulator)) + pr_err("%s: Failed to get %s pmic regulator.\n", __func__, pdata->pvdd_regulator); + ret = regulator_enable(pdata->pvdd_regulator); + pr_err("%s: Failed to enable pmic regulator: %d\n", __func__, ret); + } +#endif + + ret = gpio_request(pdata->ven, "nfc_ven"); + if (ret) { + dev_err(dev, "failed to get gpio ven\n"); + goto err_gpio_ven; + } + if (!is_charging_mode) + gpio_direction_output(pdata->ven, SEC_NFC_PW_OFF); + + if (pdata->firm) { + ret = gpio_request(pdata->firm, "nfc_firm"); + if (ret) { + dev_err(dev, "failed to get gpio firm\n"); + goto err_gpio_firm; + } + gpio_direction_output(pdata->firm, SEC_NFC_FW_OFF); + } +#ifdef CONFIG_SEC_ESE_COLDRESET + init_coldreset_mutex(); + init_sleep_wake_mutex(); + memset(sleep_wakeup_state, false, sizeof(sleep_wakeup_state)); + ret = gpio_request(pdata->coldreset, "nfc_coldreset"); + if (ret) { + dev_err(dev, "failed to get gpio coldreset(NFC-GPIO3)\n"); + goto err_gpio_coldreset; + } + gpio_direction_output(pdata->coldreset, SEC_NFC_COLDRESET_OFF); +#endif +#ifdef CONFIG_SEC_NFC_WAKE_LOCK + wake_lock_init(&info->nfc_wake_lock, WAKE_LOCK_SUSPEND, "nfc_wake_lock"); +#endif + + dev_info(dev, "%s: success info: %p, pdata %p\n", __func__, info, pdata); + + return 0; + +#ifdef CONFIG_SEC_ESE_COLDRESET +err_gpio_coldreset: + gpio_free(pdata->coldreset); +#endif +err_gpio_firm: + gpio_free(pdata->ven); +err_gpio_ven: +#ifdef CONFIG_SEC_NFC_DEDICATED_CLK + iounmap(info->clkctrl); +err_iomap: +#endif +err_dev_reg: + mutex_destroy(&info->mutex); + kfree(info); +err_info_alloc: + devm_kfree(dev, pdata); +err_pdata: + return ret; +} + +static int __sec_nfc_remove(struct device *dev) +{ + struct sec_nfc_info *info = dev_get_drvdata(dev); + struct i2c_client *client = info->i2c_info.i2c_dev; + struct sec_nfc_platform_data *pdata = info->pdata; + + dev_dbg(info->dev, "%s\n", __func__); + +#ifdef CONFIG_SEC_NFC_GPIO_CLK + if (pdata->clk) + clk_unprepare(pdata->clk); +#endif + + misc_deregister(&info->miscdev); + sec_nfc_set_mode(info, SEC_NFC_MODE_OFF); + free_irq(client->irq, info); + gpio_free(pdata->irq); + gpio_set_value(pdata->firm, 0); + gpio_free(pdata->ven); + if (pdata->firm) + gpio_free(pdata->firm); + +#ifdef CONFIG_SEC_NFC_WAKE_LOCK + wake_lock_destroy(&info->nfc_wake_lock); +#endif + + kfree(info); + + return 0; +} + +#ifdef CONFIG_SEC_NFC_IF_I2C +static struct i2c_device_id sec_nfc_id_table[] = { + { SEC_NFC_DRIVER_NAME, 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, sec_nfc_id_table); +typedef struct i2c_driver sec_nfc_driver_type; +#define SEC_NFC_INIT(driver) i2c_add_driver(driver) +#define SEC_NFC_EXIT(driver) i2c_del_driver(driver) + +static int sec_nfc_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + int ret = 0; + + ret = __sec_nfc_probe(&client->dev); + if (ret) + return ret; + + if (sec_nfc_i2c_probe(client)) + __sec_nfc_remove(&client->dev); + + return ret; +} + +static int sec_nfc_remove(struct i2c_client *client) +{ + sec_nfc_i2c_remove(&client->dev); + return __sec_nfc_remove(&client->dev); +} +#else /* CONFIG_SEC_NFC_IF_I2C */ +MODULE_DEVICE_TABLE(platform, sec_nfc_id_table); +typedef struct platform_driver sec_nfc_driver_type; +#define SEC_NFC_INIT(driver) platform_driver_register(driver); +#define SEC_NFC_EXIT(driver) platform_driver_unregister(driver); + +static int sec_nfc_probe(struct platform_device *pdev) +{ + return __sec_nfc_probe(&pdev->dev); +} + +static int sec_nfc_remove(struct platform_device *pdev) +{ + return __sec_nfc_remove(&pdev->dev); +} + +static struct platform_device_id sec_nfc_id_table[] = { + { SEC_NFC_DRIVER_NAME, 0 }, + { } +}; +#endif /* CONFIG_SEC_NFC_IF_I2C */ + +#ifdef CONFIG_OF +static const struct of_device_id nfc_match_table[] = { + { .compatible = SEC_NFC_DRIVER_NAME,}, + {}, +}; +#else /* CONFIG_OF */ +#define nfc_match_table NULL +#endif + +static struct i2c_driver sec_nfc_driver = { + .probe = sec_nfc_probe, + .id_table = sec_nfc_id_table, + .remove = sec_nfc_remove, + .driver = { + .name = SEC_NFC_DRIVER_NAME, +#ifdef CONFIG_PM + .pm = &sec_nfc_pm_ops, +#endif + .of_match_table = nfc_match_table, + }, +}; + +#if 0 +static int __init is_poweroff_charging_mode(char *str) +{ + if (strncmp("charger", str, 7) == 0) + is_charging_mode = true; + else + is_charging_mode = false; + + return 0; +} early_param("androidboot.mode", is_poweroff_charging_mode); +#endif + +static int __init sec_nfc_init(void) +{ + return SEC_NFC_INIT(&sec_nfc_driver); +} + +static void __exit sec_nfc_exit(void) +{ + SEC_NFC_EXIT(&sec_nfc_driver); +} + +module_init(sec_nfc_init); +module_exit(sec_nfc_exit); + +MODULE_DESCRIPTION("Samsung sec_nfc driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/nfc/samsung/sec_nfc.h b/drivers/nfc/samsung/sec_nfc.h new file mode 100644 index 000000000000..78d525115686 --- /dev/null +++ b/drivers/nfc/samsung/sec_nfc.h @@ -0,0 +1,142 @@ +/* + * SAMSUNG NFC Controller + * + * Copyright (C) 2013 Samsung Electronics Co.Ltd + * Author: Woonki Lee + * Author: Heejae Kim + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * Last update: 2016-01-14 + */ + +#include +#ifdef CONFIG_SEC_NFC_GPIO_CLK +#include +#endif +#ifdef CONFIG_SEC_NFC_PMIC_LDO +#include +#include +#endif + +#ifdef CONFIG_SEC_NFC_I2C /* support old driver configuration */ + +#ifndef CONFIG_SEC_NFC +#define CONFIG_SEC_NFC +#endif + +#if !defined(CONFIG_SEC_NFC_IF_I2C) && !defined(CONFIG_SEC_NFC_IF_UART) +#define CONFIG_SEC_NFC_IF_I2C +#endif + +#if !defined(CONFIG_SEC_NFC_PRODUCT_N3) && !defined(CONFIG_SEC_NFC_PRODUCT_N5) +#define CONFIG_SEC_NFC_PRODUCT_N3 +#endif + +#endif /* CONFIG_SEC_NFC_I2C */ + +#define SEC_NFC_DRIVER_NAME "sec-nfc" + +#define SEC_NFC_MAX_BUFFER_SIZE 512 + +/* ioctl */ +#define SEC_NFC_MAGIC 'S' +#define SEC_NFC_GET_MODE _IOW(SEC_NFC_MAGIC, 0, unsigned int) +#define SEC_NFC_SET_MODE _IOW(SEC_NFC_MAGIC, 1, unsigned int) +#define SEC_NFC_SLEEP _IOW(SEC_NFC_MAGIC, 2, unsigned int) +#define SEC_NFC_WAKEUP _IOW(SEC_NFC_MAGIC, 3, unsigned int) +#ifdef CONFIG_SEC_ESE_COLDRESET +#define SEC_NFC_COLD_RESET _IOW(SEC_NFC_MAGIC, 5, unsigned int) +#define SEC_NFC_SHUTDOWN _IOW(SEC_NFC_MAGIC, 6, unsigned int) +#endif + +/* size */ +#define SEC_NFC_MSG_MAX_SIZE (256 + 4) + +/* wait for device stable */ +#ifdef CONFIG_SEC_NFC_MARGINTIME +#define SEC_NFC_VEN_WAIT_TIME (150) +#else +#define SEC_NFC_VEN_WAIT_TIME (20) +#endif + +/* gpio pin configuration */ +struct sec_nfc_platform_data { + int irq; + int ven; + int firm; + int wake; + int pvdd_en; + unsigned int tvdd; + unsigned int avdd; +#ifdef CONFIG_SEC_ESE_COLDRESET + unsigned int coldreset; +#endif +#ifdef CONFIG_SEC_NFC_GPIO_CLK + unsigned int clk_req; + struct clk *clk; +#endif + + void (*cfg_gpio)(void); + u32 ven_gpio_flags; + u32 firm_gpio_flags; + u32 irq_gpio_flags; + const char *nfc_pvdd; +#ifdef CONFIG_SEC_NFC_PMIC_LDO + const char *pvdd_regulator_name; + struct regulator *pvdd_regulator; +#endif +#ifdef CONFIG_SEC_NFC_DEDICATED_CLK + phys_addr_t clkctrl_addr; +#endif +}; + +enum sec_nfc_mode { + SEC_NFC_MODE_OFF = 0, + SEC_NFC_MODE_FIRMWARE, + SEC_NFC_MODE_BOOTLOADER, + SEC_NFC_MODE_COUNT, +}; + +#ifdef CONFIG_SEC_NFC_PRODUCT_N3 +enum sec_nfc_power { + SEC_NFC_PW_OFF = 0, + SEC_NFC_PW_ON, +}; +#else /* CONFIG_SEC_NFC_PRODUCT_N3 */ +enum sec_nfc_power { + SEC_NFC_PW_ON = 0, + SEC_NFC_PW_OFF, +}; +#endif + +enum sec_nfc_firmpin { + SEC_NFC_FW_OFF = 0, + SEC_NFC_FW_ON, +}; + +enum sec_nfc_wake { + SEC_NFC_WAKE_SLEEP = 0, + SEC_NFC_WAKE_UP, +}; + +#ifdef CONFIG_SEC_ESE_COLDRESET +enum sec_nfc_coldreset{ + SEC_NFC_COLDRESET_OFF = 0, + SEC_NFC_COLDRESET_ON, +}; + +#define FIRMWARE_GUARD_TIME (4) +#define DEVICEHOST_ID (0x00) +#define ESE_ID (0x02) +#define IDX_SLEEP_WAKEUP_NFC 0 +#define IDX_SLEEP_WAKEUP_ESE 1 +#endif + +bool is_charging_mode; + +#define NFC_I2C_LDO_ON 1 +#define NFC_I2C_LDO_OFF 0 From 5af4f0287d0aaaa37d095bcf39f3ba879af0055e Mon Sep 17 00:00:00 2001 From: Fernanda Schmidt Date: Tue, 14 Mar 2023 16:15:46 -0300 Subject: [PATCH 531/698] Disabling some Debug configs Disabling CONFIG_SLUB_DEBUG_ON, CONFIG_DEBUG_MUTEXES, CONFIG_DEBUG_SPINLOCK and CONFIG_DEBUG_SPINLOCK_PANIC_ON_BUG configs, which are severily impacting on device's memory pressure. Change-Id: Id610358654b687110d9a2302ec17a8bcfe12f3b6 Reviewed-on: https://gerrit.mot.com/2539189 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Reviewed-by: Rafael Ortolan Reviewed-by: Carlos Pinho Tested-by: Jira Key Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/debug-holi-milanf.config | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm64/configs/vendor/ext_config/debug-holi-milanf.config b/arch/arm64/configs/vendor/ext_config/debug-holi-milanf.config index 018b945c19d3..3076d485f8d8 100644 --- a/arch/arm64/configs/vendor/ext_config/debug-holi-milanf.config +++ b/arch/arm64/configs/vendor/ext_config/debug-holi-milanf.config @@ -24,3 +24,7 @@ # CONFIG_RCU_TORTURE_TEST is not set # CONFIG_TEST_USER_COPY is not set # CONFIG_UFSTW is not set +# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_SPINLOCK_PANIC_ON_BUG is not set From f88628ff2a142e2560d51ac2f8bbdf9ce1cc6db7 Mon Sep 17 00:00:00 2001 From: zhaoxp3 Date: Tue, 14 Mar 2023 13:32:48 +0800 Subject: [PATCH 532/698] defconfig: define bangkk dtb Change-Id: I0a033f34b473e1d325900f5697dfa48cfe69d252 Signed-off-by: zhaoxp3 Reviewed-on: https://gerrit.mot.com/2538318 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Hua Tan Submit-Approved: tongkun1 --- arch/arm64/configs/vendor/ext_config/moto-holi-bangkk.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-bangkk.config b/arch/arm64/configs/vendor/ext_config/moto-holi-bangkk.config index 5124e86dc97c..8c1c71a39861 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-bangkk.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-bangkk.config @@ -13,7 +13,7 @@ # You can check the .config file to verify that your configuration option is # being set as expected. # -CONFIG_PENANG_DTB=y +CONFIG_BANGKK_DTB=y # CONFIG_NFC_QTI_I2C is not set CONFIG_FS_EPOLL_WAKEUP_DEBUG=y CONFIG_ZRAM_WRITEBACK=y From d9bb81177f3946525949d15a969bae72659af5b2 Mon Sep 17 00:00:00 2001 From: Fernanda Schmidt Date: Wed, 15 Mar 2023 06:22:47 -0300 Subject: [PATCH 533/698] Disabling some Debug configs Disabling CONFIG_SLUB_DEBUG_ON, CONFIG_DEBUG_MUTEXES, CONFIG_DEBUG_SPINLOCK and CONFIG_DEBUG_SPINLOCK_PANIC_ON_BUG configs, which are severily impacting on device's memory pressure. Change-Id: I376aeac5b37ebc40f01abae8ca557ad10a29687c Reviewed-on: https://gerrit.mot.com/2541251 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Reviewed-by: Rafael Ortolan Reviewed-by: Carlos Pinho Tested-by: Jira Key Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/debug-holi-rhodec.config | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm64/configs/vendor/ext_config/debug-holi-rhodec.config b/arch/arm64/configs/vendor/ext_config/debug-holi-rhodec.config index 13f71e03c466..88417720a117 100644 --- a/arch/arm64/configs/vendor/ext_config/debug-holi-rhodec.config +++ b/arch/arm64/configs/vendor/ext_config/debug-holi-rhodec.config @@ -23,3 +23,7 @@ # CONFIG_PROVE_LOCKING is not set # CONFIG_RCU_TORTURE_TEST is not set # CONFIG_TEST_USER_COPY is not set +# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_SPINLOCK_PANIC_ON_BUG is not set From ec5ba1a4d876b6d3270149fe57136c6a022bf7e7 Mon Sep 17 00:00:00 2001 From: liujg6 Date: Wed, 15 Mar 2023 15:43:46 +0800 Subject: [PATCH 534/698] arm64/ext_config: disable rt throttling on pnangn userdebug build [Details] Disable CONFIG_PANIC_ON_RT_THROTTLING on pnangn userdebug build Change-Id: I3e4830e666d7d536c53e0cb4dfae24dffaac7ef0 Reviewed-on: https://gerrit.mot.com/2541503 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Wang Wang Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/debug-holi-pnangn.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/vendor/ext_config/debug-holi-pnangn.config b/arch/arm64/configs/vendor/ext_config/debug-holi-pnangn.config index 95c989c10a1b..a77035638ae1 100644 --- a/arch/arm64/configs/vendor/ext_config/debug-holi-pnangn.config +++ b/arch/arm64/configs/vendor/ext_config/debug-holi-pnangn.config @@ -26,3 +26,4 @@ # CONFIG_UFSTW is not set # CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_PANIC_ON_RT_THROTTLING is not set From f42cfa2d066f3aee25744a9564fd5ed51fb2cb6d Mon Sep 17 00:00:00 2001 From: zhangchao Date: Wed, 22 Mar 2023 14:51:09 +0800 Subject: [PATCH 535/698] kernel/config:use gpio45/46 for ap i2c 1/2 1.GPIO45 and GPIO45 is reserved_gpios 2.modify config use gpio45/46 for ap i2c Change-Id: Ie47f9970849f95e49cb3004908540b4f28a3865d Reviewed-on: https://gerrit.mot.com/2549060 Reviewed-by: Zhengming Yao SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi-bangkk.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-bangkk.config b/arch/arm64/configs/vendor/ext_config/moto-holi-bangkk.config index 8c1c71a39861..5bf55d431a1e 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-bangkk.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-bangkk.config @@ -36,3 +36,4 @@ CONFIG_NFC=y CONFIG_SEC_NFC_PRODUCT_N5=y CONFIG_SEC_NFC=m CONFIG_SEC_NFC_IF_I2C=y +CONFIG_QUP0_SE2_AP=y From 0827c9f9a8c884a8995628eaf0b2f02aa412d6cb Mon Sep 17 00:00:00 2001 From: caoqian4 Date: Thu, 23 Mar 2023 15:11:51 +0800 Subject: [PATCH 536/698] drivers/soc/qcom/Kconfig:add config for penang5g row sm4375 add debug/factory/moto.config for penangb to build pass Change-Id: Ie8550b28fb09c724c2a0f71aec8b531f55c59912 Signed-off-by: caoqian4 Reviewed-on: https://gerrit.mot.com/2550579 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Submit-Approved: Jira Key Tested-by: Jira Key Reviewed-by: Lu Lu (cherry picked from commit 9541544542e2724692a968a2959b0b012dda6caa) Reviewed-on: https://gerrit.mot.com/2552224 Reviewed-by: Xiangpo Zhao --- .../ext_config/debug-holi-penangb.config | 28 +++++++++++++++ .../ext_config/factory-holi-penangb.config | 16 +++++++++ .../ext_config/moto-holi-penangb.config | 34 +++++++++++++++++++ drivers/soc/qcom/Kconfig | 8 +++++ 4 files changed, 86 insertions(+) create mode 100644 arch/arm64/configs/vendor/ext_config/debug-holi-penangb.config create mode 100644 arch/arm64/configs/vendor/ext_config/factory-holi-penangb.config create mode 100644 arch/arm64/configs/vendor/ext_config/moto-holi-penangb.config diff --git a/arch/arm64/configs/vendor/ext_config/debug-holi-penangb.config b/arch/arm64/configs/vendor/ext_config/debug-holi-penangb.config new file mode 100644 index 000000000000..95c989c10a1b --- /dev/null +++ b/arch/arm64/configs/vendor/ext_config/debug-holi-penangb.config @@ -0,0 +1,28 @@ +# +# Please avoid changing the Qualcomm defconfig files and use this file to +# add any Motorola-specific configuration changes that are applicable to +# userdebug, eng, and user builds. +# +# After building, a list of all of the config files that are used can be found +# at the top of: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/mapphone_defconfig +# +# The actual output of the kernel configuration system can be found at: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/.config +# +# You can check the .config file to verify that your configuration option is +# being set as expected. +# + +# CONFIG_CGROUP_DEBUG is not set +# CONFIG_CLEANCACHE is not set +# CONFIG_CMA_ALLOW_WRITE_DEBUGFS is not set +# CONFIG_CMA_DEBUG is not set +# CONFIG_PREEMPTIRQ_EVENTS is not set +# CONFIG_PREEMPT_TRACER is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_TEST_USER_COPY is not set +# CONFIG_UFSTW is not set + +# CONFIG_SLUB_DEBUG_ON is not set diff --git a/arch/arm64/configs/vendor/ext_config/factory-holi-penangb.config b/arch/arm64/configs/vendor/ext_config/factory-holi-penangb.config new file mode 100644 index 000000000000..cc7be9152bdd --- /dev/null +++ b/arch/arm64/configs/vendor/ext_config/factory-holi-penangb.config @@ -0,0 +1,16 @@ +# +# Please avoid changing the Qualcomm defconfig files and use this file to +# add any Motorola-specific configuration changes that are applicable to +# userdebug, eng, and user builds. +# +# After building, a list of all of the config files that are used can be found +# at the top of: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/mapphone_defconfig +# +# The actual output of the kernel configuration system can be found at: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/.config +# +# You can check the .config file to verify that your configuration option is +# being set as expected. +# +CONFIG_CAMERA_DISABLE_VSYNC_IRQ=y diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-penangb.config b/arch/arm64/configs/vendor/ext_config/moto-holi-penangb.config new file mode 100644 index 000000000000..15e3b9f5dbfc --- /dev/null +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-penangb.config @@ -0,0 +1,34 @@ +# +# Please avoid changing the Qualcomm defconfig files and use this file to +# add any Motorola-specific configuration changes that are applicable to +# userdebug, eng, and user builds. +# +# After building, a list of all of the config files that are used can be found +# at the top of: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/mapphone_defconfig +# +# The actual output of the kernel configuration system can be found at: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/.config +# +# You can check the .config file to verify that your configuration option is +# being set as expected. +# +CONFIG_PENANGB_DTB=y +# CONFIG_NFC_QTI_I2C is not set +CONFIG_FS_EPOLL_WAKEUP_DEBUG=y +CONFIG_ZRAM_WRITEBACK=y +# CONFIG_THERMAL_STATISTICS is not set +# CONFIG_REGULATOR_QPNP_LCDB is not set +# CONFIG_UFSTW is not set +CONFIG_CRYPTO_CHACHA20POLY1305=y +CONFIG_CAM_SENSOR_PROBE_RETRY=y +CONFIG_SND_SOC_AW87XXX=m +CONFIG_NFC_QTI_I2C=m +CONFIG_MSM_TZ_QSEE_LOG=y +CONFIG_AF_NOISE_ELIMINATION=y +# CONFIG_TOUCHSCREEN_FTS is not set +CONFIG_FELICA_MOUNT_BLOCK=y +# CONFIG_UFSFEATURE is not set +# CONFIG_UFSHPB is not set +# CONFIG_UFSTW is not set +# CONFIG_SCSI_SKHPB is not set diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index 6a28b609ffe0..fea4a4e7006c 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -118,6 +118,14 @@ config BANGKK_DTB Only include PENANG specific DTBs to limit the number that get built during kernel compilation. +config PENANGB_DTB + depends on ARCH_QCOM + default n + bool "PENANGB DTBs" + help + Only include PENANG specific DTBs to limit the number that + get built during kernel compilation. + config RHODEP_DTB depends on ARCH_QCOM default n From bad1ca0014aebb42a63c72c9c23a489df8ce3152 Mon Sep 17 00:00:00 2001 From: Shicheng Gong Date: Thu, 30 Mar 2023 11:42:42 +0800 Subject: [PATCH 537/698] arm64/config: Ban some redundant config 1.Not set config_*_blair for sm4350(Mannar). 2.Not set CONFIG_TOUCHSCREEN_NT36XXX to disturb ibiza orginal touch. 3.Not set CONFIG_SLUB_DEBUG_ON to optimize performance for userdebug build. Change-Id: Ibd17f8561e590d4d58ffcd4305758f5c6fa2e896 Signed-off-by: Shicheng Gong Reviewed-on: https://gerrit.mot.com/2559518 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xinmin Fu Reviewed-by: Hujun Liao Submit-Approved: Jira Key --- .../configs/vendor/ext_config/debug-holi-ibiza.config | 7 +++++++ .../arm64/configs/vendor/ext_config/moto-holi-ibiza.config | 1 + 2 files changed, 8 insertions(+) diff --git a/arch/arm64/configs/vendor/ext_config/debug-holi-ibiza.config b/arch/arm64/configs/vendor/ext_config/debug-holi-ibiza.config index 13f71e03c466..c207497d403c 100644 --- a/arch/arm64/configs/vendor/ext_config/debug-holi-ibiza.config +++ b/arch/arm64/configs/vendor/ext_config/debug-holi-ibiza.config @@ -23,3 +23,10 @@ # CONFIG_PROVE_LOCKING is not set # CONFIG_RCU_TORTURE_TEST is not set # CONFIG_TEST_USER_COPY is not set +# CONFIG_SM_DEBUGCC_BLAIR is not set +# CONFIG_SM_DISPCC_BLAIR is not set +# CONFIG_SM_GCC_BLAIR is not set +# CONFIG_SM_GPUCC_BLAIR is not set +# CONFIG_PINCTRL_BLAIR is not set +# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_ARCH_BLAIR is not set diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config b/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config index 8e110f97c053..4d32e413cb40 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-ibiza.config @@ -29,6 +29,7 @@ CONFIG_ZRAM_WRITEBACK=y # CONFIG_UFSHID_POC is not set # CONFIG_SCSI_SKHID is not set # CONFIG_MICRON_UFSHID is not set +# CONFIG_TOUCHSCREEN_NT36XXX is not set CONFIG_HZ_300=y CONFIG_PROCESS_RECLAIM=n CONFIG_CAM_SENSOR_PROBE_RETRY=y From be689ac94da1c32cfe80a3ce760909757d125fee Mon Sep 17 00:00:00 2001 From: "tin_qiquan.zhou_tmp" Date: Wed, 12 Apr 2023 18:08:40 +0800 Subject: [PATCH 538/698] bangkk: Secondary supply flash driver ic compatible details: 1.add CAMERA_FLASH_IIC_COMPATIBLE config 2.add "CONFIG_CAMERA_FLASH_IIC_COMPATIBLE=y" in the moto holi bangkk config Change-Id: I111a9195f510d0f10d95ddd4e43e5b838ec56f91 Signed-off-by: tin_qiquan.zhou_tmp Reviewed-on: https://gerrit.mot.com/2573838 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Reviewed-by: Reviewed-by: Reviewed-by: Reviewed-by: Zhichao Chen Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- arch/arm64/Kconfig | 6 ++++++ .../arm64/configs/vendor/ext_config/moto-holi-bangkk.config | 1 + 2 files changed, 7 insertions(+) diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index bcb062773076..7df8d2b8ef5b 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -1921,3 +1921,9 @@ config CAMERA_CCI_ADDR_SWITCH default n help Enable it to switch i2c address. + +config CAMERA_FLASH_IIC_COMPATIBLE + bool "auto select iic flash suppliers" + default n + help + Enable it, this is automatically selected flash supplers. diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-bangkk.config b/arch/arm64/configs/vendor/ext_config/moto-holi-bangkk.config index 5bf55d431a1e..aa02ba93d043 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-bangkk.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-bangkk.config @@ -37,3 +37,4 @@ CONFIG_SEC_NFC_PRODUCT_N5=y CONFIG_SEC_NFC=m CONFIG_SEC_NFC_IF_I2C=y CONFIG_QUP0_SE2_AP=y +CONFIG_CAMERA_FLASH_IIC_COMPATIBLE=y From 250751cadf055404905263146d8a9f8614f0cd67 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Tue, 21 Apr 2020 12:09:13 +0200 Subject: [PATCH 539/698] BACKPORT:sched: Provide sched_set_fifo() SCHED_FIFO (or any static priority scheduler) is a broken scheduler model; it is fundamentally incapable of resource management, the one thing an OS is actually supposed to do. It is impossible to compose static priority workloads. One cannot take two well designed and functional static priority workloads and mash them together and still expect them to work. Therefore it doesn't make sense to expose the priority field; the kernel is fundamentally incapable of setting a sensible value, it needs systems knowledge that it doesn't have. Take away sched_setschedule() / sched_setattr() from modules and replace them with: - sched_set_fifo(p); create a FIFO task (at prio 50) - sched_set_fifo_low(p); create a task higher than NORMAL, which ends up being a FIFO task at prio 1. - sched_set_normal(p, nice); (re)set the task to normal This stops the proliferation of randomly chosen, and irrelevant, FIFO priorities that dont't really mean anything anyway. The system administrator/integrator, whoever has insight into the actual system design and requirements (userspace) can set-up appropriate priorities if and when needed. Moto-CRs-Fixed:(CR) Cc: airlied@redhat.com Cc: alexander.deucher@amd.com Cc: awalls@md.metrocast.net Cc: axboe@kernel.dk Cc: broonie@kernel.org Cc: daniel.lezcano@linaro.org Cc: gregkh@linuxfoundation.org Cc: hannes@cmpxchg.org Cc: herbert@gondor.apana.org.au Cc: hverkuil@xs4all.nl Cc: john.stultz@linaro.org Cc: nico@fluxnic.net Cc: paulmck@kernel.org Cc: rafael.j.wysocki@intel.com Cc: rmk+kernel@arm.linux.org.uk Cc: sudeep.holla@arm.com Cc: tglx@linutronix.de Cc: ulf.hansson@linaro.org Cc: wim@linux-watchdog.org Signed-off-by: Peter Zijlstra (Intel) Reviewed-by: Ingo Molnar Tested-by: Paul E. McKenney Change-Id: I499a5c22a1d7bd561c3f73a90ed3af1162e79dcb Signed-off-by: William Liu Reviewed-on: https://gerrit.mot.com/2576330 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- include/linux/sched.h | 3 +++ kernel/sched/core.c | 45 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/include/linux/sched.h b/include/linux/sched.h index 74fe1d4e0807..e18e03b541b2 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1814,6 +1814,9 @@ extern int idle_cpu(int cpu); extern int available_idle_cpu(int cpu); extern int sched_setscheduler(struct task_struct *, int, const struct sched_param *); extern int sched_setscheduler_nocheck(struct task_struct *, int, const struct sched_param *); +extern void sched_set_fifo(struct task_struct *p); +extern void sched_set_fifo_low(struct task_struct *p); +extern void sched_set_normal(struct task_struct *p, int nice); extern int sched_setattr(struct task_struct *, const struct sched_attr *); extern int sched_setattr_nocheck(struct task_struct *, const struct sched_attr *); extern struct task_struct *idle_task(int cpu); diff --git a/kernel/sched/core.c b/kernel/sched/core.c index f45a1020fcd0..82c12f4d588d 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -5380,6 +5380,51 @@ int sched_setscheduler_nocheck(struct task_struct *p, int policy, } EXPORT_SYMBOL_GPL(sched_setscheduler_nocheck); +/* + * SCHED_FIFO is a broken scheduler model; that is, it is fundamentally + * incapable of resource management, which is the one thing an OS really should + * be doing. + * + * This is of course the reason it is limited to privileged users only. + * + * Worse still; it is fundamentally impossible to compose static priority + * workloads. You cannot take two correctly working static prio workloads + * and smash them together and still expect them to work. + * + * For this reason 'all' FIFO tasks the kernel creates are basically at: + * + * MAX_RT_PRIO / 2 + * + * The administrator _MUST_ configure the system, the kernel simply doesn't + * know enough information to make a sensible choice. + */ +void sched_set_fifo(struct task_struct *p) +{ + struct sched_param sp = { .sched_priority = MAX_RT_PRIO / 2 }; + WARN_ON_ONCE(sched_setscheduler_nocheck(p, SCHED_FIFO, &sp) != 0); +} +EXPORT_SYMBOL_GPL(sched_set_fifo); + +/* + * For when you don't much care about FIFO, but want to be above SCHED_NORMAL. + */ +void sched_set_fifo_low(struct task_struct *p) +{ + struct sched_param sp = { .sched_priority = 1 }; + WARN_ON_ONCE(sched_setscheduler_nocheck(p, SCHED_FIFO, &sp) != 0); +} +EXPORT_SYMBOL_GPL(sched_set_fifo_low); + +void sched_set_normal(struct task_struct *p, int nice) +{ + struct sched_attr attr = { + .sched_policy = SCHED_NORMAL, + .sched_nice = nice, + }; + WARN_ON_ONCE(sched_setattr_nocheck(p, &attr) != 0); +} +EXPORT_SYMBOL_GPL(sched_set_normal); + static int do_sched_setscheduler(pid_t pid, int policy, struct sched_param __user *param) { From 8199049168939354150faeeed0bb2d788bebddb7 Mon Sep 17 00:00:00 2001 From: Sandeep Dhavale Date: Wed, 8 Feb 2023 17:33:22 +0800 Subject: [PATCH 540/698] BACKPORT:erofs: add per-cpu threads for decompression as an option Using per-cpu thread pool we can reduce the scheduling latency compared to workqueue implementation. With this patch scheduling latency and variation is reduced as per-cpu threads are high priority kthread_workers. The results were evaluated on arm64 Android devices running 5.10 kernel. The table below shows resulting improvements of total scheduling latency for the same app launch benchmark runs with 50 iterations. Scheduling latency is the latency between when the task (workqueue kworker vs kthread_worker) became eligible to run to when it actually started running. +-------------------------+-----------+----------------+---------+ | | workqueue | kthread_worker | diff | +-------------------------+-----------+----------------+---------+ | Average (us) | 15253 | 2914 | -80.89% | | Median (us) | 14001 | 2912 | -79.20% | | Minimum (us) | 3117 | 1027 | -67.05% | | Maximum (us) | 30170 | 3805 | -87.39% | | Standard deviation (us) | 7166 | 359 | | +-------------------------+-----------+----------------+---------+ Background: Boot times and cold app launch benchmarks are very important to the Android ecosystem as they directly translate to responsiveness from user point of view. While EROFS provides a lot of important features l(CR) space savings, we saw some performance penalty in cold app launch benchmarks in few scenarios. Analysis showed that the significant variance was coming from the scheduling cost while decompression cost was more or less the same. Having per-cpu thread pool we can see from the above table that this variation is reduced by ~80% on average. This problem was discussed at LPC 2022. Link to LPC 2022 slides and talk at [1] Moto-CRs-Fixed:(CR) [1] https://lpc.events/event/16/contributions/1338/ [ Gao Xiang: At least, we have to add this until WQ_UNBOUND workqueue issue [2] on many arm64 devices is resolved. ] [2] https://lore.kernel.org/r/CAJkfWY490-m6wNubkxiTPsW59sfsQs37Wey279LmiRxKt7aQYg@mail.gmail.com Change-Id: Idd8f0760f29d58356f5f1ea93c92eb57680686d5 Signed-off-by: Sandeep Dhavale Signed-off-by: Gao Xiang Signed-off-by: William Liu Reviewed-on: https://gerrit.mot.com/2576331 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- fs/erofs/Kconfig | 18 +++++ fs/erofs/zdata.c | 188 ++++++++++++++++++++++++++++++++++++++++++----- fs/erofs/zdata.h | 2 + 3 files changed, 190 insertions(+), 18 deletions(-) diff --git a/fs/erofs/Kconfig b/fs/erofs/Kconfig index 858b3339f381..3adc06ad950a 100644 --- a/fs/erofs/Kconfig +++ b/fs/erofs/Kconfig @@ -76,3 +76,21 @@ config EROFS_FS_ZIP If you don't want to enable compression feature, say N. + +config EROFS_FS_PCPU_KTHREAD + bool "EROFS per-cpu decompression kthread workers" + depends on EROFS_FS_ZIP + help + Saying Y here enables per-CPU kthread workers pool to carry out + async decompression for low latencies on some architectures. + + If unsure, say N. + +config EROFS_FS_PCPU_KTHREAD_HIPRI + bool "EROFS high priority per-CPU kthread workers" + depends on EROFS_FS_ZIP && EROFS_FS_PCPU_KTHREAD + help + This permits EROFS to configure per-CPU kthread workers to run + at higher priority. + + If unsure, say N. \ No newline at end of file diff --git a/fs/erofs/zdata.c b/fs/erofs/zdata.c index 15e03d0f60a0..1bfda6b57a0d 100644 --- a/fs/erofs/zdata.c +++ b/fs/erofs/zdata.c @@ -7,7 +7,7 @@ #include "zdata.h" #include "compress.h" #include - +#include #include /* @@ -125,24 +125,130 @@ typedef tagptr1_t compressed_page_t; static struct workqueue_struct *z_erofs_workqueue __read_mostly; -void z_erofs_exit_zip_subsystem(void) +#ifdef CONFIG_EROFS_FS_PCPU_KTHREAD +static struct kthread_worker __rcu **z_erofs_pcpu_workers; + +static void erofs_destroy_percpu_workers(void) { - destroy_workqueue(z_erofs_workqueue); - z_erofs_destroy_pcluster_pool(); + struct kthread_worker *worker; + unsigned int cpu; + + for_each_possible_cpu(cpu) { + worker = rcu_dereference_protected( + z_erofs_pcpu_workers[cpu], 1); + rcu_assign_pointer(z_erofs_pcpu_workers[cpu], NULL); + if (worker) + kthread_destroy_worker(worker); + } + kfree(z_erofs_pcpu_workers); } -static inline int z_erofs_init_workqueue(void) +static struct kthread_worker *erofs_init_percpu_worker(int cpu) { - const unsigned int onlinecpus = num_possible_cpus(); - /* - * no need to spawn too many threads, limiting threads could minimum - * scheduling overhead, perhaps per-CPU threads should be better? - */ - z_erofs_workqueue = alloc_workqueue("erofs_unzipd", - WQ_UNBOUND | WQ_HIGHPRI, - onlinecpus + onlinecpus / 4); - return z_erofs_workqueue ? 0 : -ENOMEM; + struct kthread_worker *worker = + kthread_create_worker_on_cpu(cpu, 0, "erofs_worker/%u", cpu); + + if (IS_ERR(worker)) + return worker; + if (IS_ENABLED(CONFIG_EROFS_FS_PCPU_KTHREAD_HIPRI)) + sched_set_fifo_low(worker->task); + else + sched_set_normal(worker->task, 0); + + return worker; +} + +static int erofs_init_percpu_workers(void) +{ + struct kthread_worker *worker; + unsigned int cpu; + + z_erofs_pcpu_workers = kcalloc(num_possible_cpus(), + sizeof(struct kthread_worker *), GFP_ATOMIC); + if (!z_erofs_pcpu_workers) + return -ENOMEM; + + for_each_online_cpu(cpu) { /* could miss cpu{off,on}line? */ + worker = erofs_init_percpu_worker(cpu); + if (!IS_ERR(worker)) + rcu_assign_pointer(z_erofs_pcpu_workers[cpu], worker); + } + return 0; +} +#else +static inline void erofs_destroy_percpu_workers(void) {} +static inline int erofs_init_percpu_workers(void) { return 0; } +#endif + +#if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_EROFS_FS_PCPU_KTHREAD) +static DEFINE_SPINLOCK(z_erofs_pcpu_worker_lock); +static enum cpuhp_state erofs_cpuhp_state; + +static int erofs_cpu_online(unsigned int cpu) +{ + struct kthread_worker *worker, *old; + + worker = erofs_init_percpu_worker(cpu); + if (IS_ERR(worker)) + return PTR_ERR(worker); + + spin_lock(&z_erofs_pcpu_worker_lock); + old = rcu_dereference_protected(z_erofs_pcpu_workers[cpu], + lockdep_is_held(&z_erofs_pcpu_worker_lock)); + if (!old) + rcu_assign_pointer(z_erofs_pcpu_workers[cpu], worker); + spin_unlock(&z_erofs_pcpu_worker_lock); + if (old) + kthread_destroy_worker(worker); + return 0; +} + +static int erofs_cpu_offline(unsigned int cpu) +{ + struct kthread_worker *worker; + + spin_lock(&z_erofs_pcpu_worker_lock); + worker = rcu_dereference_protected(z_erofs_pcpu_workers[cpu], + lockdep_is_held(&z_erofs_pcpu_worker_lock)); + rcu_assign_pointer(z_erofs_pcpu_workers[cpu], NULL); + spin_unlock(&z_erofs_pcpu_worker_lock); + + synchronize_rcu(); + if (worker) + kthread_destroy_worker(worker); + return 0; +} + +static int erofs_cpu_hotplug_init(void) +{ + int state; + + state = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN, + "fs/erofs:online", erofs_cpu_online, erofs_cpu_offline); + if (state < 0) + return state; + + erofs_cpuhp_state = state; + return 0; +} + +static void erofs_cpu_hotplug_destroy(void) +{ + if (erofs_cpuhp_state) + cpuhp_remove_state_nocalls(erofs_cpuhp_state); +} +#else /* !CONFIG_HOTPLUG_CPU || !CONFIG_EROFS_FS_PCPU_KTHREAD */ +static inline int erofs_cpu_hotplug_init(void) { return 0; } +static inline void erofs_cpu_hotplug_destroy(void) {} +#endif + +void z_erofs_exit_zip_subsystem(void) +{ + erofs_cpu_hotplug_destroy(); + erofs_destroy_percpu_workers(); + destroy_workqueue(z_erofs_workqueue); + z_erofs_destroy_pcluster_pool(); } int __init z_erofs_init_zip_subsystem(void) @@ -150,10 +256,30 @@ int __init z_erofs_init_zip_subsystem(void) int err = z_erofs_create_pcluster_pool(); if (err) - return err; - err = z_erofs_init_workqueue(); + goto out_error_pcluster_pool; + + z_erofs_workqueue = alloc_workqueue("erofs_worker", + WQ_UNBOUND | WQ_HIGHPRI, num_possible_cpus()); + if (!z_erofs_workqueue) + goto out_error_workqueue_init; + + err = erofs_init_percpu_workers(); if (err) - z_erofs_destroy_pcluster_pool(); + goto out_error_pcpu_worker; + + err = erofs_cpu_hotplug_init(); + if (err < 0) + goto out_error_cpuhp_init; + return err; + +out_error_cpuhp_init: + erofs_destroy_percpu_workers(); +out_error_pcpu_worker: + destroy_workqueue(z_erofs_workqueue); +out_error_workqueue_init: + z_erofs_destroy_pcluster_pool(); +out_error_pcluster_pool: + return err; } @@ -784,6 +910,12 @@ err_out: } static void z_erofs_decompressqueue_work(struct work_struct *work); +#ifdef CONFIG_EROFS_FS_PCPU_KTHREAD +static void z_erofs_decompressqueue_kthread_work(struct kthread_work *work) +{ + z_erofs_decompressqueue_work((struct work_struct *)work); +} +#endif static void z_erofs_decompress_kickoff(struct z_erofs_decompressqueue *io, bool sync, int bios) { @@ -804,7 +936,22 @@ static void z_erofs_decompress_kickoff(struct z_erofs_decompressqueue *io, return; /* Use workqueue and sync decompression for atomic contexts only */ if (in_atomic() || irqs_disabled()) { +#ifdef CONFIG_EROFS_FS_PCPU_KTHREAD + struct kthread_worker *worker; + + rcu_read_lock(); + worker = rcu_dereference( + z_erofs_pcpu_workers[raw_smp_processor_id()]); + if (!worker) { + INIT_WORK(&io->u.work, z_erofs_decompressqueue_work); + queue_work(z_erofs_workqueue, &io->u.work); + } else { + kthread_queue_work(worker, &io->u.kthread_work); + } + rcu_read_unlock(); +#else queue_work(z_erofs_workqueue, &io->u.work); +#endif sbi->ctx.readahead_sync_decompress = true; return; } @@ -1212,7 +1359,12 @@ jobqueue_init(struct super_block *sb, *fg = true; goto fg_out; } +#ifdef CONFIG_EROFS_FS_PCPU_KTHREAD + kthread_init_work(&q->u.kthread_work, + z_erofs_decompressqueue_kthread_work); +#else INIT_WORK(&q->u.work, z_erofs_decompressqueue_work); +#endif } else { fg_out: q = fgq; @@ -1353,7 +1505,7 @@ submit_bio_retry: /* * although background is preferred, no one is pending for submission. - * don't issue workqueue for decompression but drop it directly instead. + * don't issue decompression but drop it directly instead. */ if (!*force_fg && !nr_bios) { kvfree(q[JQ_SUBMIT]); diff --git a/fs/erofs/zdata.h b/fs/erofs/zdata.h index 942ee69dff6a..fd0fa55b00f4 100644 --- a/fs/erofs/zdata.h +++ b/fs/erofs/zdata.h @@ -7,6 +7,7 @@ #ifndef __EROFS_FS_ZDATA_H #define __EROFS_FS_ZDATA_H +#include #include "internal.h" #include "zpvec.h" @@ -92,6 +93,7 @@ struct z_erofs_decompressqueue { union { wait_queue_head_t wait; struct work_struct work; + struct kthread_work kthread_work; } u; }; From 5e13d881af5b7eac1cd6d1d1980f3da1a2805780 Mon Sep 17 00:00:00 2001 From: William Liu Date: Fri, 14 Apr 2023 13:26:46 +0800 Subject: [PATCH 541/698] config:Enable EROFS PCPU performance improvement Enable the PCPU erofs performance Improvement option on penang Change-Id: I4637e998fb997938783588df5618b7017e2a1f76 Signed-off-by: William Liu Reviewed-on: https://gerrit.mot.com/2576332 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi-penang.config | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-penang.config b/arch/arm64/configs/vendor/ext_config/moto-holi-penang.config index c4315a1195cf..9059e025d4c2 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-penang.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-penang.config @@ -32,3 +32,5 @@ CONFIG_FELICA_MOUNT_BLOCK=y # CONFIG_UFSHPB is not set # CONFIG_UFSTW is not set # CONFIG_SCSI_SKHPB is not set +CONFIG_EROFS_FS_PCPU_KTHREAD=y +CONFIG_EROFS_FS_PCPU_KTHREAD_HIPRI=y From 34486c7365d32ca7ccae52814292e995d7ce0f4b Mon Sep 17 00:00:00 2001 From: William Liu Date: Fri, 14 Apr 2023 13:29:28 +0800 Subject: [PATCH 542/698] config:Enable EROFS PCPU performance improvement Enable the PCPU erofs performance Improvement option on bangkk Change-Id: Ib16e2b65f4a2a71d5c8983595844bf6ae76f3fed Signed-off-by: William Liu Reviewed-on: https://gerrit.mot.com/2576333 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi-bangkk.config | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-bangkk.config b/arch/arm64/configs/vendor/ext_config/moto-holi-bangkk.config index aa02ba93d043..9c9a7fa94347 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-bangkk.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-bangkk.config @@ -38,3 +38,5 @@ CONFIG_SEC_NFC=m CONFIG_SEC_NFC_IF_I2C=y CONFIG_QUP0_SE2_AP=y CONFIG_CAMERA_FLASH_IIC_COMPATIBLE=y +CONFIG_EROFS_FS_PCPU_KTHREAD=y +CONFIG_EROFS_FS_PCPU_KTHREAD_HIPRI=y From 45482ab6d38d38a3167e9b8bd48824cee7890263 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 16 Feb 2023 15:13:04 +0300 Subject: [PATCH 543/698] UPSTREAM: erofs: fix an error code in z_erofs_init_zip_subsystem() Moto-CRs-Fixed:(CR) Return -ENOMEM if alloc_workqueue() fails. Don't return success. Fixes: d8a650adf429 ("erofs: add per-cpu threads for decompression as an option") Bug: 271636421 Tests: launch_cvd Change-Id: I49dcf8094655db47ac71ae8967b5402373fc7adc Signed-off-by: Dan Carpenter Reviewed-by: Gao Xiang Link: https://lore.kernel.org/r/Y+4d0FRsUq8jPoOu@kili Signed-off-by: Gao Xiang (cherry picked from commit 8d1b80a79452630f157bf634ae9cfcd9f4eed161) Signed-off-by: Sandeep Dhavale (cherry picked from commit 5004cc655730355d681b333ff5eafd62a4ee02f2) Reviewed-on: https://gerrit.mot.com/2579833 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- fs/erofs/zdata.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fs/erofs/zdata.c b/fs/erofs/zdata.c index 1bfda6b57a0d..f54710a05b4d 100644 --- a/fs/erofs/zdata.c +++ b/fs/erofs/zdata.c @@ -260,8 +260,10 @@ int __init z_erofs_init_zip_subsystem(void) z_erofs_workqueue = alloc_workqueue("erofs_worker", WQ_UNBOUND | WQ_HIGHPRI, num_possible_cpus()); - if (!z_erofs_workqueue) + if (!z_erofs_workqueue) { + err = -ENOMEM; goto out_error_workqueue_init; + } err = erofs_init_percpu_workers(); if (err) From 5d7abefcf84033dfa87717103e38e1eae44d8649 Mon Sep 17 00:00:00 2001 From: Jia He Date: Fri, 11 Oct 2019 22:09:36 +0800 Subject: [PATCH 544/698] BACKPORT: arm64: cpufeature: introduce helper cpu_has_hw_af() We unconditionally set the HW_AFDBM capability and only enable it on CPUs which really have the feature. But sometimes we need to know whether this cpu has the capability of HW AF. So decouple AF from DBM by a new helper cpu_has_hw_af(). If later we noticed a potential performance issue on this path, we can turn it into a static label as with other CPU features. Moto-CRs-Fixed:(CR) Link: https://lore.kernel.org/r/20191011140939.6115-2-justin.he@arm.com/ Change-Id: Ifed339bfe6c86ada6e45eddefa6aa010a7fe465d Signed-off-by: Jia He Suggested-by: Suzuki Poulose Reviewed-by: Catalin Marinas Signed-off-by: Catalin Marinas (cherry picked from commit 47d7b15b88f96a90694cfc607d0717d62dff6c45) Bug: 261052246 Signed-off-by: Kalesh Singh Reviewed-on: https://gerrit.mot.com/2491776 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- arch/arm64/include/asm/cpufeature.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h index 95f661f1933f..74bc372ec016 100644 --- a/arch/arm64/include/asm/cpufeature.h +++ b/arch/arm64/include/asm/cpufeature.h @@ -707,6 +707,19 @@ static inline u32 id_aa64mmfr0_parange_to_phys_shift(int parange) extern bool cpu_has_amu_feat(int cpu); #endif +/* Check whether hardware update of the Access flag is supported */ +static inline bool cpu_has_hw_af(void) +{ + u64 mmfr1; + + if (!IS_ENABLED(CONFIG_ARM64_HW_AFDBM)) + return false; + + mmfr1 = read_cpuid(ID_AA64MMFR1_EL1); + return cpuid_feature_extract_unsigned_field(mmfr1, + ID_AA64MMFR1_HADBS_SHIFT); +} + #endif /* __ASSEMBLY__ */ #endif From adb8e3c5c0fa3cccf0ae11fe344d5c6bb26d6a57 Mon Sep 17 00:00:00 2001 From: Jia He Date: Fri, 11 Oct 2019 22:09:37 +0800 Subject: [PATCH 545/698] UPSTREAM: arm64: mm: implement arch_faults_on_old_pte() on arm64 On arm64 without hardware Access Flag, copying from user will fail because the pte is old and cannot be marked young. So we always end up with zeroed page after fork() + CoW for pfn mappings. We don't always have a hardware-managed Access Flag on arm64. Hence implement arch_faults_on_old_pte on arm64 to indicate that it might cause page fault when accessing old pte. Moto-CRs-Fixed:(CR) Link: https://lore.kernel.org/r/20191011140939.6115-3-justin.he@arm.com/ Change-Id: Ica230a882941cb17a1acdd6c6c9f3ec1b3f494b3 Signed-off-by: Jia He Reviewed-by: Catalin Marinas Signed-off-by: Catalin Marinas (cherry picked from commit 6af31226d0394691f5562eca0134262bb935fa9c) Bug: 261052246 Signed-off-by: Kalesh Singh Reviewed-on: https://gerrit.mot.com/2491777 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- arch/arm64/include/asm/pgtable.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h index 9197acde622a..30588e12752b 100644 --- a/arch/arm64/include/asm/pgtable.h +++ b/arch/arm64/include/asm/pgtable.h @@ -886,6 +886,20 @@ static inline void update_mmu_cache(struct vm_area_struct *vma, #define phys_to_ttbr(addr) (addr) #endif +/* + * On arm64 without hardware Access Flag, copying from user will fail because + * the pte is old and cannot be marked young. So we always end up with zeroed + * page after fork() + CoW for pfn mappings. We don't always have a + * hardware-managed access flag on arm64. + */ +static inline bool arch_faults_on_old_pte(void) +{ + WARN_ON(preemptible()); + + return !cpu_has_hw_af(); +} +#define arch_faults_on_old_pte arch_faults_on_old_pte + #endif /* !__ASSEMBLY__ */ #endif /* __ASM_PGTABLE_H */ From 0389a60f62b93e32dd5fea615fd6ce556f79bcb6 Mon Sep 17 00:00:00 2001 From: Jia He Date: Fri, 11 Oct 2019 22:09:38 +0800 Subject: [PATCH 546/698] UPSTREAM: x86/mm: implement arch_faults_on_old_pte() stub on x86 arch_faults_on_old_pte is a helper to indicate that it might cause page fault when accessing old pte. But on x86, there is feature to setting pte access flag by hardware. Hence implement an overriding stub which always returns false. Moto-CRs-Fixed:(CR) Link: https://lore.kernel.org/r/20191011140939.6115-4-justin.he@arm.com/ Change-Id: I69cd5568e648cdf098269958de9e8bcedd603df4 Signed-off-by: Jia He Suggested-by: Will Deacon Signed-off-by: Catalin Marinas (cherry picked from commit f2c4e5970cece75a895fcc45f0cd66b5a5ec0819) Bug: 261052246 Signed-off-by: Kalesh Singh Reviewed-on: https://gerrit.mot.com/2491778 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- arch/x86/include/asm/pgtable.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h index 1ae7c20f5469..cc64fbb33f66 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h @@ -1467,6 +1467,12 @@ static inline bool arch_has_pfn_modify_check(void) return boot_cpu_has_bug(X86_BUG_L1TF); } +#define arch_faults_on_old_pte arch_faults_on_old_pte +static inline bool arch_faults_on_old_pte(void) +{ + return false; +} + #include #endif /* __ASSEMBLY__ */ From 502d61e3b87a8b8014679d6b522b8ccef91fd0b2 Mon Sep 17 00:00:00 2001 From: Steven Price Date: Mon, 3 Feb 2020 17:35:01 -0800 Subject: [PATCH 547/698] UPSTREAM: mm: add generic p?d_leaf() macros Patch series "Generic page walk and ptdump", v17. Many architectures current have a debugfs file for dumping the kernel page tables. Currently each architecture has to implement custom functions for this because the details of walking the page tables used by the kernel are different between architectures. This series extends the capabilities of walk_page_range() so that it can deal with the page tables of the kernel (which have no VMAs and can contain larger huge pages than exist for user space). A generic PTDUMP implementation is the implemented making use of the new functionality of walk_page_range() and finally arm64 and x86 are switch to using it, removing the custom table walkers. To enable a generic page table walker to walk the unusual mappings of the kernel we need to implement a set of functions which let us know when the walker has reached the leaf entry. After a suggestion from Will Deacon I've chosen the name p?d_leaf() as this (hopefully) describes the purpose (and is a new name so has no historic baggage). Some architectures have p?d_large macros but this is easily confused with "large pages". This series ends with a generic PTDUMP implemention for arm64 and x86. Mostly this is a clean up and there should be very little functional change. The exceptions are: * arm64 PTDUMP debugfs now displays pages which aren't present (patch 22). * arm64 has the ability to efficiently process KASAN pages (which previously only x86 implemented). This means that the combination of KASAN and DEBUG_WX is now useable. This patch (of 23): Exposing the pud/pgd levels of the page tables to walk_page_range() means we may come across the exotic large mappings that come with large areas of contiguous memory (such as the kernel's linear map). For architectures that don't provide all p?d_leaf() macros, provide generic do nothing default that are suitable where there cannot be leaf pages at that level. Futher patches will add implementations for individual architectures. The name p?d_leaf() is chosen to minimize the confusion with existing uses of "large" pages and "huge" pages which do not necessary mean that the entry is a leaf (for example it may be a set of contiguous entries that only take 1 TLB slot). For the purpose of walking the page tables we don't need to know how it will be represented in the TLB, but we do need to know for sure if it is a leaf of the tree. Moto-CRs-Fixed:(CR) Link: http://lkml.kernel.org/r/20191218162402.45610-2-steven.price@arm.com Change-Id: Ibc89e157616134076969b8daa9e9ce104d6c0900 Signed-off-by: Steven Price Acked-by: Mark Rutland Cc: Perry Lutomirski Cc: Ard Biesheuvel Cc: Arnd Bergmann Cc: Borislav Petkov Cc: Catalin Marinas Cc: Dave Hansen Cc: Ingo Molnar Cc: James Morse Cc: Jerome Glisse Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Will Deacon Cc: "H. Peter Anvin" Cc: "Liang, Kan" Cc: Albert Ou Cc: Alexandre Ghiti Cc: Benjamin Herrenschmidt Cc: Christian Borntraeger Cc: David S. Miller Cc: He(CR) Carstens Cc: James Hogan Cc: Michael Ellerman Cc: Paul Racer_turbo Cc: Paul Mackerras Cc: Paul Walmsley Cc: Ralf Baechle Cc: Russell King Cc: Vasily Gorb(CR) Cc: Vineet Gupta Cc: Zong Li Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds (cherry picked from commit 93fab1b22ef7c4abcbc760ce4432762b02e7f3d1) Bug: 261052246 Signed-off-by: Kalesh Singh Reviewed-on: https://gerrit.mot.com/2491779 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- include/asm-generic/pgtable.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h index 15f77361eb13..f5895a174b3b 100644 --- a/include/asm-generic/pgtable.h +++ b/include/asm-generic/pgtable.h @@ -1206,4 +1206,24 @@ static inline bool arch_has_pfn_modify_check(void) #define mm_pmd_folded(mm) __is_defined(__PAGETABLE_PMD_FOLDED) #endif +/* + * p?d_leaf() - true if this entry is a final mapping to a physical address. + * This differs from p?d_huge() by the fact that they are always available (if + * the architecture supports large pages at the appropriate level) even + * if CONFIG_HUGETLB_PAGE is not defined. + * Only meaningful when called on a valid entry. + */ +#ifndef pgd_leaf +#define pgd_leaf(x) 0 +#endif +#ifndef p4d_leaf +#define p4d_leaf(x) 0 +#endif +#ifndef pud_leaf +#define pud_leaf(x) 0 +#endif +#ifndef pmd_leaf +#define pmd_leaf(x) 0 +#endif + #endif /* _ASM_GENERIC_PGTABLE_H */ From 0a3f0ce826a274443a0d63eecf9fd7c2546478a0 Mon Sep 17 00:00:00 2001 From: Steven Price Date: Mon, 3 Feb 2020 17:35:14 -0800 Subject: [PATCH 548/698] UPSTREAM: arm64: mm: add p?d_leaf() definitions walk_page_range() is going to be allowed to walk page tables other than those of user space. For this it needs to know when it has reached a 'leaf' entry in the page tables. This information will be provided by the p?d_leaf() functions/macros. For arm64, we already have p?d_sect() macros which we can reuse for p?d_leaf(). pud_sect() is defined as a dummy function when CONFIG_PGTABLE_LEVELS < 3 or CONFIG_ARM64_64K_PAGES is defined. However when the kernel is configured this way then architecturally it isn't allowed to have a large page at this level, and any code using these page walking macros is implicitly relying on the page size/number of levels being the same as the kernel. So it is safe to reuse this for p?d_leaf() as it is an architectural restriction. Moto-CRs-Fixed:(CR) Link: http://lkml.kernel.org/r/20191218162402.45610-5-steven.price@arm.com Change-Id: Ic031474949c96e9d3d191dd93f232cc20603032d Signed-off-by: Steven Price Acked-by: Catalin Marinas Cc: Catalin Marinas Cc: Will Deacon Cc: Albert Ou Cc: Alexandre Ghiti Cc: Perry Lutomirski Cc: Ard Biesheuvel Cc: Arnd Bergmann Cc: Benjamin Herrenschmidt Cc: Borislav Petkov Cc: Christian Borntraeger Cc: Dave Hansen Cc: David S. Miller Cc: He(CR) Carstens Cc: "H. Peter Anvin" Cc: Ingo Molnar Cc: James Hogan Cc: James Morse Cc: Jerome Glisse Cc: "Liang, Kan" Cc: Mark Rutland Cc: Michael Ellerman Cc: Paul Racer_turbo Cc: Paul Mackerras Cc: Paul Walmsley Cc: Peter Zijlstra Cc: Ralf Baechle Cc: Russell King Cc: Thomas Gleixner Cc: Vasily Gorb(CR) Cc: Vineet Gupta Cc: Zong Li Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds (cherry picked from commit 8aa82df3c123129025a364d8f823929cc488b834) Bug: 261052246 Signed-off-by: Kalesh Singh Reviewed-on: https://gerrit.mot.com/2491780 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- arch/arm64/include/asm/pgtable.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h index 30588e12752b..d3c05457377b 100644 --- a/arch/arm64/include/asm/pgtable.h +++ b/arch/arm64/include/asm/pgtable.h @@ -455,6 +455,7 @@ extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, PMD_TYPE_TABLE) #define pmd_sect(pmd) ((pmd_val(pmd) & PMD_TYPE_MASK) == \ PMD_TYPE_SECT) +#define pmd_leaf(pmd) pmd_sect(pmd) #if defined(CONFIG_ARM64_64K_PAGES) || CONFIG_PGTABLE_LEVELS < 3 static inline bool pud_sect(pud_t pud) { return false; } @@ -546,6 +547,7 @@ static inline unsigned long pmd_page_vaddr(pmd_t pmd) #define pud_none(pud) (!pud_val(pud)) #define pud_bad(pud) (!(pud_val(pud) & PUD_TABLE_BIT)) #define pud_present(pud) pte_present(pud_pte(pud)) +#define pud_leaf(pud) pud_sect(pud) #define pud_valid(pud) pte_valid(pud_pte(pud)) static inline void set_pud(pud_t *pudp, pud_t pud) From b84c1a93a8782ebcec5e02aaa6d4c87de8675f3f Mon Sep 17 00:00:00 2001 From: Muchun Song Date: Fri, 22 Apr 2022 14:00:33 +0800 Subject: [PATCH 549/698] BACKPORT: arm64: mm: fix p?d_leaf() The pmd_leaf() is used to test a leaf mapped PMD, however, it misses the PROT_NONE mapped PMD on arm64. Fix it. A real world issue [1] caused by this was reported by Qian Cai. Also fix pud_leaf(). Moto-CRs-Fixed:(CR) Link: https://patchwork.kernel.org/comment/24798260/ [1] Fixes: 8aa82df3c123 ("arm64: mm: add p?d_leaf() definitions") Reported-by: Qian Cai Change-Id: I3b632d653c4e00a8825e1cc626d935ca5cbac194 Signed-off-by: Muchun Song Link: https://lore.kernel.org/r/20220422060033.48711-1-songmuchun@bytedance.com Signed-off-by: Will Deacon (cherry picked from commit 23bc8f69f0eceecbb87c3801d2e48827d2dca92b) Bug: 261052246 Signed-off-by: Kalesh Singh Reviewed-on: https://gerrit.mot.com/2491781 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- arch/arm64/include/asm/pgtable.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h index d3c05457377b..4f48704996dc 100644 --- a/arch/arm64/include/asm/pgtable.h +++ b/arch/arm64/include/asm/pgtable.h @@ -455,7 +455,7 @@ extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, PMD_TYPE_TABLE) #define pmd_sect(pmd) ((pmd_val(pmd) & PMD_TYPE_MASK) == \ PMD_TYPE_SECT) -#define pmd_leaf(pmd) pmd_sect(pmd) +#define pmd_leaf(pmd) (pmd_present(pmd) && !pmd_table(pmd)) #if defined(CONFIG_ARM64_64K_PAGES) || CONFIG_PGTABLE_LEVELS < 3 static inline bool pud_sect(pud_t pud) { return false; } @@ -547,7 +547,7 @@ static inline unsigned long pmd_page_vaddr(pmd_t pmd) #define pud_none(pud) (!pud_val(pud)) #define pud_bad(pud) (!(pud_val(pud) & PUD_TABLE_BIT)) #define pud_present(pud) pte_present(pud_pte(pud)) -#define pud_leaf(pud) pud_sect(pud) +#define pud_leaf(pud) (pud_present(pud) && !pud_table(pud)) #define pud_valid(pud) pte_valid(pud_pte(pud)) static inline void set_pud(pud_t *pudp, pud_t pud) From 76f9f031cb4b1424ffd1fe8c828d540b8870279f Mon Sep 17 00:00:00 2001 From: Steven Price Date: Mon, 3 Feb 2020 17:35:41 -0800 Subject: [PATCH 550/698] UPSTREAM: x86: mm: add p?d_leaf() definitions walk_page_range() is going to be allowed to walk page tables other than those of user space. For this it needs to know when it has reached a 'leaf' entry in the page tables. This information is provided by the p?d_leaf() functions/macros. For x86 we already have p?d_large() functions, so simply add macros to provide the generic p?d_leaf() names for the generic code. Moto-CRs-Fixed:(CR) Link: http://lkml.kernel.org/r/20191218162402.45610-11-steven.price@arm.com Change-Id: Ie5684899f3e89133422324fa2ce12d9f0740fee9 Signed-off-by: Steven Price Cc: Albert Ou Cc: Alexandre Ghiti Cc: Perry Lutomirski Cc: Ard Biesheuvel Cc: Arnd Bergmann Cc: Benjamin Herrenschmidt Cc: Borislav Petkov Cc: Catalin Marinas Cc: Christian Borntraeger Cc: Dave Hansen Cc: David S. Miller Cc: He(CR) Carstens Cc: "H. Peter Anvin" Cc: Ingo Molnar Cc: James Hogan Cc: James Morse Cc: Jerome Glisse Cc: "Liang, Kan" Cc: Mark Rutland Cc: Michael Ellerman Cc: Paul Racer_turbo Cc: Paul Mackerras Cc: Paul Walmsley Cc: Peter Zijlstra Cc: Ralf Baechle Cc: Russell King Cc: Thomas Gleixner Cc: Vasily Gorb(CR) Cc: Vineet Gupta Cc: Will Deacon Cc: Zong Li Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds (cherry picked from commit 757b2a4ab560b84d1859cfdfb9c7489af4ef5fd6) Bug: 261052246 Signed-off-by: Kalesh Singh Reviewed-on: https://gerrit.mot.com/2491782 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- arch/x86/include/asm/pgtable.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h index cc64fbb33f66..d711bc431a2c 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h @@ -239,6 +239,7 @@ static inline unsigned long pgd_pfn(pgd_t pgd) return (pgd_val(pgd) & PTE_PFN_MASK) >> PAGE_SHIFT; } +#define p4d_leaf p4d_large static inline int p4d_large(p4d_t p4d) { /* No 512 GiB pages yet */ @@ -247,6 +248,7 @@ static inline int p4d_large(p4d_t p4d) #define pte_page(pte) pfn_to_page(pte_pfn(pte)) +#define pmd_leaf pmd_large static inline int pmd_large(pmd_t pte) { return pmd_flags(pte) & _PAGE_PSE; @@ -878,6 +880,7 @@ static inline pmd_t *pmd_offset(pud_t *pud, unsigned long address) return (pmd_t *)pud_page_vaddr(*pud) + pmd_index(address); } +#define pud_leaf pud_large static inline int pud_large(pud_t pud) { return (pud_val(pud) & (_PAGE_PSE | _PAGE_PRESENT)) == @@ -889,6 +892,7 @@ static inline int pud_bad(pud_t pud) return (pud_flags(pud) & ~(_KERNPG_TABLE | _PAGE_USER)) != 0; } #else +#define pud_leaf pud_large static inline int pud_large(pud_t pud) { return 0; @@ -1237,6 +1241,7 @@ static inline bool pgdp_maps_userspace(void *__ptr) return (((ptr & ~PAGE_MASK) / sizeof(pgd_t)) < PGD_KERNEL_START); } +#define pgd_leaf pgd_large static inline int pgd_large(pgd_t pgd) { return 0; } #ifdef CONFIG_PAGE_TABLE_ISOLATION From fd534464e4ffe64f8f1b6f7627cedfb9f99c5ad4 Mon Sep 17 00:00:00 2001 From: Steven Price Date: Mon, 3 Feb 2020 17:35:45 -0800 Subject: [PATCH 551/698] BACKPORT: mm: pagewalk: add p4d_entry() and pgd_entry() pgd_entry() and pud_entry() were removed by commit 0b1fbfe50006c410 ("mm/pagewalk: remove pgd_entry() and pud_entry()") because there were no users. We're about to add users so reintroduce them, along with p4d_entry() as we now have 5 levels of tables. Note that commit a00cc7d9dd93d66a ("mm, x86: add support for PUD-sized transparent hugepages") already re-added pud_entry() but with different semantics to the other callbacks. This commit reverts the semantics back to match the other callbacks. To support hmm.c which now uses the new semantics of pud_entry() a new member ('action') of struct mm_walk is added which allows the callbacks to either descend (ACTION_SUBTREE, the default), skip (ACTION_CONTINUE) or repeat the callback (ACTION_AGAIN). hmm.c is then updated to call pud_trans_huge_lock() itself and make use of the splitting/retry logic of the core code. After this change pud_entry() is called for all entries, not just transparent huge pages. Moto-CRs-Fixed:(CR) [arnd@arndb.de: fix unused variable warning] Link: http://lkml.kernel.org/r/20200107204607.1533842-1-arnd@arndb.de Link: http://lkml.kernel.org/r/20191218162402.45610-12-steven.price@arm.com Change-Id: Id8578aab7de0f670db45d32cb3752993b81464be Signed-off-by: Steven Price Signed-off-by: Arnd Bergmann Cc: Albert Ou Cc: Alexandre Ghiti Cc: Perry Lutomirski Cc: Ard Biesheuvel Cc: Arnd Bergmann Cc: Benjamin Herrenschmidt Cc: Borislav Petkov Cc: Catalin Marinas Cc: Christian Borntraeger Cc: Dave Hansen Cc: David S. Miller Cc: He(CR) Carstens Cc: "H. Peter Anvin" Cc: Ingo Molnar Cc: James Hogan Cc: James Morse Cc: Jerome Glisse Cc: "Liang, Kan" Cc: Mark Rutland Cc: Michael Ellerman Cc: Paul Racer_turbo Cc: Paul Mackerras Cc: Paul Walmsley Cc: Peter Zijlstra Cc: Ralf Baechle Cc: Russell King Cc: Thomas Gleixner Cc: Vasily Gorb(CR) Cc: Vineet Gupta Cc: Will Deacon Cc: Zong Li Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds (cherry picked from commit 3afc423632a194d7d6afef34e4bb98f804cd071d) Bug: 261052246 Signed-off-by: Kalesh Singh Reviewed-on: https://gerrit.mot.com/2491783 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- include/linux/pagewalk.h | 34 ++++++++++++++++++----- mm/hmm.c | 58 ++++++++++++++++++++++------------------ mm/pagewalk.c | 50 +++++++++++++++++++++++----------- 3 files changed, 95 insertions(+), 47 deletions(-) diff --git a/include/linux/pagewalk.h b/include/linux/pagewalk.h index bddd9759bab9..ed30c86195b0 100644 --- a/include/linux/pagewalk.h +++ b/include/linux/pagewalk.h @@ -8,15 +8,15 @@ struct mm_walk; /** * mm_walk_ops - callbacks for walk_page_range - * @pud_entry: if set, called for each non-empty PUD (2nd-level) entry - * this handler should only handle pud_trans_huge() puds. - * the pmd_entry or pte_entry callbacks will be used for - * regular PUDs. - * @pmd_entry: if set, called for each non-empty PMD (3rd-level) entry + * @pgd_entry: if set, called for each non-empty PGD (top-level) entry + * @p4d_entry: if set, called for each non-empty P4D entry + * @pud_entry: if set, called for each non-empty PUD entry + * @pmd_entry: if set, called for each non-empty PMD entry * this handler is required to be able to handle * pmd_trans_huge() pmds. They may simply choose to * split_huge_page() instead of handling it explicitly. - * @pte_entry: if set, called for each non-empty PTE (4th-level) entry + * @pte_entry: if set, called for each non-empty PTE (lowest-level) + * entry * @pte_hole: if set, called for each hole at all levels * @hugetlb_entry: if set, called for each hugetlb entry * @test_walk: caller specific callback function to determine whether @@ -24,8 +24,15 @@ struct mm_walk; * "do page table walk over the current vma", returning * a negative value means "abort current page table walk * right now" and returning 1 means "skip the current vma" + * + * p?d_entry callbacks are called even if those levels are folded on a + * particular architecture/configuration. */ struct mm_walk_ops { + int (*pgd_entry)(pgd_t *pgd, unsigned long addr, + unsigned long next, struct mm_walk *walk); + int (*p4d_entry)(p4d_t *p4d, unsigned long addr, + unsigned long next, struct mm_walk *walk); int (*pud_entry)(pud_t *pud, unsigned long addr, unsigned long next, struct mm_walk *walk); int (*pmd_entry)(pmd_t *pmd, unsigned long addr, @@ -41,11 +48,25 @@ struct mm_walk_ops { struct mm_walk *walk); }; +/* + * Action for pud_entry / pmd_entry callbacks. + * ACTION_SUBTREE is the default + */ +enum page_walk_action { + /* Descend to next level, splitting huge pages if needed and possible */ + ACTION_SUBTREE = 0, + /* Continue to next entry at this level (ignoring any subtree) */ + ACTION_CONTINUE = 1, + /* Call again for this entry */ + ACTION_AGAIN = 2 +}; + /** * mm_walk - walk_page_range data * @ops: operation to call during the walk * @mm: mm_struct representing the target process of page table walk * @vma: vma currently walked (NULL if walking outside vmas) + * @action: next action to perform (see enum page_walk_action) * @private: private data for callbacks' usage * * (see the comment on walk_page_range() for more details) @@ -54,6 +75,7 @@ struct mm_walk { const struct mm_walk_ops *ops; struct mm_struct *mm; struct vm_area_struct *vma; + enum page_walk_action action; void *private; }; diff --git a/mm/hmm.c b/mm/hmm.c index 902f5fa6bf93..231de978d647 100644 --- a/mm/hmm.c +++ b/mm/hmm.c @@ -658,23 +658,32 @@ static int hmm_vma_walk_pud(pud_t *pudp, unsigned long start, unsigned long end, { struct hmm_vma_walk *hmm_vma_walk = walk->private; struct hmm_range *range = hmm_vma_walk->range; - unsigned long addr = start, next; - pmd_t *pmdp; + unsigned long addr = start; pud_t pud; - int ret; + int ret = 0; + spinlock_t *ptl = pud_trans_huge_lock(pudp, walk->vma); + + if (!ptl) + return 0; + + /* Normally we don't want to split the huge page */ + walk->action = ACTION_CONTINUE; -again: pud = READ_ONCE(*pudp); - if (pud_none(pud)) - return hmm_vma_walk_hole(start, end, walk); + if (pud_none(pud)) { + ret = hmm_vma_walk_hole(start, end, walk); + goto out_unlock; + } if (pud_huge(pud) && pud_devmap(pud)) { unsigned long i, npages, pfn; uint64_t *pfns, cpu_flags; bool fault, write_fault; - if (!pud_present(pud)) - return hmm_vma_walk_hole(start, end, walk); + if (!pud_present(pud)) { + ret = hmm_vma_walk_hole(start, end, walk); + goto out_unlock; + } i = (addr - range->start) >> PAGE_SHIFT; npages = (end - addr) >> PAGE_SHIFT; @@ -683,16 +692,20 @@ again: cpu_flags = pud_to_hmm_pfn_flags(range, pud); hmm_range_need_fault(hmm_vma_walk, pfns, npages, cpu_flags, &fault, &write_fault); - if (fault || write_fault) - return hmm_vma_walk_hole_(addr, end, fault, - write_fault, walk); + if (fault || write_fault) { + ret = hmm_vma_walk_hole_(addr, end, fault, + write_fault, walk); + goto out_unlock; + } pfn = pud_pfn(pud) + ((addr & ~PUD_MASK) >> PAGE_SHIFT); for (i = 0; i < npages; ++i, ++pfn) { hmm_vma_walk->pgmap = get_dev_pagemap(pfn, hmm_vma_walk->pgmap); - if (unlikely(!hmm_vma_walk->pgmap)) - return -EBUSY; + if (unlikely(!hmm_vma_walk->pgmap)) { + ret = -EBUSY; + goto out_unlock; + } pfns[i] = hmm_device_entry_from_pfn(range, pfn) | cpu_flags; } @@ -701,22 +714,15 @@ again: hmm_vma_walk->pgmap = NULL; } hmm_vma_walk->last = end; - return 0; + goto out_unlock; } - split_huge_pud(walk->vma, pudp, addr); - if (pud_none(*pudp)) - goto again; + /* Ask for the PUD to be split */ + walk->action = ACTION_SUBTREE; - pmdp = pmd_offset(pudp, addr); - do { - next = pmd_addr_end(addr, end); - ret = hmm_vma_walk_pmd(pmdp, addr, next, walk); - if (ret) - return ret; - } while (pmdp++, addr = next, addr != end); - - return 0; +out_unlock: + spin_unlock(ptl); + return ret; } #else #define hmm_vma_walk_pud NULL diff --git a/mm/pagewalk.c b/mm/pagewalk.c index ec41e7552f37..0d4c6159a4ea 100644 --- a/mm/pagewalk.c +++ b/mm/pagewalk.c @@ -45,6 +45,9 @@ again: break; continue; } + + walk->action = ACTION_SUBTREE; + /* * This implies that each ->pmd_entry() handler * needs to know about pmd_trans_huge() pmds @@ -54,16 +57,21 @@ again: if (err) break; + if (walk->action == ACTION_AGAIN) + goto again; + /* * Check this here so we only break down trans_huge * pages when we _need_ to */ - if (!ops->pte_entry) + if (walk->action == ACTION_CONTINUE || + !(ops->pte_entry)) continue; split_huge_pmd(walk->vma, pmd, addr); if (pmd_trans_unstable(pmd)) goto again; + err = walk_pte_range(pmd, addr, next, walk); if (err) break; @@ -92,24 +100,25 @@ static int walk_pud_range(p4d_t *p4d, unsigned long addr, unsigned long end, continue; } - if (ops->pud_entry) { - spinlock_t *ptl = pud_trans_huge_lock(pud, walk->vma); + walk->action = ACTION_SUBTREE; - if (ptl) { - err = ops->pud_entry(pud, addr, next, walk); - spin_unlock(ptl); - if (err) - break; - continue; - } - } + if (ops->pud_entry) + err = ops->pud_entry(pud, addr, next, walk); + if (err) + break; + + if (walk->action == ACTION_AGAIN) + goto again; + + if (walk->action == ACTION_CONTINUE || + !(ops->pmd_entry || ops->pte_entry)) + continue; split_huge_pud(walk->vma, pud, addr); if (pud_none(*pud)) goto again; - if (ops->pmd_entry || ops->pte_entry) - err = walk_pmd_range(pud, addr, next, walk); + err = walk_pmd_range(pud, addr, next, walk); if (err) break; } while (pud++, addr = next, addr != end); @@ -135,7 +144,12 @@ static int walk_p4d_range(pgd_t *pgd, unsigned long addr, unsigned long end, break; continue; } - if (ops->pmd_entry || ops->pte_entry) + if (ops->p4d_entry) { + err = ops->p4d_entry(p4d, addr, next, walk); + if (err) + break; + } + if (ops->pud_entry || ops->pmd_entry || ops->pte_entry) err = walk_pud_range(p4d, addr, next, walk); if (err) break; @@ -162,7 +176,13 @@ static int walk_pgd_range(unsigned long addr, unsigned long end, break; continue; } - if (ops->pmd_entry || ops->pte_entry) + if (ops->pgd_entry) { + err = ops->pgd_entry(pgd, addr, next, walk); + if (err) + break; + } + if (ops->p4d_entry || ops->pud_entry || ops->pmd_entry || + ops->pte_entry) err = walk_p4d_range(pgd, addr, next, walk); if (err) break; From 87ee083dbc70a1e4ba5a4f1b3b0593eadf8bf229 Mon Sep 17 00:00:00 2001 From: Jason Gunthorpe Date: Mon, 2 Mar 2020 15:26:44 -0400 Subject: [PATCH 552/698] BACKPORT: mm/hmm: do not call hmm_vma_walk_hole() while holding a spinlock This eventually calls into handle_mm_fault() which is a sleeping function. Release the lock first. hmm_vma_walk_hole() does not touch the contents of the PUD, so it does not need the lock. Moto-CRs-Fixed:(CR) Link: https://lore.kernel.org/r/20200311183506.3997-4-jgg@ziepe.ca/ Fixes: 3afc423632a1 ("mm: pagewalk: add p4d_entry() and pgd_entry()") Cc: Steven Price Reviewed-by: Ralph Campbell Reviewed-by: Steven Price Reviewed-by: Christoph Hellwig Change-Id: I4dd851a2fcf242877ae7acd082f3521e7202d258 Signed-off-by: Jason Gunthorpe (cherry picked from commit 05fc1df95e5dc09802813bab9c1e718f1e419d93) Bug: 261052246 Signed-off-by: Kalesh Singh Reviewed-on: https://gerrit.mot.com/2491784 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- mm/hmm.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/mm/hmm.c b/mm/hmm.c index 231de978d647..795faf021085 100644 --- a/mm/hmm.c +++ b/mm/hmm.c @@ -671,8 +671,8 @@ static int hmm_vma_walk_pud(pud_t *pudp, unsigned long start, unsigned long end, pud = READ_ONCE(*pudp); if (pud_none(pud)) { - ret = hmm_vma_walk_hole(start, end, walk); - goto out_unlock; + spin_unlock(ptl); + return hmm_vma_walk_hole(start, end, walk); } if (pud_huge(pud) && pud_devmap(pud)) { @@ -681,8 +681,8 @@ static int hmm_vma_walk_pud(pud_t *pudp, unsigned long start, unsigned long end, bool fault, write_fault; if (!pud_present(pud)) { - ret = hmm_vma_walk_hole(start, end, walk); - goto out_unlock; + spin_unlock(ptl); + return hmm_vma_walk_hole(start, end, walk); } i = (addr - range->start) >> PAGE_SHIFT; @@ -693,9 +693,9 @@ static int hmm_vma_walk_pud(pud_t *pudp, unsigned long start, unsigned long end, hmm_range_need_fault(hmm_vma_walk, pfns, npages, cpu_flags, &fault, &write_fault); if (fault || write_fault) { - ret = hmm_vma_walk_hole_(addr, end, fault, - write_fault, walk); - goto out_unlock; + spin_unlock(ptl); + return hmm_vma_walk_hole_(addr, end, fault, write_fault, + walk); } pfn = pud_pfn(pud) + ((addr & ~PUD_MASK) >> PAGE_SHIFT); From 59492259cbe90a9a0d8a9ba2ea192b2d70480ff4 Mon Sep 17 00:00:00 2001 From: Wei Yang Date: Wed, 3 Jun 2020 16:01:12 -0700 Subject: [PATCH 553/698] UPSTREAM: mm/vmscan.c: use update_lru_size() in update_lru_sizes() We already defined the helper update_lru_size(). Let's use this to reduce code duplication. Moto-CRs-Fixed:(CR) Change-Id: Icae4274c4f4c9bdfd70355bb32eb2fe1800a79c1 Signed-off-by: Wei Yang Signed-off-by: Andrew Morton Reviewed-by: Baoquan He Reviewed-by: Andrew Morton Acked-by: Michal Hocko Link: http://lkml.kernel.org/r/20200331221550.1011-1-richard.weiyang@gmail.com Signed-off-by: Linus Torvalds (cherry picked from commit a892cb6b977ffe209683809e5e9d627656d20aa8) Bug: 261052246 Signed-off-by: Kalesh Singh Reviewed-on: https://gerrit.mot.com/2491785 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- mm/vmscan.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/mm/vmscan.c b/mm/vmscan.c index 90ef9c46e2f3..3cae1a1866f1 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -1722,10 +1722,7 @@ static __always_inline void update_lru_sizes(struct lruvec *lruvec, if (!nr_zone_taken[zid]) continue; - __update_lru_size(lruvec, lru, zid, -nr_zone_taken[zid]); -#ifdef CONFIG_MEMCG - mem_cgroup_update_lru_size(lruvec, lru, zid, -nr_zone_taken[zid]); -#endif + update_lru_size(lruvec, lru, zid, -nr_zone_taken[zid]); } } From 76b93a65505041decfe8d342c9e34cb8b91aaaff Mon Sep 17 00:00:00 2001 From: Joonsoo Kim Date: Tue, 11 Aug 2020 18:30:47 -0700 Subject: [PATCH 554/698] BACKPORT: mm/swapcache: support to handle the shadow entries Workingset detection for anonymous page will be implemented in the following patch and it requires to store the shadow entries into the swapcache. This patch implements an infrastructure to store the shadow entry in the swapcache. Moto-CRs-Fixed:(CR) Change-Id: Id9c2ac3af7ae73f95ba06cdda5e28aa678954d08 Signed-off-by: Joonsoo Kim Signed-off-by: Andrew Morton Acked-by: Johannes Weiner Cc: Hugh Dickins Cc: Matthew Wilcox Cc: Mel Gorman Cc: Michal Hocko Cc: Minchan Kim Cc: Vlastimil Babka Link: http://lkml.kernel.org/r/1595490560-15117-5-git-send-email-iamjoonsoo.kim@lge.com Signed-off-by: Linus Torvalds (cherry picked from commit 3852f6768ede542ed48b9077bedf482c7ecb6327) Bug: 261052246 Signed-off-by: Kalesh Singh Reviewed-on: https://gerrit.mot.com/2491786 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- include/linux/swap.h | 18 ++++++++++---- mm/shmem.c | 2 +- mm/swap_state.c | 59 ++++++++++++++++++++++++++++++++++++++------ mm/swapfile.c | 2 ++ mm/vmscan.c | 2 +- 5 files changed, 69 insertions(+), 14 deletions(-) diff --git a/include/linux/swap.h b/include/linux/swap.h index bb50a6d0eee4..0cc833d21ce2 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h @@ -415,10 +415,13 @@ extern struct address_space *swapper_spaces[]; extern unsigned long total_swapcache_pages(void); extern void show_swap_cache_info(void); extern int add_to_swap(struct page *page); -extern int add_to_swap_cache(struct page *, swp_entry_t, gfp_t); -extern int __add_to_swap_cache(struct page *page, swp_entry_t entry); -extern void __delete_from_swap_cache(struct page *, swp_entry_t entry); +extern int add_to_swap_cache(struct page *page, swp_entry_t entry, + gfp_t gfp, void **shadowp); +extern void __delete_from_swap_cache(struct page *page, + swp_entry_t entry, void *shadow); extern void delete_from_swap_cache(struct page *); +extern void clear_shadow_from_swap_cache(int type, unsigned long begin, + unsigned long end); extern void free_page_and_swap_cache(struct page *); extern void free_pages_and_swap_cache(struct page **, int); extern struct page *lookup_swap_cache(swp_entry_t entry, @@ -573,13 +576,13 @@ static inline int add_to_swap(struct page *page) } static inline int add_to_swap_cache(struct page *page, swp_entry_t entry, - gfp_t gfp_mask) + gfp_t gfp_mask, void **shadowp) { return -1; } static inline void __delete_from_swap_cache(struct page *page, - swp_entry_t entry) + swp_entry_t entry, void *shadow) { } @@ -587,6 +590,11 @@ static inline void delete_from_swap_cache(struct page *page) { } +static inline void clear_shadow_from_swap_cache(int type, unsigned long begin, + unsigned long end) +{ +} + static inline int page_swapcount(struct page *page) { return 0; diff --git a/mm/shmem.c b/mm/shmem.c index 28deb63c21a7..a5b110795c54 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -1374,7 +1374,7 @@ static int shmem_writepage(struct page *page, struct writeback_control *wbc) if (list_empty(&info->swaplist)) list_add(&info->swaplist, &shmem_swaplist); - if (add_to_swap_cache(page, swap, GFP_ATOMIC) == 0) { + if (add_to_swap_cache(page, swap, GFP_ATOMIC, NULL) == 0) { spin_lock_irq(&info->lock); shmem_recalc_inode(inode); info->swapped++; diff --git a/mm/swap_state.c b/mm/swap_state.c index 16709312e949..e8bd52bb23b1 100644 --- a/mm/swap_state.c +++ b/mm/swap_state.c @@ -112,12 +112,14 @@ void show_swap_cache_info(void) * add_to_swap_cache resembles add_to_page_cache_locked on swapper_space, * but sets SwapCache flag and private instead of mapping and index. */ -int add_to_swap_cache(struct page *page, swp_entry_t entry, gfp_t gfp) +int add_to_swap_cache(struct page *page, swp_entry_t entry, + gfp_t gfp, void **shadowp) { struct address_space *address_space = swap_address_space(entry); pgoff_t idx = swp_offset(entry); XA_STATE_ORDER(xas, &address_space->i_pages, idx, compound_order(page)); - unsigned long i, nr = compound_nr(page); + unsigned long i, nr = hpage_nr_pages(page); + void *old; VM_BUG_ON_PAGE(!PageLocked(page), page); VM_BUG_ON_PAGE(PageSwapCache(page), page); @@ -127,16 +129,25 @@ int add_to_swap_cache(struct page *page, swp_entry_t entry, gfp_t gfp) SetPageSwapCache(page); do { + unsigned long nr_shadows = 0; + xas_lock_irq(&xas); xas_create_range(&xas); if (xas_error(&xas)) goto unlock; for (i = 0; i < nr; i++) { VM_BUG_ON_PAGE(xas.xa_index != idx + i, page); + old = xas_load(&xas); + if (xa_is_value(old)) { + nr_shadows++; + if (shadowp) + *shadowp = old; + } set_page_private(page + i, entry.val + i); xas_store(&xas, page); xas_next(&xas); } + address_space->nrexceptional -= nr_shadows; address_space->nrpages += nr; __mod_node_page_state(page_pgdat(page), NR_FILE_PAGES, nr); ADD_CACHE_INFO(add_total, nr); @@ -156,7 +167,8 @@ unlock: * This must be called only on pages that have * been verified to be in the swap cache. */ -void __delete_from_swap_cache(struct page *page, swp_entry_t entry) +void __delete_from_swap_cache(struct page *page, + swp_entry_t entry, void *shadow) { struct address_space *address_space = swap_address_space(entry); int i, nr = hpage_nr_pages(page); @@ -168,12 +180,14 @@ void __delete_from_swap_cache(struct page *page, swp_entry_t entry) VM_BUG_ON_PAGE(PageWriteback(page), page); for (i = 0; i < nr; i++) { - void *entry = xas_store(&xas, NULL); + void *entry = xas_store(&xas, shadow); VM_BUG_ON_PAGE(entry != page, entry); set_page_private(page + i, 0); xas_next(&xas); } ClearPageSwapCache(page); + if (shadow) + address_space->nrexceptional += nr; address_space->nrpages -= nr; __mod_node_page_state(page_pgdat(page), NR_FILE_PAGES, -nr); ADD_CACHE_INFO(del_total, nr); @@ -210,7 +224,7 @@ int add_to_swap(struct page *page) * Add it to the swap cache. */ err = add_to_swap_cache(page, entry, - __GFP_HIGH|__GFP_NOMEMALLOC|__GFP_NOWARN); + __GFP_HIGH|__GFP_NOMEMALLOC|__GFP_NOWARN, NULL); if (err) /* * add_to_swap_cache() doesn't return -EEXIST, so we can safely @@ -248,13 +262,44 @@ void delete_from_swap_cache(struct page *page) struct address_space *address_space = swap_address_space(entry); xa_lock_irq(&address_space->i_pages); - __delete_from_swap_cache(page, entry); + __delete_from_swap_cache(page, entry, NULL); xa_unlock_irq(&address_space->i_pages); put_swap_page(page, entry); page_ref_sub(page, hpage_nr_pages(page)); } +void clear_shadow_from_swap_cache(int type, unsigned long begin, + unsigned long end) +{ + unsigned long curr = begin; + void *old; + + for (;;) { + unsigned long nr_shadows = 0; + swp_entry_t entry = swp_entry(type, curr); + struct address_space *address_space = swap_address_space(entry); + XA_STATE(xas, &address_space->i_pages, curr); + + xa_lock_irq(&address_space->i_pages); + xas_for_each(&xas, old, end) { + if (!xa_is_value(old)) + continue; + xas_store(&xas, NULL); + nr_shadows++; + } + address_space->nrexceptional -= nr_shadows; + xa_unlock_irq(&address_space->i_pages); + + /* search the next swapcache until we meet end */ + curr >>= SWAP_ADDRESS_SPACE_SHIFT; + curr++; + curr <<= SWAP_ADDRESS_SPACE_SHIFT; + if (curr > end) + break; + } +} + /* * If we are the only user, then try to free up the swap cache. * @@ -420,7 +465,7 @@ struct page *__read_swap_cache_async(swp_entry_t entry, gfp_t gfp_mask, __SetPageLocked(new_page); __SetPageSwapBacked(new_page); err = add_to_swap_cache(new_page, entry, - gfp_mask & GFP_RECLAIM_MASK); + gfp_mask & GFP_RECLAIM_MASK, NULL); if (likely(!err)) { /* Initiate read into locked page */ SetPageWorkingset(new_page); diff --git a/mm/swapfile.c b/mm/swapfile.c index f0f77c750c56..0a1485f4b59c 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -716,6 +716,7 @@ static void add_to_avail_list(struct swap_info_struct *p) static void swap_range_free(struct swap_info_struct *si, unsigned long offset, unsigned int nr_entries) { + unsigned long begin = offset; unsigned long end = offset + nr_entries - 1; void (*swap_slot_free_notify)(struct block_device *, unsigned long); @@ -741,6 +742,7 @@ static void swap_range_free(struct swap_info_struct *si, unsigned long offset, swap_slot_free_notify(si->bdev, offset); offset++; } + clear_shadow_from_swap_cache(si->type, begin, end); } static int scan_swap_map_slots(struct swap_info_struct *si, diff --git a/mm/vmscan.c b/mm/vmscan.c index 3cae1a1866f1..46261548525b 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -965,7 +965,7 @@ static int __remove_mapping(struct address_space *mapping, struct page *page, if (PageSwapCache(page)) { swp_entry_t swap = { .val = page_private(page) }; mem_cgroup_swapout(page, swap); - __delete_from_swap_cache(page, swap); + __delete_from_swap_cache(page, swap, NULL); xa_unlock_irqrestore(&mapping->i_pages, flags); put_swap_page(page, swap); } else { From f8d273257a24200a44d1804c78ee023351b1764e Mon Sep 17 00:00:00 2001 From: Yu Zhao Date: Sat, 18 Jul 2020 01:46:37 -0600 Subject: [PATCH 555/698] BACKPORT: mm: remove superfluous __ClearPageActive() To activate a page, mark_page_accessed() always holds a reference on it. It either gets a new reference when adding a page to lru_pvecs.activate_page or reuses an existing one it previously got when it added a page to lru_pvecs.lru_add. So it doesn't call SetPageActive() on a page that doesn't have any reference left. Therefore, the race is impossible these days (I didn't brother to dig into its history). For other paths, namely reclaim and migration, a reference count is always held while calling SetPageActive() on a page. SetPageSlabPfmemalloc() also uses SetPageActive(), but it's irrelevant to LRU pages. Moto-CRs-Fixed:(CR) Change-Id: If818ad43f98960f6b397dae7c2dd555bd4469854 Signed-off-by: Yu Zhao Signed-off-by: Andrew Morton Reviewed-by: Yang Shi Cc: Alexander Duyck Cc: David Hildenbrand Cc: Huang Ying Cc: Hugh Dickins Cc: Joonsoo Kim Cc: Mel Gorman Cc: Michal Hocko Cc: Nicholas Piggin Cc: Qian Cai Link: http://lkml.kernel.org/r/20200818184704.3625199-2-yuzhao@google.com Signed-off-by: Linus Torvalds (cherry picked from commit 6f4dd8de4835563de9bae797ce1d7a13465a7a7d) Bug: 261052246 Signed-off-by: Kalesh Singh Reviewed-on: https://gerrit.mot.com/2491787 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- mm/memremap.c | 2 -- mm/swap.c | 2 -- 2 files changed, 4 deletions(-) diff --git a/mm/memremap.c b/mm/memremap.c index c51c6bd2fe34..b268b184eab3 100644 --- a/mm/memremap.c +++ b/mm/memremap.c @@ -419,8 +419,6 @@ void __put_devmap_managed_page(struct page *page) * holds a reference on the page. */ if (count == 1) { - /* Clear Active bit in case of parallel mark_page_accessed */ - __ClearPageActive(page); __ClearPageWaiters(page); mem_cgroup_uncharge(page); diff --git a/mm/swap.c b/mm/swap.c index 159174565497..8362cfde85aa 100644 --- a/mm/swap.c +++ b/mm/swap.c @@ -829,8 +829,6 @@ void release_pages(struct page **pages, int nr) del_page_from_lru_list(page, lruvec, page_off_lru(page)); } - /* Clear Active bit in case of parallel mark_page_accessed */ - __ClearPageActive(page); __ClearPageWaiters(page); list_add(&page->lru, &pages_to_free); From d5c04fec663a386885c3fdccbc8c8aeffbb422b4 Mon Sep 17 00:00:00 2001 From: Yu Zhao Date: Thu, 15 Oct 2020 20:09:55 -0700 Subject: [PATCH 556/698] BACKPORT: mm: use self-explanatory macros rather than "2" Moto-CRs-Fixed:(CR) Change-Id: I4bb60eb4191c2a378c3d7c5a8c8170eb72d598ae Signed-off-by: Yu Zhao Signed-off-by: Andrew Morton Cc: Alex Shi Link: http://lkml.kernel.org/r/20200831175042.3527153-2-yuzhao@google.com Signed-off-by: Linus Torvalds (cherry picked from commit ed0173733dd468883198c3136284394320b8fad6) Bug: 261052246 Signed-off-by: Kalesh Singh Reviewed-on: https://gerrit.mot.com/2491788 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- include/linux/mmzone.h | 12 ++++++++---- mm/vmscan.c | 4 +--- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index 6f2a15015435..97f9d4576d2e 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -293,6 +293,8 @@ static inline int is_active_lru(enum lru_list lru) return (lru == LRU_ACTIVE_ANON || lru == LRU_ACTIVE_FILE); } +#define ANON_AND_FILE 2 + struct zone_reclaim_stat { /* * The pageout code in vmscan.c keeps track of how many of the @@ -302,8 +304,8 @@ struct zone_reclaim_stat { * * The anon LRU stats live in [0], file LRU stats in [1] */ - unsigned long recent_rotated[2]; - unsigned long recent_scanned[2]; + unsigned long recent_rotated[ANON_AND_FILE]; + unsigned long recent_scanned[ANON_AND_FILE]; }; struct lruvec { @@ -425,6 +427,8 @@ enum zone_type { #ifndef __GENERATING_BOUNDS_H +#define ASYNC_AND_SYNC 2 + struct zone { /* Read-mostly fields */ @@ -548,8 +552,8 @@ struct zone { #if defined CONFIG_COMPACTION || defined CONFIG_CMA /* pfn where compaction free scanner should start */ unsigned long compact_cached_free_pfn; - /* pfn where async and sync compaction migration scanner should start */ - unsigned long compact_cached_migrate_pfn[2]; + /* pfn where compaction migration scanner should start */ + unsigned long compact_cached_migrate_pfn[ASYNC_AND_SYNC]; unsigned long compact_init_migrate_pfn; unsigned long compact_init_free_pfn; #endif diff --git a/mm/vmscan.c b/mm/vmscan.c index 46261548525b..cc14927c44ee 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -2375,7 +2375,7 @@ static void get_scan_count(struct lruvec *lruvec, struct mem_cgroup *memcg, { int swappiness = mem_cgroup_swappiness(memcg); struct zone_reclaim_stat *reclaim_stat = &lruvec->reclaim_stat; - u64 fraction[2]; + u64 fraction[ANON_AND_FILE]; u64 denominator = 0; /* gcc */ struct pglist_data *pgdat = lruvec_pgdat(lruvec); unsigned long anon_prio, file_prio; @@ -2487,8 +2487,6 @@ static void get_scan_count(struct lruvec *lruvec, struct mem_cgroup *memcg, * Because workloads change over time (and to avoid overflow) * we keep these statistics as a floating average, which ends * up weighing recent references more than old ones. - * - * anon in [0], file in [1] */ anon = lruvec_lru_size(lruvec, LRU_ACTIVE_ANON, MAX_NR_ZONES) + From d35214451255c8372b8b5b15722321a33d9cfc25 Mon Sep 17 00:00:00 2001 From: Yu Zhao Date: Mon, 13 Jul 2020 11:37:30 -0600 Subject: [PATCH 557/698] BACKPORT: mm/vmscan.c: use add_page_to_lru_list() Patch series "mm: lru related cleanups", v2. The cleanups are intended to reduce the verbosity in lru list operations and make them less error-prone. A typical example would be how the patches change __activate_page(): static void __activate_page(struct page *page, struct lruvec *lruvec) { if (!PageActive(page) && !PageUnevictable(page)) { - int lru = page_lru_base_type(page); int nr_pages = thp_nr_pages(page); - del_page_from_lru_list(page, lruvec, lru); + del_page_from_lru_list(page, lruvec); SetPageActive(page); - lru += LRU_ACTIVE; - add_page_to_lru_list(page, lruvec, lru); + add_page_to_lru_list(page, lruvec); trace_mm_lru_activate(page); There are a few more places l(CR) __activate_page() and they are unnecessarily repetitive in terms of figuring out which list a page should be added onto or deleted from. And with the duplicated code removed, they are easier to read, IMO. Patch 1 to 5 basically cover the above. Patch 6 and 7 make code more robust by improving bug reporting. Patch 8, 9 and 10 take care of some dangling helpers left in header files. Moto-CRs-Fixed:(CR) This patch (of 10): There is add_page_to_lru_list(), and move_pages_to_lru() should reuse it, not duplicate it. Link: https://lkml.kernel.org/r/20210122220600.906146-1-yuzhao@google.com Link: https://lore.kernel.org/linux-mm/20201207220949.830352-2-yuzhao@google.com/ Link: https://lkml.kernel.org/r/20210122220600.906146-2-yuzhao@google.com Change-Id: Ic8de94d421c2477a077249a7c337e3fafdd41ff3 Signed-off-by: Yu Zhao Reviewed-by: Alex Shi Acked-by: Vlastimil Babka Reviewed-by: Miaohe Lin Cc: Hugh Dickins Cc: Michal Hocko Cc: Johannes Weiner Cc: Vladimir Davydov Cc: Roman Gushchin Cc: Matthew Wilcox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds (cherry picked from commit 42895ea73bcd37c4a79e4c9f681ab8b82243c7f7) Bug: 261052246 Signed-off-by: Kalesh Singh Reviewed-on: https://gerrit.mot.com/2491789 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- mm/vmscan.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/mm/vmscan.c b/mm/vmscan.c index cc14927c44ee..e2b824d0f847 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -1954,8 +1954,8 @@ static unsigned noinline_for_stack move_pages_to_lru(struct lruvec *lruvec, while (!list_empty(list)) { page = lru_to_page(list); VM_BUG_ON_PAGE(PageLRU(page), page); + list_del(&page->lru); if (unlikely(!page_evictable(page))) { - list_del(&page->lru); spin_unlock_irq(&pgdat->lru_lock); putback_lru_page(page); spin_lock_irq(&pgdat->lru_lock); @@ -1965,10 +1965,7 @@ static unsigned noinline_for_stack move_pages_to_lru(struct lruvec *lruvec, SetPageLRU(page); lru = page_lru(page); - - nr_pages = hpage_nr_pages(page); - update_lru_size(lruvec, lru, page_zonenum(page), nr_pages); - list_move(&page->lru, &lruvec->lists[lru]); + add_page_to_lru_list(page, lruvec, lru); if (put_page_testzero(page)) { __ClearPageLRU(page); @@ -1982,6 +1979,7 @@ static unsigned noinline_for_stack move_pages_to_lru(struct lruvec *lruvec, } else list_add(&page->lru, &pages_to_free); } else { + nr_pages = hpage_nr_pages(page); nr_moved += nr_pages; } } From 974a4afb4d6486f2871a1b1fa1c6e8d37168419b Mon Sep 17 00:00:00 2001 From: Yu Zhao Date: Wed, 24 Feb 2021 12:08:13 -0800 Subject: [PATCH 558/698] BACKPORT: include/linux/mm_inline.h: shuffle lru list addition and deletion functions These functions will call page_lru() in the following patches. Move them below page_lru() to avoid the forward declaration. Moto-CRs-Fixed:(CR) Link: https://lore.kernel.org/linux-mm/20201207220949.830352-3-yuzhao@google.com/ Link: https://lkml.kernel.org/r/20210122220600.906146-3-yuzhao@google.com Change-Id: I3f0d2411e98a92acd82e31d31139ac5ed6d7c1c6 Signed-off-by: Yu Zhao Acked-by: Vlastimil Babka Reviewed-by: Miaohe Lin Cc: Alex Shi Cc: Hugh Dickins Cc: Johannes Weiner Cc: Matthew Wilcox Cc: Michal Hocko Cc: Roman Gushchin Cc: Vladimir Davydov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds (cherry picked from commit f90d8191ac864df33b1898bc7edc54eaa24e22bc) Bug: 261052246 Signed-off-by: Kalesh Singh Reviewed-on: https://gerrit.mot.com/2491790 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- include/linux/mm_inline.h | 43 ++++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/include/linux/mm_inline.h b/include/linux/mm_inline.h index 6f2fef7b0784..85e526fb0d1f 100644 --- a/include/linux/mm_inline.h +++ b/include/linux/mm_inline.h @@ -44,27 +44,6 @@ static __always_inline void update_lru_size(struct lruvec *lruvec, #endif } -static __always_inline void add_page_to_lru_list(struct page *page, - struct lruvec *lruvec, enum lru_list lru) -{ - update_lru_size(lruvec, lru, page_zonenum(page), hpage_nr_pages(page)); - list_add(&page->lru, &lruvec->lists[lru]); -} - -static __always_inline void add_page_to_lru_list_tail(struct page *page, - struct lruvec *lruvec, enum lru_list lru) -{ - update_lru_size(lruvec, lru, page_zonenum(page), hpage_nr_pages(page)); - list_add_tail(&page->lru, &lruvec->lists[lru]); -} - -static __always_inline void del_page_from_lru_list(struct page *page, - struct lruvec *lruvec, enum lru_list lru) -{ - list_del(&page->lru); - update_lru_size(lruvec, lru, page_zonenum(page), -hpage_nr_pages(page)); -} - /** * page_lru_base_type - which LRU list type should a page be on? * @page: the page to test @@ -124,4 +103,26 @@ static __always_inline enum lru_list page_lru(struct page *page) } return lru; } + +static __always_inline void add_page_to_lru_list(struct page *page, + struct lruvec *lruvec, enum lru_list lru) +{ + update_lru_size(lruvec, lru, page_zonenum(page), hpage_nr_pages(page)); + list_add(&page->lru, &lruvec->lists[lru]); +} + +static __always_inline void add_page_to_lru_list_tail(struct page *page, + struct lruvec *lruvec, enum lru_list lru) +{ + update_lru_size(lruvec, lru, page_zonenum(page), hpage_nr_pages(page)); + list_add_tail(&page->lru, &lruvec->lists[lru]); +} + +static __always_inline void del_page_from_lru_list(struct page *page, + struct lruvec *lruvec, enum lru_list lru) +{ + list_del(&page->lru); + update_lru_size(lruvec, lru, page_zonenum(page), -hpage_nr_pages(page)); +} + #endif From 4cda66ef707e20523aeb5405e875bc537db4be50 Mon Sep 17 00:00:00 2001 From: Yu Zhao Date: Wed, 24 Feb 2021 12:08:17 -0800 Subject: [PATCH 559/698] BACKPORT: mm: don't pass "enum lru_list" to lru list addition functions The "enum lru_list" parameter to add_page_to_lru_list() and add_page_to_lru_list_tail() is redundant in the sense that it can be extracted from the "struct page" parameter by page_lru(). A caveat is that we need to make sure PageActive() or PageUnevictable() is correctly set or cleared before calling these two functions. And they are indeed. Moto-CRs-Fixed:(CR) Link: https://lore.kernel.org/linux-mm/20201207220949.830352-4-yuzhao@google.com/ Link: https://lkml.kernel.org/r/20210122220600.906146-4-yuzhao@google.com Change-Id: If050c0d8d802e9290c37aabeb693b00a714cfb70 Signed-off-by: Yu Zhao Cc: Alex Shi Cc: Hugh Dickins Cc: Johannes Weiner Cc: Matthew Wilcox Cc: Michal Hocko Cc: Roman Gushchin Cc: Vladimir Davydov Cc: Vlastimil Babka Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds (cherry picked from commit 3a9c9788a3149d9745b7eb2eae811e57ef3b127c) Bug: 261052246 Signed-off-by: Kalesh Singh Reviewed-on: https://gerrit.mot.com/2491791 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- include/linux/mm_inline.h | 8 ++++++-- mm/memcontrol.c | 2 +- mm/swap.c | 18 ++++++++---------- mm/vmscan.c | 6 ++---- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/include/linux/mm_inline.h b/include/linux/mm_inline.h index 85e526fb0d1f..d01a06dae3b7 100644 --- a/include/linux/mm_inline.h +++ b/include/linux/mm_inline.h @@ -105,15 +105,19 @@ static __always_inline enum lru_list page_lru(struct page *page) } static __always_inline void add_page_to_lru_list(struct page *page, - struct lruvec *lruvec, enum lru_list lru) + struct lruvec *lruvec) { + enum lru_list lru = page_lru(page); + update_lru_size(lruvec, lru, page_zonenum(page), hpage_nr_pages(page)); list_add(&page->lru, &lruvec->lists[lru]); } static __always_inline void add_page_to_lru_list_tail(struct page *page, - struct lruvec *lruvec, enum lru_list lru) + struct lruvec *lruvec) { + enum lru_list lru = page_lru(page); + update_lru_size(lruvec, lru, page_zonenum(page), hpage_nr_pages(page)); list_add_tail(&page->lru, &lruvec->lists[lru]); } diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 0140629b7cb2..d464f39389a2 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -2757,7 +2757,7 @@ static void unlock_page_lru(struct page *page, int isolated) lruvec = mem_cgroup_page_lruvec(page, pgdat); VM_BUG_ON_PAGE(PageLRU(page), page); SetPageLRU(page); - add_page_to_lru_list(page, lruvec, page_lru(page)); + add_page_to_lru_list(page, lruvec); } spin_unlock_irq(&pgdat->lru_lock); } diff --git a/mm/swap.c b/mm/swap.c index 8362cfde85aa..e4616bde21e1 100644 --- a/mm/swap.c +++ b/mm/swap.c @@ -224,7 +224,7 @@ static void pagevec_move_tail_fn(struct page *page, struct lruvec *lruvec, if (PageLRU(page) && !PageUnevictable(page)) { del_page_from_lru_list(page, lruvec, page_lru(page)); ClearPageActive(page); - add_page_to_lru_list_tail(page, lruvec, page_lru(page)); + add_page_to_lru_list_tail(page, lruvec); (*pgmoved)++; } } @@ -281,8 +281,7 @@ static void __activate_page(struct page *page, struct lruvec *lruvec, del_page_from_lru_list(page, lruvec, lru); SetPageActive(page); - lru += LRU_ACTIVE; - add_page_to_lru_list(page, lruvec, lru); + add_page_to_lru_list(page, lruvec); trace_mm_lru_activate(page); __count_vm_event(PGACTIVATE); @@ -523,14 +522,14 @@ static void lru_deactivate_file_fn(struct page *page, struct lruvec *lruvec, * It can make readahead confusing. But race window * is _really_ small and it's non-critical problem. */ - add_page_to_lru_list(page, lruvec, lru); + add_page_to_lru_list(page, lruvec); SetPageReclaim(page); } else { /* * The page's writeback ends up during pagevec * We moves tha page into tail of inactive. */ - add_page_to_lru_list_tail(page, lruvec, lru); + add_page_to_lru_list_tail(page, lruvec); __count_vm_event(PGROTATED); } @@ -549,7 +548,7 @@ static void lru_deactivate_fn(struct page *page, struct lruvec *lruvec, del_page_from_lru_list(page, lruvec, lru + LRU_ACTIVE); ClearPageActive(page); ClearPageReferenced(page); - add_page_to_lru_list(page, lruvec, lru); + add_page_to_lru_list(page, lruvec); __count_vm_events(PGDEACTIVATE, hpage_nr_pages(page)); update_page_reclaim_stat(lruvec, file, 0); @@ -573,7 +572,7 @@ static void lru_lazyfree_fn(struct page *page, struct lruvec *lruvec, * pages */ ClearPageSwapBacked(page); - add_page_to_lru_list(page, lruvec, LRU_INACTIVE_FILE); + add_page_to_lru_list(page, lruvec); __count_vm_events(PGLAZYFREE, hpage_nr_pages(page)); count_memcg_page_event(page, PGLAZYFREE); @@ -891,8 +890,7 @@ void lru_add_page_tail(struct page *page, struct page *page_tail, * Put page_tail on the list at the correct position * so they all end up in order. */ - add_page_to_lru_list_tail(page_tail, lruvec, - page_lru(page_tail)); + add_page_to_lru_list_tail(page_tail, lruvec); } if (!PageUnevictable(page)) @@ -951,7 +949,7 @@ static void __pagevec_lru_add_fn(struct page *page, struct lruvec *lruvec, count_vm_event(UNEVICTABLE_PGCULLED); } - add_page_to_lru_list(page, lruvec, lru); + add_page_to_lru_list(page, lruvec); trace_mm_lru_insertion(page, lru); } diff --git a/mm/vmscan.c b/mm/vmscan.c index e2b824d0f847..214e43dd38c3 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -1965,7 +1965,7 @@ static unsigned noinline_for_stack move_pages_to_lru(struct lruvec *lruvec, SetPageLRU(page); lru = page_lru(page); - add_page_to_lru_list(page, lruvec, lru); + add_page_to_lru_list(page, lruvec); if (put_page_testzero(page)) { __ClearPageLRU(page); @@ -4566,12 +4566,10 @@ void check_move_unevictable_pages(struct pagevec *pvec) continue; if (page_evictable(page)) { - enum lru_list lru = page_lru_base_type(page); - VM_BUG_ON_PAGE(PageActive(page), page); ClearPageUnevictable(page); del_page_from_lru_list(page, lruvec, LRU_UNEVICTABLE); - add_page_to_lru_list(page, lruvec, lru); + add_page_to_lru_list(page, lruvec); pgrescued++; } } From 23b552d0e27cb7d186faa34cb5bc632d71d89ab1 Mon Sep 17 00:00:00 2001 From: Yu Zhao Date: Wed, 24 Feb 2021 12:08:21 -0800 Subject: [PATCH 560/698] BACKPORT: mm/swap.c: don't pass "enum lru_list" to trace_mm_lru_insertion() The parameter is redundant in the sense that it can be extracted from the "struct page" parameter by page_lru() correctly. Moto-CRs-Fixed:(CR) Link: https://lore.kernel.org/linux-mm/20201207220949.830352-5-yuzhao@google.com/ Link: https://lkml.kernel.org/r/20210122220600.906146-5-yuzhao@google.com Change-Id: Ib2bcf361ce6ca4575c705869e7a5a21d6530f4fe Signed-off-by: Yu Zhao Reviewed-by: Alex Shi Cc: Hugh Dickins Cc: Johannes Weiner Cc: Matthew Wilcox Cc: Michal Hocko Cc: Roman Gushchin Cc: Vladimir Davydov Cc: Vlastimil Babka Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds (cherry picked from commit 861404536a3af3c39f1b10959a40def3d8efa2dd) Bug: 261052246 Signed-off-by: Kalesh Singh Reviewed-on: https://gerrit.mot.com/2491792 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- include/trace/events/pagemap.h | 11 ++++------- mm/swap.c | 5 +---- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/include/trace/events/pagemap.h b/include/trace/events/pagemap.h index 8fd1babae761..e1735fe7c76a 100644 --- a/include/trace/events/pagemap.h +++ b/include/trace/events/pagemap.h @@ -27,24 +27,21 @@ TRACE_EVENT(mm_lru_insertion, - TP_PROTO( - struct page *page, - int lru - ), + TP_PROTO(struct page *page), - TP_ARGS(page, lru), + TP_ARGS(page), TP_STRUCT__entry( __field(struct page *, page ) __field(unsigned long, pfn ) - __field(int, lru ) + __field(enum lru_list, lru ) __field(unsigned long, flags ) ), TP_fast_assign( __entry->page = page; __entry->pfn = page_to_pfn(page); - __entry->lru = lru; + __entry->lru = page_lru(page); __entry->flags = trace_pagemap_flags(page); ), diff --git a/mm/swap.c b/mm/swap.c index e4616bde21e1..1be4213f4807 100644 --- a/mm/swap.c +++ b/mm/swap.c @@ -901,7 +901,6 @@ void lru_add_page_tail(struct page *page, struct page *page_tail, static void __pagevec_lru_add_fn(struct page *page, struct lruvec *lruvec, void *arg) { - enum lru_list lru; int was_unevictable = TestClearPageUnevictable(page); VM_BUG_ON_PAGE(PageLRU(page), page); @@ -936,13 +935,11 @@ static void __pagevec_lru_add_fn(struct page *page, struct lruvec *lruvec, smp_mb(); if (page_evictable(page)) { - lru = page_lru(page); update_page_reclaim_stat(lruvec, page_is_file_cache(page), PageActive(page)); if (was_unevictable) count_vm_event(UNEVICTABLE_PGRESCUED); } else { - lru = LRU_UNEVICTABLE; ClearPageActive(page); SetPageUnevictable(page); if (!was_unevictable) @@ -950,7 +947,7 @@ static void __pagevec_lru_add_fn(struct page *page, struct lruvec *lruvec, } add_page_to_lru_list(page, lruvec); - trace_mm_lru_insertion(page, lru); + trace_mm_lru_insertion(page); } /* From 155c9883ff3b536962797087060a3206a02756e4 Mon Sep 17 00:00:00 2001 From: Yu Zhao Date: Wed, 24 Feb 2021 12:08:25 -0800 Subject: [PATCH 561/698] BACKPORT: mm/swap.c: don't pass "enum lru_list" to del_page_from_lru_list() The parameter is redundant in the sense that it can be potentially extracted from the "struct page" parameter by page_lru(). We need to make sure that existing PageActive() or PageUnevictable() remains until the function returns. A few places don't conform, and simple reordering fixes them. This patch may have left page_off_lru() seemingly odd, and we'll take care of it in the next patch. Moto-CRs-Fixed:(CR) Link: https://lore.kernel.org/linux-mm/20201207220949.830352-6-yuzhao@google.com/ Link: https://lkml.kernel.org/r/20210122220600.906146-6-yuzhao@google.com Change-Id: I0a59491e861e60d7e4856a8232e131f81273c8f9 Signed-off-by: Yu Zhao Cc: Alex Shi Cc: Hugh Dickins Cc: Johannes Weiner Cc: Matthew Wilcox Cc: Michal Hocko Cc: Roman Gushchin Cc: Vladimir Davydov Cc: Vlastimil Babka Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds (cherry picked from commit 46ae6b2cc2a47904a368d238425531ea91f3a2a5) Bug: 261052246 Signed-off-by: Kalesh Singh Reviewed-on: https://gerrit.mot.com/2491793 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- include/linux/mm_inline.h | 5 +++-- mm/compaction.c | 2 +- mm/memcontrol.c | 2 +- mm/mlock.c | 2 +- mm/swap.c | 23 ++++++++++------------- mm/vmscan.c | 9 +++------ 6 files changed, 19 insertions(+), 24 deletions(-) diff --git a/include/linux/mm_inline.h b/include/linux/mm_inline.h index d01a06dae3b7..04872cd8fb1c 100644 --- a/include/linux/mm_inline.h +++ b/include/linux/mm_inline.h @@ -123,10 +123,11 @@ static __always_inline void add_page_to_lru_list_tail(struct page *page, } static __always_inline void del_page_from_lru_list(struct page *page, - struct lruvec *lruvec, enum lru_list lru) + struct lruvec *lruvec) { list_del(&page->lru); - update_lru_size(lruvec, lru, page_zonenum(page), -hpage_nr_pages(page)); + update_lru_size(lruvec, page_lru(page), page_zonenum(page), + -hpage_nr_pages(page)); } #endif diff --git a/mm/compaction.c b/mm/compaction.c index 2293de8dffe5..195dce9221c2 100644 --- a/mm/compaction.c +++ b/mm/compaction.c @@ -984,7 +984,7 @@ isolate_migratepages_block(struct compact_control *cc, unsigned long low_pfn, VM_BUG_ON_PAGE(PageCompound(page), page); /* Successfully isolated */ - del_page_from_lru_list(page, lruvec, page_lru(page)); + del_page_from_lru_list(page, lruvec); inc_node_page_state(page, NR_ISOLATED_ANON + page_is_file_cache(page)); diff --git a/mm/memcontrol.c b/mm/memcontrol.c index d464f39389a2..9171eccfd971 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -2741,7 +2741,7 @@ static void lock_page_lru(struct page *page, int *isolated) lruvec = mem_cgroup_page_lruvec(page, pgdat); ClearPageLRU(page); - del_page_from_lru_list(page, lruvec, page_lru(page)); + del_page_from_lru_list(page, lruvec); *isolated = 1; } else *isolated = 0; diff --git a/mm/mlock.c b/mm/mlock.c index 395bf08f86d8..94a4828072a7 100644 --- a/mm/mlock.c +++ b/mm/mlock.c @@ -115,7 +115,7 @@ static bool __munlock_isolate_lru_page(struct page *page, bool getpage) if (getpage) get_page(page); ClearPageLRU(page); - del_page_from_lru_list(page, lruvec, page_lru(page)); + del_page_from_lru_list(page, lruvec); return true; } diff --git a/mm/swap.c b/mm/swap.c index 1be4213f4807..26e2dd8cf33e 100644 --- a/mm/swap.c +++ b/mm/swap.c @@ -68,7 +68,8 @@ static void __page_cache_release(struct page *page) lruvec = mem_cgroup_page_lruvec(page, pgdat); VM_BUG_ON_PAGE(!PageLRU(page), page); __ClearPageLRU(page); - del_page_from_lru_list(page, lruvec, page_off_lru(page)); + del_page_from_lru_list(page, lruvec); + page_off_lru(page); spin_unlock_irqrestore(&pgdat->lru_lock, flags); } __ClearPageWaiters(page); @@ -222,7 +223,7 @@ static void pagevec_move_tail_fn(struct page *page, struct lruvec *lruvec, int *pgmoved = arg; if (PageLRU(page) && !PageUnevictable(page)) { - del_page_from_lru_list(page, lruvec, page_lru(page)); + del_page_from_lru_list(page, lruvec); ClearPageActive(page); add_page_to_lru_list_tail(page, lruvec); (*pgmoved)++; @@ -277,9 +278,8 @@ static void __activate_page(struct page *page, struct lruvec *lruvec, { if (PageLRU(page) && !PageActive(page) && !PageUnevictable(page)) { int file = page_is_file_cache(page); - int lru = page_lru_base_type(page); - del_page_from_lru_list(page, lruvec, lru); + del_page_from_lru_list(page, lruvec); SetPageActive(page); add_page_to_lru_list(page, lruvec); trace_mm_lru_activate(page); @@ -495,7 +495,7 @@ void __lru_cache_add_active_or_unevictable(struct page *page, static void lru_deactivate_file_fn(struct page *page, struct lruvec *lruvec, void *arg) { - int lru, file; + int file; bool active; if (!PageLRU(page)) @@ -510,9 +510,8 @@ static void lru_deactivate_file_fn(struct page *page, struct lruvec *lruvec, active = PageActive(page); file = page_is_file_cache(page); - lru = page_lru_base_type(page); - del_page_from_lru_list(page, lruvec, lru + active); + del_page_from_lru_list(page, lruvec); ClearPageActive(page); ClearPageReferenced(page); @@ -543,9 +542,8 @@ static void lru_deactivate_fn(struct page *page, struct lruvec *lruvec, { if (PageLRU(page) && PageActive(page) && !PageUnevictable(page)) { int file = page_is_file_cache(page); - int lru = page_lru_base_type(page); - del_page_from_lru_list(page, lruvec, lru + LRU_ACTIVE); + del_page_from_lru_list(page, lruvec); ClearPageActive(page); ClearPageReferenced(page); add_page_to_lru_list(page, lruvec); @@ -560,10 +558,8 @@ static void lru_lazyfree_fn(struct page *page, struct lruvec *lruvec, { if (PageLRU(page) && PageAnon(page) && PageSwapBacked(page) && !PageSwapCache(page) && !PageUnevictable(page)) { - bool active = PageActive(page); - del_page_from_lru_list(page, lruvec, - LRU_INACTIVE_ANON + active); + del_page_from_lru_list(page, lruvec); ClearPageActive(page); ClearPageReferenced(page); /* @@ -825,7 +821,8 @@ void release_pages(struct page **pages, int nr) lruvec = mem_cgroup_page_lruvec(page, locked_pgdat); VM_BUG_ON_PAGE(!PageLRU(page), page); __ClearPageLRU(page); - del_page_from_lru_list(page, lruvec, page_off_lru(page)); + del_page_from_lru_list(page, lruvec); + page_off_lru(page); } __ClearPageWaiters(page); diff --git a/mm/vmscan.c b/mm/vmscan.c index 214e43dd38c3..677b408b154d 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -1874,10 +1874,9 @@ int isolate_lru_page(struct page *page) spin_lock_irq(&pgdat->lru_lock); lruvec = mem_cgroup_page_lruvec(page, pgdat); if (PageLRU(page)) { - int lru = page_lru(page); get_page(page); ClearPageLRU(page); - del_page_from_lru_list(page, lruvec, lru); + del_page_from_lru_list(page, lruvec); ret = 0; } spin_unlock_irq(&pgdat->lru_lock); @@ -1949,7 +1948,6 @@ static unsigned noinline_for_stack move_pages_to_lru(struct lruvec *lruvec, int nr_pages, nr_moved = 0; LIST_HEAD(pages_to_free); struct page *page; - enum lru_list lru; while (!list_empty(list)) { page = lru_to_page(list); @@ -1964,13 +1962,12 @@ static unsigned noinline_for_stack move_pages_to_lru(struct lruvec *lruvec, lruvec = mem_cgroup_page_lruvec(page, pgdat); SetPageLRU(page); - lru = page_lru(page); add_page_to_lru_list(page, lruvec); if (put_page_testzero(page)) { __ClearPageLRU(page); + del_page_from_lru_list(page, lruvec); __ClearPageActive(page); - del_page_from_lru_list(page, lruvec, lru); if (unlikely(PageCompound(page))) { spin_unlock_irq(&pgdat->lru_lock); @@ -4567,8 +4564,8 @@ void check_move_unevictable_pages(struct pagevec *pvec) if (page_evictable(page)) { VM_BUG_ON_PAGE(PageActive(page), page); + del_page_from_lru_list(page, lruvec); ClearPageUnevictable(page); - del_page_from_lru_list(page, lruvec, LRU_UNEVICTABLE); add_page_to_lru_list(page, lruvec); pgrescued++; } From 3222504626a11c814cd3310332efa2a6df147d7a Mon Sep 17 00:00:00 2001 From: Yu Zhao Date: Wed, 24 Feb 2021 12:08:28 -0800 Subject: [PATCH 562/698] BACKPORT: mm: add __clear_page_lru_flags() to replace page_off_lru() Similar to page_off_lru(), the new function does non-atomic clearing of PageLRU() in addition to PageActive() and PageUnevictable(), on a page that has no references left. If PageActive() and PageUnevictable() are both set, refuse to clear either and leave them to bad_page(). This is a behavior change that is meant to help debug. Moto-CRs-Fixed:(CR) Link: https://lore.kernel.org/linux-mm/20201207220949.830352-7-yuzhao@google.com/ Link: https://lkml.kernel.org/r/20210122220600.906146-7-yuzhao@google.com Change-Id: I7b25e4b8e8ae2b926678da62afb20560801d5be2 Signed-off-by: Yu Zhao Cc: Alex Shi Cc: Hugh Dickins Cc: Johannes Weiner Cc: Matthew Wilcox Cc: Michal Hocko Cc: Roman Gushchin Cc: Vladimir Davydov Cc: Vlastimil Babka Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds (cherry picked from commit 875601796267214f286d3581fe74f2805d060fe8) Bug: 261052246 Signed-off-by: Kalesh Singh Reviewed-on: https://gerrit.mot.com/2491794 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- include/linux/mm_inline.h | 28 ++++++++++------------------ mm/swap.c | 6 ++---- mm/vmscan.c | 3 +-- 3 files changed, 13 insertions(+), 24 deletions(-) diff --git a/include/linux/mm_inline.h b/include/linux/mm_inline.h index 04872cd8fb1c..3cdbd538aa5f 100644 --- a/include/linux/mm_inline.h +++ b/include/linux/mm_inline.h @@ -60,27 +60,19 @@ static inline enum lru_list page_lru_base_type(struct page *page) } /** - * page_off_lru - which LRU list was page on? clearing its lru flags. - * @page: the page to test - * - * Returns the LRU list a page was on, as an index into the array of LRU - * lists; and clears its Unevictable or Active flags, ready for freeing. + * __clear_page_lru_flags - clear page lru flags before releasing a page + * @page: the page that was on lru and now has a zero reference */ -static __always_inline enum lru_list page_off_lru(struct page *page) +static __always_inline void __clear_page_lru_flags(struct page *page) { - enum lru_list lru; + __ClearPageLRU(page); - if (PageUnevictable(page)) { - __ClearPageUnevictable(page); - lru = LRU_UNEVICTABLE; - } else { - lru = page_lru_base_type(page); - if (PageActive(page)) { - __ClearPageActive(page); - lru += LRU_ACTIVE; - } - } - return lru; + /* this shouldn't happen, so leave the flags to bad_page() */ + if (PageActive(page) && PageUnevictable(page)) + return; + + __ClearPageActive(page); + __ClearPageUnevictable(page); } /** diff --git a/mm/swap.c b/mm/swap.c index 26e2dd8cf33e..dda66aeb7b11 100644 --- a/mm/swap.c +++ b/mm/swap.c @@ -67,9 +67,8 @@ static void __page_cache_release(struct page *page) spin_lock_irqsave(&pgdat->lru_lock, flags); lruvec = mem_cgroup_page_lruvec(page, pgdat); VM_BUG_ON_PAGE(!PageLRU(page), page); - __ClearPageLRU(page); del_page_from_lru_list(page, lruvec); - page_off_lru(page); + __clear_page_lru_flags(page); spin_unlock_irqrestore(&pgdat->lru_lock, flags); } __ClearPageWaiters(page); @@ -820,9 +819,8 @@ void release_pages(struct page **pages, int nr) lruvec = mem_cgroup_page_lruvec(page, locked_pgdat); VM_BUG_ON_PAGE(!PageLRU(page), page); - __ClearPageLRU(page); del_page_from_lru_list(page, lruvec); - page_off_lru(page); + __clear_page_lru_flags(page); } __ClearPageWaiters(page); diff --git a/mm/vmscan.c b/mm/vmscan.c index 677b408b154d..8c32f6d7a317 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -1965,9 +1965,8 @@ static unsigned noinline_for_stack move_pages_to_lru(struct lruvec *lruvec, add_page_to_lru_list(page, lruvec); if (put_page_testzero(page)) { - __ClearPageLRU(page); del_page_from_lru_list(page, lruvec); - __ClearPageActive(page); + __clear_page_lru_flags(page); if (unlikely(PageCompound(page))) { spin_unlock_irq(&pgdat->lru_lock); From 73c8f574240fc30958b93bdae9a50ecc5667e799 Mon Sep 17 00:00:00 2001 From: Yu Zhao Date: Fri, 2 Oct 2020 02:08:58 -0600 Subject: [PATCH 563/698] BACKPORT: mm: VM_BUG_ON lru page flags Move scattered VM_BUG_ONs to two essential places that cover all lru list additions and deletions. Moto-CRs-Fixed:(CR) Link: https://lore.kernel.org/linux-mm/20201207220949.830352-8-yuzhao@google.com/ Link: https://lkml.kernel.org/r/20210122220600.906146-8-yuzhao@google.com Change-Id: I7c8682617398a8eb145607788d2ead33726d8f08 Signed-off-by: Yu Zhao Cc: Alex Shi Cc: Hugh Dickins Cc: Johannes Weiner Cc: Matthew Wilcox Cc: Michal Hocko Cc: Roman Gushchin Cc: Vladimir Davydov Cc: Vlastimil Babka Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds (cherry picked from commit bc7112719e1e80e4208eef3fc9bd8d2b6c263e7d) Bug: 261052246 Signed-off-by: Kalesh Singh Reviewed-on: https://gerrit.mot.com/2491795 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- include/linux/mm_inline.h | 4 ++++ mm/swap.c | 2 -- mm/vmscan.c | 1 - 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/include/linux/mm_inline.h b/include/linux/mm_inline.h index 3cdbd538aa5f..24dbfcfe4a6d 100644 --- a/include/linux/mm_inline.h +++ b/include/linux/mm_inline.h @@ -65,6 +65,8 @@ static inline enum lru_list page_lru_base_type(struct page *page) */ static __always_inline void __clear_page_lru_flags(struct page *page) { + VM_BUG_ON_PAGE(!PageLRU(page), page); + __ClearPageLRU(page); /* this shouldn't happen, so leave the flags to bad_page() */ @@ -86,6 +88,8 @@ static __always_inline enum lru_list page_lru(struct page *page) { enum lru_list lru; + VM_BUG_ON_PAGE(PageActive(page) && PageUnevictable(page), page); + if (PageUnevictable(page)) lru = LRU_UNEVICTABLE; else { diff --git a/mm/swap.c b/mm/swap.c index dda66aeb7b11..34bedd0e7619 100644 --- a/mm/swap.c +++ b/mm/swap.c @@ -66,7 +66,6 @@ static void __page_cache_release(struct page *page) spin_lock_irqsave(&pgdat->lru_lock, flags); lruvec = mem_cgroup_page_lruvec(page, pgdat); - VM_BUG_ON_PAGE(!PageLRU(page), page); del_page_from_lru_list(page, lruvec); __clear_page_lru_flags(page); spin_unlock_irqrestore(&pgdat->lru_lock, flags); @@ -818,7 +817,6 @@ void release_pages(struct page **pages, int nr) } lruvec = mem_cgroup_page_lruvec(page, locked_pgdat); - VM_BUG_ON_PAGE(!PageLRU(page), page); del_page_from_lru_list(page, lruvec); __clear_page_lru_flags(page); } diff --git a/mm/vmscan.c b/mm/vmscan.c index 8c32f6d7a317..084f48f95afd 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -4562,7 +4562,6 @@ void check_move_unevictable_pages(struct pagevec *pvec) continue; if (page_evictable(page)) { - VM_BUG_ON_PAGE(PageActive(page), page); del_page_from_lru_list(page, lruvec); ClearPageUnevictable(page); add_page_to_lru_list(page, lruvec); From 048d2c17f7412a1b15b16d290e942921519e246d Mon Sep 17 00:00:00 2001 From: Yu Zhao Date: Sun, 18 Sep 2022 01:59:58 -0600 Subject: [PATCH 564/698] BACKPORT: mm: x86, arm64: add arch_has_hw_pte_young() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Patch series "Multi-Gen LRU Framework", v14. What's new ========== 1. OpenWrt, in addition to Android, Arch Linux Zen, Armbian, ChromeOS, Liquorix, post-factum and XanMod, is now shipping MGLRU on 5.15. 2. Fixed long-tailed direct reclaim latency seen on high-memory (TBs) machines. The old direct reclaim backoff, which tries to enforce a minimum fairness among all eligible memcgs, over-swapped by about (total_mem>>DEF_PRIORITY)-nr_to_reclaim. The new backoff, which pulls the plug on swapping once the target is met, trades some fairness for curtailed latency: https://lore.kernel.org/r/20220918080010.2920238-10-yuzhao@google.com/ 3. Fixed minior build warnings and conflicts. More comments and nits. TLDR ==== The current page reclaim is too expensive in terms of CPU usage and it often makes poor choices about what to evict. This patchset offers an alternative solution that is performant, versatile and straightforward. Patchset overview ================= The design and implementation overview is in patch 14: https://lore.kernel.org/r/20220918080010.2920238-15-yuzhao@google.com/ 01. mm: x86, arm64: add arch_has_hw_pte_young() 02. mm: x86: add CONFIG_ARCH_HAS_NONLEAF_PMD_YOUNG Take advantage of hardware features when trying to clear the accessed bit in many PTEs. 03. mm/vmscan.c: refactor shrink_node() 04. Revert "include/linux/mm_inline.h: fold __update_lru_size() into its sole caller" Minor refactors to improve readability for the following patches. 05. mm: multi-gen LRU: groundwork Adds the basic data structure and the functions that insert pages to and remove pages from the multi-gen LRU (MGLRU) lists. 06. mm: multi-gen LRU: minimal implementation A minimal implementation without optimizations. 07. mm: multi-gen LRU: exploit locality in rmap Exploits spatial locality to improve efficiency when using the rmap. 08. mm: multi-gen LRU: support page table walks Further exploits spatial locality by optionally scanning page tables. 09. mm: multi-gen LRU: optimize multiple memcgs Optimizes the overall performance for multiple memcgs running mixed types of workloads. 10. mm: multi-gen LRU: kill switch Adds a kill switch to enable or disable MGLRU at runtime. 11. mm: multi-gen LRU: thrashing prevention 12. mm: multi-gen LRU: debugfs interface Provide userspace with features l(CR) thrashing prevention, working set estimation and proactive reclaim. 13. mm: multi-gen LRU: admin guide 14. mm: multi-gen LRU: design doc Add an admin guide and a design doc. Benchmark results ================= Independent lab results ----------------------- Based on the popularity of searches [01] and the memory usage in Google's public cloud, the most popular open-source memory-hungry applications, in alphabetical order, are: Apache Cassandra Memcached Apache Hadoop MongoDB Apache Spark PostgreSQL MariaDB (MySQL) Redis An independent lab evaluated MGLRU with the most widely used benchmark suites for the above applications. They posted 960 data points along with kernel metrics and perf profiles collected over more than 500 hours of total benchmark time. Their final reports show that, with 95% confidence intervals (CIs), the above applications all performed significantly better for at least part of their benchmark matrices. On 5.14: 1. Apache Spark [02] took 95% CIs [9.28, 11.19]% and [12.20, 14.93]% less wall time to sort three billion random integers, respectively, under the medium- and the high-concurrency conditions, when overcommitting memory. There were no statistically significant changes in wall time for the rest of the benchmark matrix. 2. MariaDB [03] achieved 95% CIs [5.24, 10.71]% and [20.22, 25.97]% more transactions per minute (TPM), respectively, under the medium- and the high-concurrency conditions, when overcommitting memory. There were no statistically significant changes in TPM for the rest of the benchmark matrix. 3. Memcached [04] achieved 95% CIs [23.54, 32.25]%, [20.76, 41.61]% and [21.59, 30.02]% more operations per second (OPS), respectively, for sequential access, random access and Gaussian (distribution) access, when THP=always; 95% CIs [13.85, 15.97]% and [23.94, 29.92]% more OPS, respectively, for random access and Gaussian access, when THP=never. There were no statistically significant changes in OPS for the rest of the benchmark matrix. 4. MongoDB [05] achieved 95% CIs [2.23, 3.44]%, [6.97, 9.73]% and [2.16, 3.55]% more operations per second (OPS), respectively, for exponential (distribution) access, random access and Zipfian (distribution) access, when underutilizing memory; 95% CIs [8.83, 10.03]%, [21.12, 23.14]% and [5.53, 6.46]% more OPS, respectively, for exponential access, random access and Zipfian access, when overcommitting memory. On 5.15: 5. Apache Cassandra [06] achieved 95% CIs [1.06, 4.10]%, [1.94, 5.43]% and [4.11, 7.50]% more operations per second (OPS), respectively, for exponential (distribution) access, random access and Zipfian (distribution) access, when swap was off; 95% CIs [0.50, 2.60]%, [6.51, 8.77]% and [3.29, 6.75]% more OPS, respectively, for exponential access, random access and Zipfian access, when swap was on. 6. Apache Hadoop [07] took 95% CIs [5.31, 9.69]% and [2.02, 7.86]% less average wall time to finish twelve parallel TeraSort jobs, respectively, under the medium- and the high-concurrency conditions, when swap was on. There were no statistically significant changes in average wall time for the rest of the benchmark matrix. 7. PostgreSQL [08] achieved 95% CI [1.75, 6.42]% more transactions per minute (TPM) under the high-concurrency condition, when swap was off; 95% CIs [12.82, 18.69]% and [22.70, 46.86]% more TPM, respectively, under the medium- and the high-concurrency conditions, when swap was on. There were no statistically significant changes in TPM for the rest of the benchmark matrix. 8. Redis [09] achieved 95% CIs [0.58, 5.94]%, [6.55, 14.58]% and [11.47, 19.36]% more total operations per second (OPS), respectively, for sequential access, random access and Gaussian (distribution) access, when THP=always; 95% CIs [1.27, 3.54]%, [10.11, 14.81]% and [8.75, 13.64]% more total OPS, respectively, for sequential access, random access and Gaussian access, when THP=never. Our lab results --------------- To supplement the above results, we ran the following benchmark suites on 5.16-rc7 and found no regressions [10]. fs_fio_bench_hdd_mq pft fs_lmbench pgsql-hammerdb fs_parallelio redis fs_postmark stream hackbench sysbenchthread kernbench tpcc_spark memcached unixbench multichase vm-scalability mutilate will-it-scale nginx [01] https://trends.google.com [02] https://lore.kernel.org/r/20211102002002.92051-1-bot@edi.works/ [03] https://lore.kernel.org/r/20211009054315.47073-1-bot@edi.works/ [04] https://lore.kernel.org/r/20211021194103.65648-1-bot@edi.works/ [05] https://lore.kernel.org/r/20211109021346.50266-1-bot@edi.works/ [06] https://lore.kernel.org/r/20211202062806.80365-1-bot@edi.works/ [07] https://lore.kernel.org/r/20211209072416.33606-1-bot@edi.works/ [08] https://lore.kernel.org/r/20211218071041.24077-1-bot@edi.works/ [09] https://lore.kernel.org/r/20211122053248.57311-1-bot@edi.works/ [10] https://lore.kernel.org/r/20220104202247.2903702-1-yuzhao@google.com/ Read-world applications ======================= Third-party testimonials ------------------------ Konstantin reported [11]: I have Archlinux with 8G RAM + zswap + swap. While developing, I have lots of apps opened such as multiple LSP-servers for different langs, chats, two browsers, etc... Usually, my system gets quickly to a point of SWAP-storms, where I have to kill LSP-servers, restart browsers to free memory, etc, otherwise the system lags heavily and is barely usable. 1.5 day ago I migrated from 5.11.15 kernel to 5.12 + the LRU patchset, and I started up by opening lots of apps to create memory pressure, and worked for a day l(CR) this. Till now I had not a single SWAP-storm, and mind you I got 3.4G in SWAP. I was never getting to the point of 3G in SWAP before without a single SWAP-storm. Vaibhav from IBM reported [12]: In a synthetic MongoDB Benchmark, seeing an average of ~19% throughput improvement on POWER10(Radix MMU + 64K Page Size) with MGLRU patches on top of 5.16 kernel for MongoDB + YCSB across three different request distributions, namely, Exponential, Uniform and Zipfan. Shuang from U of Rochester reported [13]: With the MGLRU, fio achieved 95% CIs [38.95, 40.26]%, [4.12, 6.64]% and [9.26, 10.36]% higher throughput, respectively, for random access, Zipfian (distribution) access and Gaussian (distribution) access, when the average number of jobs per CPU is 1; 95% CIs [42.32, 49.15]%, [9.44, 9.89]% and [20.99, 22.86]% higher throughput, respectively, for random access, Zipfian access and Gaussian access, when the average number of jobs per CPU is 2. Daniel from Michigan Tech reported [14]: With Memcached allocating ~100GB of byte-addressable Optante, performance improvement in terms of throughput (measured as queries per second) was about 10% for a series of workloads. Large-scale deployments ----------------------- We've rolled out MGLRU to tens of millions of ChromeOS users and about a million Android users. Google's fleetwide profiling [15] shows an overall 40% decrease in kswapd CPU usage, in addition to improvements in other UX metrics, e.g., an 85% decrease in the number of low-memory kills at the 75th percentile and an 18% decrease in app launch time at the 50th percentile. Moto-CRs-Fixed:(CR) The downstream kernels that have been using MGLRU include: 1. Android [16] 2. Arch Linux Zen [17] 3. Armbian [18] 4. ChromeOS [19] 5. Liquorix [20] 6. OpenWrt [21] 7. post-factum [22] 8. XanMod [23] [11] https://lore.kernel.org/r/140226722f2032c86301fbd326d91baefe3d7d23.camel@yandex.ru/ [12] https://lore.kernel.org/r/87czj3mux0.fsf@vajain21.in.ibm.com/ [13] https://lore.kernel.org/r/20220105024423.26409-1-szhai2@cs.rochester.edu/ [14] https://lore.kernel.org/r/CA+4-3vksGvKd18FgRinxhqHetBS1hQekJE2gwco8Ja-bJWKtFw@mail.gmail.com/ [15] https://dl.acm.org/doi/10.1145/2749469.2750392 [16] https://android.com [17] https://archlinux.org [18] https://armbian.com [19] https://chromium.org [20] https://liquorix.net [21] https://openwrt.org [22] https://codeberg.org/pf-kernel [23] https://xanmod.org Summary ======= The facts are: 1. The independent lab results and the real-world applications indicate substantial improvements; there are no known regressions. 2. Thrashing prevention, working set estimation and proactive reclaim work out of the box; there are no equivalent solutions. 3. There is a lot of new code; no smaller changes have been demonstrated similar effects. Our options, accordingly, are: 1. Given the amount of evidence, the reported improvements will l(CR)ly materialize for a wide range of workloads. 2. Gauging the interest from the past discussions, the new features will l(CR)ly be put to use for both personal computers and data centers. 3. Based on Google's track record, the new code will l(CR)ly be well maintained in the long term. It'd be more difficult if not impossible to achieve similar effects with other approaches. This patch (of 14): Some architectures automatically set the accessed bit in PTEs, e.g., x86 and arm64 v8.2. On architectures that do not have this capability, clearing the accessed bit in a PTE usually triggers a page fault following the TLB miss of this PTE (to emulate the accessed bit). Being aware of this capability can help make better decisions, e.g., whether to spread the work out over a period of time to reduce bursty page faults when trying to clear the accessed bit in many PTEs. Note that theoretically this capability can be unreliable, e.g., hotplugged CPUs might be different from builtin ones. Therefore it should not be used in architecture-independent code that involves correctness, e.g., to determine whether TLB flushes are required (in combination with the accessed bit). Link: https://lkml.kernel.org/r/20220918080010.2920238-1-yuzhao@google.com Link: https://lkml.kernel.org/r/20220918080010.2920238-2-yuzhao@google.com Change-Id: I7c94aa3ffeb0a8e570c2d7db15183f87658d0141 Signed-off-by: Yu Zhao Reviewed-by: Barry Song Acked-by: Brian Geffon Acked-by: Jan Alexander Steffens (heftig) Acked-by: Oleksandr Natalenko Acked-by: Steven Barrett Acked-by: Suleiman Souhlal Acked-by: Will Deacon Tested-by: Daniel Byrne Tested-by: Donald Carr Tested-by: Holger Hoffstätte Tested-by: Konstantin Kharlamov Tested-by: Shuang Zhai Tested-by: Sofia Trinh Tested-by: Vaibhav Jain Cc: Andi Kleen Cc: Aneesh Kumar K.V Cc: Catalin Marinas Cc: Dave Hansen Cc: Hillf Danton Cc: Jens Axboe Cc: Johannes Weiner Cc: Jonathan Corbet Cc: Linus Torvalds Cc: linux-arm-kernel@lists.infradead.org Cc: Matthew Wilcox Cc: Mel Gorman Cc: Michael Larabel Cc: Michal Hocko Cc: M(CR) Rapoport Cc: Peter Zijlstra Cc: Tejun Heo Cc: Vlastimil Babka Cc: Miaohe Lin Cc: M(CR) Rapoport Cc: Qi Zheng Signed-off-by: Andrew Morton (cherry picked from commit e1fd09e3d1dd4a1a8b3b33bc1fd647eee9f4e475) [Kalesh Singh - Fix trivial conflict in arch/arm64/include/asm/pgtable.h] Bug: 261052246 Signed-off-by: Kalesh Singh Reviewed-on: https://gerrit.mot.com/2491796 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- arch/arm64/include/asm/pgtable.h | 8 +------- arch/x86/include/asm/pgtable.h | 6 +++--- include/asm-generic/pgtable.h | 13 +++++++++++++ mm/memory.c | 14 +------------- 4 files changed, 18 insertions(+), 23 deletions(-) diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h index 4f48704996dc..6a1976149af4 100644 --- a/arch/arm64/include/asm/pgtable.h +++ b/arch/arm64/include/asm/pgtable.h @@ -894,13 +894,7 @@ static inline void update_mmu_cache(struct vm_area_struct *vma, * page after fork() + CoW for pfn mappings. We don't always have a * hardware-managed access flag on arm64. */ -static inline bool arch_faults_on_old_pte(void) -{ - WARN_ON(preemptible()); - - return !cpu_has_hw_af(); -} -#define arch_faults_on_old_pte arch_faults_on_old_pte +#define arch_has_hw_pte_young cpu_has_hw_af #endif /* !__ASSEMBLY__ */ diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h index d711bc431a2c..0c6e2b758857 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h @@ -1472,10 +1472,10 @@ static inline bool arch_has_pfn_modify_check(void) return boot_cpu_has_bug(X86_BUG_L1TF); } -#define arch_faults_on_old_pte arch_faults_on_old_pte -static inline bool arch_faults_on_old_pte(void) +#define arch_has_hw_pte_young arch_has_hw_pte_young +static inline bool arch_has_hw_pte_young(void) { - return false; + return true; } #include diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h index f5895a174b3b..3ac04e08b568 100644 --- a/include/asm-generic/pgtable.h +++ b/include/asm-generic/pgtable.h @@ -121,6 +121,19 @@ static inline int pmdp_clear_flush_young(struct vm_area_struct *vma, #endif /* CONFIG_TRANSPARENT_HUGEPAGE */ #endif +#ifndef arch_has_hw_pte_young +/* + * Return whether the accessed bit is supported on the local CPU. + * + * This stub assumes accessing through an old PTE triggers a page fault. + * Architectures that automatically set the access bit should overwrite it. + */ +static inline bool arch_has_hw_pte_young(void) +{ + return false; +} +#endif + #ifndef __HAVE_ARCH_PTEP_GET_AND_CLEAR static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long address, diff --git a/mm/memory.c b/mm/memory.c index 609e32cfbb0e..175ea2765182 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -120,18 +120,6 @@ int randomize_va_space __read_mostly = 2; #endif -#ifndef arch_faults_on_old_pte -static inline bool arch_faults_on_old_pte(void) -{ - /* - * Those arches which don't have hw access flag feature need to - * implement their own helper. By default, "true" means pagefault - * will be hit on old pte. - */ - return true; -} -#endif - static int __init disable_randmaps(char *s) { randomize_va_space = 0; @@ -2371,7 +2359,7 @@ static inline bool cow_user_page(struct page *dst, struct page *src, * On architectures with software "accessed" bits, we would * take a double page fault, so mark it accessed here. */ - if (arch_faults_on_old_pte() && !pte_young(vmf->orig_pte)) { + if (!arch_has_hw_pte_young() && !pte_young(vmf->orig_pte)) { pte_t entry; vmf->pte = pte_offset_map_lock(mm, vmf->pmd, addr, &vmf->ptl); From 16b45fe747b044727be2a1dbd96b0600260f20ac Mon Sep 17 00:00:00 2001 From: Yu Zhao Date: Sun, 18 Sep 2022 01:59:59 -0600 Subject: [PATCH 565/698] BACKPORT: mm: x86: add CONFIG_ARCH_HAS_NONLEAF_PMD_YOUNG MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some architectures support the accessed bit in non-leaf PMD entries, e.g., x86 sets the accessed bit in a non-leaf PMD entry when using it as part of linear address translation [1]. Page table walkers that clear the accessed bit may use this capability to reduce their search space. Note that: 1. Although an inline function is preferable, this capability is added as a configuration option for consistency with the existing macros. 2. Due to the little interest in other varieties, this capability was only tested on Intel and AMD CPUs. Thanks to the following developers for their efforts [2][3]. RPerry Dunlap Stephen Rothwell Moto-CRs-Fixed:(CR) [1]: Intel 64 and IA-32 Architectures Software Developer's Manual Volume 3 (June 2021), section 4.8 [2] https://lore.kernel.org/r/bfdcc7c8-922f-61a9-aa15-7e7250f04af7@infradead.org/ [3] https://lore.kernel.org/r/20220413151513.5a0d7a7e@canb.auug.org.au/ Link: https://lkml.kernel.org/r/20220918080010.2920238-3-yuzhao@google.com Change-Id: Iccf98138153b8d466c393232df80187dd3687036 Signed-off-by: Yu Zhao Reviewed-by: Barry Song Acked-by: Brian Geffon Acked-by: Jan Alexander Steffens (heftig) Acked-by: Oleksandr Natalenko Acked-by: Steven Barrett Acked-by: Suleiman Souhlal Tested-by: Daniel Byrne Tested-by: Donald Carr Tested-by: Holger Hoffstätte Tested-by: Konstantin Kharlamov Tested-by: Shuang Zhai Tested-by: Sofia Trinh Tested-by: Vaibhav Jain Cc: Andi Kleen Cc: Aneesh Kumar K.V Cc: Catalin Marinas Cc: Dave Hansen Cc: Hillf Danton Cc: Jens Axboe Cc: Johannes Weiner Cc: Jonathan Corbet Cc: Linus Torvalds Cc: Matthew Wilcox Cc: Mel Gorman Cc: Miaohe Lin Cc: Michael Larabel Cc: Michal Hocko Cc: M(CR) Rapoport Cc: M(CR) Rapoport Cc: Peter Zijlstra Cc: Qi Zheng Cc: Tejun Heo Cc: Vlastimil Babka Cc: Will Deacon Signed-off-by: Andrew Morton (cherry picked from commit eed9a328aa1ae6ac1edaa026957e6882f57de0dd) [Kalesh Singh - Fix trivial conflict in arch/Kconfig] Bug: 261052246 Signed-off-by: Kalesh Singh Reviewed-on: https://gerrit.mot.com/2491797 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- arch/Kconfig | 8 ++++++++ arch/x86/Kconfig | 1 + arch/x86/include/asm/pgtable.h | 3 ++- arch/x86/mm/pgtable.c | 5 ++++- include/asm-generic/pgtable.h | 4 ++-- 5 files changed, 17 insertions(+), 4 deletions(-) diff --git a/arch/Kconfig b/arch/Kconfig index 136a633b28a7..e7d5df0a8186 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -1071,6 +1071,14 @@ config RELR config ARCH_HAS_MEM_ENCRYPT bool +config ARCH_HAS_NONLEAF_PMD_YOUNG + bool + help + Architectures that select this option are capable of setting the + accessed bit in non-leaf PMD entries when using them as part of linear + address translations. Page table walkers that clear the accessed bit + may use this capability to reduce their search space. + source "kernel/gcov/Kconfig" source "scripts/gcc-plugins/Kconfig" diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 63fd3706316d..295518328228 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -74,6 +74,7 @@ config X86 select ARCH_HAS_PMEM_API if X86_64 select ARCH_HAS_PTE_DEVMAP if X86_64 select ARCH_HAS_PTE_SPECIAL + select ARCH_HAS_NONLEAF_PMD_YOUNG if PGTABLE_LEVELS > 2 select ARCH_HAS_UACCESS_FLUSHCACHE if X86_64 select ARCH_HAS_UACCESS_MCSAFE if X86_64 && X86_MCE select ARCH_HAS_SET_MEMORY diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h index 0c6e2b758857..91dc85dfa1f9 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h @@ -844,7 +844,8 @@ static inline pte_t *pte_offset_kernel(pmd_t *pmd, unsigned long address) static inline int pmd_bad(pmd_t pmd) { - return (pmd_flags(pmd) & ~_PAGE_USER) != _KERNPG_TABLE; + return (pmd_flags(pmd) & ~(_PAGE_USER | _PAGE_ACCESSED)) != + (_KERNPG_TABLE & ~_PAGE_ACCESSED); } static inline unsigned long pages_to_mb(unsigned long npg) diff --git a/arch/x86/mm/pgtable.c b/arch/x86/mm/pgtable.c index 7982f13807aa..18e63df7ee76 100644 --- a/arch/x86/mm/pgtable.c +++ b/arch/x86/mm/pgtable.c @@ -543,7 +543,7 @@ int ptep_test_and_clear_young(struct vm_area_struct *vma, return ret; } -#ifdef CONFIG_TRANSPARENT_HUGEPAGE +#if defined(CONFIG_TRANSPARENT_HUGEPAGE) || defined(CONFIG_ARCH_HAS_NONLEAF_PMD_YOUNG) int pmdp_test_and_clear_young(struct vm_area_struct *vma, unsigned long addr, pmd_t *pmdp) { @@ -555,6 +555,9 @@ int pmdp_test_and_clear_young(struct vm_area_struct *vma, return ret; } +#endif + +#ifdef CONFIG_TRANSPARENT_HUGEPAGE int pudp_test_and_clear_young(struct vm_area_struct *vma, unsigned long addr, pud_t *pudp) { diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h index 3ac04e08b568..ac0be045e487 100644 --- a/include/asm-generic/pgtable.h +++ b/include/asm-generic/pgtable.h @@ -74,7 +74,7 @@ static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, #endif #ifndef __HAVE_ARCH_PMDP_TEST_AND_CLEAR_YOUNG -#ifdef CONFIG_TRANSPARENT_HUGEPAGE +#if defined(CONFIG_TRANSPARENT_HUGEPAGE) || defined(CONFIG_ARCH_HAS_NONLEAF_PMD_YOUNG) static inline int pmdp_test_and_clear_young(struct vm_area_struct *vma, unsigned long address, pmd_t *pmdp) @@ -95,7 +95,7 @@ static inline int pmdp_test_and_clear_young(struct vm_area_struct *vma, BUILD_BUG(); return 0; } -#endif /* CONFIG_TRANSPARENT_HUGEPAGE */ +#endif /* CONFIG_TRANSPARENT_HUGEPAGE || CONFIG_ARCH_HAS_NONLEAF_PMD_YOUNG */ #endif #ifndef __HAVE_ARCH_PTEP_CLEAR_YOUNG_FLUSH From 98d7dde2049154cbac2667ab2382d18037d14cbc Mon Sep 17 00:00:00 2001 From: Yu Zhao Date: Sun, 18 Sep 2022 02:00:02 -0600 Subject: [PATCH 566/698] BACKPORT: mm: multi-gen LRU: groundwork MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Evictable pages are divided into multiple generations for each lruvec. The youngest generation number is stored in lrugen->max_seq for both anon and file types as they are aged on an equal footing. The oldest generation numbers are stored in lrugen->min_seq[] separately for anon and file types as clean file pages can be evicted regardless of swap constraints. These three variables are monotonically increasing. Generation numbers are truncated into order_base_2(MAX_NR_GENS+1) bits in order to fit into the gen counter in page->flags. Each truncated generation number is an index to lrugen->lists[]. The sliding window technique is used to track at least MIN_NR_GENS and at most MAX_NR_GENS generations. The gen counter stores a value within [1, MAX_NR_GENS] while a page is on one of lrugen->lists[]. Otherwise it stores 0. There are two conceptually independent procedures: "the aging", which produces young generations, and "the eviction", which consumes old generations. They form a closed-loop system, i.e., "the page reclaim". Both procedures can be invoked from userspace for the purposes of working set estimation and proactive reclaim. These techniques are commonly used to optimize job scheduling (bin packing) in data centers [1][2]. To avoid confusion, the terms "hot" and "cold" will be applied to the multi-gen LRU, as a new convention; the terms "active" and "inactive" will be applied to the active/inactive LRU, as usual. The protection of hot pages and the selection of cold pages are based on page access channels and patterns. There are two access channels: one through page tables and the other through file descriptors. The protection of the former channel is by design stronger because: 1. The uncertainty in determining the access patterns of the former channel is higher due to the approximation of the accessed bit. 2. The cost of evicting the former channel is higher due to the TLB flushes required and the l(CR) of encountering the dirty bit. 3. The penalty of underprotecting the former channel is higher because applications usually do not prepare themselves for major page faults l(CR) they do for blocked I/O. E.g., GUI applications commonly use dedicated I/O threads to avoid blocking rendering threads. There are also two access patterns: one with temporal locality and the other without. For the reasons listed above, the former channel is assumed to follow the former pattern unless VM_SEQ_READ or VM_RAND_READ is present; the latter channel is assumed to follow the latter pattern unless outlying refaults have been observed [3][4]. The next patch will address the "outlying refaults". Three macros, i.e., LRU_REFS_WIDTH, LRU_REFS_PGOFF and LRU_REFS_MASK, used later are added in this patch to make the entire patchset less diffy. A page is added to the youngest generation on faulting. The aging needs to check the accessed bit at least twice before handing this page over to the eviction. The first check takes care of the accessed bit set on the initial fault; the second check makes sure this page has not been used since then. This protocol, AKA second chance, requires a minimum of two generations, hence MIN_NR_GENS. Moto-CRs-Fixed:(CR) [1] https://dl.acm.org/doi/10.1145/3297858.3304053 [2] https://dl.acm.org/doi/10.1145/3503222.3507731 [3] https://lwn.net/Articles/495543/ [4] https://lwn.net/Articles/815342/ Link: https://lkml.kernel.org/r/20220918080010.2920238-6-yuzhao@google.com Change-Id: I7b24d1e9d263e4eb2c2ee23f2eb143824fcb5201 Signed-off-by: Yu Zhao Acked-by: Brian Geffon Acked-by: Jan Alexander Steffens (heftig) Acked-by: Oleksandr Natalenko Acked-by: Steven Barrett Acked-by: Suleiman Souhlal Tested-by: Daniel Byrne Tested-by: Donald Carr Tested-by: Holger Hoffstätte Tested-by: Konstantin Kharlamov Tested-by: Shuang Zhai Tested-by: Sofia Trinh Tested-by: Vaibhav Jain Cc: Andi Kleen Cc: Aneesh Kumar K.V Cc: Barry Song Cc: Catalin Marinas Cc: Dave Hansen Cc: Hillf Danton Cc: Jens Axboe Cc: Johannes Weiner Cc: Jonathan Corbet Cc: Linus Torvalds Cc: Matthew Wilcox Cc: Mel Gorman Cc: Miaohe Lin Cc: Michael Larabel Cc: Michal Hocko Cc: M(CR) Rapoport Cc: M(CR) Rapoport Cc: Peter Zijlstra Cc: Qi Zheng Cc: Tejun Heo Cc: Vlastimil Babka Cc: Will Deacon Signed-off-by: Andrew Morton (cherry picked from commit ec1c86b25f4bdd9dce6436c0539d2a6ae676e1c4) [ Resolve conflicts in mm/memory.c, mm/memcontrol.c, mm/Kconfig, include/linux/mm_inline.h] Bug: 261052246 Signed-off-by: Kalesh Singh Reviewed-on: https://gerrit.mot.com/2491798 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- fs/fuse/dev.c | 3 +- include/linux/mm.h | 2 + include/linux/mm_inline.h | 177 +++++++++++++++++++++++++++++- include/linux/mmzone.h | 100 +++++++++++++++++ include/linux/page-flags-layout.h | 13 ++- include/linux/page-flags.h | 4 +- include/linux/sched.h | 4 + kernel/bounds.c | 5 + mm/Kconfig | 7 ++ mm/huge_memory.c | 3 +- mm/memcontrol.c | 2 + mm/memory.c | 24 ++++ mm/mm_init.c | 7 +- mm/mmzone.c | 2 + mm/swap.c | 10 +- mm/vmscan.c | 75 +++++++++++++ 16 files changed, 424 insertions(+), 14 deletions(-) diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index a4b663f50701..d1cae08ba1cb 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -776,7 +776,8 @@ static int fuse_check_page(struct page *page) 1 << PG_active | 1 << PG_workingset | 1 << PG_reclaim | - 1 << PG_waiters))) { + 1 << PG_waiters | + LRU_GEN_MASK | LRU_REFS_MASK))) { pr_warn("trying to steal weird page\n"); pr_warn(" page=%p index=%li flags=%08lx, count=%i, mapcount=%i, mapping=%p\n", page, page->index, page->flags, page_count(page), page_mapcount(page), page->mapping); return 1; diff --git a/include/linux/mm.h b/include/linux/mm.h index 5114ec750e19..0389ca4f7c3f 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -966,6 +966,8 @@ vm_fault_t finish_mkwrite_fault(struct vm_fault *vmf); #define ZONES_PGOFF (NODES_PGOFF - ZONES_WIDTH) #define LAST_CPUPID_PGOFF (ZONES_PGOFF - LAST_CPUPID_WIDTH) #define KASAN_TAG_PGOFF (LAST_CPUPID_PGOFF - KASAN_TAG_WIDTH) +#define LRU_GEN_PGOFF (KASAN_TAG_PGOFF - LRU_GEN_WIDTH) +#define LRU_REFS_PGOFF (LRU_GEN_PGOFF - LRU_REFS_WIDTH) /* * Define the bit shifts to access each section. For non-existent diff --git a/include/linux/mm_inline.h b/include/linux/mm_inline.h index 24dbfcfe4a6d..1d0414b49e66 100644 --- a/include/linux/mm_inline.h +++ b/include/linux/mm_inline.h @@ -25,10 +25,13 @@ static inline int page_is_file_cache(struct page *page) static __always_inline void __update_lru_size(struct lruvec *lruvec, enum lru_list lru, enum zone_type zid, - int nr_pages) + long nr_pages) { struct pglist_data *pgdat = lruvec_pgdat(lruvec); + lockdep_assert_held(&pgdat->lru_lock); + WARN_ON_ONCE(nr_pages != (int)nr_pages); + __mod_lruvec_state(lruvec, NR_LRU_BASE + lru, nr_pages); __mod_zone_page_state(&pgdat->node_zones[zid], NR_ZONE_LRU_BASE + lru, nr_pages); @@ -100,11 +103,177 @@ static __always_inline enum lru_list page_lru(struct page *page) return lru; } +#ifdef CONFIG_LRU_GEN + +static inline bool lru_gen_enabled(void) +{ + return true; +} + +static inline bool lru_gen_in_fault(void) +{ + return current->in_lru_fault; +} + +static inline int lru_gen_from_seq(unsigned long seq) +{ + return seq % MAX_NR_GENS; +} + +static inline int page_lru_gen(struct page *page) +{ + unsigned long flags = READ_ONCE(page->flags); + + return ((flags & LRU_GEN_MASK) >> LRU_GEN_PGOFF) - 1; +} + +static inline bool lru_gen_is_active(struct lruvec *lruvec, int gen) +{ + unsigned long max_seq = lruvec->lrugen.max_seq; + + VM_WARN_ON_ONCE(gen >= MAX_NR_GENS); + + /* see the comment on MIN_NR_GENS */ + return gen == lru_gen_from_seq(max_seq) || gen == lru_gen_from_seq(max_seq - 1); +} + +static inline void lru_gen_update_size(struct lruvec *lruvec, struct page *page, + int old_gen, int new_gen) +{ + int type = page_is_file_cache(page); + int zone = page_zonenum(page); + int delta = hpage_nr_pages(page); + enum lru_list lru = type * LRU_INACTIVE_FILE; + struct lru_gen_struct *lrugen = &lruvec->lrugen; + + VM_WARN_ON_ONCE(old_gen != -1 && old_gen >= MAX_NR_GENS); + VM_WARN_ON_ONCE(new_gen != -1 && new_gen >= MAX_NR_GENS); + VM_WARN_ON_ONCE(old_gen == -1 && new_gen == -1); + + if (old_gen >= 0) + WRITE_ONCE(lrugen->nr_pages[old_gen][type][zone], + lrugen->nr_pages[old_gen][type][zone] - delta); + if (new_gen >= 0) + WRITE_ONCE(lrugen->nr_pages[new_gen][type][zone], + lrugen->nr_pages[new_gen][type][zone] + delta); + + /* addition */ + if (old_gen < 0) { + if (lru_gen_is_active(lruvec, new_gen)) + lru += LRU_ACTIVE; + __update_lru_size(lruvec, lru, zone, delta); + return; + } + + /* deletion */ + if (new_gen < 0) { + if (lru_gen_is_active(lruvec, old_gen)) + lru += LRU_ACTIVE; + __update_lru_size(lruvec, lru, zone, -delta); + return; + } +} + +static inline bool lru_gen_add_page(struct lruvec *lruvec, struct page *page, bool reclaiming) +{ + unsigned long seq; + unsigned long flags; + int gen = page_lru_gen(page); + int type = page_is_file_cache(page); + int zone = page_zonenum(page); + struct lru_gen_struct *lrugen = &lruvec->lrugen; + + VM_WARN_ON_ONCE_PAGE(gen != -1, page); + + if (PageUnevictable(page)) + return false; + /* + * There are three common cases for this page: + * 1. If it's hot, e.g., freshly faulted in or previously hot and + * migrated, add it to the youngest generation. + * 2. If it's cold but can't be evicted immediately, i.e., an anon page + * not in swapcache or a dirty page pending writeback, add it to the + * second oldest generation. + * 3. Everything else (clean, cold) is added to the oldest generation. + */ + if (PageActive(page)) + seq = lrugen->max_seq; + else if ((type == LRU_GEN_ANON && !PageSwapCache(page)) || + (PageReclaim(page) && + (PageDirty(page) || PageWriteback(page)))) + seq = lrugen->min_seq[type] + 1; + else + seq = lrugen->min_seq[type]; + + gen = lru_gen_from_seq(seq); + flags = (gen + 1UL) << LRU_GEN_PGOFF; + /* see the comment on MIN_NR_GENS about PG_active */ + set_mask_bits(&page->flags, LRU_GEN_MASK | BIT(PG_active), flags); + + lru_gen_update_size(lruvec, page, -1, gen); + /* for rotate_reclaimable_page() */ + if (reclaiming) + list_add_tail(&page->lru, &lrugen->lists[gen][type][zone]); + else + list_add(&page->lru, &lrugen->lists[gen][type][zone]); + + return true; +} + +static inline bool lru_gen_del_page(struct lruvec *lruvec, struct page *page, bool reclaiming) +{ + unsigned long flags; + int gen = page_lru_gen(page); + + if (gen < 0) + return false; + + VM_WARN_ON_ONCE_PAGE(PageActive(page), page); + VM_WARN_ON_ONCE_PAGE(PageUnevictable(page), page); + + /* for migrate_page_states() */ + flags = !reclaiming && lru_gen_is_active(lruvec, gen) ? BIT(PG_active) : 0; + flags = set_mask_bits(&page->flags, LRU_GEN_MASK, flags); + gen = ((flags & LRU_GEN_MASK) >> LRU_GEN_PGOFF) - 1; + + lru_gen_update_size(lruvec, page, gen, -1); + list_del(&page->lru); + + return true; +} + +#else /* !CONFIG_LRU_GEN */ + +static inline bool lru_gen_enabled(void) +{ + return false; +} + +static inline bool lru_gen_in_fault(void) +{ + return false; +} + +static inline bool lru_gen_add_page(struct lruvec *lruvec, struct page *page, bool reclaiming) +{ + return false; +} + +static inline bool lru_gen_del_page(struct lruvec *lruvec, struct page *page, bool reclaiming) +{ + return false; +} + +#endif /* CONFIG_LRU_GEN */ + static __always_inline void add_page_to_lru_list(struct page *page, struct lruvec *lruvec) { enum lru_list lru = page_lru(page); + if (lru_gen_add_page(lruvec, page, false)) + return; + update_lru_size(lruvec, lru, page_zonenum(page), hpage_nr_pages(page)); list_add(&page->lru, &lruvec->lists[lru]); } @@ -114,6 +283,9 @@ static __always_inline void add_page_to_lru_list_tail(struct page *page, { enum lru_list lru = page_lru(page); + if (lru_gen_add_page(lruvec, page, true)) + return; + update_lru_size(lruvec, lru, page_zonenum(page), hpage_nr_pages(page)); list_add_tail(&page->lru, &lruvec->lists[lru]); } @@ -121,6 +293,9 @@ static __always_inline void add_page_to_lru_list_tail(struct page *page, static __always_inline void del_page_from_lru_list(struct page *page, struct lruvec *lruvec) { + if (lru_gen_del_page(lruvec, page, false)) + return; + list_del(&page->lru); update_lru_size(lruvec, page_lru(page), page_zonenum(page), -hpage_nr_pages(page)); diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index 97f9d4576d2e..b4aa67cfbf41 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -308,6 +308,102 @@ struct zone_reclaim_stat { unsigned long recent_scanned[ANON_AND_FILE]; }; +#endif /* !__GENERATING_BOUNDS_H */ + +/* + * Evictable pages are divided into multiple generations. The youngest and the + * oldest generation numbers, max_seq and min_seq, are monotonically increasing. + * They form a sliding window of a variable size [MIN_NR_GENS, MAX_NR_GENS]. An + * offset within MAX_NR_GENS, i.e., gen, indexes the LRU list of the + * corresponding generation. The gen counter in page->flags stores gen+1 while + * a page is on one of lrugen->lists[]. Otherwise it stores 0. + * + * A page is added to the youngest generation on faulting. The aging needs to + * check the accessed bit at least twice before handing this page over to the + * eviction. The first check takes care of the accessed bit set on the initial + * fault; the second check makes sure this page hasn't been used since then. + * This process, AKA second chance, requires a minimum of two generations, + * hence MIN_NR_GENS. And to maintain ABI compatibility with the active/inactive + * LRU, e.g., /proc/vmstat, these two generations are considered active; the + * rest of generations, if they exist, are considered inactive. See + * lru_gen_is_active(). + * + * PG_active is always cleared while a page is on one of lrugen->lists[] so that + * the aging needs not to worry about it. And it's set again when a page + * considered active is isolated for non-reclaiming purposes, e.g., migration. + * See lru_gen_add_page() and lru_gen_del_page(). + * + * MAX_NR_GENS is set to 4 so that the multi-gen LRU can support twice the + * number of categories of the active/inactive LRU when keeping track of + * accesses through page tables. This requires order_base_2(MAX_NR_GENS+1) bits + * in page->flags. + */ +#define MIN_NR_GENS 2U +#define MAX_NR_GENS 4U + +#ifndef __GENERATING_BOUNDS_H + +struct lruvec; + +#define LRU_GEN_MASK ((BIT(LRU_GEN_WIDTH) - 1) << LRU_GEN_PGOFF) +#define LRU_REFS_MASK ((BIT(LRU_REFS_WIDTH) - 1) << LRU_REFS_PGOFF) + +#ifdef CONFIG_LRU_GEN + +enum { + LRU_GEN_ANON, + LRU_GEN_FILE, +}; + +/* + * The youngest generation number is stored in max_seq for both anon and file + * types as they are aged on an equal footing. The oldest generation numbers are + * stored in min_seq[] separately for anon and file types as clean file pages + * can be evicted regardless of swap constraints. + * + * Normally anon and file min_seq are in sync. But if swapping is constrained, + * e.g., out of swap space, file min_seq is allowed to advance and leave anon + * min_seq behind. + * + * The number of pages in each generation is eventually consistent and therefore + * can be transiently negative. + */ +struct lru_gen_struct { + /* the aging increments the youngest generation number */ + unsigned long max_seq; + /* the eviction increments the oldest generation numbers */ + unsigned long min_seq[ANON_AND_FILE]; + /* the multi-gen LRU lists, lazily sorted on eviction */ + struct list_head lists[MAX_NR_GENS][ANON_AND_FILE][MAX_NR_ZONES]; + /* the multi-gen LRU sizes, eventually consistent */ + long nr_pages[MAX_NR_GENS][ANON_AND_FILE][MAX_NR_ZONES]; +}; + +void lru_gen_init_lruvec(struct lruvec *lruvec); + +#ifdef CONFIG_MEMCG +void lru_gen_init_memcg(struct mem_cgroup *memcg); +void lru_gen_exit_memcg(struct mem_cgroup *memcg); +#endif + +#else /* !CONFIG_LRU_GEN */ + +static inline void lru_gen_init_lruvec(struct lruvec *lruvec) +{ +} + +#ifdef CONFIG_MEMCG +static inline void lru_gen_init_memcg(struct mem_cgroup *memcg) +{ +} + +static inline void lru_gen_exit_memcg(struct mem_cgroup *memcg) +{ +} +#endif + +#endif /* CONFIG_LRU_GEN */ + struct lruvec { struct list_head lists[NR_LRU_LISTS]; struct zone_reclaim_stat reclaim_stat; @@ -315,6 +411,10 @@ struct lruvec { atomic_long_t inactive_age; /* Refaults at the time of last reclaim cycle */ unsigned long refaults; +#ifdef CONFIG_LRU_GEN + /* evictable pages divided into generations */ + struct lru_gen_struct lrugen; +#endif #ifdef CONFIG_MEMCG struct pglist_data *pgdat; #endif diff --git a/include/linux/page-flags-layout.h b/include/linux/page-flags-layout.h index 71283739ffd2..18b0bff4550a 100644 --- a/include/linux/page-flags-layout.h +++ b/include/linux/page-flags-layout.h @@ -56,7 +56,8 @@ #define ZONES_WIDTH ZONES_SHIFT -#if SECTIONS_WIDTH+ZONES_WIDTH+NODES_SHIFT <= BITS_PER_LONG - NR_PAGEFLAGS +#if ZONES_WIDTH + LRU_GEN_WIDTH + SECTIONS_WIDTH + NODES_SHIFT \ + <= BITS_PER_LONG - NR_PAGEFLAGS #define NODES_WIDTH NODES_SHIFT #else #ifdef CONFIG_SPARSEMEM_VMEMMAP @@ -83,18 +84,20 @@ #define KASAN_TAG_WIDTH 0 #endif -#if SECTIONS_WIDTH+ZONES_WIDTH+NODES_SHIFT+LAST_CPUPID_SHIFT+KASAN_TAG_WIDTH \ - <= BITS_PER_LONG - NR_PAGEFLAGS +#if ZONES_WIDTH + LRU_GEN_WIDTH + SECTIONS_WIDTH + NODES_WIDTH + \ + KASAN_TAG_WIDTH + LAST_CPUPID_SHIFT <= BITS_PER_LONG - NR_PAGEFLAGS #define LAST_CPUPID_WIDTH LAST_CPUPID_SHIFT #else #define LAST_CPUPID_WIDTH 0 #endif -#if SECTIONS_WIDTH+NODES_WIDTH+ZONES_WIDTH+LAST_CPUPID_WIDTH+KASAN_TAG_WIDTH \ - > BITS_PER_LONG - NR_PAGEFLAGS +#if ZONES_WIDTH + LRU_GEN_WIDTH + SECTIONS_WIDTH + NODES_WIDTH + \ + KASAN_TAG_WIDTH + LAST_CPUPID_WIDTH > BITS_PER_LONG - NR_PAGEFLAGS #error "Not enough bits in page flags" #endif +#define LRU_REFS_WIDTH 0 + /* * We are going to use the flags for the page to node mapping if its in * there. This includes the case where there is no node, so it is implicit. diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h index 77de28bfefb0..6c57922d8fb4 100644 --- a/include/linux/page-flags.h +++ b/include/linux/page-flags.h @@ -827,7 +827,7 @@ static inline void ClearPageSlabPfmemalloc(struct page *page) 1UL << PG_private | 1UL << PG_private_2 | \ 1UL << PG_writeback | 1UL << PG_reserved | \ 1UL << PG_slab | 1UL << PG_active | \ - 1UL << PG_unevictable | __PG_MLOCKED) + 1UL << PG_unevictable | __PG_MLOCKED | LRU_GEN_MASK) /* * Flags checked when a page is prepped for return by the page allocator. @@ -838,7 +838,7 @@ static inline void ClearPageSlabPfmemalloc(struct page *page) * alloc-free cycle to prevent from reusing the page. */ #define PAGE_FLAGS_CHECK_AT_PREP \ - (((1UL << NR_PAGEFLAGS) - 1) & ~__PG_HWPOISON) + ((((1UL << NR_PAGEFLAGS) - 1) & ~__PG_HWPOISON) | LRU_GEN_MASK | LRU_REFS_MASK) #define PAGE_FLAGS_PRIVATE \ (1UL << PG_private | 1UL << PG_private_2) diff --git a/include/linux/sched.h b/include/linux/sched.h index e18e03b541b2..bbd5c55774ed 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -946,6 +946,10 @@ struct task_struct { #ifdef CONFIG_MEMCG unsigned in_user_fault:1; #endif +#ifdef CONFIG_LRU_GEN + /* whether the LRU algorithm may apply to this access */ + unsigned in_lru_fault:1; +#endif #ifdef CONFIG_COMPAT_BRK unsigned brk_randomized:1; #endif diff --git a/kernel/bounds.c b/kernel/bounds.c index 9795d75b09b2..5ee60777d8e4 100644 --- a/kernel/bounds.c +++ b/kernel/bounds.c @@ -22,6 +22,11 @@ int main(void) DEFINE(NR_CPUS_BITS, ilog2(CONFIG_NR_CPUS)); #endif DEFINE(SPINLOCK_SIZE, sizeof(spinlock_t)); +#ifdef CONFIG_LRU_GEN + DEFINE(LRU_GEN_WIDTH, order_base_2(MAX_NR_GENS + 1)); +#else + DEFINE(LRU_GEN_WIDTH, 0); +#endif /* End of constants */ return 0; diff --git a/mm/Kconfig b/mm/Kconfig index fe6c22bc562c..57de0038609e 100644 --- a/mm/Kconfig +++ b/mm/Kconfig @@ -856,6 +856,13 @@ config OOM_TASK_PRIORITY_ADJ_LIMIT With this parameter you can limit the OOM killer to first kill tasks with an oom_score_adj value above a certain threshold before considering tasks with a lower oom_score_adj value. +config LRU_GEN + bool "Multi-Gen LRU" + depends on MMU + # make sure page->flags has enough spare bits + depends on 64BIT || !SPARSEMEM || SPARSEMEM_VMEMMAP + help + A high performance LRU implementation to overcommit memory. endmenu diff --git a/mm/huge_memory.c b/mm/huge_memory.c index e86ae9ed9685..db1ff286b144 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -2509,7 +2509,8 @@ static void __split_huge_page_tail(struct page *head, int tail, (1L << PG_workingset) | (1L << PG_locked) | (1L << PG_unevictable) | - (1L << PG_dirty))); + (1L << PG_dirty) | + LRU_GEN_MASK | LRU_REFS_MASK)); /* ->mapping in first tail page is compound_mapcount */ VM_BUG_ON_PAGE(tail > 2 && page_tail->mapping != TAIL_MAPPING, diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 9171eccfd971..e9caf18e133c 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -5107,6 +5107,7 @@ static void __mem_cgroup_free(struct mem_cgroup *memcg) static void mem_cgroup_free(struct mem_cgroup *memcg) { + lru_gen_exit_memcg(memcg); memcg_wb_domain_exit(memcg); /* * Flush percpu vmstats and vmevents to guarantee the value correctness @@ -5179,6 +5180,7 @@ static struct mem_cgroup *mem_cgroup_alloc(void) memcg->deferred_split_queue.split_queue_len = 0; #endif idr_replace(&mem_cgroup_idr, memcg, memcg->id.id); + lru_gen_init_memcg(memcg); return memcg; fail: mem_cgroup_id_remove(memcg); diff --git a/mm/memory.c b/mm/memory.c index 175ea2765182..cd892d43d03f 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -4617,6 +4617,26 @@ bool can_reuse_spf_vma(struct vm_area_struct *vma, unsigned long address) return ret; } #endif /* CONFIG_SPECULATIVE_PAGE_FAULT */ +#ifdef CONFIG_LRU_GEN +static void lru_gen_enter_fault(struct vm_area_struct *vma) +{ + /* the LRU algorithm doesn't apply to sequential or random reads */ + current->in_lru_fault = !(vma->vm_flags & (VM_SEQ_READ | VM_RAND_READ)); +} + +static void lru_gen_exit_fault(void) +{ + current->in_lru_fault = false; +} +#else +static void lru_gen_enter_fault(struct vm_area_struct *vma) +{ +} + +static void lru_gen_exit_fault(void) +{ +} +#endif /* CONFIG_LRU_GEN */ /* * By the time we get here, we already hold the mm semaphore @@ -4649,11 +4669,15 @@ vm_fault_t handle_mm_fault(struct vm_area_struct *vma, unsigned long address, if (flags & FAULT_FLAG_USER) mem_cgroup_enter_user_fault(); + lru_gen_enter_fault(vma); + if (unlikely(is_vm_hugetlb_page(vma))) ret = hugetlb_fault(vma->vm_mm, vma, address, flags); else ret = __handle_mm_fault(vma, address, flags); + lru_gen_exit_fault(); + if (flags & FAULT_FLAG_USER) { mem_cgroup_exit_user_fault(); /* diff --git a/mm/mm_init.c b/mm/mm_init.c index 5c918388de99..f4d9f66051d1 100644 --- a/mm/mm_init.c +++ b/mm/mm_init.c @@ -67,13 +67,16 @@ void __init mminit_verify_pageflags_layout(void) unsigned long or_mask, add_mask; shift = 8 * sizeof(unsigned long); - width = shift - SECTIONS_WIDTH - NODES_WIDTH - ZONES_WIDTH - LAST_CPUPID_SHIFT; + width = shift - SECTIONS_WIDTH - NODES_WIDTH - ZONES_WIDTH + - LAST_CPUPID_SHIFT - LRU_GEN_WIDTH - LRU_REFS_WIDTH; mminit_dprintk(MMINIT_TRACE, "pageflags_layout_widths", - "Section %d Node %d Zone %d Lastcpupid %d Flags %d\n", + "Section %d Node %d Zone %d Lastcpupid %d Gen %d Tier %d Flags %d\n", SECTIONS_WIDTH, NODES_WIDTH, ZONES_WIDTH, LAST_CPUPID_WIDTH, + LRU_GEN_WIDTH, + LRU_REFS_WIDTH, NR_PAGEFLAGS); mminit_dprintk(MMINIT_TRACE, "pageflags_layout_shifts", "Section %d Node %d Zone %d Lastcpupid %d\n", diff --git a/mm/mmzone.c b/mm/mmzone.c index f337831affc2..d76ca549e424 100644 --- a/mm/mmzone.c +++ b/mm/mmzone.c @@ -80,6 +80,8 @@ void lruvec_init(struct lruvec *lruvec) for_each_lru(lru) INIT_LIST_HEAD(&lruvec->lists[lru]); + + lru_gen_init_lruvec(lruvec); } #if defined(CONFIG_NUMA_BALANCING) && !defined(LAST_CPUPID_NOT_IN_PAGE_FLAGS) diff --git a/mm/swap.c b/mm/swap.c index 34bedd0e7619..3cd3d1ec8f4c 100644 --- a/mm/swap.c +++ b/mm/swap.c @@ -436,6 +436,12 @@ void lru_cache_add(struct page *page) { VM_BUG_ON_PAGE(PageActive(page) && PageUnevictable(page), page); VM_BUG_ON_PAGE(PageLRU(page), page); + + /* see the comment in lru_gen_add_page() */ + if (lru_gen_enabled() && !PageUnevictable(page) && + lru_gen_in_fault() && !(current->flags & PF_MEMALLOC)) + SetPageActive(page); + __lru_cache_add(page); } @@ -538,7 +544,7 @@ static void lru_deactivate_file_fn(struct page *page, struct lruvec *lruvec, static void lru_deactivate_fn(struct page *page, struct lruvec *lruvec, void *arg) { - if (PageLRU(page) && PageActive(page) && !PageUnevictable(page)) { + if (PageLRU(page) && !PageUnevictable(page) && (PageActive(page) || lru_gen_enabled())) { int file = page_is_file_cache(page); del_page_from_lru_list(page, lruvec); @@ -647,7 +653,7 @@ void deactivate_file_page(struct page *page) */ void deactivate_page(struct page *page) { - if (PageLRU(page) && PageActive(page) && !PageUnevictable(page)) { + if (PageLRU(page) && !PageUnevictable(page) && (PageActive(page) || lru_gen_enabled())) { struct pagevec *pvec = &get_cpu_var(lru_deactivate_pvecs); get_page(page); diff --git a/mm/vmscan.c b/mm/vmscan.c index 084f48f95afd..8db231e0b758 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -2627,6 +2627,81 @@ out: } } +#ifdef CONFIG_LRU_GEN + +/****************************************************************************** + * shorthand helpers + ******************************************************************************/ + +#define for_each_gen_type_zone(gen, type, zone) \ + for ((gen) = 0; (gen) < MAX_NR_GENS; (gen)++) \ + for ((type) = 0; (type) < ANON_AND_FILE; (type)++) \ + for ((zone) = 0; (zone) < MAX_NR_ZONES; (zone)++) + +static struct lruvec __maybe_unused *get_lruvec(struct mem_cgroup *memcg, int nid) +{ + struct pglist_data *pgdat = NODE_DATA(nid); + +#ifdef CONFIG_MEMCG + if (memcg) { + struct lruvec *lruvec = &memcg->nodeinfo[nid]->lruvec; + + /* for hotadd_new_pgdat() */ + if (!lruvec->pgdat) + lruvec->pgdat = pgdat; + + return lruvec; + } +#endif + VM_WARN_ON_ONCE(!mem_cgroup_disabled()); + + return pgdat ? &pgdat->lruvec : NULL; +} + +/****************************************************************************** + * initialization + ******************************************************************************/ + +void lru_gen_init_lruvec(struct lruvec *lruvec) +{ + int gen, type, zone; + struct lru_gen_struct *lrugen = &lruvec->lrugen; + + lrugen->max_seq = MIN_NR_GENS + 1; + + for_each_gen_type_zone(gen, type, zone) + INIT_LIST_HEAD(&lrugen->lists[gen][type][zone]); +} + +#ifdef CONFIG_MEMCG +void lru_gen_init_memcg(struct mem_cgroup *memcg) +{ +} + +void lru_gen_exit_memcg(struct mem_cgroup *memcg) +{ + int nid; + + for_each_node(nid) { + struct lruvec *lruvec = get_lruvec(memcg, nid); + + VM_WARN_ON_ONCE(memchr_inv(lruvec->lrugen.nr_pages, 0, + sizeof(lruvec->lrugen.nr_pages))); + } +} +#endif + +static int __init init_lru_gen(void) +{ + BUILD_BUG_ON(MIN_NR_GENS + 1 >= MAX_NR_GENS); + BUILD_BUG_ON(BIT(LRU_GEN_WIDTH) <= MAX_NR_GENS); + + return 0; +}; +late_initcall(init_lru_gen); + +#endif /* CONFIG_LRU_GEN */ + /* * This is a basic per-node page freer. Used by both kswapd and direct reclaim. */ From b9257462b8909d634353e032851afcba4270ff0c Mon Sep 17 00:00:00 2001 From: Yu Zhao Date: Sun, 18 Sep 2022 02:00:03 -0600 Subject: [PATCH 567/698] BACKPORT: mm: multi-gen LRU: minimal implementation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To avoid confusion, the terms "promotion" and "demotion" will be applied to the multi-gen LRU, as a new convention; the terms "activation" and "deactivation" will be applied to the active/inactive LRU, as usual. The aging produces young generations. Given an lruvec, it increments max_seq when max_seq-min_seq+1 approaches MIN_NR_GENS. The aging promotes hot pages to the youngest generation when it finds them accessed through page tables; the demotion of cold pages happens consequently when it increments max_seq. Promotion in the aging path does not involve any LRU list operations, only the updates of the gen counter and lrugen->nr_pages[]; demotion, unless as the result of the increment of max_seq, requires LRU list operations, e.g., lru_deactivate_fn(). The aging has the complexity O(nr_hot_pages), since it is only interested in hot pages. The eviction consumes old generations. Given an lruvec, it increments min_seq when lrugen->lists[] indexed by min_seq%MAX_NR_GENS becomes empty. A feedback loop modeled after the PID controller monitors refaults over anon and file types and decides which type to evict when both types are available from the same generation. The protection of pages accessed multiple times through file descriptors takes place in the eviction path. Each generation is divided into multiple tiers. A page accessed N times through file descriptors is in tier order_base_2(N). Tiers do not have dedicated lrugen->lists[], only bits in page->flags. The aforementioned feedback loop also monitors refaults over all tiers and decides when to protect pages in which tiers (N>1), using the first tier (N=0,1) as a baseline. The first tier contains single-use unmapped clean pages, which are most l(CR) the best choices. In contrast to promotion in the aging path, the protection of a page in the eviction path is achieved by moving this page to the next generation, i.e., min_seq+1, if the feedback loop decides so. This approach has the following advantages: 1. It removes the cost of activation in the buffered access path by inferring whether pages accessed multiple times through file descriptors are statistically hot and thus worth protecting in the eviction path. 2. It takes pages accessed through page tables into account and avoids overprotecting pages accessed multiple times through file descriptors. (Pages accessed through page tables are in the first tier, since N=0.) 3. More tiers provide better protection for pages accessed more than twice through file descriptors, when under heavy buffered I/O workloads. Moto-CRs-Fixed:(CR) Server benchmark results: Single workload: fio (buffered I/O): +[30, 32]% IOPS BW 5.19-rc1: 2673k 10.2GiB/s patch1-6: 3491k 13.3GiB/s Single workload: memcached (anon): -[4, 6]% Ops/sec KB/sec 5.19-rc1: 1161501.04 45177.25 patch1-6: 1106168.46 43025.04 Configurations: CPU: two Xeon 6154 Mem: total 256G Node 1 was only used as a ram disk to reduce the variance in the results. patch drivers/block/brd.c < gfp_flags = GFP_NOIO | __GFP_ZERO | __GFP_HIGHMEM | __GFP_THISNODE; > page = alloc_pages_node(1, gfp_flags, 0); EOF cat >>/etc/systemd/system.conf <>/etc/memcached.conf </sys/fs/cgroup/user.slice/test/memory.max echo $$ >/sys/fs/cgroup/user.slice/test/cgroup.procs fio -name=mglru --numjobs=72 --directory=/mnt --size=1408m \ --buffered=1 --ioengine=io_uring --iodepth=128 \ --iodepth_batch_submit=32 --iodepth_batch_complete=32 \ --rw=randread --random_distribution=random --norandommap \ --time_based --ramp_time=10m --runtime=5m --group_reporting cat memcached.sh modprobe brd rd_nr=1 rd_size=113246208 swapoff -a mkswap /dev/ram0 swapon /dev/ram0 memtier_benchmark -S /var/run/memcached/memcached.sock \ -P memcache_binary -n allkeys --key-minimum=1 \ --key-maximum=65000000 --key-pattern=P:P -c 1 -t 36 \ --ratio 1:0 --pipeline 8 -d 2000 memtier_benchmark -S /var/run/memcached/memcached.sock \ -P memcache_binary -n allkeys --key-minimum=1 \ --key-maximum=65000000 --key-pattern=R:R -c 1 -t 36 \ --ratio 0:1 --pipeline 8 --randomize --distinct-client-seed Client benchmark results: kswapd profiles: 5.19-rc1 40.33% page_vma_mapped_walk (overhead) 21.80% lzo1x_1_do_compress (real work) 7.53% do_raw_spin_lock 3.95% _raw_spin_unlock_irq 2.52% vma_interval_tree_iter_next 2.37% page_referenced_one 2.28% vma_interval_tree_subtree_search 1.97% anon_vma_interval_tree_iter_first 1.60% ptep_clear_flush 1.06% __zram_bvec_write patch1-6 39.03% lzo1x_1_do_compress (real work) 18.47% page_vma_mapped_walk (overhead) 6.74% _raw_spin_unlock_irq 3.97% do_raw_spin_lock 2.49% ptep_clear_flush 2.48% anon_vma_interval_tree_iter_first 1.92% page_referenced_one 1.88% __zram_bvec_write 1.48% memmove 1.31% vma_interval_tree_iter_next Configurations: CPU: single Snapdragon 7c Mem: total 4G ChromeOS MemoryPressure [1] [1] https://chromium.googlesource.com/chromiumos/platform/tast-tests/ Link: https://lkml.kernel.org/r/20220918080010.2920238-7-yuzhao@google.com Signed-off-by: Yu Zhao Acked-by: Brian Geffon Acked-by: Jan Alexander Steffens (heftig) Acked-by: Oleksandr Natalenko Acked-by: Steven Barrett Acked-by: Suleiman Souhlal Tested-by: Daniel Byrne Tested-by: Donald Carr Tested-by: Holger Hoffstätte Tested-by: Konstantin Kharlamov Tested-by: Shuang Zhai Tested-by: Sofia Trinh Tested-by: Vaibhav Jain Cc: Andi Kleen Cc: Aneesh Kumar K.V Cc: Barry Song Cc: Catalin Marinas Cc: Dave Hansen Cc: Hillf Danton Cc: Jens Axboe Cc: Johannes Weiner Cc: Jonathan Corbet Cc: Linus Torvalds Cc: Matthew Wilcox Cc: Mel Gorman Cc: Miaohe Lin Cc: Michael Larabel Cc: Michal Hocko Cc: M(CR) Rapoport Cc: M(CR) Rapoport Cc: Peter Zijlstra Cc: Qi Zheng Cc: Tejun Heo Cc: Vlastimil Babka Cc: Will Deacon Signed-off-by: Andrew Morton (cherry picked from commit ac35a490237446b71e3b4b782b1596967edd0aa8) [Resolve confilcts in mm/Kconfig, mm/swap.c, mm/vmscan.c Remove isolation race check in isolate_page() - TestClearPageLRU() not available in 5.10 ] Bug: 261052246 Signed-off-by: Kalesh Singh WIP: DO NOT SUBMIT: swap refault / shadow fixup I've commented out the bits so we don't hit the panic Change-Id: Ia1340031d028201e74469c2e8b8e61a2426b1278 Reviewed-on: https://gerrit.mot.com/2491799 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- include/linux/mm_inline.h | 36 ++ include/linux/mmzone.h | 44 ++ include/linux/page-flags-layout.h | 5 +- kernel/bounds.c | 2 + mm/Kconfig | 11 + mm/memory.c | 19 +- mm/swap.c | 41 ++ mm/swap_state.c | 9 +- mm/vmscan.c | 780 +++++++++++++++++++++++++++++- mm/workingset.c | 114 ++++- 10 files changed, 1047 insertions(+), 14 deletions(-) diff --git a/include/linux/mm_inline.h b/include/linux/mm_inline.h index 1d0414b49e66..64b33e79165b 100644 --- a/include/linux/mm_inline.h +++ b/include/linux/mm_inline.h @@ -120,6 +120,33 @@ static inline int lru_gen_from_seq(unsigned long seq) return seq % MAX_NR_GENS; } +static inline int lru_hist_from_seq(unsigned long seq) +{ + return seq % NR_HIST_GENS; +} + +static inline int lru_tier_from_refs(int refs) +{ + VM_WARN_ON_ONCE(refs > BIT(LRU_REFS_WIDTH)); + + /* see the comment in page_lru_refs() */ + return order_base_2(refs + 1); +} + +static inline int page_lru_refs(struct page *page) +{ + unsigned long flags = READ_ONCE(page->flags); + bool workingset = flags & BIT(PG_workingset); + + /* + * Return the number of accesses beyond PG_referenced, i.e., N-1 if the + * total number of accesses is N>1, since N=0,1 both map to the first + * tier. lru_tier_from_refs() will account for this off-by-one. Also see + * the comment on MAX_NR_TIERS. + */ + return ((flags & LRU_REFS_MASK) >> LRU_REFS_PGOFF) + workingset; +} + static inline int page_lru_gen(struct page *page) { unsigned long flags = READ_ONCE(page->flags); @@ -172,6 +199,15 @@ static inline void lru_gen_update_size(struct lruvec *lruvec, struct page *page, __update_lru_size(lruvec, lru, zone, -delta); return; } + + /* promotion */ + if (!lru_gen_is_active(lruvec, old_gen) && lru_gen_is_active(lruvec, new_gen)) { + __update_lru_size(lruvec, lru, zone, -delta); + __update_lru_size(lruvec, lru + LRU_ACTIVE, zone, delta); + } + + /* demotion requires isolation, e.g., lru_deactivate_fn() */ + VM_WARN_ON_ONCE(lru_gen_is_active(lruvec, old_gen) && !lru_gen_is_active(lruvec, new_gen)); } static inline bool lru_gen_add_page(struct lruvec *lruvec, struct page *page, bool reclaiming) diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index b4aa67cfbf41..2721b50970fe 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -341,6 +341,28 @@ struct zone_reclaim_stat { #define MIN_NR_GENS 2U #define MAX_NR_GENS 4U +/* + * Each generation is divided into multiple tiers. A page accessed N times + * through file descriptors is in tier order_base_2(N). A page in the first tier + * (N=0,1) is marked by PG_referenced unless it was faulted in through page + * tables or read ahead. A page in any other tier (N>1) is marked by + * PG_referenced and PG_workingset. This implies a minimum of two tiers is + * supported without using additional bits in page->flags. + * + * In contrast to moving across generations which requires the LRU lock, moving + * across tiers only involves atomic operations on page->flags and therefore + * has a negligible cost in the buffered access path. In the eviction path, + * comparisons of refaulted/(evicted+protected) from the first tier and the + * rest infer whether pages accessed multiple times through file descriptors + * are statistically hot and thus worth protecting. + * + * MAX_NR_TIERS is set to 4 so that the multi-gen LRU can support twice the + * number of categories of the active/inactive LRU when keeping track of + * accesses through file descriptors. This uses MAX_NR_TIERS-2 spare bits in + * page->flags. + */ +#define MAX_NR_TIERS 4U + #ifndef __GENERATING_BOUNDS_H struct lruvec; @@ -348,6 +370,9 @@ struct lruvec; #define LRU_GEN_MASK ((BIT(LRU_GEN_WIDTH) - 1) << LRU_GEN_PGOFF) #define LRU_REFS_MASK ((BIT(LRU_REFS_WIDTH) - 1) << LRU_REFS_PGOFF) +void *lru_gen_eviction(struct page *page); +void lru_gen_refault(struct page *page, void *shadow); + #ifdef CONFIG_LRU_GEN enum { @@ -355,6 +380,16 @@ enum { LRU_GEN_FILE, }; +#define MIN_LRU_BATCH BITS_PER_LONG +#define MAX_LRU_BATCH (MIN_LRU_BATCH * 64) + +/* whether to keep historical stats from evicted generations */ +#ifdef CONFIG_LRU_GEN_STATS +#define NR_HIST_GENS MAX_NR_GENS +#else +#define NR_HIST_GENS 1U +#endif + /* * The youngest generation number is stored in max_seq for both anon and file * types as they are aged on an equal footing. The oldest generation numbers are @@ -377,6 +412,15 @@ struct lru_gen_struct { struct list_head lists[MAX_NR_GENS][ANON_AND_FILE][MAX_NR_ZONES]; /* the multi-gen LRU sizes, eventually consistent */ long nr_pages[MAX_NR_GENS][ANON_AND_FILE][MAX_NR_ZONES]; + /* the exponential moving average of refaulted */ + unsigned long avg_refaulted[ANON_AND_FILE][MAX_NR_TIERS]; + /* the exponential moving average of evicted+protected */ + unsigned long avg_total[ANON_AND_FILE][MAX_NR_TIERS]; + /* the first tier doesn't need protection, hence the minus one */ + unsigned long protected[NR_HIST_GENS][ANON_AND_FILE][MAX_NR_TIERS - 1]; + /* can be modified without holding the LRU lock */ + atomic_long_t evicted[NR_HIST_GENS][ANON_AND_FILE][MAX_NR_TIERS]; + atomic_long_t refaulted[NR_HIST_GENS][ANON_AND_FILE][MAX_NR_TIERS]; }; void lru_gen_init_lruvec(struct lruvec *lruvec); diff --git a/include/linux/page-flags-layout.h b/include/linux/page-flags-layout.h index 18b0bff4550a..f89a37da49d2 100644 --- a/include/linux/page-flags-layout.h +++ b/include/linux/page-flags-layout.h @@ -96,7 +96,10 @@ #error "Not enough bits in page flags" #endif -#define LRU_REFS_WIDTH 0 +/* see the comment on MAX_NR_TIERS */ +#define LRU_REFS_WIDTH min(__LRU_REFS_WIDTH, BITS_PER_LONG - NR_PAGEFLAGS - \ + ZONES_WIDTH - LRU_GEN_WIDTH - SECTIONS_WIDTH - \ + NODES_WIDTH - KASAN_TAG_WIDTH - LAST_CPUPID_WIDTH) /* * We are going to use the flags for the page to node mapping if its in diff --git a/kernel/bounds.c b/kernel/bounds.c index 5ee60777d8e4..b529182e8b04 100644 --- a/kernel/bounds.c +++ b/kernel/bounds.c @@ -24,8 +24,10 @@ int main(void) DEFINE(SPINLOCK_SIZE, sizeof(spinlock_t)); #ifdef CONFIG_LRU_GEN DEFINE(LRU_GEN_WIDTH, order_base_2(MAX_NR_GENS + 1)); + DEFINE(__LRU_REFS_WIDTH, MAX_NR_TIERS - 2); #else DEFINE(LRU_GEN_WIDTH, 0); + DEFINE(__LRU_REFS_WIDTH, 0); #endif /* End of constants */ diff --git a/mm/Kconfig b/mm/Kconfig index 57de0038609e..5f7638bc90e4 100644 --- a/mm/Kconfig +++ b/mm/Kconfig @@ -856,6 +856,7 @@ config OOM_TASK_PRIORITY_ADJ_LIMIT With this parameter you can limit the OOM killer to first kill tasks with an oom_score_adj value above a certain threshold before considering tasks with a lower oom_score_adj value. +# multi-gen LRU { config LRU_GEN bool "Multi-Gen LRU" depends on MMU @@ -864,6 +865,16 @@ config LRU_GEN help A high performance LRU implementation to overcommit memory. +config LRU_GEN_STATS + bool "Full stats for debugging" + depends on LRU_GEN + help + Do not enable this option unless you plan to look at historical stats + from evicted generations for debugging purpose. + + This option has a per-memcg and per-node memory overhead. +# } + endmenu config PROCESS_RECLAIM diff --git a/mm/memory.c b/mm/memory.c index cd892d43d03f..63d684cf3f8d 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -71,6 +71,8 @@ #include #include #include +#include +#include #include @@ -3017,6 +3019,19 @@ void unmap_mapping_range(struct address_space *mapping, } EXPORT_SYMBOL(unmap_mapping_range); +static void lru_gen_swap_refault(struct page *page, swp_entry_t entry) +{ + if (lru_gen_enabled()) { + void *item; + struct address_space *mapping = swap_address_space(entry); + pgoff_t index = swp_offset(entry); + + item = xa_load(&mapping->i_pages, index); + if (xa_is_value(item)) + lru_gen_refault(page, item); + } +} + /* * We enter with non-exclusive mmap_sem (to exclude vma changes, * but allow concurrent faults), and pte mapped but not yet locked. @@ -3097,6 +3112,7 @@ vm_fault_t do_swap_page(struct vm_fault *vmf) __SetPageLocked(page); __SetPageSwapBacked(page); set_page_private(page, entry.val); + lru_gen_swap_refault(page, entry); lru_cache_add_anon(page); swap_readpage(page, true); } @@ -3230,7 +3246,8 @@ vm_fault_t do_swap_page(struct vm_fault *vmf) } else { do_page_add_anon_rmap(page, vma, vmf->address, exclusive); mem_cgroup_commit_charge(page, memcg, true, false); - activate_page(page); + if (!lru_gen_enabled()) + activate_page(page); } swap_free(entry); diff --git a/mm/swap.c b/mm/swap.c index 3cd3d1ec8f4c..9003e635e255 100644 --- a/mm/swap.c +++ b/mm/swap.c @@ -357,6 +357,41 @@ static void __lru_cache_activate_page(struct page *page) put_cpu_var(lru_add_pvec); } +#ifdef CONFIG_LRU_GEN +static void page_inc_refs(struct page *page) +{ + unsigned long new_flags, old_flags; + + if (PageUnevictable(page)) + return; + + if (!PageReferenced(page)) { + SetPageReferenced(page); + return; + } + + if (!PageWorkingset(page)) { + SetPageWorkingset(page); + return; + } + + /* see the comment on MAX_NR_TIERS */ + do { + old_flags = READ_ONCE(page->flags); + new_flags = old_flags & LRU_REFS_MASK; + if (new_flags == LRU_REFS_MASK) + break; + + new_flags += BIT(LRU_REFS_PGOFF); + new_flags |= old_flags & ~LRU_REFS_MASK; + } while (cmpxchg(&page->flags, old_flags, new_flags) != old_flags); +} +#else +static void page_inc_refs(struct page *page) +{ +} +#endif /* CONFIG_LRU_GEN */ + /* * Mark a page as having seen activity. * @@ -370,6 +405,12 @@ static void __lru_cache_activate_page(struct page *page) void mark_page_accessed(struct page *page) { page = compound_head(page); + + if (lru_gen_enabled()) { + page_inc_refs(page); + return; + } + if (!PageActive(page) && !PageUnevictable(page) && PageReferenced(page)) { diff --git a/mm/swap_state.c b/mm/swap_state.c index e8bd52bb23b1..505e54000952 100644 --- a/mm/swap_state.c +++ b/mm/swap_state.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include "internal.h" @@ -409,6 +410,7 @@ struct page *__read_swap_cache_async(swp_entry_t entry, gfp_t gfp_mask, struct page *found_page = NULL, *new_page = NULL; struct swap_info_struct *si; int err; + void *shadow; *new_page_allocated = false; do { @@ -465,10 +467,13 @@ struct page *__read_swap_cache_async(swp_entry_t entry, gfp_t gfp_mask, __SetPageLocked(new_page); __SetPageSwapBacked(new_page); err = add_to_swap_cache(new_page, entry, - gfp_mask & GFP_RECLAIM_MASK, NULL); + gfp_mask & GFP_RECLAIM_MASK, &shadow); if (likely(!err)) { /* Initiate read into locked page */ - SetPageWorkingset(new_page); + if (!lru_gen_enabled()) + SetPageWorkingset(new_page); + else if (shadow) + lru_gen_refault(new_page, shadow); lru_cache_add_anon(new_page); *new_page_allocated = true; return new_page; diff --git a/mm/vmscan.c b/mm/vmscan.c index 8db231e0b758..7cf42b2eaee2 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -923,6 +923,7 @@ static int __remove_mapping(struct address_space *mapping, struct page *page, { unsigned long flags; int refcount; + void *shadow = NULL; BUG_ON(!PageLocked(page)); BUG_ON(mapping != page_mapping(page)); @@ -964,8 +965,11 @@ static int __remove_mapping(struct address_space *mapping, struct page *page, if (PageSwapCache(page)) { swp_entry_t swap = { .val = page_private(page) }; + + if (lru_gen_enabled()) + shadow = lru_gen_eviction(page); mem_cgroup_swapout(page, swap); - __delete_from_swap_cache(page, swap, NULL); + __delete_from_swap_cache(page, swap, shadow); xa_unlock_irqrestore(&mapping->i_pages, flags); put_swap_page(page, swap); } else { @@ -2633,6 +2637,17 @@ out: * shorthand helpers ******************************************************************************/ +#define LRU_REFS_FLAGS (BIT(PG_referenced) | BIT(PG_workingset)) + +#define DEFINE_MAX_SEQ(lruvec) \ + unsigned long max_seq = READ_ONCE((lruvec)->lrugen.max_seq) + +#define DEFINE_MIN_SEQ(lruvec) \ + unsigned long min_seq[ANON_AND_FILE] = { \ + READ_ONCE((lruvec)->lrugen.min_seq[LRU_GEN_ANON]), \ + READ_ONCE((lruvec)->lrugen.min_seq[LRU_GEN_FILE]), \ + } + #define for_each_gen_type_zone(gen, type, zone) \ for ((gen) = 0; (gen) < MAX_NR_GENS; (gen)++) \ for ((type) = 0; (type) < ANON_AND_FILE; (type)++) \ @@ -2658,6 +2673,734 @@ static struct lruvec __maybe_unused *get_lruvec(struct mem_cgroup *memcg, int ni return pgdat ? &pgdat->lruvec : NULL; } +static int get_swappiness(struct lruvec *lruvec, struct scan_control *sc) +{ + struct mem_cgroup *memcg = lruvec_memcg(lruvec); + + if (mem_cgroup_get_nr_swap_pages(memcg) < MIN_LRU_BATCH) + return 0; + + return mem_cgroup_swappiness(memcg); +} + +static int get_nr_gens(struct lruvec *lruvec, int type) +{ + return lruvec->lrugen.max_seq - lruvec->lrugen.min_seq[type] + 1; +} + +static bool __maybe_unused seq_is_valid(struct lruvec *lruvec) +{ + /* see the comment on lru_gen_struct */ + return get_nr_gens(lruvec, LRU_GEN_FILE) >= MIN_NR_GENS && + get_nr_gens(lruvec, LRU_GEN_FILE) <= get_nr_gens(lruvec, LRU_GEN_ANON) && + get_nr_gens(lruvec, LRU_GEN_ANON) <= MAX_NR_GENS; +} + +/****************************************************************************** + * refault feedback loop + ******************************************************************************/ + +/* + * A feedback loop based on Proportional-Integral-Derivative (PID) controller. + * + * The P term is refaulted/(evicted+protected) from a tier in the generation + * currently being evicted; the I term is the exponential moving average of the + * P term over the generations previously evicted, using the smoothing factor + * 1/2; the D term isn't supported. + * + * The setpoint (SP) is always the first tier of one type; the process variable + * (PV) is either any tier of the other type or any other tier of the same + * type. + * + * The error is the difference between the SP and the PV; the correction is to + * turn off protection when SP>PV or turn on protection when SPlrugen; + int hist = lru_hist_from_seq(lrugen->min_seq[type]); + + pos->refaulted = lrugen->avg_refaulted[type][tier] + + atomic_long_read(&lrugen->refaulted[hist][type][tier]); + pos->total = lrugen->avg_total[type][tier] + + atomic_long_read(&lrugen->evicted[hist][type][tier]); + if (tier) + pos->total += lrugen->protected[hist][type][tier - 1]; + pos->gain = gain; +} + +static void reset_ctrl_pos(struct lruvec *lruvec, int type, bool carryover) +{ + int hist, tier; + struct lru_gen_struct *lrugen = &lruvec->lrugen; + bool clear = carryover ? NR_HIST_GENS == 1 : NR_HIST_GENS > 1; + unsigned long seq = carryover ? lrugen->min_seq[type] : lrugen->max_seq + 1; + + lockdep_assert_held(&lruvec_pgdat(lruvec)->lru_lock); + + if (!carryover && !clear) + return; + + hist = lru_hist_from_seq(seq); + + for (tier = 0; tier < MAX_NR_TIERS; tier++) { + if (carryover) { + unsigned long sum; + + sum = lrugen->avg_refaulted[type][tier] + + atomic_long_read(&lrugen->refaulted[hist][type][tier]); + WRITE_ONCE(lrugen->avg_refaulted[type][tier], sum / 2); + + sum = lrugen->avg_total[type][tier] + + atomic_long_read(&lrugen->evicted[hist][type][tier]); + if (tier) + sum += lrugen->protected[hist][type][tier - 1]; + WRITE_ONCE(lrugen->avg_total[type][tier], sum / 2); + } + + if (clear) { + atomic_long_set(&lrugen->refaulted[hist][type][tier], 0); + atomic_long_set(&lrugen->evicted[hist][type][tier], 0); + if (tier) + WRITE_ONCE(lrugen->protected[hist][type][tier - 1], 0); + } + } +} + +static bool positive_ctrl_err(struct ctrl_pos *sp, struct ctrl_pos *pv) +{ + /* + * Return true if the PV has a limited number of refaults or a lower + * refaulted/total than the SP. + */ + return pv->refaulted < MIN_LRU_BATCH || + pv->refaulted * (sp->total + MIN_LRU_BATCH) * sp->gain <= + (sp->refaulted + 1) * pv->total * pv->gain; +} + +/****************************************************************************** + * the aging + ******************************************************************************/ + +/* protect pages accessed multiple times through file descriptors */ +static int page_inc_gen(struct lruvec *lruvec, struct page *page, bool reclaiming) +{ + int type = page_is_file_cache(page); + struct lru_gen_struct *lrugen = &lruvec->lrugen; + int new_gen, old_gen = lru_gen_from_seq(lrugen->min_seq[type]); + unsigned long new_flags, old_flags; + + do { + old_flags = READ_ONCE(page->flags); + + VM_WARN_ON_ONCE_PAGE(!(old_flags & LRU_GEN_MASK), page); + + new_gen = (old_gen + 1) % MAX_NR_GENS; + + new_flags = old_flags & ~(LRU_GEN_MASK | LRU_REFS_MASK | LRU_REFS_FLAGS); + new_flags |= (new_gen + 1UL) << LRU_GEN_PGOFF; + /* for end_page_writeback() */ + if (reclaiming) + new_flags |= BIT(PG_reclaim); + } while (cmpxchg(&page->flags, old_flags, new_flags) != old_flags); + + lru_gen_update_size(lruvec, page, old_gen, new_gen); + + return new_gen; +} + +static void inc_min_seq(struct lruvec *lruvec, int type) +{ + struct lru_gen_struct *lrugen = &lruvec->lrugen; + + reset_ctrl_pos(lruvec, type, true); + WRITE_ONCE(lrugen->min_seq[type], lrugen->min_seq[type] + 1); +} + +static bool try_to_inc_min_seq(struct lruvec *lruvec, bool can_swap) +{ + int gen, type, zone; + bool success = false; + struct lru_gen_struct *lrugen = &lruvec->lrugen; + DEFINE_MIN_SEQ(lruvec); + + VM_WARN_ON_ONCE(!seq_is_valid(lruvec)); + + /* find the oldest populated generation */ + for (type = !can_swap; type < ANON_AND_FILE; type++) { + while (min_seq[type] + MIN_NR_GENS <= lrugen->max_seq) { + gen = lru_gen_from_seq(min_seq[type]); + + for (zone = 0; zone < MAX_NR_ZONES; zone++) { + if (!list_empty(&lrugen->lists[gen][type][zone])) + goto next; + } + + min_seq[type]++; + } +next: + ; + } + + /* see the comment on lru_gen_struct */ + if (can_swap) { + min_seq[LRU_GEN_ANON] = min(min_seq[LRU_GEN_ANON], min_seq[LRU_GEN_FILE]); + min_seq[LRU_GEN_FILE] = max(min_seq[LRU_GEN_ANON], lrugen->min_seq[LRU_GEN_FILE]); + } + + for (type = !can_swap; type < ANON_AND_FILE; type++) { + if (min_seq[type] == lrugen->min_seq[type]) + continue; + + reset_ctrl_pos(lruvec, type, true); + WRITE_ONCE(lrugen->min_seq[type], min_seq[type]); + success = true; + } + + return success; +} + +static void inc_max_seq(struct lruvec *lruvec, unsigned long max_seq, bool can_swap) +{ + int prev, next; + int type, zone; + struct lru_gen_struct *lrugen = &lruvec->lrugen; + struct pglist_data *pgdat = lruvec_pgdat(lruvec); + + spin_lock_irq(&pgdat->lru_lock); + + VM_WARN_ON_ONCE(!seq_is_valid(lruvec)); + + if (max_seq != lrugen->max_seq) + goto unlock; + + for (type = ANON_AND_FILE - 1; type >= 0; type--) { + if (get_nr_gens(lruvec, type) != MAX_NR_GENS) + continue; + + VM_WARN_ON_ONCE(type == LRU_GEN_FILE || can_swap); + + inc_min_seq(lruvec, type); + } + + /* + * Update the active/inactive LRU sizes for compatibility. Both sides of + * the current max_seq need to be covered, since max_seq+1 can overlap + * with min_seq[LRU_GEN_ANON] if swapping is constrained. And if they do + * overlap, cold/hot inversion happens. + */ + prev = lru_gen_from_seq(lrugen->max_seq - 1); + next = lru_gen_from_seq(lrugen->max_seq + 1); + + for (type = 0; type < ANON_AND_FILE; type++) { + for (zone = 0; zone < MAX_NR_ZONES; zone++) { + enum lru_list lru = type * LRU_INACTIVE_FILE; + long delta = lrugen->nr_pages[prev][type][zone] - + lrugen->nr_pages[next][type][zone]; + + if (!delta) + continue; + + __update_lru_size(lruvec, lru, zone, delta); + __update_lru_size(lruvec, lru + LRU_ACTIVE, zone, -delta); + } + } + + for (type = 0; type < ANON_AND_FILE; type++) + reset_ctrl_pos(lruvec, type, false); + + /* make sure preceding modifications appear */ + smp_store_release(&lrugen->max_seq, lrugen->max_seq + 1); +unlock: + spin_unlock_irq(&pgdat->lru_lock); +} + +static bool should_run_aging(struct lruvec *lruvec, unsigned long max_seq, unsigned long *min_seq, + struct scan_control *sc, bool can_swap, unsigned long *nr_to_scan) +{ + int gen, type, zone; + unsigned long old = 0; + unsigned long young = 0; + unsigned long total = 0; + struct lru_gen_struct *lrugen = &lruvec->lrugen; + struct mem_cgroup *memcg = lruvec_memcg(lruvec); + + for (type = !can_swap; type < ANON_AND_FILE; type++) { + unsigned long seq; + + for (seq = min_seq[type]; seq <= max_seq; seq++) { + unsigned long size = 0; + + gen = lru_gen_from_seq(seq); + + for (zone = 0; zone < MAX_NR_ZONES; zone++) + size += max(READ_ONCE(lrugen->nr_pages[gen][type][zone]), 0L); + + total += size; + if (seq == max_seq) + young += size; + else if (seq + MIN_NR_GENS == max_seq) + old += size; + } + } + + /* try to scrape all its memory if this memcg was deleted */ + *nr_to_scan = mem_cgroup_online(memcg) ? (total >> sc->priority) : total; + + /* + * The aging tries to be lazy to reduce the overhead, while the eviction + * stalls when the number of generations reaches MIN_NR_GENS. Hence, the + * ideal number of generations is MIN_NR_GENS+1. + */ + if (min_seq[!can_swap] + MIN_NR_GENS > max_seq) + return true; + if (min_seq[!can_swap] + MIN_NR_GENS < max_seq) + return false; + + /* + * It's also ideal to spread pages out evenly, i.e., 1/(MIN_NR_GENS+1) + * of the total number of pages for each generation. A reasonable range + * for this average portion is [1/MIN_NR_GENS, 1/(MIN_NR_GENS+2)]. The + * aging cares about the upper bound of hot pages, while the eviction + * cares about the lower bound of cold pages. + */ + if (young * MIN_NR_GENS > total) + return true; + if (old * (MIN_NR_GENS + 2) < total) + return true; + + return false; +} + +static void age_lruvec(struct lruvec *lruvec, struct scan_control *sc) +{ + bool need_aging; + unsigned long nr_to_scan; + int swappiness = get_swappiness(lruvec, sc); + struct mem_cgroup *memcg = lruvec_memcg(lruvec); + enum mem_cgroup_protection prot = mem_cgroup_protected(NULL, memcg); + DEFINE_MAX_SEQ(lruvec); + DEFINE_MIN_SEQ(lruvec); + + VM_WARN_ON_ONCE(sc->memcg_low_reclaim); + + if (prot == MEMCG_PROT_MIN) + return; + + need_aging = should_run_aging(lruvec, max_seq, min_seq, sc, swappiness, &nr_to_scan); + if (need_aging) + inc_max_seq(lruvec, max_seq, swappiness); +} + +static void lru_gen_age_node(struct pglist_data *pgdat, struct scan_control *sc) +{ + struct mem_cgroup *memcg; + + VM_WARN_ON_ONCE(!current_is_kswapd()); + + memcg = mem_cgroup_iter(NULL, NULL, NULL); + do { + struct lruvec *lruvec = mem_cgroup_lruvec(pgdat, memcg); + + age_lruvec(lruvec, sc); + + cond_resched(); + } while ((memcg = mem_cgroup_iter(NULL, memcg, NULL))); +} + +/****************************************************************************** + * the eviction + ******************************************************************************/ + +static bool sort_page(struct lruvec *lruvec, struct page *page, int tier_idx) +{ + bool success; + int gen = page_lru_gen(page); + int type = page_is_file_cache(page); + int zone = page_zonenum(page); + int delta = hpage_nr_pages(page); + int refs = page_lru_refs(page); + int tier = lru_tier_from_refs(refs); + struct lru_gen_struct *lrugen = &lruvec->lrugen; + + VM_WARN_ON_ONCE_PAGE(gen >= MAX_NR_GENS, page); + + /* unevictable */ + if (!page_evictable(page)) { + success = lru_gen_del_page(lruvec, page, true); + VM_WARN_ON_ONCE_PAGE(!success, page); + SetPageUnevictable(page); + add_page_to_lru_list(page, lruvec); + __count_vm_events(UNEVICTABLE_PGCULLED, delta); + return true; + } + + /* dirty lazyfree */ + if (type == LRU_GEN_FILE && PageAnon(page) && PageDirty(page)) { + success = lru_gen_del_page(lruvec, page, true); + VM_WARN_ON_ONCE_PAGE(!success, page); + SetPageSwapBacked(page); + add_page_to_lru_list_tail(page, lruvec); + return true; + } + + /* protected */ + if (tier > tier_idx) { + int hist = lru_hist_from_seq(lrugen->min_seq[type]); + + gen = page_inc_gen(lruvec, page, false); + list_move_tail(&page->lru, &lrugen->lists[gen][type][zone]); + + WRITE_ONCE(lrugen->protected[hist][type][tier - 1], + lrugen->protected[hist][type][tier - 1] + delta); + __mod_lruvec_state(lruvec, WORKINGSET_ACTIVATE, delta); + return true; + } + + /* waiting for writeback */ + if (PageLocked(page) || PageWriteback(page) || + (type == LRU_GEN_FILE && PageDirty(page))) { + gen = page_inc_gen(lruvec, page, true); + list_move(&page->lru, &lrugen->lists[gen][type][zone]); + return true; + } + + return false; +} + +static bool isolate_page(struct lruvec *lruvec, struct page *page, struct scan_control *sc) +{ + bool success; + + /* unmapping inhibited */ + if (!sc->may_unmap && page_mapped(page)) + return false; + + /* swapping inhibited */ + if (!(sc->may_writepage && (sc->gfp_mask & __GFP_IO)) && + (PageDirty(page) || + (PageAnon(page) && !PageSwapCache(page)))) + return false; + + /* raced with release_pages() */ + if (!get_page_unless_zero(page)) + return false; + + ClearPageLRU(page); + + /* see the comment on MAX_NR_TIERS */ + if (!PageReferenced(page)) + set_mask_bits(&page->flags, LRU_REFS_MASK | LRU_REFS_FLAGS, 0); + + /* for shrink_page_list() */ + ClearPageReclaim(page); + ClearPageReferenced(page); + + success = lru_gen_del_page(lruvec, page, true); + VM_WARN_ON_ONCE_PAGE(!success, page); + + return true; +} + +static int scan_pages(struct lruvec *lruvec, struct scan_control *sc, + int type, int tier, struct list_head *list) +{ + int gen, zone; + enum vm_event_item item; + int sorted = 0; + int scanned = 0; + int isolated = 0; + int remaining = MAX_LRU_BATCH; + struct lru_gen_struct *lrugen = &lruvec->lrugen; + struct mem_cgroup *memcg = lruvec_memcg(lruvec); + + VM_WARN_ON_ONCE(!list_empty(list)); + + if (get_nr_gens(lruvec, type) == MIN_NR_GENS) + return 0; + + gen = lru_gen_from_seq(lrugen->min_seq[type]); + + for (zone = sc->reclaim_idx; zone >= 0; zone--) { + LIST_HEAD(moved); + int skipped = 0; + struct list_head *head = &lrugen->lists[gen][type][zone]; + + while (!list_empty(head)) { + struct page *page = lru_to_page(head); + int delta = hpage_nr_pages(page); + + VM_WARN_ON_ONCE_PAGE(PageUnevictable(page), page); + VM_WARN_ON_ONCE_PAGE(PageActive(page), page); + VM_WARN_ON_ONCE_PAGE(page_is_file_cache(page) != type, page); + VM_WARN_ON_ONCE_PAGE(page_zonenum(page) != zone, page); + + scanned += delta; + + if (sort_page(lruvec, page, tier)) + sorted += delta; + else if (isolate_page(lruvec, page, sc)) { + list_add(&page->lru, list); + isolated += delta; + } else { + list_move(&page->lru, &moved); + skipped += delta; + } + + if (!--remaining || max(isolated, skipped) >= MIN_LRU_BATCH) + break; + } + + if (skipped) { + list_splice(&moved, head); + __count_zid_vm_events(PGSCAN_SKIP, zone, skipped); + } + + if (!remaining || isolated >= MIN_LRU_BATCH) + break; + } + + item = current_is_kswapd() ? PGSCAN_KSWAPD : PGSCAN_DIRECT; + if (global_reclaim(sc)) { + __count_vm_events(item, isolated); + __count_vm_events(PGREFILL, sorted); + } + __count_memcg_events(memcg, item, isolated); + __count_memcg_events(memcg, PGREFILL, sorted); + + /* + * There might not be eligible pages due to reclaim_idx, may_unmap and + * may_writepage. Check the remaining to prevent livelock if it's not + * making progress. + */ + return isolated || !remaining ? scanned : 0; +} + +static int get_tier_idx(struct lruvec *lruvec, int type) +{ + int tier; + struct ctrl_pos sp, pv; + + /* + * To leave a margin for fluctuations, use a larger gain factor (1:2). + * This value is chosen because any other tier would have at least twice + * as many refaults as the first tier. + */ + read_ctrl_pos(lruvec, type, 0, 1, &sp); + for (tier = 1; tier < MAX_NR_TIERS; tier++) { + read_ctrl_pos(lruvec, type, tier, 2, &pv); + if (!positive_ctrl_err(&sp, &pv)) + break; + } + + return tier - 1; +} + +static int get_type_to_scan(struct lruvec *lruvec, int swappiness, int *tier_idx) +{ + int type, tier; + struct ctrl_pos sp, pv; + int gain[ANON_AND_FILE] = { swappiness, 200 - swappiness }; + + /* + * Compare the first tier of anon with that of file to determine which + * type to scan. Also need to compare other tiers of the selected type + * with the first tier of the other type to determine the last tier (of + * the selected type) to evict. + */ + read_ctrl_pos(lruvec, LRU_GEN_ANON, 0, gain[LRU_GEN_ANON], &sp); + read_ctrl_pos(lruvec, LRU_GEN_FILE, 0, gain[LRU_GEN_FILE], &pv); + type = positive_ctrl_err(&sp, &pv); + + read_ctrl_pos(lruvec, !type, 0, gain[!type], &sp); + for (tier = 1; tier < MAX_NR_TIERS; tier++) { + read_ctrl_pos(lruvec, type, tier, gain[type], &pv); + if (!positive_ctrl_err(&sp, &pv)) + break; + } + + *tier_idx = tier - 1; + + return type; +} + +static int isolate_pages(struct lruvec *lruvec, struct scan_control *sc, int swappiness, + int *type_scanned, struct list_head *list) +{ + int i; + int type; + int scanned; + int tier = -1; + DEFINE_MIN_SEQ(lruvec); + + /* + * Try to make the obvious choice first. When anon and file are both + * available from the same generation, interpret swappiness 1 as file + * first and 200 as anon first. + */ + if (!swappiness) + type = LRU_GEN_FILE; + else if (min_seq[LRU_GEN_ANON] < min_seq[LRU_GEN_FILE]) + type = LRU_GEN_ANON; + else if (swappiness == 1) + type = LRU_GEN_FILE; + else if (swappiness == 200) + type = LRU_GEN_ANON; + else + type = get_type_to_scan(lruvec, swappiness, &tier); + + for (i = !swappiness; i < ANON_AND_FILE; i++) { + if (tier < 0) + tier = get_tier_idx(lruvec, type); + + scanned = scan_pages(lruvec, sc, type, tier, list); + if (scanned) + break; + + type = !type; + tier = -1; + } + + *type_scanned = type; + + return scanned; +} + +static int evict_pages(struct lruvec *lruvec, struct scan_control *sc, int swappiness) +{ + int type; + int scanned; + int reclaimed; + LIST_HEAD(list); + struct page *page; + enum vm_event_item item; + struct reclaim_stat stat; + struct mem_cgroup *memcg = lruvec_memcg(lruvec); + struct pglist_data *pgdat = lruvec_pgdat(lruvec); + + spin_lock_irq(&pgdat->lru_lock); + + scanned = isolate_pages(lruvec, sc, swappiness, &type, &list); + + scanned += try_to_inc_min_seq(lruvec, swappiness); + + if (get_nr_gens(lruvec, !swappiness) == MIN_NR_GENS) + scanned = 0; + + spin_unlock_irq(&pgdat->lru_lock); + + if (list_empty(&list)) + return scanned; + + reclaimed = shrink_page_list(&list, pgdat, sc, 0, &stat, false); + + list_for_each_entry(page, &list, lru) { + /* restore LRU_REFS_FLAGS cleared by isolate_page() */ + if (PageWorkingset(page)) + SetPageReferenced(page); + + /* don't add rejected pages to the oldest generation */ + if (PageReclaim(page) && + (PageDirty(page) || PageWriteback(page))) + ClearPageActive(page); + else + SetPageActive(page); + } + + spin_lock_irq(&pgdat->lru_lock); + + move_pages_to_lru(lruvec, &list); + + item = current_is_kswapd() ? PGSTEAL_KSWAPD : PGSTEAL_DIRECT; + if (global_reclaim(sc)) + __count_vm_events(item, reclaimed); + __count_memcg_events(memcg, item, reclaimed); + + spin_unlock_irq(&pgdat->lru_lock); + + mem_cgroup_uncharge_list(&list); + free_unref_page_list(&list); + + sc->nr_reclaimed += reclaimed; + + return scanned; +} + +static unsigned long get_nr_to_scan(struct lruvec *lruvec, struct scan_control *sc, + bool can_swap) +{ + bool need_aging; + unsigned long nr_to_scan; + DEFINE_MAX_SEQ(lruvec); + DEFINE_MIN_SEQ(lruvec); + + need_aging = should_run_aging(lruvec, max_seq, min_seq, sc, can_swap, &nr_to_scan); + if (!need_aging) + return nr_to_scan; + + /* skip the aging path at the default priority */ + if (sc->priority == DEF_PRIORITY) + goto done; + + /* leave the work to lru_gen_age_node() */ + if (current_is_kswapd()) + return 0; + + inc_max_seq(lruvec, max_seq, can_swap); +done: + return min_seq[!can_swap] + MIN_NR_GENS <= max_seq ? nr_to_scan : 0; +} + +static void lru_gen_shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc) +{ + struct blk_plug plug; + unsigned long scanned = 0; + + lru_add_drain(); + + blk_start_plug(&plug); + + while (true) { + int delta; + int swappiness; + unsigned long nr_to_scan; + + if (sc->may_swap) + swappiness = get_swappiness(lruvec, sc); + else if (global_reclaim(sc) && get_swappiness(lruvec, sc)) + swappiness = 1; + else + swappiness = 0; + + nr_to_scan = get_nr_to_scan(lruvec, sc, swappiness); + if (!nr_to_scan) + break; + + delta = evict_pages(lruvec, sc, swappiness); + if (!delta) + break; + + scanned += delta; + if (scanned >= nr_to_scan) + break; + + cond_resched(); + } + + blk_finish_plug(&plug); +} + /****************************************************************************** * initialization ******************************************************************************/ @@ -2700,6 +3443,16 @@ static int __init init_lru_gen(void) }; late_initcall(init_lru_gen); +#else /* !CONFIG_LRU_GEN */ + +static void lru_gen_age_node(struct pglist_data *pgdat, struct scan_control *sc) +{ +} + +static void lru_gen_shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc) +{ +} + #endif /* CONFIG_LRU_GEN */ /* @@ -2718,6 +3471,11 @@ static void shrink_node_memcg(struct pglist_data *pgdat, struct mem_cgroup *memc struct blk_plug plug; bool scan_adjusted; + if (lru_gen_enabled()) { + lru_gen_shrink_lruvec(lruvec, sc); + return; + } + get_scan_count(lruvec, memcg, sc, nr, lru_pages); /* Record the original scan target for proportional adjustments later */ @@ -3192,6 +3950,9 @@ static void snapshot_refaults(struct mem_cgroup *root_memcg, pg_data_t *pgdat) { struct mem_cgroup *memcg; + if (lru_gen_enabled()) + return; + memcg = mem_cgroup_iter(root_memcg, NULL, NULL); do { unsigned long refaults; @@ -3549,11 +4310,15 @@ unsigned long try_to_free_mem_cgroup_pages(struct mem_cgroup *memcg, } #endif -static void age_active_anon(struct pglist_data *pgdat, - struct scan_control *sc) +static void kswapd_age_node(struct pglist_data *pgdat, struct scan_control *sc) { struct mem_cgroup *memcg; + if (lru_gen_enabled()) { + lru_gen_age_node(pgdat, sc); + return; + } + if (!total_swap_pages) return; @@ -3833,12 +4598,11 @@ restart: sc.may_swap = !nr_boost_reclaim; /* - * Do some background aging of the anon list, to give - * pages a chance to be referenced before reclaiming. All - * pages are rotated regardless of classzone as this is - * about consistent aging. + * Do some background aging, to give pages a chance to be + * referenced before reclaiming. All pages are rotated + * regardless of classzone as this is about consistent aging. */ - age_active_anon(pgdat, &sc); + kswapd_age_node(pgdat, &sc); /* * If we're getting trouble reclaiming, start doing writepage diff --git a/mm/workingset.c b/mm/workingset.c index b51d8eace8a0..3f422d514ff6 100644 --- a/mm/workingset.c +++ b/mm/workingset.c @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -184,7 +185,6 @@ static unsigned int bucket_order __read_mostly; static void *pack_shadow(int memcgid, pg_data_t *pgdat, unsigned long eviction, bool workingset) { - eviction >>= bucket_order; eviction &= EVICTION_MASK; eviction = (eviction << MEM_CGROUP_ID_SHIFT) | memcgid; eviction = (eviction << NODES_SHIFT) | pgdat->node_id; @@ -209,10 +209,110 @@ static void unpack_shadow(void *shadow, int *memcgidp, pg_data_t **pgdat, *memcgidp = memcgid; *pgdat = NODE_DATA(nid); - *evictionp = entry << bucket_order; + *evictionp = entry; *workingsetp = workingset; } +#ifdef CONFIG_LRU_GEN + +void *lru_gen_eviction(struct page *page) +{ + int hist; + unsigned long token; + unsigned long min_seq; + struct lruvec *lruvec; + struct lru_gen_struct *lrugen; + int type = page_is_file_cache(page); + int delta = hpage_nr_pages(page); + int refs = page_lru_refs(page); + int tier = lru_tier_from_refs(refs); + struct mem_cgroup *memcg = page_memcg(page); + struct pglist_data *pgdat = page_pgdat(page); + + if (!mem_cgroup_disabled() && !memcg) + return NULL; + + BUILD_BUG_ON(LRU_GEN_WIDTH + LRU_REFS_WIDTH > BITS_PER_LONG - EVICTION_SHIFT); + + lruvec = mem_cgroup_lruvec(pgdat, memcg); + lrugen = &lruvec->lrugen; + min_seq = READ_ONCE(lrugen->min_seq[type]); + token = (min_seq << LRU_REFS_WIDTH) | max(refs - 1, 0); + + hist = lru_hist_from_seq(min_seq); + atomic_long_add(delta, &lrugen->evicted[hist][type][tier]); + + return pack_shadow(mem_cgroup_id(memcg), pgdat, token, refs); +} + +void lru_gen_refault(struct page *page, void *shadow) +{ + int hist, tier, refs; + int memcg_id; + bool workingset; + unsigned long token; + unsigned long min_seq; + struct lruvec *lruvec; + struct lru_gen_struct *lrugen; + struct mem_cgroup *memcg; + struct pglist_data *pgdat; + int type = page_is_file_cache(page); + int delta = hpage_nr_pages(page); + + unpack_shadow(shadow, &memcg_id, &pgdat, &token, &workingset); + + if (pgdat != page_pgdat(page)) + return; + + rcu_read_lock(); + + memcg = page_memcg_rcu(page); + if ((!mem_cgroup_disabled() && !memcg) || memcg_id != mem_cgroup_id(memcg)) + goto unlock; + + lruvec = mem_cgroup_lruvec(pgdat, memcg); + lrugen = &lruvec->lrugen; + + min_seq = READ_ONCE(lrugen->min_seq[type]); + if ((token >> LRU_REFS_WIDTH) != (min_seq & (EVICTION_MASK >> LRU_REFS_WIDTH))) + goto unlock; + + hist = lru_hist_from_seq(min_seq); + /* see the comment in page_lru_refs() */ + refs = (token & (BIT(LRU_REFS_WIDTH) - 1)) + workingset; + tier = lru_tier_from_refs(refs); + + atomic_long_add(delta, &lrugen->refaulted[hist][type][tier]); + mod_lruvec_state(lruvec, WORKINGSET_REFAULT, delta); + + /* + * Count the following two cases as stalls: + * 1. For pages accessed through page tables, hotter pages pushed out + * hot pages which refaulted immediately. + * 2. For pages accessed multiple times through file descriptors, + * numbers of accesses might have been out of the range. + */ + if (lru_gen_in_fault() || refs == BIT(LRU_REFS_WIDTH)) { + SetPageWorkingset(page); + mod_lruvec_state(lruvec, WORKINGSET_RESTORE, delta); + } +unlock: + rcu_read_unlock(); +} + +#else /* !CONFIG_LRU_GEN */ + +void *lru_gen_eviction(struct page *page) +{ + return NULL; +} + +void lru_gen_refault(struct page *page, void *shadow) +{ +} + +#endif /* CONFIG_LRU_GEN */ + /** * workingset_eviction - note the eviction of a page from memory * @page: the page being evicted @@ -228,6 +328,9 @@ void *workingset_eviction(struct page *page) unsigned long eviction; struct lruvec *lruvec; + if (lru_gen_enabled()) + return lru_gen_eviction(page); + /* Page is fully exclusive and pins page->mem_cgroup */ VM_BUG_ON_PAGE(PageLRU(page), page); VM_BUG_ON_PAGE(page_count(page), page); @@ -235,6 +338,7 @@ void *workingset_eviction(struct page *page) lruvec = mem_cgroup_lruvec(pgdat, memcg); eviction = atomic_long_inc_return(&lruvec->inactive_age); + eviction >>= bucket_order; return pack_shadow(memcgid, pgdat, eviction, PageWorkingset(page)); } @@ -258,7 +362,13 @@ void workingset_refault(struct page *page, void *shadow) bool workingset; int memcgid; + if (lru_gen_enabled()) { + lru_gen_refault(page, shadow); + return; + } + unpack_shadow(shadow, &memcgid, &pgdat, &eviction, &workingset); + eviction <<= bucket_order; rcu_read_lock(); /* From 4ad1d61d9de838f09636bf9568432610c2bf0998 Mon Sep 17 00:00:00 2001 From: Yu Zhao Date: Sun, 18 Sep 2022 02:00:04 -0600 Subject: [PATCH 568/698] BACKPORT: mm: multi-gen LRU: exploit locality in rmap MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Searching the rmap for PTEs mapping each page on an LRU list (to test and clear the accessed bit) can be expensive because pages from different VMAs (PA space) are not cache friendly to the rmap (VA space). For workloads mostly using mapped pages, searching the rmap can incur the highest CPU cost in the reclaim path. This patch exploits spatial locality to reduce the trips into the rmap. When shrink_page_list() walks the rmap and finds a young PTE, a new function lru_gen_look_around() scans at most BITS_PER_LONG-1 adjacent PTEs. On finding another young PTE, it clears the accessed bit and updates the gen counter of the page mapped by this PTE to (max_seq%MAX_NR_GENS)+1. Moto-CRs-Fixed:(CR) Server benchmark results: Single workload: fio (buffered I/O): no change Single workload: memcached (anon): +[3, 5]% Ops/sec KB/sec patch1-6: 1106168.46 43025.04 patch1-7: 1147696.57 44640.29 Configurations: no change Client benchmark results: kswapd profiles: patch1-6 39.03% lzo1x_1_do_compress (real work) 18.47% page_vma_mapped_walk (overhead) 6.74% _raw_spin_unlock_irq 3.97% do_raw_spin_lock 2.49% ptep_clear_flush 2.48% anon_vma_interval_tree_iter_first 1.92% page_referenced_one 1.88% __zram_bvec_write 1.48% memmove 1.31% vma_interval_tree_iter_next patch1-7 48.16% lzo1x_1_do_compress (real work) 8.20% page_vma_mapped_walk (overhead) 7.06% _raw_spin_unlock_irq 2.92% ptep_clear_flush 2.53% __zram_bvec_write 2.11% do_raw_spin_lock 2.02% memmove 1.93% lru_gen_look_around 1.56% free_unref_page_list 1.40% memset Configurations: no change Link: https://lkml.kernel.org/r/20220918080010.2920238-8-yuzhao@google.com Change-Id: Iac405b6d42e2e3f632b6748368f61202c164f1ad Signed-off-by: Yu Zhao Acked-by: Barry Song Acked-by: Brian Geffon Acked-by: Jan Alexander Steffens (heftig) Acked-by: Oleksandr Natalenko Acked-by: Steven Barrett Acked-by: Suleiman Souhlal Tested-by: Daniel Byrne Tested-by: Donald Carr Tested-by: Holger Hoffstätte Tested-by: Konstantin Kharlamov Tested-by: Shuang Zhai Tested-by: Sofia Trinh Tested-by: Vaibhav Jain Cc: Andi Kleen Cc: Aneesh Kumar K.V Cc: Catalin Marinas Cc: Dave Hansen Cc: Hillf Danton Cc: Jens Axboe Cc: Johannes Weiner Cc: Jonathan Corbet Cc: Linus Torvalds Cc: Matthew Wilcox Cc: Mel Gorman Cc: Miaohe Lin Cc: Michael Larabel Cc: Michal Hocko Cc: M(CR) Rapoport Cc: M(CR) Rapoport Cc: Peter Zijlstra Cc: Qi Zheng Cc: Tejun Heo Cc: Vlastimil Babka Cc: Will Deacon Signed-off-by: Andrew Morton (cherry picked from commit 018ee47f14893d500131dfca2ff9f3ff8ebd4ed2) Bug: 261052246 Signed-off-by: Kalesh Singh Reviewed-on: https://gerrit.mot.com/2491800 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- include/linux/memcontrol.h | 29 ++++++ include/linux/mmzone.h | 6 ++ mm/internal.h | 1 + mm/rmap.c | 7 ++ mm/vmscan.c | 186 +++++++++++++++++++++++++++++++++++++ 5 files changed, 229 insertions(+) diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h index a1b04d916526..45709b7bef1a 100644 --- a/include/linux/memcontrol.h +++ b/include/linux/memcontrol.h @@ -659,6 +659,23 @@ static inline unsigned long memcg_page_state_local(struct mem_cgroup *memcg, void __mod_memcg_state(struct mem_cgroup *memcg, int idx, int val); +/* try to stablize page_memcg() for all the pages in a memcg */ +static inline bool mem_cgroup_trylock_pages(struct mem_cgroup *memcg) +{ + rcu_read_lock(); + + if (mem_cgroup_disabled() || !atomic_read(&memcg->moving_account)) + return true; + + rcu_read_unlock(); + return false; +} + +static inline void mem_cgroup_unlock_pages(void) +{ + rcu_read_unlock(); +} + /* idx can be of type enum memcg_stat_item or node_stat_item */ static inline void mod_memcg_state(struct mem_cgroup *memcg, int idx, int val) @@ -1059,6 +1076,18 @@ static inline void unlock_page_memcg(struct page *page) { } +static inline bool mem_cgroup_trylock_pages(struct mem_cgroup *memcg) +{ + /* to match page_memcg_rcu() */ + rcu_read_lock(); + return true; +} + +static inline void mem_cgroup_unlock_pages(void) +{ + rcu_read_unlock(); +} + static inline void mem_cgroup_handle_over_high(void) { } diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index 2721b50970fe..4d6a1cff0e70 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -366,6 +366,7 @@ struct zone_reclaim_stat { #ifndef __GENERATING_BOUNDS_H struct lruvec; +struct page_vma_mapped_walk; #define LRU_GEN_MASK ((BIT(LRU_GEN_WIDTH) - 1) << LRU_GEN_PGOFF) #define LRU_REFS_MASK ((BIT(LRU_REFS_WIDTH) - 1) << LRU_REFS_PGOFF) @@ -424,6 +425,7 @@ struct lru_gen_struct { }; void lru_gen_init_lruvec(struct lruvec *lruvec); +void lru_gen_look_around(struct page_vma_mapped_walk *pvmw); #ifdef CONFIG_MEMCG void lru_gen_init_memcg(struct mem_cgroup *memcg); @@ -436,6 +438,10 @@ static inline void lru_gen_init_lruvec(struct lruvec *lruvec) { } +static inline void lru_gen_look_around(struct page_vma_mapped_walk *pvmw) +{ +} + #ifdef CONFIG_MEMCG static inline void lru_gen_init_memcg(struct mem_cgroup *memcg) { diff --git a/mm/internal.h b/mm/internal.h index 6504edd8a447..f14974189fbf 100644 --- a/mm/internal.h +++ b/mm/internal.h @@ -35,6 +35,7 @@ void page_writeback_init(void); vm_fault_t do_swap_page(struct vm_fault *vmf); +void activate_page(struct page *page); #ifdef CONFIG_SPECULATIVE_PAGE_FAULT extern struct vm_area_struct *get_vma(struct mm_struct *mm, diff --git a/mm/rmap.c b/mm/rmap.c index 2b5886600b38..46416f1dc6fa 100644 --- a/mm/rmap.c +++ b/mm/rmap.c @@ -66,6 +66,7 @@ #include #include #include +#include #include @@ -781,6 +782,12 @@ static bool page_referenced_one(struct page *page, struct vm_area_struct *vma, } if (pvmw.pte) { + if (lru_gen_enabled() && pte_young(*pvmw.pte) && + !(vma->vm_flags & (VM_SEQ_READ | VM_RAND_READ))) { + lru_gen_look_around(&pvmw); + referenced++; + } + if (ptep_clear_flush_young_notify(vma, address, pvmw.pte)) { /* diff --git a/mm/vmscan.c b/mm/vmscan.c index 7cf42b2eaee2..c6e98e805bf5 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -1190,6 +1190,11 @@ static unsigned long shrink_page_list(struct list_head *page_list, if (!sc->may_unmap && page_mapped(page)) goto keep_locked; + /* page_update_gen() tried to promote this page? */ + if (lru_gen_enabled() && !ignore_references && + page_mapped(page) && PageReferenced(page)) + goto keep_locked; + may_enter_fs = (sc->gfp_mask & __GFP_FS) || (PageSwapCache(page) && (sc->gfp_mask & __GFP_IO)); @@ -2793,6 +2798,31 @@ static bool positive_ctrl_err(struct ctrl_pos *sp, struct ctrl_pos *pv) * the aging ******************************************************************************/ +/* promote pages accessed through page tables */ +static int page_update_gen(struct page *page, int gen) +{ + unsigned long new_flags, old_flags; + + VM_WARN_ON_ONCE(gen >= MAX_NR_GENS); + VM_WARN_ON_ONCE(!rcu_read_lock_held()); + + do { + old_flags = READ_ONCE(page->flags); + + /* lru_gen_del_page() has isolated this page? */ + if (!(old_flags & LRU_GEN_MASK)) { + /* for shrink_page_list() */ + new_flags = old_flags | BIT(PG_referenced); + continue; + } + + new_flags = old_flags & ~(LRU_GEN_MASK | LRU_REFS_MASK | LRU_REFS_FLAGS); + new_flags |= (gen + 1UL) << LRU_GEN_PGOFF; + } while (cmpxchg(&page->flags, old_flags, new_flags) != old_flags); + + return ((old_flags & LRU_GEN_MASK) >> LRU_GEN_PGOFF) - 1; +} + /* protect pages accessed multiple times through file descriptors */ static int page_inc_gen(struct lruvec *lruvec, struct page *page, bool reclaiming) { @@ -2806,6 +2836,11 @@ static int page_inc_gen(struct lruvec *lruvec, struct page *page, bool reclaimin VM_WARN_ON_ONCE_PAGE(!(old_flags & LRU_GEN_MASK), page); + new_gen = ((old_flags & LRU_GEN_MASK) >> LRU_GEN_PGOFF) - 1; + /* page_update_gen() has promoted this page? */ + if (new_gen >= 0 && new_gen != old_gen) + return new_gen; + new_gen = (old_gen + 1) % MAX_NR_GENS; new_flags = old_flags & ~(LRU_GEN_MASK | LRU_REFS_MASK | LRU_REFS_FLAGS); @@ -2820,6 +2855,43 @@ static int page_inc_gen(struct lruvec *lruvec, struct page *page, bool reclaimin return new_gen; } +static unsigned long get_pte_pfn(pte_t pte, struct vm_area_struct *vma, unsigned long addr) +{ + unsigned long pfn = pte_pfn(pte); + + VM_WARN_ON_ONCE(addr < vma->vm_start || addr >= vma->vm_end); + + if (!pte_present(pte) || is_zero_pfn(pfn)) + return -1; + + if (WARN_ON_ONCE(pte_devmap(pte) || pte_special(pte))) + return -1; + + if (WARN_ON_ONCE(!pfn_valid(pfn))) + return -1; + + return pfn; +} + +static struct page *get_pfn_page(unsigned long pfn, struct mem_cgroup *memcg, + struct pglist_data *pgdat) +{ + struct page *page; + + /* try to avoid unnecessary memory loads */ + if (pfn < pgdat->node_start_pfn || pfn >= pgdat_end_pfn(pgdat)) + return NULL; + + page = compound_head(pfn_to_page(pfn)); + if (page_to_nid(page) != pgdat->node_id) + return NULL; + + if (page_memcg_rcu(page) != memcg) + return NULL; + + return page; +} + static void inc_min_seq(struct lruvec *lruvec, int type) { struct lru_gen_struct *lrugen = &lruvec->lrugen; @@ -3019,6 +3091,114 @@ static void lru_gen_age_node(struct pglist_data *pgdat, struct scan_control *sc) } while ((memcg = mem_cgroup_iter(NULL, memcg, NULL))); } +/* + * This function exploits spatial locality when shrink_page_list() walks the + * rmap. It scans the adjacent PTEs of a young PTE and promotes hot pages. + */ +void lru_gen_look_around(struct page_vma_mapped_walk *pvmw) +{ + int i; + pte_t *pte; + unsigned long start; + unsigned long end; + unsigned long addr; + unsigned long bitmap[BITS_TO_LONGS(MIN_LRU_BATCH)] = {}; + struct page *page = pvmw->page; + struct mem_cgroup *memcg = page_memcg(page); + struct pglist_data *pgdat = page_pgdat(page); + struct lruvec *lruvec = mem_cgroup_lruvec(pgdat, memcg); + DEFINE_MAX_SEQ(lruvec); + int old_gen, new_gen = lru_gen_from_seq(max_seq); + + lockdep_assert_held(pvmw->ptl); + VM_WARN_ON_ONCE_PAGE(PageLRU(page), page); + + if (spin_is_contended(pvmw->ptl)) + return; + + start = max(pvmw->address & PMD_MASK, pvmw->vma->vm_start); + end = min(pvmw->address | ~PMD_MASK, pvmw->vma->vm_end - 1) + 1; + + if (end - start > MIN_LRU_BATCH * PAGE_SIZE) { + if (pvmw->address - start < MIN_LRU_BATCH * PAGE_SIZE / 2) + end = start + MIN_LRU_BATCH * PAGE_SIZE; + else if (end - pvmw->address < MIN_LRU_BATCH * PAGE_SIZE / 2) + start = end - MIN_LRU_BATCH * PAGE_SIZE; + else { + start = pvmw->address - MIN_LRU_BATCH * PAGE_SIZE / 2; + end = pvmw->address + MIN_LRU_BATCH * PAGE_SIZE / 2; + } + } + + pte = pvmw->pte - (pvmw->address - start) / PAGE_SIZE; + + rcu_read_lock(); + arch_enter_lazy_mmu_mode(); + + for (i = 0, addr = start; addr != end; i++, addr += PAGE_SIZE) { + unsigned long pfn; + + pfn = get_pte_pfn(pte[i], pvmw->vma, addr); + if (pfn == -1) + continue; + + if (!pte_young(pte[i])) + continue; + + page = get_pfn_page(pfn, memcg, pgdat); + if (!page) + continue; + + if (!ptep_test_and_clear_young(pvmw->vma, addr, pte + i)) + VM_WARN_ON_ONCE(true); + + if (pte_dirty(pte[i]) && !PageDirty(page) && + !(PageAnon(page) && PageSwapBacked(page) && + !PageSwapCache(page))) + set_page_dirty(page); + + old_gen = page_lru_gen(page); + if (old_gen < 0) + SetPageReferenced(page); + else if (old_gen != new_gen) + __set_bit(i, bitmap); + } + + arch_leave_lazy_mmu_mode(); + rcu_read_unlock(); + + if (bitmap_weight(bitmap, MIN_LRU_BATCH) < PAGEVEC_SIZE) { + for_each_set_bit(i, bitmap, MIN_LRU_BATCH) { + page = pte_page(pte[i]); + activate_page(page); + } + return; + } + + /* page_update_gen() requires stable page_memcg() */ + if (!mem_cgroup_trylock_pages(memcg)) + return; + + spin_lock_irq(&pgdat->lru_lock); + new_gen = lru_gen_from_seq(lruvec->lrugen.max_seq); + + for_each_set_bit(i, bitmap, MIN_LRU_BATCH) { + page = compound_head(pte_page(pte[i])); + if (page_memcg_rcu(page) != memcg) + continue; + + old_gen = page_update_gen(page, new_gen); + if (old_gen < 0 || old_gen == new_gen) + continue; + + lru_gen_update_size(lruvec, page, old_gen, new_gen); + } + + spin_unlock_irq(&pgdat->lru_lock); + + mem_cgroup_unlock_pages(); +} + /****************************************************************************** * the eviction ******************************************************************************/ @@ -3055,6 +3235,12 @@ static bool sort_page(struct lruvec *lruvec, struct page *page, int tier_idx) return true; } + /* promoted */ + if (gen != lru_gen_from_seq(lrugen->min_seq[type])) { + list_move(&page->lru, &lrugen->lists[gen][type][zone]); + return true; + } + /* protected */ if (tier > tier_idx) { int hist = lru_hist_from_seq(lrugen->min_seq[type]); From d5d7b93920c73815dcdbf29e311c5794b7edea3d Mon Sep 17 00:00:00 2001 From: Yu Zhao Date: Sun, 18 Sep 2022 02:00:05 -0600 Subject: [PATCH 569/698] BACKPORT: mm: multi-gen LRU: support page table walks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To further exploit spatial locality, the aging prefers to walk page tables to search for young PTEs and promote hot pages. A kill switch will be added in the next patch to disable this behavior. When disabled, the aging relies on the rmap only. NB: this behavior has nothing similar with the page table scanning in the 2.4 kernel [1], which searches page tables for old PTEs, adds cold pages to swapcache and unmaps them. To avoid confusion, the term "iteration" specifically means the traversal of an entire mm_struct list; the term "walk" will be applied to page tables and the rmap, as usual. An mm_struct list is maintained for each memcg, and an mm_struct follows its owner task to the new memcg when this task is migrated. Given an lruvec, the aging iterates lruvec_memcg()->mm_list and calls walk_page_range() with each mm_struct on this list to promote hot pages before it increments max_seq. When multiple page table walkers iterate the same list, each of them gets a unique mm_struct; therefore they can run concurrently. Page table walkers ignore any misplaced pages, e.g., if an mm_struct was migrated, pages it left in the previous memcg will not be promoted when its current memcg is under reclaim. Similarly, page table walkers will not promote pages from nodes other than the one under reclaim. This patch uses the following optimizations when walking page tables: 1. It tracks the usage of mm_struct's between context switches so that page table walkers can skip processes that have been sleeping since the last iteration. 2. It uses generational Bloom filters to record populated branches so that page table walkers can reduce their search space based on the query results, e.g., to skip page tables containing mostly holes or misplaced pages. 3. It takes advantage of the accessed bit in non-leaf PMD entries when CONFIG_ARCH_HAS_NONLEAF_PMD_YOUNG=y. 4. It does not zigzag between a PGD table and the same PMD table spanning multiple VMAs. IOW, it finishes all the VMAs within the range of the same PMD table before it returns to a PGD table. This improves the cache performance for workloads that have large numbers of tiny VMAs [2], especially when CONFIG_PGTABLE_LEVELS=5. Moto-CRs-Fixed:(CR) Server benchmark results: Single workload: fio (buffered I/O): no change Single workload: memcached (anon): +[8, 10]% Ops/sec KB/sec patch1-7: 1147696.57 44640.29 patch1-8: 1245274.91 48435.66 Configurations: no change Client benchmark results: kswapd profiles: patch1-7 48.16% lzo1x_1_do_compress (real work) 8.20% page_vma_mapped_walk (overhead) 7.06% _raw_spin_unlock_irq 2.92% ptep_clear_flush 2.53% __zram_bvec_write 2.11% do_raw_spin_lock 2.02% memmove 1.93% lru_gen_look_around 1.56% free_unref_page_list 1.40% memset patch1-8 49.44% lzo1x_1_do_compress (real work) 6.19% page_vma_mapped_walk (overhead) 5.97% _raw_spin_unlock_irq 3.13% get_pfn_page 2.85% ptep_clear_flush 2.42% __zram_bvec_write 2.08% do_raw_spin_lock 1.92% memmove 1.44% alloc_zspage 1.36% memset Configurations: no change Thanks to the following developers for their efforts [3]. kernel test robot [1] https://lwn.net/Articles/23732/ [2] https://llvm.org/docs/ScudoHardenedAllocator.html [3] https://lore.kernel.org/r/202204160827.ekEARWQo-lkp@intel.com/ Link: https://lkml.kernel.org/r/20220918080010.2920238-9-yuzhao@google.com Change-Id: I7ed3daf288e664e15bfd34991a77467a19a4e39a Signed-off-by: Yu Zhao Acked-by: Brian Geffon Acked-by: Jan Alexander Steffens (heftig) Acked-by: Oleksandr Natalenko Acked-by: Steven Barrett Acked-by: Suleiman Souhlal Tested-by: Daniel Byrne Tested-by: Donald Carr Tested-by: Holger Hoffstätte Tested-by: Konstantin Kharlamov Tested-by: Shuang Zhai Tested-by: Sofia Trinh Tested-by: Vaibhav Jain Cc: Andi Kleen Cc: Aneesh Kumar K.V Cc: Barry Song Cc: Catalin Marinas Cc: Dave Hansen Cc: Hillf Danton Cc: Jens Axboe Cc: Johannes Weiner Cc: Jonathan Corbet Cc: Linus Torvalds Cc: Matthew Wilcox Cc: Mel Gorman Cc: Miaohe Lin Cc: Michael Larabel Cc: Michal Hocko Cc: M(CR) Rapoport Cc: M(CR) Rapoport Cc: Peter Zijlstra Cc: Qi Zheng Cc: Tejun Heo Cc: Vlastimil Babka Cc: Will Deacon Signed-off-by: Andrew Morton (cherry picked from commit bd74fdaea146029e4fa12c6de89adbe0779348a9) [ Resolve conflicts in include/linux/memcontrol.h, include/linux/mm_types.h ] Bug: 261052246 Signed-off-by: Kalesh Singh Reviewed-on: https://gerrit.mot.com/2491801 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- fs/exec.c | 2 + include/linux/memcontrol.h | 5 + include/linux/mm.h | 5 + include/linux/mm_types.h | 78 +++ include/linux/mmzone.h | 56 +- include/linux/swap.h | 4 + kernel/exit.c | 1 + kernel/fork.c | 9 + kernel/sched/core.c | 1 + mm/memcontrol.c | 25 + mm/memory.c | 5 - mm/vmscan.c | 1011 +++++++++++++++++++++++++++++++++++- 12 files changed, 1180 insertions(+), 22 deletions(-) diff --git a/fs/exec.c b/fs/exec.c index 6860cd572e17..1969aa7eee21 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -1047,6 +1047,7 @@ static int exec_mmap(struct mm_struct *mm) active_mm = tsk->active_mm; tsk->active_mm = mm; tsk->mm = mm; + lru_gen_add_mm(mm); /* * This prevents preemption while active_mm is being loaded and * it and mm are being updated, which could cause problems for @@ -1062,6 +1063,7 @@ static int exec_mmap(struct mm_struct *mm) tsk->mm->vmacache_seqnum = 0; vmacache_flush(tsk); task_unlock(tsk); + lru_gen_use_mm(mm); if (old_mm) { up_read(&old_mm->mmap_sem); BUG_ON(active_mm != old_mm); diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h index 45709b7bef1a..e796f3440fc3 100644 --- a/include/linux/memcontrol.h +++ b/include/linux/memcontrol.h @@ -334,6 +334,11 @@ struct mem_cgroup { struct deferred_split deferred_split_queue; #endif +#ifdef CONFIG_LRU_GEN + /* per-memcg mm_struct list */ + struct lru_gen_mm_list mm_list; +#endif + struct mem_cgroup_per_node *nodeinfo[0]; /* WARNING: nodeinfo must be the last member here */ }; diff --git a/include/linux/mm.h b/include/linux/mm.h index 0389ca4f7c3f..080da96a4566 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -584,6 +584,11 @@ static inline bool vma_is_anonymous(struct vm_area_struct *vma) return !vma->vm_ops; } +static inline bool vma_is_accessible(struct vm_area_struct *vma) +{ + return vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE); +} + #ifdef CONFIG_SHMEM /* * The vma_is_shmem is not inline because it is used only by slow diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h index 32f9f55f2868..0cfd5bd73d1d 100644 --- a/include/linux/mm_types.h +++ b/include/linux/mm_types.h @@ -546,6 +546,24 @@ struct mm_struct { atomic_long_t hugetlb_usage; #endif struct work_struct async_put_work; +#ifdef CONFIG_LRU_GEN + struct { + /* this mm_struct is on lru_gen_mm_list */ + struct list_head list; + /* + * Set when switching to this mm_struct, as a hint of + * whether it has been used since the last time per-node + * page table walkers cleared the corresponding bits. + */ + unsigned long bitmap; +#ifdef CONFIG_MEMCG + /* points to the memcg of "owner" above */ + struct mem_cgroup *memcg; +#endif + } lru_gen; +#endif /* CONFIG_LRU_GEN */ + + ANDROID_KABI_RESERVE(1); ANDROID_VENDOR_DATA(1); } __randomize_layout; @@ -573,6 +591,66 @@ static inline cpumask_t *mm_cpumask(struct mm_struct *mm) return (struct cpumask *)&mm->cpu_bitmap; } +#ifdef CONFIG_LRU_GEN + +struct lru_gen_mm_list { + /* mm_struct list for page table walkers */ + struct list_head fifo; + /* protects the list above */ + spinlock_t lock; +}; + +void lru_gen_add_mm(struct mm_struct *mm); +void lru_gen_del_mm(struct mm_struct *mm); +#ifdef CONFIG_MEMCG +void lru_gen_migrate_mm(struct mm_struct *mm); +#endif + +static inline void lru_gen_init_mm(struct mm_struct *mm) +{ + INIT_LIST_HEAD(&mm->lru_gen.list); + mm->lru_gen.bitmap = 0; +#ifdef CONFIG_MEMCG + mm->lru_gen.memcg = NULL; +#endif +} + +static inline void lru_gen_use_mm(struct mm_struct *mm) +{ + /* + * When the bitmap is set, page reclaim knows this mm_struct has been + * used since the last time it cleared the bitmap. So it might be worth + * walking the page tables of this mm_struct to clear the accessed bit. + */ + WRITE_ONCE(mm->lru_gen.bitmap, -1); +} + +#else /* !CONFIG_LRU_GEN */ + +static inline void lru_gen_add_mm(struct mm_struct *mm) +{ +} + +static inline void lru_gen_del_mm(struct mm_struct *mm) +{ +} + +#ifdef CONFIG_MEMCG +static inline void lru_gen_migrate_mm(struct mm_struct *mm) +{ +} +#endif + +static inline void lru_gen_init_mm(struct mm_struct *mm) +{ +} + +static inline void lru_gen_use_mm(struct mm_struct *mm) +{ +} + +#endif /* CONFIG_LRU_GEN */ + struct mmu_gather; extern void tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned long start, unsigned long end); diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index 4d6a1cff0e70..f4fb963c963e 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -402,7 +402,7 @@ enum { * min_seq behind. * * The number of pages in each generation is eventually consistent and therefore - * can be transiently negative. + * can be transiently negative when reset_batch_size() is pending. */ struct lru_gen_struct { /* the aging increments the youngest generation number */ @@ -424,6 +424,53 @@ struct lru_gen_struct { atomic_long_t refaulted[NR_HIST_GENS][ANON_AND_FILE][MAX_NR_TIERS]; }; +enum { + MM_LEAF_TOTAL, /* total leaf entries */ + MM_LEAF_OLD, /* old leaf entries */ + MM_LEAF_YOUNG, /* young leaf entries */ + MM_NONLEAF_TOTAL, /* total non-leaf entries */ + MM_NONLEAF_FOUND, /* non-leaf entries found in Bloom filters */ + MM_NONLEAF_ADDED, /* non-leaf entries added to Bloom filters */ + NR_MM_STATS +}; + +/* double-buffering Bloom filters */ +#define NR_BLOOM_FILTERS 2 + +struct lru_gen_mm_state { + /* set to max_seq after each iteration */ + unsigned long seq; + /* where the current iteration continues (inclusive) */ + struct list_head *head; + /* where the last iteration ended (exclusive) */ + struct list_head *tail; + /* to wait for the last page table walker to finish */ + struct wait_queue_head wait; + /* Bloom filters flip after each iteration */ + unsigned long *filters[NR_BLOOM_FILTERS]; + /* the mm stats for debugging */ + unsigned long stats[NR_HIST_GENS][NR_MM_STATS]; + /* the number of concurrent page table walkers */ + int nr_walkers; +}; + +struct lru_gen_mm_walk { + /* the lruvec under reclaim */ + struct lruvec *lruvec; + /* unstable max_seq from lru_gen_struct */ + unsigned long max_seq; + /* the next address within an mm to scan */ + unsigned long next_addr; + /* to batch promoted pages */ + int nr_pages[MAX_NR_GENS][ANON_AND_FILE][MAX_NR_ZONES]; + /* to batch the mm stats */ + int mm_stats[NR_MM_STATS]; + /* total batched items */ + int batched; + bool can_swap; + bool force_scan; +}; + void lru_gen_init_lruvec(struct lruvec *lruvec); void lru_gen_look_around(struct page_vma_mapped_walk *pvmw); @@ -464,6 +511,8 @@ struct lruvec { #ifdef CONFIG_LRU_GEN /* evictable pages divided into generations */ struct lru_gen_struct lrugen; + /* to concurrently iterate lru_gen_mm_list */ + struct lru_gen_mm_state mm_state; #endif #ifdef CONFIG_MEMCG struct pglist_data *pgdat; @@ -954,6 +1003,11 @@ typedef struct pglist_data { unsigned long flags; +#ifdef CONFIG_LRU_GEN + /* kswap mm walk data */ + struct lru_gen_mm_walk mm_walk; +#endif + ZONE_PADDING(_pad2_) /* Per-node vmstats */ diff --git a/include/linux/swap.h b/include/linux/swap.h index 0cc833d21ce2..df8c42d861d1 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h @@ -130,6 +130,10 @@ union swap_header { */ struct reclaim_state { unsigned long reclaimed_slab; +#ifdef CONFIG_LRU_GEN + /* per-thread mm walk data */ + struct lru_gen_mm_walk *mm_walk; +#endif }; #ifdef __KERNEL__ diff --git a/kernel/exit.c b/kernel/exit.c index f286f432869d..5cb9e73cd231 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -470,6 +470,7 @@ assign_new_owner: goto retry; } WRITE_ONCE(mm->owner, c); + lru_gen_migrate_mm(mm); task_unlock(c); put_task_struct(c); } diff --git a/kernel/fork.c b/kernel/fork.c index 74f6f5e26ee4..742672fb434d 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -1104,6 +1104,7 @@ static struct mm_struct *mm_init(struct mm_struct *mm, struct task_struct *p, goto fail_nocontext; mm->user_ns = get_user_ns(user_ns); + lru_gen_init_mm(mm); return mm; fail_nocontext: @@ -1146,6 +1147,7 @@ static inline void __mmput(struct mm_struct *mm) } if (mm->binfmt) module_put(mm->binfmt->module); + lru_gen_del_mm(mm); mmdrop(mm); } @@ -2457,6 +2459,13 @@ long _do_fork(struct kernel_clone_args *args) get_task_struct(p); } + if (IS_ENABLED(CONFIG_LRU_GEN) && !(clone_flags & CLONE_VM)) { + /* lock the task to synchronize with memcg migration */ + task_lock(p); + lru_gen_add_mm(p->mm); + task_unlock(p); + } + wake_up_new_task(p); /* forking complete and child started to run, tell ptracer */ diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 82c12f4d588d..240c885a4a63 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -3614,6 +3614,7 @@ context_switch(struct rq *rq, struct task_struct *prev, * finish_task_switch()'s mmdrop(). */ switch_mm_irqs_off(prev->active_mm, next->mm, next); + lru_gen_use_mm(next->mm); if (!prev->mm) { // from kernel /* will mmdrop() in finish_task_switch(). */ diff --git a/mm/memcontrol.c b/mm/memcontrol.c index e9caf18e133c..07550b3145e4 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -6072,6 +6072,30 @@ static void mem_cgroup_move_task(void) } #endif +#ifdef CONFIG_LRU_GEN +static void mem_cgroup_attach(struct cgroup_taskset *tset) +{ + struct task_struct *task; + struct cgroup_subsys_state *css; + + /* find the first leader if there is any */ + cgroup_taskset_for_each_leader(task, css, tset) + break; + + if (!task) + return; + + task_lock(task); + if (task->mm && READ_ONCE(task->mm->owner) == task) + lru_gen_migrate_mm(task->mm); + task_unlock(task); +} +#else +static void mem_cgroup_attach(struct cgroup_taskset *tset) +{ +} +#endif /* CONFIG_LRU_GEN */ + /* * Cgroup retains root cgroups across [un]mount cycles making it necessary * to verify whether we're attached to the default hierarchy on each mount @@ -6372,6 +6396,7 @@ struct cgroup_subsys memory_cgrp_subsys = { .css_free = mem_cgroup_css_free, .css_reset = mem_cgroup_css_reset, .can_attach = mem_cgroup_can_attach, + .attach = mem_cgroup_attach, .cancel_attach = mem_cgroup_cancel_attach, .post_attach = mem_cgroup_move_task, .bind = mem_cgroup_bind, diff --git a/mm/memory.c b/mm/memory.c index 63d684cf3f8d..95c5937f2050 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -4158,11 +4158,6 @@ static inline vm_fault_t wp_huge_pmd(struct vm_fault *vmf, pmd_t orig_pmd) return VM_FAULT_FALLBACK; } -static inline bool vma_is_accessible(struct vm_area_struct *vma) -{ - return vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE); -} - static vm_fault_t create_huge_pud(struct vm_fault *vmf) { #ifdef CONFIG_TRANSPARENT_HUGEPAGE diff --git a/mm/vmscan.c b/mm/vmscan.c index c6e98e805bf5..cdf2aded13e9 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -51,6 +51,8 @@ #include #include #include +#include +#include #include #include @@ -2658,7 +2660,7 @@ out: for ((type) = 0; (type) < ANON_AND_FILE; (type)++) \ for ((zone) = 0; (zone) < MAX_NR_ZONES; (zone)++) -static struct lruvec __maybe_unused *get_lruvec(struct mem_cgroup *memcg, int nid) +static struct lruvec *get_lruvec(struct mem_cgroup *memcg, int nid) { struct pglist_data *pgdat = NODE_DATA(nid); @@ -2701,6 +2703,371 @@ static bool __maybe_unused seq_is_valid(struct lruvec *lruvec) get_nr_gens(lruvec, LRU_GEN_ANON) <= MAX_NR_GENS; } +/****************************************************************************** + * mm_struct list + ******************************************************************************/ + +static struct lru_gen_mm_list *get_mm_list(struct mem_cgroup *memcg) +{ + static struct lru_gen_mm_list mm_list = { + .fifo = LIST_HEAD_INIT(mm_list.fifo), + .lock = __SPIN_LOCK_UNLOCKED(mm_list.lock), + }; + +#ifdef CONFIG_MEMCG + if (memcg) + return &memcg->mm_list; +#endif + VM_WARN_ON_ONCE(!mem_cgroup_disabled()); + + return &mm_list; +} + +void lru_gen_add_mm(struct mm_struct *mm) +{ + int nid; + struct mem_cgroup *memcg = get_mem_cgroup_from_mm(mm); + struct lru_gen_mm_list *mm_list = get_mm_list(memcg); + + VM_WARN_ON_ONCE(!list_empty(&mm->lru_gen.list)); +#ifdef CONFIG_MEMCG + VM_WARN_ON_ONCE(mm->lru_gen.memcg); + mm->lru_gen.memcg = memcg; +#endif + spin_lock(&mm_list->lock); + + for_each_node_state(nid, N_MEMORY) { + struct lruvec *lruvec = get_lruvec(memcg, nid); + + if (!lruvec) + continue; + + /* the first addition since the last iteration */ + if (lruvec->mm_state.tail == &mm_list->fifo) + lruvec->mm_state.tail = &mm->lru_gen.list; + } + + list_add_tail(&mm->lru_gen.list, &mm_list->fifo); + + spin_unlock(&mm_list->lock); +} + +void lru_gen_del_mm(struct mm_struct *mm) +{ + int nid; + struct lru_gen_mm_list *mm_list; + struct mem_cgroup *memcg = NULL; + + if (list_empty(&mm->lru_gen.list)) + return; + +#ifdef CONFIG_MEMCG + memcg = mm->lru_gen.memcg; +#endif + mm_list = get_mm_list(memcg); + + spin_lock(&mm_list->lock); + + for_each_node(nid) { + struct lruvec *lruvec = get_lruvec(memcg, nid); + + if (!lruvec) + continue; + + /* where the last iteration ended (exclusive) */ + if (lruvec->mm_state.tail == &mm->lru_gen.list) + lruvec->mm_state.tail = lruvec->mm_state.tail->next; + + /* where the current iteration continues (inclusive) */ + if (lruvec->mm_state.head != &mm->lru_gen.list) + continue; + + lruvec->mm_state.head = lruvec->mm_state.head->next; + /* the deletion ends the current iteration */ + if (lruvec->mm_state.head == &mm_list->fifo) + WRITE_ONCE(lruvec->mm_state.seq, lruvec->mm_state.seq + 1); + } + + list_del_init(&mm->lru_gen.list); + + spin_unlock(&mm_list->lock); + +#ifdef CONFIG_MEMCG + mem_cgroup_put(mm->lru_gen.memcg); + mm->lru_gen.memcg = NULL; +#endif +} + +#ifdef CONFIG_MEMCG +void lru_gen_migrate_mm(struct mm_struct *mm) +{ + struct mem_cgroup *memcg; + struct task_struct *task = rcu_dereference_protected(mm->owner, true); + + VM_WARN_ON_ONCE(task->mm != mm); + lockdep_assert_held(&task->alloc_lock); + + /* for mm_update_next_owner() */ + if (mem_cgroup_disabled()) + return; + + rcu_read_lock(); + memcg = mem_cgroup_from_task(task); + rcu_read_unlock(); + if (memcg == mm->lru_gen.memcg) + return; + + VM_WARN_ON_ONCE(!mm->lru_gen.memcg); + VM_WARN_ON_ONCE(list_empty(&mm->lru_gen.list)); + + lru_gen_del_mm(mm); + lru_gen_add_mm(mm); +} +#endif + +/* + * Bloom filters with m=1<<15, k=2 and the false positive rates of ~1/5 when + * n=10,000 and ~1/2 when n=20,000, where, conventionally, m is the number of + * bits in a bitmap, k is the number of hash functions and n is the number of + * inserted items. + * + * Page table walkers use one of the two filters to reduce their search space. + * To get rid of non-leaf entries that no longer have enough leaf entries, the + * aging uses the double-buffering technique to flip to the other filter each + * time it produces a new generation. For non-leaf entries that have enough + * leaf entries, the aging carries them over to the next generation in + * walk_pmd_range(); the eviction also report them when walking the rmap + * in lru_gen_look_around(). + * + * For future optimizations: + * 1. It's not necessary to keep both filters all the time. The spare one can be + * freed after the RCU grace period and reallocated if needed again. + * 2. And when reallocating, it's worth scaling its size according to the number + * of inserted entries in the other filter, to reduce the memory overhead on + * small systems and false positives on large systems. + * 3. Jenkins' hash function is an alternative to Knuth's. + */ +#define BLOOM_FILTER_SHIFT 15 + +static inline int filter_gen_from_seq(unsigned long seq) +{ + return seq % NR_BLOOM_FILTERS; +} + +static void get_item_key(void *item, int *key) +{ + u32 hash = hash_ptr(item, BLOOM_FILTER_SHIFT * 2); + + BUILD_BUG_ON(BLOOM_FILTER_SHIFT * 2 > BITS_PER_TYPE(u32)); + + key[0] = hash & (BIT(BLOOM_FILTER_SHIFT) - 1); + key[1] = hash >> BLOOM_FILTER_SHIFT; +} + +static void reset_bloom_filter(struct lruvec *lruvec, unsigned long seq) +{ + unsigned long *filter; + int gen = filter_gen_from_seq(seq); + + filter = lruvec->mm_state.filters[gen]; + if (filter) { + bitmap_clear(filter, 0, BIT(BLOOM_FILTER_SHIFT)); + return; + } + + filter = bitmap_zalloc(BIT(BLOOM_FILTER_SHIFT), + __GFP_HIGH | __GFP_NOMEMALLOC | __GFP_NOWARN); + WRITE_ONCE(lruvec->mm_state.filters[gen], filter); +} + +static void update_bloom_filter(struct lruvec *lruvec, unsigned long seq, void *item) +{ + int key[2]; + unsigned long *filter; + int gen = filter_gen_from_seq(seq); + + filter = READ_ONCE(lruvec->mm_state.filters[gen]); + if (!filter) + return; + + get_item_key(item, key); + + if (!test_bit(key[0], filter)) + set_bit(key[0], filter); + if (!test_bit(key[1], filter)) + set_bit(key[1], filter); +} + +static bool test_bloom_filter(struct lruvec *lruvec, unsigned long seq, void *item) +{ + int key[2]; + unsigned long *filter; + int gen = filter_gen_from_seq(seq); + + filter = READ_ONCE(lruvec->mm_state.filters[gen]); + if (!filter) + return true; + + get_item_key(item, key); + + return test_bit(key[0], filter) && test_bit(key[1], filter); +} + +static void reset_mm_stats(struct lruvec *lruvec, struct lru_gen_mm_walk *walk, bool last) +{ + int i; + int hist; + + lockdep_assert_held(&get_mm_list(lruvec_memcg(lruvec))->lock); + + if (walk) { + hist = lru_hist_from_seq(walk->max_seq); + + for (i = 0; i < NR_MM_STATS; i++) { + WRITE_ONCE(lruvec->mm_state.stats[hist][i], + lruvec->mm_state.stats[hist][i] + walk->mm_stats[i]); + walk->mm_stats[i] = 0; + } + } + + if (NR_HIST_GENS > 1 && last) { + hist = lru_hist_from_seq(lruvec->mm_state.seq + 1); + + for (i = 0; i < NR_MM_STATS; i++) + WRITE_ONCE(lruvec->mm_state.stats[hist][i], 0); + } +} + +static bool should_skip_mm(struct mm_struct *mm, struct lru_gen_mm_walk *walk) +{ + int type; + unsigned long size = 0; + struct pglist_data *pgdat = lruvec_pgdat(walk->lruvec); + int key = pgdat->node_id % BITS_PER_TYPE(mm->lru_gen.bitmap); + + if (!walk->force_scan && !test_bit(key, &mm->lru_gen.bitmap)) + return true; + + clear_bit(key, &mm->lru_gen.bitmap); + + for (type = !walk->can_swap; type < ANON_AND_FILE; type++) { + size += type ? get_mm_counter(mm, MM_FILEPAGES) : + get_mm_counter(mm, MM_ANONPAGES) + + get_mm_counter(mm, MM_SHMEMPAGES); + } + + if (size < MIN_LRU_BATCH) + return true; + + return !mmget_not_zero(mm); +} + +static bool iterate_mm_list(struct lruvec *lruvec, struct lru_gen_mm_walk *walk, + struct mm_struct **iter) +{ + bool first = false; + bool last = true; + struct mm_struct *mm = NULL; + struct mem_cgroup *memcg = lruvec_memcg(lruvec); + struct lru_gen_mm_list *mm_list = get_mm_list(memcg); + struct lru_gen_mm_state *mm_state = &lruvec->mm_state; + + /* + * There are four interesting cases for this page table walker: + * 1. It tries to start a new iteration of mm_list with a stale max_seq; + * there is nothing left to do. + * 2. It's the first of the current generation, and it needs to reset + * the Bloom filter for the next generation. + * 3. It reaches the end of mm_list, and it needs to increment + * mm_state->seq; the iteration is done. + * 4. It's the last of the current generation, and it needs to reset the + * mm stats counters for the next generation. + */ + spin_lock(&mm_list->lock); + + VM_WARN_ON_ONCE(mm_state->seq + 1 < walk->max_seq); + VM_WARN_ON_ONCE(*iter && mm_state->seq > walk->max_seq); + VM_WARN_ON_ONCE(*iter && !mm_state->nr_walkers); + + if (walk->max_seq <= mm_state->seq) { + if (!*iter) + last = false; + goto done; + } + + if (!mm_state->nr_walkers) { + VM_WARN_ON_ONCE(mm_state->head && mm_state->head != &mm_list->fifo); + + mm_state->head = mm_list->fifo.next; + first = true; + } + + while (!mm && mm_state->head != &mm_list->fifo) { + mm = list_entry(mm_state->head, struct mm_struct, lru_gen.list); + + mm_state->head = mm_state->head->next; + + /* force scan for those added after the last iteration */ + if (!mm_state->tail || mm_state->tail == &mm->lru_gen.list) { + mm_state->tail = mm_state->head; + walk->force_scan = true; + } + + if (should_skip_mm(mm, walk)) + mm = NULL; + } + + if (mm_state->head == &mm_list->fifo) + WRITE_ONCE(mm_state->seq, mm_state->seq + 1); +done: + if (*iter && !mm) + mm_state->nr_walkers--; + if (!*iter && mm) + mm_state->nr_walkers++; + + if (mm_state->nr_walkers) + last = false; + + if (*iter || last) + reset_mm_stats(lruvec, walk, last); + + spin_unlock(&mm_list->lock); + + if (mm && first) + reset_bloom_filter(lruvec, walk->max_seq + 1); + + if (*iter) + mmput_async(*iter); + + *iter = mm; + + return last; +} + +static bool iterate_mm_list_nowalk(struct lruvec *lruvec, unsigned long max_seq) +{ + bool success = false; + struct mem_cgroup *memcg = lruvec_memcg(lruvec); + struct lru_gen_mm_list *mm_list = get_mm_list(memcg); + struct lru_gen_mm_state *mm_state = &lruvec->mm_state; + + spin_lock(&mm_list->lock); + + VM_WARN_ON_ONCE(mm_state->seq + 1 < max_seq); + + if (max_seq > mm_state->seq && !mm_state->nr_walkers) { + VM_WARN_ON_ONCE(mm_state->head && mm_state->head != &mm_list->fifo); + + WRITE_ONCE(mm_state->seq, mm_state->seq + 1); + reset_mm_stats(lruvec, NULL, true); + success = true; + } + + spin_unlock(&mm_list->lock); + + return success; +} + /****************************************************************************** * refault feedback loop ******************************************************************************/ @@ -2855,6 +3222,118 @@ static int page_inc_gen(struct lruvec *lruvec, struct page *page, bool reclaimin return new_gen; } +static void update_batch_size(struct lru_gen_mm_walk *walk, struct page *page, + int old_gen, int new_gen) +{ + int type = page_is_file_cache(page); + int zone = page_zonenum(page); + int delta = hpage_nr_pages(page); + + VM_WARN_ON_ONCE(old_gen >= MAX_NR_GENS); + VM_WARN_ON_ONCE(new_gen >= MAX_NR_GENS); + + walk->batched++; + + walk->nr_pages[old_gen][type][zone] -= delta; + walk->nr_pages[new_gen][type][zone] += delta; +} + +static void reset_batch_size(struct lruvec *lruvec, struct lru_gen_mm_walk *walk) +{ + int gen, type, zone; + struct lru_gen_struct *lrugen = &lruvec->lrugen; + + walk->batched = 0; + + for_each_gen_type_zone(gen, type, zone) { + enum lru_list lru = type * LRU_INACTIVE_FILE; + int delta = walk->nr_pages[gen][type][zone]; + + if (!delta) + continue; + + walk->nr_pages[gen][type][zone] = 0; + WRITE_ONCE(lrugen->nr_pages[gen][type][zone], + lrugen->nr_pages[gen][type][zone] + delta); + + if (lru_gen_is_active(lruvec, gen)) + lru += LRU_ACTIVE; + __update_lru_size(lruvec, lru, zone, delta); + } +} + +static int should_skip_vma(unsigned long start, unsigned long end, struct mm_walk *args) +{ + struct address_space *mapping; + struct vm_area_struct *vma = args->vma; + struct lru_gen_mm_walk *walk = args->private; + + if (!vma_is_accessible(vma)) + return true; + + if (is_vm_hugetlb_page(vma)) + return true; + + if (vma->vm_flags & (VM_LOCKED | VM_SPECIAL | VM_SEQ_READ | VM_RAND_READ)) + return true; + + if (vma == get_gate_vma(vma->vm_mm)) + return true; + + if (vma_is_anonymous(vma)) + return !walk->can_swap; + + if (WARN_ON_ONCE(!vma->vm_file || !vma->vm_file->f_mapping)) + return true; + + mapping = vma->vm_file->f_mapping; + if (mapping_unevictable(mapping)) + return true; + + if (shmem_mapping(mapping)) + return !walk->can_swap; + + /* to exclude special mappings like dax, etc. */ + return !mapping->a_ops->readpage; +} + +/* + * Some userspace memory allocators map many single-page VMAs. Instead of + * returning back to the PGD table for each of such VMAs, finish an entire PMD + * table to reduce zigzags and improve cache performance. + */ +static bool get_next_vma(unsigned long mask, unsigned long size, struct mm_walk *args, + unsigned long *vm_start, unsigned long *vm_end) +{ + unsigned long start = round_up(*vm_end, size); + unsigned long end = (start | ~mask) + 1; + + VM_WARN_ON_ONCE(mask & size); + VM_WARN_ON_ONCE((start & mask) != (*vm_start & mask)); + + while (args->vma) { + if (start >= args->vma->vm_end) { + args->vma = args->vma->vm_next; + continue; + } + + if (end && end <= args->vma->vm_start) + return false; + + if (should_skip_vma(args->vma->vm_start, args->vma->vm_end, args)) { + args->vma = args->vma->vm_next; + continue; + } + + *vm_start = max(start, args->vma->vm_start); + *vm_end = min(end - 1, args->vma->vm_end - 1) + 1; + + return true; + } + + return false; +} + static unsigned long get_pte_pfn(pte_t pte, struct vm_area_struct *vma, unsigned long addr) { unsigned long pfn = pte_pfn(pte); @@ -2873,8 +3352,28 @@ static unsigned long get_pte_pfn(pte_t pte, struct vm_area_struct *vma, unsigned return pfn; } +#if defined(CONFIG_TRANSPARENT_HUGEPAGE) || defined(CONFIG_ARCH_HAS_NONLEAF_PMD_YOUNG) +static unsigned long get_pmd_pfn(pmd_t pmd, struct vm_area_struct *vma, unsigned long addr) +{ + unsigned long pfn = pmd_pfn(pmd); + + VM_WARN_ON_ONCE(addr < vma->vm_start || addr >= vma->vm_end); + + if (!pmd_present(pmd) || is_huge_zero_pmd(pmd)) + return -1; + + if (WARN_ON_ONCE(pmd_devmap(pmd))) + return -1; + + if (WARN_ON_ONCE(!pfn_valid(pfn))) + return -1; + + return pfn; +} +#endif + static struct page *get_pfn_page(unsigned long pfn, struct mem_cgroup *memcg, - struct pglist_data *pgdat) + struct pglist_data *pgdat, bool can_swap) { struct page *page; @@ -2889,9 +3388,378 @@ static struct page *get_pfn_page(unsigned long pfn, struct mem_cgroup *memcg, if (page_memcg_rcu(page) != memcg) return NULL; + /* file VMAs can contain anon pages from COW */ + if (!page_is_file_cache(page) && !can_swap) + return NULL; + return page; } +static bool suitable_to_scan(int total, int young) +{ + int n = clamp_t(int, cache_line_size() / sizeof(pte_t), 2, 8); + + /* suitable if the average number of young PTEs per cacheline is >=1 */ + return young * n >= total; +} + +static bool walk_pte_range(pmd_t *pmd, unsigned long start, unsigned long end, + struct mm_walk *args) +{ + int i; + pte_t *pte; + spinlock_t *ptl; + unsigned long addr; + int total = 0; + int young = 0; + struct lru_gen_mm_walk *walk = args->private; + struct mem_cgroup *memcg = lruvec_memcg(walk->lruvec); + struct pglist_data *pgdat = lruvec_pgdat(walk->lruvec); + int old_gen, new_gen = lru_gen_from_seq(walk->max_seq); + + VM_WARN_ON_ONCE(pmd_leaf(*pmd)); + + ptl = pte_lockptr(args->mm, pmd); + if (!spin_trylock(ptl)) + return false; + + arch_enter_lazy_mmu_mode(); + + pte = pte_offset_map(pmd, start & PMD_MASK); +restart: + for (i = pte_index(start), addr = start; addr != end; i++, addr += PAGE_SIZE) { + unsigned long pfn; + struct page *page; + + total++; + walk->mm_stats[MM_LEAF_TOTAL]++; + + pfn = get_pte_pfn(pte[i], args->vma, addr); + if (pfn == -1) + continue; + + if (!pte_young(pte[i])) { + walk->mm_stats[MM_LEAF_OLD]++; + continue; + } + + page = get_pfn_page(pfn, memcg, pgdat, walk->can_swap); + if (!page) + continue; + + if (!ptep_test_and_clear_young(args->vma, addr, pte + i)) + VM_WARN_ON_ONCE(true); + + young++; + walk->mm_stats[MM_LEAF_YOUNG]++; + + if (pte_dirty(pte[i]) && !PageDirty(page) && + !(PageAnon(page) && PageSwapBacked(page) && + !PageSwapCache(page))) + set_page_dirty(page); + + old_gen = page_update_gen(page, new_gen); + if (old_gen >= 0 && old_gen != new_gen) + update_batch_size(walk, page, old_gen, new_gen); + } + + if (i < PTRS_PER_PTE && get_next_vma(PMD_MASK, PAGE_SIZE, args, &start, &end)) + goto restart; + + pte_unmap(pte); + + arch_leave_lazy_mmu_mode(); + spin_unlock(ptl); + + return suitable_to_scan(total, young); +} + +#if defined(CONFIG_TRANSPARENT_HUGEPAGE) || defined(CONFIG_ARCH_HAS_NONLEAF_PMD_YOUNG) +static void walk_pmd_range_locked(pud_t *pud, unsigned long next, struct vm_area_struct *vma, + struct mm_walk *args, unsigned long *bitmap, unsigned long *start) +{ + int i; + pmd_t *pmd; + spinlock_t *ptl; + struct lru_gen_mm_walk *walk = args->private; + struct mem_cgroup *memcg = lruvec_memcg(walk->lruvec); + struct pglist_data *pgdat = lruvec_pgdat(walk->lruvec); + int old_gen, new_gen = lru_gen_from_seq(walk->max_seq); + + VM_WARN_ON_ONCE(pud_leaf(*pud)); + + /* try to batch at most 1+MIN_LRU_BATCH+1 entries */ + if (*start == -1) { + *start = next; + return; + } + + i = next == -1 ? 0 : ((next - *start) >> PMD_SHIFT) & (PTRS_PER_PMD - 1); + if (i && i <= MIN_LRU_BATCH) { + __set_bit(i - 1, bitmap); + return; + } + + pmd = pmd_offset(pud, *start); + + ptl = pmd_lockptr(args->mm, pmd); + if (!spin_trylock(ptl)) + goto done; + + arch_enter_lazy_mmu_mode(); + + do { + unsigned long pfn; + struct page *page; + unsigned long addr = i ? (*start & PMD_MASK) + i * PMD_SIZE : *start; + + pfn = get_pmd_pfn(pmd[i], vma, addr); + if (pfn == -1) + goto next; + + if (!pmd_trans_huge(pmd[i])) { + if (IS_ENABLED(CONFIG_ARCH_HAS_NONLEAF_PMD_YOUNG)) + pmdp_test_and_clear_young(vma, addr, pmd + i); + goto next; + } + + page = get_pfn_page(pfn, memcg, pgdat, walk->can_swap); + if (!page) + goto next; + + if (!pmdp_test_and_clear_young(vma, addr, pmd + i)) + goto next; + + walk->mm_stats[MM_LEAF_YOUNG]++; + + if (pmd_dirty(pmd[i]) && !PageDirty(page) && + !(PageAnon(page) && PageSwapBacked(page) && + !PageSwapCache(page))) + set_page_dirty(page); + + old_gen = page_update_gen(page, new_gen); + if (old_gen >= 0 && old_gen != new_gen) + update_batch_size(walk, page, old_gen, new_gen); +next: + i = i > MIN_LRU_BATCH ? 0 : find_next_bit(bitmap, MIN_LRU_BATCH, i) + 1; + } while (i <= MIN_LRU_BATCH); + + arch_leave_lazy_mmu_mode(); + spin_unlock(ptl); +done: + *start = -1; + bitmap_zero(bitmap, MIN_LRU_BATCH); +} +#else +static void walk_pmd_range_locked(pud_t *pud, unsigned long next, struct vm_area_struct *vma, + struct mm_walk *args, unsigned long *bitmap, unsigned long *start) +{ +} +#endif + +static void walk_pmd_range(pud_t *pud, unsigned long start, unsigned long end, + struct mm_walk *args) +{ + int i; + pmd_t *pmd; + unsigned long next; + unsigned long addr; + struct vm_area_struct *vma; + unsigned long pos = -1; + struct lru_gen_mm_walk *walk = args->private; + unsigned long bitmap[BITS_TO_LONGS(MIN_LRU_BATCH)] = {}; + + VM_WARN_ON_ONCE(pud_leaf(*pud)); + + /* + * Finish an entire PMD in two passes: the first only reaches to PTE + * tables to avoid taking the PMD lock; the second, if necessary, takes + * the PMD lock to clear the accessed bit in PMD entries. + */ + pmd = pmd_offset(pud, start & PUD_MASK); +restart: + /* walk_pte_range() may call get_next_vma() */ + vma = args->vma; + i = (start >> PMD_SHIFT) & (PTRS_PER_PMD - 1); + for (addr = start; addr != end; i++, addr = next) { + pmd_t val = pmd_read_atomic(pmd + i); + + /* for pmd_read_atomic() */ + barrier(); + + next = pmd_addr_end(addr, end); + + if (!pmd_present(val) || is_huge_zero_pmd(val)) { + walk->mm_stats[MM_LEAF_TOTAL]++; + continue; + } + +#ifdef CONFIG_TRANSPARENT_HUGEPAGE + if (pmd_trans_huge(val)) { + unsigned long pfn = pmd_pfn(val); + struct pglist_data *pgdat = lruvec_pgdat(walk->lruvec); + + walk->mm_stats[MM_LEAF_TOTAL]++; + + if (!pmd_young(val)) { + walk->mm_stats[MM_LEAF_OLD]++; + continue; + } + + /* try to avoid unnecessary memory loads */ + if (pfn < pgdat->node_start_pfn || pfn >= pgdat_end_pfn(pgdat)) + continue; + + walk_pmd_range_locked(pud, addr, vma, args, bitmap, &pos); + continue; + } +#endif + walk->mm_stats[MM_NONLEAF_TOTAL]++; + +#ifdef CONFIG_ARCH_HAS_NONLEAF_PMD_YOUNG + if (!pmd_young(val)) + continue; + + walk_pmd_range_locked(pud, addr, vma, args, bitmap, &pos); +#endif + if (!walk->force_scan && !test_bloom_filter(walk->lruvec, walk->max_seq, pmd + i)) + continue; + + walk->mm_stats[MM_NONLEAF_FOUND]++; + + if (!walk_pte_range(&val, addr, next, args)) + continue; + + walk->mm_stats[MM_NONLEAF_ADDED]++; + + /* carry over to the next generation */ + update_bloom_filter(walk->lruvec, walk->max_seq + 1, pmd + i); + } + + walk_pmd_range_locked(pud, -1, vma, args, bitmap, &pos); + + if (i < PTRS_PER_PMD && get_next_vma(PUD_MASK, PMD_SIZE, args, &start, &end)) + goto restart; +} + +static int walk_pud_range(p4d_t *p4d, unsigned long start, unsigned long end, + struct mm_walk *args) +{ + int i; + pud_t *pud; + unsigned long addr; + unsigned long next; + struct lru_gen_mm_walk *walk = args->private; + + VM_WARN_ON_ONCE(p4d_leaf(*p4d)); + + pud = pud_offset(p4d, start & P4D_MASK); +restart: + i = (start >> PUD_SHIFT) & (PTRS_PER_PUD - 1); + for (addr = start; addr != end; i++, addr = next) { + pud_t val = READ_ONCE(pud[i]); + + next = pud_addr_end(addr, end); + + if (!pud_present(val) || WARN_ON_ONCE(pud_leaf(val))) + continue; + + walk_pmd_range(&val, addr, next, args); + + /* a racy check to curtail the waiting time */ + if (wq_has_sleeper(&walk->lruvec->mm_state.wait)) + return 1; + + if (need_resched() || walk->batched >= MAX_LRU_BATCH) { + end = (addr | ~PUD_MASK) + 1; + goto done; + } + } + + if (i < PTRS_PER_PUD && get_next_vma(P4D_MASK, PUD_SIZE, args, &start, &end)) + goto restart; + + end = round_up(end, P4D_SIZE); +done: + if (!end || !args->vma) + return 1; + + walk->next_addr = max(end, args->vma->vm_start); + + return -EAGAIN; +} + +static void walk_mm(struct lruvec *lruvec, struct mm_struct *mm, struct lru_gen_mm_walk *walk) +{ + static const struct mm_walk_ops mm_walk_ops = { + .test_walk = should_skip_vma, + .p4d_entry = walk_pud_range, + }; + + int err; + struct mem_cgroup *memcg = lruvec_memcg(lruvec); + struct pglist_data *pgdat = lruvec_pgdat(lruvec); + + walk->next_addr = FIRST_USER_ADDRESS; + + do { + err = -EBUSY; + + /* page_update_gen() requires stable page_memcg() */ + if (!mem_cgroup_trylock_pages(memcg)) + break; + + /* the caller might be holding the lock for write */ + if (mmap_read_trylock(mm)) { + err = walk_page_range(mm, walk->next_addr, ULONG_MAX, &mm_walk_ops, walk); + + mmap_read_unlock(mm); + } + + mem_cgroup_unlock_pages(); + + if (walk->batched) { + spin_lock_irq(&pgdat->lru_lock); + reset_batch_size(lruvec, walk); + spin_unlock_irq(&pgdat->lru_lock); + } + + cond_resched(); + } while (err == -EAGAIN); +} + +static struct lru_gen_mm_walk *set_mm_walk(struct pglist_data *pgdat) +{ + struct lru_gen_mm_walk *walk = current->reclaim_state->mm_walk; + + if (pgdat && current_is_kswapd()) { + VM_WARN_ON_ONCE(walk); + + walk = &pgdat->mm_walk; + } else if (!pgdat && !walk) { + VM_WARN_ON_ONCE(current_is_kswapd()); + + walk = kzalloc(sizeof(*walk), __GFP_HIGH | __GFP_NOMEMALLOC | __GFP_NOWARN); + } + + current->reclaim_state->mm_walk = walk; + + return walk; +} + +static void clear_mm_walk(void) +{ + struct lru_gen_mm_walk *walk = current->reclaim_state->mm_walk; + + VM_WARN_ON_ONCE(walk && memchr_inv(walk->nr_pages, 0, sizeof(walk->nr_pages))); + VM_WARN_ON_ONCE(walk && memchr_inv(walk->mm_stats, 0, sizeof(walk->mm_stats))); + + current->reclaim_state->mm_walk = NULL; + + if (!current_is_kswapd()) + kfree(walk); +} + static void inc_min_seq(struct lruvec *lruvec, int type) { struct lru_gen_struct *lrugen = &lruvec->lrugen; @@ -2943,7 +3811,7 @@ next: return success; } -static void inc_max_seq(struct lruvec *lruvec, unsigned long max_seq, bool can_swap) +static void inc_max_seq(struct lruvec *lruvec, bool can_swap) { int prev, next; int type, zone; @@ -2954,9 +3822,6 @@ static void inc_max_seq(struct lruvec *lruvec, unsigned long max_seq, bool can_s VM_WARN_ON_ONCE(!seq_is_valid(lruvec)); - if (max_seq != lrugen->max_seq) - goto unlock; - for (type = ANON_AND_FILE - 1; type >= 0; type--) { if (get_nr_gens(lruvec, type) != MAX_NR_GENS) continue; @@ -2994,10 +3859,74 @@ static void inc_max_seq(struct lruvec *lruvec, unsigned long max_seq, bool can_s /* make sure preceding modifications appear */ smp_store_release(&lrugen->max_seq, lrugen->max_seq + 1); -unlock: + spin_unlock_irq(&pgdat->lru_lock); } +static bool try_to_inc_max_seq(struct lruvec *lruvec, unsigned long max_seq, + struct scan_control *sc, bool can_swap) +{ + bool success; + struct lru_gen_mm_walk *walk; + struct mm_struct *mm = NULL; + struct lru_gen_struct *lrugen = &lruvec->lrugen; + + VM_WARN_ON_ONCE(max_seq > READ_ONCE(lrugen->max_seq)); + + /* see the comment in iterate_mm_list() */ + if (max_seq <= READ_ONCE(lruvec->mm_state.seq)) { + success = false; + goto done; + } + + /* + * If the hardware doesn't automatically set the accessed bit, fallback + * to lru_gen_look_around(), which only clears the accessed bit in a + * handful of PTEs. Spreading the work out over a period of time usually + * is less efficient, but it avoids bursty page faults. + */ + if (!arch_has_hw_pte_young()) { + success = iterate_mm_list_nowalk(lruvec, max_seq); + goto done; + } + + walk = set_mm_walk(NULL); + if (!walk) { + success = iterate_mm_list_nowalk(lruvec, max_seq); + goto done; + } + + walk->lruvec = lruvec; + walk->max_seq = max_seq; + walk->can_swap = can_swap; + walk->force_scan = false; + + do { + success = iterate_mm_list(lruvec, walk, &mm); + if (mm) + walk_mm(lruvec, mm, walk); + + cond_resched(); + } while (mm); +done: + if (!success) { + if (sc->priority <= DEF_PRIORITY - 2) + wait_event_killable(lruvec->mm_state.wait, + max_seq < READ_ONCE(lrugen->max_seq)); + + return max_seq < READ_ONCE(lrugen->max_seq); + } + + VM_WARN_ON_ONCE(max_seq != READ_ONCE(lrugen->max_seq)); + + inc_max_seq(lruvec, can_swap); + /* either this sees any waiters or they will see updated max_seq */ + if (wq_has_sleeper(&lruvec->mm_state.wait)) + wake_up_all(&lruvec->mm_state.wait); + + return true; +} + static bool should_run_aging(struct lruvec *lruvec, unsigned long max_seq, unsigned long *min_seq, struct scan_control *sc, bool can_swap, unsigned long *nr_to_scan) { @@ -3072,7 +4001,7 @@ static void age_lruvec(struct lruvec *lruvec, struct scan_control *sc) need_aging = should_run_aging(lruvec, max_seq, min_seq, sc, swappiness, &nr_to_scan); if (need_aging) - inc_max_seq(lruvec, max_seq, swappiness); + try_to_inc_max_seq(lruvec, max_seq, sc, swappiness); } static void lru_gen_age_node(struct pglist_data *pgdat, struct scan_control *sc) @@ -3081,6 +4010,8 @@ static void lru_gen_age_node(struct pglist_data *pgdat, struct scan_control *sc) VM_WARN_ON_ONCE(!current_is_kswapd()); + set_mm_walk(pgdat); + memcg = mem_cgroup_iter(NULL, NULL, NULL); do { struct lruvec *lruvec = mem_cgroup_lruvec(pgdat, memcg); @@ -3089,11 +4020,16 @@ static void lru_gen_age_node(struct pglist_data *pgdat, struct scan_control *sc) cond_resched(); } while ((memcg = mem_cgroup_iter(NULL, memcg, NULL))); + + clear_mm_walk(); } /* * This function exploits spatial locality when shrink_page_list() walks the - * rmap. It scans the adjacent PTEs of a young PTE and promotes hot pages. + * rmap. It scans the adjacent PTEs of a young PTE and promotes hot pages. If + * the scan was done cacheline efficiently, it adds the PMD entry pointing to + * the PTE table to the Bloom filter. This forms a feedback loop between the + * eviction and the aging. */ void lru_gen_look_around(struct page_vma_mapped_walk *pvmw) { @@ -3102,6 +4038,8 @@ void lru_gen_look_around(struct page_vma_mapped_walk *pvmw) unsigned long start; unsigned long end; unsigned long addr; + struct lru_gen_mm_walk *walk; + int young = 0; unsigned long bitmap[BITS_TO_LONGS(MIN_LRU_BATCH)] = {}; struct page *page = pvmw->page; struct mem_cgroup *memcg = page_memcg(page); @@ -3116,6 +4054,9 @@ void lru_gen_look_around(struct page_vma_mapped_walk *pvmw) if (spin_is_contended(pvmw->ptl)) return; + /* avoid taking the LRU lock under the PTL when possible */ + walk = current->reclaim_state ? current->reclaim_state->mm_walk : NULL; + start = max(pvmw->address & PMD_MASK, pvmw->vma->vm_start); end = min(pvmw->address | ~PMD_MASK, pvmw->vma->vm_end - 1) + 1; @@ -3145,13 +4086,15 @@ void lru_gen_look_around(struct page_vma_mapped_walk *pvmw) if (!pte_young(pte[i])) continue; - page = get_pfn_page(pfn, memcg, pgdat); + page = get_pfn_page(pfn, memcg, pgdat, !walk || walk->can_swap); if (!page) continue; if (!ptep_test_and_clear_young(pvmw->vma, addr, pte + i)) VM_WARN_ON_ONCE(true); + young++; + if (pte_dirty(pte[i]) && !PageDirty(page) && !(PageAnon(page) && PageSwapBacked(page) && !PageSwapCache(page))) @@ -3167,7 +4110,11 @@ void lru_gen_look_around(struct page_vma_mapped_walk *pvmw) arch_leave_lazy_mmu_mode(); rcu_read_unlock(); - if (bitmap_weight(bitmap, MIN_LRU_BATCH) < PAGEVEC_SIZE) { + /* feedback from rmap walkers to page table walkers */ + if (suitable_to_scan(i, young)) + update_bloom_filter(lruvec, max_seq, pvmw->pmd); + + if (!walk && bitmap_weight(bitmap, MIN_LRU_BATCH) < PAGEVEC_SIZE) { for_each_set_bit(i, bitmap, MIN_LRU_BATCH) { page = pte_page(pte[i]); activate_page(page); @@ -3179,8 +4126,10 @@ void lru_gen_look_around(struct page_vma_mapped_walk *pvmw) if (!mem_cgroup_trylock_pages(memcg)) return; - spin_lock_irq(&pgdat->lru_lock); - new_gen = lru_gen_from_seq(lruvec->lrugen.max_seq); + if (!walk) { + spin_lock_irq(&pgdat->lru_lock); + new_gen = lru_gen_from_seq(lruvec->lrugen.max_seq); + } for_each_set_bit(i, bitmap, MIN_LRU_BATCH) { page = compound_head(pte_page(pte[i])); @@ -3191,10 +4140,14 @@ void lru_gen_look_around(struct page_vma_mapped_walk *pvmw) if (old_gen < 0 || old_gen == new_gen) continue; - lru_gen_update_size(lruvec, page, old_gen, new_gen); + if (walk) + update_batch_size(walk, page, old_gen, new_gen); + else + lru_gen_update_size(lruvec, page, old_gen, new_gen); } - spin_unlock_irq(&pgdat->lru_lock); + if (!walk) + spin_unlock_irq(&pgdat->lru_lock); mem_cgroup_unlock_pages(); } @@ -3472,6 +4425,7 @@ static int evict_pages(struct lruvec *lruvec, struct scan_control *sc, int swapp struct page *page; enum vm_event_item item; struct reclaim_stat stat; + struct lru_gen_mm_walk *walk; struct mem_cgroup *memcg = lruvec_memcg(lruvec); struct pglist_data *pgdat = lruvec_pgdat(lruvec); @@ -3508,6 +4462,10 @@ static int evict_pages(struct lruvec *lruvec, struct scan_control *sc, int swapp move_pages_to_lru(lruvec, &list); + walk = current->reclaim_state->mm_walk; + if (walk && walk->batched) + reset_batch_size(lruvec, walk); + item = current_is_kswapd() ? PGSTEAL_KSWAPD : PGSTEAL_DIRECT; if (global_reclaim(sc)) __count_vm_events(item, reclaimed); @@ -3523,6 +4481,11 @@ static int evict_pages(struct lruvec *lruvec, struct scan_control *sc, int swapp return scanned; } +/* + * For future optimizations: + * 1. Defer try_to_inc_max_seq() to workqueues to reduce latency for memcg + * reclaim. + */ static unsigned long get_nr_to_scan(struct lruvec *lruvec, struct scan_control *sc, bool can_swap) { @@ -3543,7 +4506,8 @@ static unsigned long get_nr_to_scan(struct lruvec *lruvec, struct scan_control * if (current_is_kswapd()) return 0; - inc_max_seq(lruvec, max_seq, can_swap); + if (try_to_inc_max_seq(lruvec, max_seq, sc, can_swap)) + return nr_to_scan; done: return min_seq[!can_swap] + MIN_NR_GENS <= max_seq ? nr_to_scan : 0; } @@ -3557,6 +4521,8 @@ static void lru_gen_shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc blk_start_plug(&plug); + set_mm_walk(lruvec_pgdat(lruvec)); + while (true) { int delta; int swappiness; @@ -3584,6 +4550,8 @@ static void lru_gen_shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc cond_resched(); } + clear_mm_walk(); + blk_finish_plug(&plug); } @@ -3600,15 +4568,21 @@ void lru_gen_init_lruvec(struct lruvec *lruvec) for_each_gen_type_zone(gen, type, zone) INIT_LIST_HEAD(&lrugen->lists[gen][type][zone]); + + lruvec->mm_state.seq = MIN_NR_GENS; + init_waitqueue_head(&lruvec->mm_state.wait); } #ifdef CONFIG_MEMCG void lru_gen_init_memcg(struct mem_cgroup *memcg) { + INIT_LIST_HEAD(&memcg->mm_list.fifo); + spin_lock_init(&memcg->mm_list.lock); } void lru_gen_exit_memcg(struct mem_cgroup *memcg) { + int i; int nid; for_each_node(nid) { @@ -3616,6 +4590,11 @@ void lru_gen_exit_memcg(struct mem_cgroup *memcg) VM_WARN_ON_ONCE(memchr_inv(lruvec->lrugen.nr_pages, 0, sizeof(lruvec->lrugen.nr_pages))); + + for (i = 0; i < NR_BLOOM_FILTERS; i++) { + bitmap_free(lruvec->mm_state.filters[i]); + lruvec->mm_state.filters[i] = NULL; + } } } #endif From 3dc679b544df61bc3bb86074cd654136efb5230c Mon Sep 17 00:00:00 2001 From: Yu Zhao Date: Sun, 18 Sep 2022 02:00:06 -0600 Subject: [PATCH 570/698] BACKPORT: mm: multi-gen LRU: optimize multiple memcgs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When multiple memcgs are available, it is possible to use generations as a frame of reference to make better choices and improve overall performance under global memory pressure. This patch adds a basic optimization to select memcgs that can drop single-use unmapped clean pages first. Doing so reduces the chance of going into the aging path or swapping, which can be costly. A typical example that benefits from this optimization is a server running mixed types of workloads, e.g., heavy anon workload in one memcg and heavy buffered I/O workload in the other. Though this optimization can be applied to both kswapd and direct reclaim, it is only added to kswapd to keep the patchset manageable. Later improvements may cover the direct reclaim path. While ensuring certain fairness to all eligible memcgs, proportional scans of individual memcgs also require proper backoff to avoid overshooting their aggregate reclaim target by too much. Otherwise it can cause high direct reclaim latency. The conditions for backoff are: 1. At low priorities, for direct reclaim, if aging fairness or direct reclaim latency is at risk, i.e., aging one memcg multiple times or swapping after the target is met. 2. At high priorities, for global reclaim, if per-zone free pages are above respective watermarks. Moto-CRs-Fixed:(CR) Server benchmark results: Mixed workloads: fio (buffered I/O): +[19, 21]% IOPS BW patch1-8: 1880k 7343MiB/s patch1-9: 2252k 8796MiB/s memcached (anon): +[119, 123]% Ops/sec KB/sec patch1-8: 862768.65 33514.68 patch1-9: 1911022.12 74234.54 Mixed workloads: fio (buffered I/O): +[75, 77]% IOPS BW 5.19-rc1: 1279k 4996MiB/s patch1-9: 2252k 8796MiB/s memcached (anon): +[13, 15]% Ops/sec KB/sec 5.19-rc1: 1673524.04 65008.87 patch1-9: 1911022.12 74234.54 Configurations: (changes since patch 6) cat mixed.sh modprobe brd rd_nr=2 rd_size=56623104 swapoff -a mkswap /dev/ram0 swapon /dev/ram0 mkfs.ext4 /dev/ram1 mount -t ext4 /dev/ram1 /mnt memtier_benchmark -S /var/run/memcached/memcached.sock \ -P memcache_binary -n allkeys --key-minimum=1 \ --key-maximum=50000000 --key-pattern=P:P -c 1 -t 36 \ --ratio 1:0 --pipeline 8 -d 2000 fio -name=mglru --numjobs=36 --directory=/mnt --size=1408m \ --buffered=1 --ioengine=io_uring --iodepth=128 \ --iodepth_batch_submit=32 --iodepth_batch_complete=32 \ --rw=randread --random_distribution=random --norandommap \ --time_based --ramp_time=10m --runtime=90m --group_reporting & pid=$! sleep 200 memtier_benchmark -S /var/run/memcached/memcached.sock \ -P memcache_binary -n allkeys --key-minimum=1 \ --key-maximum=50000000 --key-pattern=R:R -c 1 -t 36 \ --ratio 0:1 --pipeline 8 --randomize --distinct-client-seed kill -INT $pid wait Client benchmark results: no change (CONFIG_MEMCG=n) Link: https://lkml.kernel.org/r/20220918080010.2920238-10-yuzhao@google.com Change-Id: I590780e6381d577d800d4c4551a702047fc31cc7 Signed-off-by: Yu Zhao Acked-by: Brian Geffon Acked-by: Jan Alexander Steffens (heftig) Acked-by: Oleksandr Natalenko Acked-by: Steven Barrett Acked-by: Suleiman Souhlal Tested-by: Daniel Byrne Tested-by: Donald Carr Tested-by: Holger Hoffstätte Tested-by: Konstantin Kharlamov Tested-by: Shuang Zhai Tested-by: Sofia Trinh Tested-by: Vaibhav Jain Cc: Andi Kleen Cc: Aneesh Kumar K.V Cc: Barry Song Cc: Catalin Marinas Cc: Dave Hansen Cc: Hillf Danton Cc: Jens Axboe Cc: Johannes Weiner Cc: Jonathan Corbet Cc: Linus Torvalds Cc: Matthew Wilcox Cc: Mel Gorman Cc: Miaohe Lin Cc: Michael Larabel Cc: Michal Hocko Cc: M(CR) Rapoport Cc: M(CR) Rapoport Cc: Peter Zijlstra Cc: Qi Zheng Cc: Tejun Heo Cc: Vlastimil Babka Cc: Will Deacon Signed-off-by: Andrew Morton (cherry picked from commit f76c83378851f8e70f032848c4e61203f39480e4) Bug: 261052246 Signed-off-by: Kalesh Singh Reviewed-on: https://gerrit.mot.com/2491802 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- mm/vmscan.c | 104 +++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 95 insertions(+), 9 deletions(-) diff --git a/mm/vmscan.c b/mm/vmscan.c index cdf2aded13e9..dcdbe3eb1c87 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -106,6 +106,12 @@ struct scan_control { /* One of the zones is ready for compaction */ unsigned int compaction_ready:1; +#ifdef CONFIG_LRU_GEN + /* help kswapd make better choices among multiple memcgs */ + unsigned int memcgs_need_aging:1; + unsigned long last_reclaimed; +#endif + /* Allocation order */ s8 order; @@ -4010,6 +4016,19 @@ static void lru_gen_age_node(struct pglist_data *pgdat, struct scan_control *sc) VM_WARN_ON_ONCE(!current_is_kswapd()); + sc->last_reclaimed = sc->nr_reclaimed; + + /* + * To reduce the chance of going into the aging path, which can be + * costly, optimistically skip it if the flag below was cleared in the + * eviction path. This improves the overall performance when multiple + * memcgs are available. + */ + if (!sc->memcgs_need_aging) { + sc->memcgs_need_aging = true; + return; + } + set_mm_walk(pgdat); memcg = mem_cgroup_iter(NULL, NULL, NULL); @@ -4416,7 +4435,8 @@ static int isolate_pages(struct lruvec *lruvec, struct scan_control *sc, int swa return scanned; } -static int evict_pages(struct lruvec *lruvec, struct scan_control *sc, int swappiness) +static int evict_pages(struct lruvec *lruvec, struct scan_control *sc, int swappiness, + bool *need_swapping) { int type; int scanned; @@ -4478,6 +4498,9 @@ static int evict_pages(struct lruvec *lruvec, struct scan_control *sc, int swapp sc->nr_reclaimed += reclaimed; + if (need_swapping && type == LRU_GEN_ANON) + *need_swapping = true; + return scanned; } @@ -4487,15 +4510,14 @@ static int evict_pages(struct lruvec *lruvec, struct scan_control *sc, int swapp * reclaim. */ static unsigned long get_nr_to_scan(struct lruvec *lruvec, struct scan_control *sc, - bool can_swap) + bool can_swap, bool *need_aging) { - bool need_aging; unsigned long nr_to_scan; DEFINE_MAX_SEQ(lruvec); DEFINE_MIN_SEQ(lruvec); - need_aging = should_run_aging(lruvec, max_seq, min_seq, sc, can_swap, &nr_to_scan); - if (!need_aging) + *need_aging = should_run_aging(lruvec, max_seq, min_seq, sc, can_swap, &nr_to_scan); + if (!*need_aging) return nr_to_scan; /* skip the aging path at the default priority */ @@ -4512,10 +4534,67 @@ done: return min_seq[!can_swap] + MIN_NR_GENS <= max_seq ? nr_to_scan : 0; } +static bool should_abort_scan(struct lruvec *lruvec, unsigned long seq, + struct scan_control *sc, bool need_swapping) +{ + int i; + DEFINE_MAX_SEQ(lruvec); + + if (!current_is_kswapd()) { + /* age each memcg at most once to ensure fairness */ + if (max_seq - seq > 1) + return true; + + /* over-swapping can increase allocation latency */ + if (sc->nr_reclaimed >= sc->nr_to_reclaim && need_swapping) + return true; + + /* give this thread a chance to exit and free its memory */ + if (fatal_signal_pending(current)) { + sc->nr_reclaimed += MIN_LRU_BATCH; + return true; + } + + if (!global_reclaim(sc)) + return false; + } else if (sc->nr_reclaimed - sc->last_reclaimed < sc->nr_to_reclaim) + return false; + + /* keep scanning at low priorities to ensure fairness */ + if (sc->priority > DEF_PRIORITY - 2) + return false; + + /* + * A minimum amount of work was done under global memory pressure. For + * kswapd, it may be overshooting. For direct reclaim, the allocation + * may succeed if all suitable zones are somewhat safe. In either case, + * it's better to stop now, and restart later if necessary. + */ + for (i = 0; i <= sc->reclaim_idx; i++) { + unsigned long wmark; + struct zone *zone = lruvec_pgdat(lruvec)->node_zones + i; + + if (!managed_zone(zone)) + continue; + + wmark = current_is_kswapd() ? high_wmark_pages(zone) : low_wmark_pages(zone); + if (wmark > zone_page_state(zone, NR_FREE_PAGES)) + return false; + } + + sc->nr_reclaimed += MIN_LRU_BATCH; + + return true; +} + static void lru_gen_shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc) { struct blk_plug plug; + bool need_aging = false; + bool need_swapping = false; unsigned long scanned = 0; + unsigned long reclaimed = sc->nr_reclaimed; + DEFINE_MAX_SEQ(lruvec); lru_add_drain(); @@ -4535,21 +4614,28 @@ static void lru_gen_shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc else swappiness = 0; - nr_to_scan = get_nr_to_scan(lruvec, sc, swappiness); + nr_to_scan = get_nr_to_scan(lruvec, sc, swappiness, &need_aging); if (!nr_to_scan) - break; + goto done; - delta = evict_pages(lruvec, sc, swappiness); + delta = evict_pages(lruvec, sc, swappiness, &need_swapping); if (!delta) - break; + goto done; scanned += delta; if (scanned >= nr_to_scan) break; + if (should_abort_scan(lruvec, max_seq, sc, need_swapping)) + break; + cond_resched(); } + /* see the comment in lru_gen_age_node() */ + if (sc->nr_reclaimed - reclaimed >= MIN_LRU_BATCH && !need_aging) + sc->memcgs_need_aging = false; +done: clear_mm_walk(); blk_finish_plug(&plug); From 6ec277958fd14670531f844beab7720774b46516 Mon Sep 17 00:00:00 2001 From: Yu Zhao Date: Sun, 18 Sep 2022 02:00:07 -0600 Subject: [PATCH 571/698] BACKPORT: mm: multi-gen LRU: kill switch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add /sys/kernel/mm/lru_gen/enabled as a kill switch. Components that can be disabled include: 0x0001: the multi-gen LRU core 0x0002: walking page table, when arch_has_hw_pte_young() returns true 0x0004: clearing the accessed bit in non-leaf PMD entries, when CONFIG_ARCH_HAS_NONLEAF_PMD_YOUNG=y [yYnN]: apply to all the components above E.g., echo y >/sys/kernel/mm/lru_gen/enabled cat /sys/kernel/mm/lru_gen/enabled 0x0007 echo 5 >/sys/kernel/mm/lru_gen/enabled cat /sys/kernel/mm/lru_gen/enabled 0x0005 NB: the page table walks happen on the scale of seconds under heavy memory pressure, in which case the mmap_lock contention is a lesser concern, compared with the LRU lock contention and the I/O congestion. So far the only well-known case of the mmap_lock contention happens on Android, due to Scudo [1] which allocates several thousand VMAs for merely a few hundred MBs. The SPF and the Maple Tree also have provided their own assessments [2][3]. However, if walking page tables does worsen the mmap_lock contention, the kill switch can be used to disable it. In this case the multi-gen LRU will suffer a minor performance degradation, as shown previously. Clearing the accessed bit in non-leaf PMD entries can also be disabled, since this behavior was not tested on x86 varieties other than Intel and AMD. Moto-CRs-Fixed:(CR) [1] https://source.android.com/devices/tech/debug/scudo [2] https://lore.kernel.org/r/20220128131006.67712-1-michel@lespinasse.org/ [3] https://lore.kernel.org/r/20220426150616.3937571-1-Liam.Howlett@oracle.com/ Link: https://lkml.kernel.org/r/20220918080010.2920238-11-yuzhao@google.com Change-Id: If3116e6698cc6967b6992c2017962fac6c2d3a11 Signed-off-by: Yu Zhao Acked-by: Brian Geffon Acked-by: Jan Alexander Steffens (heftig) Acked-by: Oleksandr Natalenko Acked-by: Steven Barrett Acked-by: Suleiman Souhlal Tested-by: Daniel Byrne Tested-by: Donald Carr Tested-by: Holger Hoffstätte Tested-by: Konstantin Kharlamov Tested-by: Shuang Zhai Tested-by: Sofia Trinh Tested-by: Vaibhav Jain Cc: Andi Kleen Cc: Aneesh Kumar K.V Cc: Barry Song Cc: Catalin Marinas Cc: Dave Hansen Cc: Hillf Danton Cc: Jens Axboe Cc: Johannes Weiner Cc: Jonathan Corbet Cc: Linus Torvalds Cc: Matthew Wilcox Cc: Mel Gorman Cc: Miaohe Lin Cc: Michael Larabel Cc: Michal Hocko Cc: M(CR) Rapoport Cc: M(CR) Rapoport Cc: Peter Zijlstra Cc: Qi Zheng Cc: Tejun Heo Cc: Vlastimil Babka Cc: Will Deacon Signed-off-by: Andrew Morton (cherry picked from commit 354ed597442952fb680c9cafc7e4eb8a76f9514c) Bug: 261052246 Signed-off-by: Kalesh Singh Reviewed-on: https://gerrit.mot.com/2491803 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- include/linux/cgroup.h | 15 ++- include/linux/mm_inline.h | 15 ++- include/linux/mmzone.h | 9 ++ kernel/cgroup/cgroup-internal.h | 1 - mm/Kconfig | 6 + mm/vmscan.c | 229 +++++++++++++++++++++++++++++++- 6 files changed, 266 insertions(+), 9 deletions(-) diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h index bf290358507c..3933ddd082e9 100644 --- a/include/linux/cgroup.h +++ b/include/linux/cgroup.h @@ -428,6 +428,18 @@ static inline void cgroup_put(struct cgroup *cgrp) css_put(&cgrp->self); } +extern struct mutex cgroup_mutex; + +static inline void cgroup_lock(void) +{ + mutex_lock(&cgroup_mutex); +} + +static inline void cgroup_unlock(void) +{ + mutex_unlock(&cgroup_mutex); +} + /** * task_css_set_check - obtain a task's css_set with extra access conditions * @task: the task to obtain css_set for @@ -442,7 +454,6 @@ static inline void cgroup_put(struct cgroup *cgrp) * as locks used during the cgroup_subsys::attach() methods. */ #ifdef CONFIG_PROVE_RCU -extern struct mutex cgroup_mutex; extern spinlock_t css_set_lock; #define task_css_set_check(task, __c) \ rcu_dereference_check((task)->cgroups, \ @@ -707,6 +718,8 @@ struct cgroup; static inline void css_get(struct cgroup_subsys_state *css) {} static inline void css_put(struct cgroup_subsys_state *css) {} +static inline void cgroup_lock(void) {} +static inline void cgroup_unlock(void) {} static inline int cgroup_attach_task_all(struct task_struct *from, struct task_struct *t) { return 0; } static inline int cgroupstats_build(struct cgroupstats *stats, diff --git a/include/linux/mm_inline.h b/include/linux/mm_inline.h index 64b33e79165b..663dc926dbac 100644 --- a/include/linux/mm_inline.h +++ b/include/linux/mm_inline.h @@ -105,10 +105,21 @@ static __always_inline enum lru_list page_lru(struct page *page) #ifdef CONFIG_LRU_GEN +#ifdef CONFIG_LRU_GEN_ENABLED static inline bool lru_gen_enabled(void) { - return true; + DECLARE_STATIC_KEY_TRUE(lru_gen_caps[NR_LRU_GEN_CAPS]); + + return static_branch_likely(&lru_gen_caps[LRU_GEN_CORE]); } +#else +static inline bool lru_gen_enabled(void) +{ + DECLARE_STATIC_KEY_FALSE(lru_gen_caps[NR_LRU_GEN_CAPS]); + + return static_branch_unlikely(&lru_gen_caps[LRU_GEN_CORE]); +} +#endif static inline bool lru_gen_in_fault(void) { @@ -221,7 +232,7 @@ static inline bool lru_gen_add_page(struct lruvec *lruvec, struct page *page, bo VM_WARN_ON_ONCE_PAGE(gen != -1, page); - if (PageUnevictable(page)) + if (PageUnevictable(page) || !lrugen->enabled) return false; /* * There are three common cases for this page: diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index f4fb963c963e..5a9c5192155b 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -381,6 +381,13 @@ enum { LRU_GEN_FILE, }; +enum { + LRU_GEN_CORE, + LRU_GEN_MM_WALK, + LRU_GEN_NONLEAF_YOUNG, + NR_LRU_GEN_CAPS +}; + #define MIN_LRU_BATCH BITS_PER_LONG #define MAX_LRU_BATCH (MIN_LRU_BATCH * 64) @@ -422,6 +429,8 @@ struct lru_gen_struct { /* can be modified without holding the LRU lock */ atomic_long_t evicted[NR_HIST_GENS][ANON_AND_FILE][MAX_NR_TIERS]; atomic_long_t refaulted[NR_HIST_GENS][ANON_AND_FILE][MAX_NR_TIERS]; + /* whether the multi-gen LRU is enabled */ + bool enabled; }; enum { diff --git a/kernel/cgroup/cgroup-internal.h b/kernel/cgroup/cgroup-internal.h index 803989eae99e..ec985923f7c8 100644 --- a/kernel/cgroup/cgroup-internal.h +++ b/kernel/cgroup/cgroup-internal.h @@ -165,7 +165,6 @@ struct cgroup_mgctx { #define DEFINE_CGROUP_MGCTX(name) \ struct cgroup_mgctx name = CGROUP_MGCTX_INIT(name) -extern struct mutex cgroup_mutex; extern spinlock_t css_set_lock; extern struct cgroup_subsys *cgroup_subsys[]; extern struct list_head cgroup_roots; diff --git a/mm/Kconfig b/mm/Kconfig index 5f7638bc90e4..b96975666710 100644 --- a/mm/Kconfig +++ b/mm/Kconfig @@ -865,6 +865,12 @@ config LRU_GEN help A high performance LRU implementation to overcommit memory. +config LRU_GEN_ENABLED + bool "Enable by default" + depends on LRU_GEN + help + This option enables the multi-gen LRU by default. + config LRU_GEN_STATS bool "Full stats for debugging" depends on LRU_GEN diff --git a/mm/vmscan.c b/mm/vmscan.c index dcdbe3eb1c87..8304d81ab3ac 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -53,6 +53,7 @@ #include #include #include +#include #include #include @@ -2646,6 +2647,14 @@ out: #ifdef CONFIG_LRU_GEN +#ifdef CONFIG_LRU_GEN_ENABLED +DEFINE_STATIC_KEY_ARRAY_TRUE(lru_gen_caps, NR_LRU_GEN_CAPS); +#define get_cap(cap) static_branch_likely(&lru_gen_caps[cap]) +#else +DEFINE_STATIC_KEY_ARRAY_FALSE(lru_gen_caps, NR_LRU_GEN_CAPS); +#define get_cap(cap) static_branch_unlikely(&lru_gen_caps[cap]) +#endif + /****************************************************************************** * shorthand helpers ******************************************************************************/ @@ -3524,7 +3533,8 @@ static void walk_pmd_range_locked(pud_t *pud, unsigned long next, struct vm_area goto next; if (!pmd_trans_huge(pmd[i])) { - if (IS_ENABLED(CONFIG_ARCH_HAS_NONLEAF_PMD_YOUNG)) + if (IS_ENABLED(CONFIG_ARCH_HAS_NONLEAF_PMD_YOUNG) && + get_cap(LRU_GEN_NONLEAF_YOUNG)) pmdp_test_and_clear_young(vma, addr, pmd + i); goto next; } @@ -3623,10 +3633,12 @@ restart: walk->mm_stats[MM_NONLEAF_TOTAL]++; #ifdef CONFIG_ARCH_HAS_NONLEAF_PMD_YOUNG - if (!pmd_young(val)) - continue; + if (get_cap(LRU_GEN_NONLEAF_YOUNG)) { + if (!pmd_young(val)) + continue; - walk_pmd_range_locked(pud, addr, vma, args, bitmap, &pos); + walk_pmd_range_locked(pud, addr, vma, args, bitmap, &pos); + } #endif if (!walk->force_scan && !test_bloom_filter(walk->lruvec, walk->max_seq, pmd + i)) continue; @@ -3891,7 +3903,7 @@ static bool try_to_inc_max_seq(struct lruvec *lruvec, unsigned long max_seq, * handful of PTEs. Spreading the work out over a period of time usually * is less efficient, but it avoids bursty page faults. */ - if (!arch_has_hw_pte_young()) { + if (!(arch_has_hw_pte_young() && get_cap(LRU_GEN_MM_WALK))) { success = iterate_mm_list_nowalk(lruvec, max_seq); goto done; } @@ -4641,6 +4653,209 @@ done: blk_finish_plug(&plug); } +/****************************************************************************** + * state change + ******************************************************************************/ + +static bool __maybe_unused state_is_valid(struct lruvec *lruvec) +{ + struct lru_gen_struct *lrugen = &lruvec->lrugen; + + if (lrugen->enabled) { + enum lru_list lru; + + for_each_evictable_lru(lru) { + if (!list_empty(&lruvec->lists[lru])) + return false; + } + } else { + int gen, type, zone; + + for_each_gen_type_zone(gen, type, zone) { + if (!list_empty(&lrugen->lists[gen][type][zone])) + return false; + } + } + + return true; +} + +static bool fill_evictable(struct lruvec *lruvec) +{ + enum lru_list lru; + int remaining = MAX_LRU_BATCH; + + for_each_evictable_lru(lru) { + int type = is_file_lru(lru); + bool active = is_active_lru(lru); + struct list_head *head = &lruvec->lists[lru]; + + while (!list_empty(head)) { + bool success; + struct page *page = lru_to_page(head); + + VM_WARN_ON_ONCE_PAGE(PageUnevictable(page), page); + VM_WARN_ON_ONCE_PAGE(PageActive(page) != active, page); + VM_WARN_ON_ONCE_PAGE(page_is_file_cache(page) != type, page); + VM_WARN_ON_ONCE_PAGE(page_lru_gen(page) != -1, page); + + del_page_from_lru_list(page, lruvec); + success = lru_gen_add_page(lruvec, page, false); + VM_WARN_ON_ONCE(!success); + + if (!--remaining) + return false; + } + } + + return true; +} + +static bool drain_evictable(struct lruvec *lruvec) +{ + int gen, type, zone; + int remaining = MAX_LRU_BATCH; + + for_each_gen_type_zone(gen, type, zone) { + struct list_head *head = &lruvec->lrugen.lists[gen][type][zone]; + + while (!list_empty(head)) { + bool success; + struct page *page = lru_to_page(head); + + VM_WARN_ON_ONCE_PAGE(PageUnevictable(page), page); + VM_WARN_ON_ONCE_PAGE(PageActive(page), page); + VM_WARN_ON_ONCE_PAGE(page_is_file_cache(page) != type, page); + VM_WARN_ON_ONCE_PAGE(page_zonenum(page) != zone, page); + + success = lru_gen_del_page(lruvec, page, false); + VM_WARN_ON_ONCE(!success); + add_page_to_lru_list(page, lruvec); + + if (!--remaining) + return false; + } + } + + return true; +} + +static void lru_gen_change_state(bool enabled) +{ + static DEFINE_MUTEX(state_mutex); + + struct mem_cgroup *memcg; + + cgroup_lock(); + cpus_read_lock(); + get_online_mems(); + mutex_lock(&state_mutex); + + if (enabled == lru_gen_enabled()) + goto unlock; + + if (enabled) + static_branch_enable_cpuslocked(&lru_gen_caps[LRU_GEN_CORE]); + else + static_branch_disable_cpuslocked(&lru_gen_caps[LRU_GEN_CORE]); + + memcg = mem_cgroup_iter(NULL, NULL, NULL); + do { + int nid; + + for_each_node(nid) { + struct pglist_data *pgdat = NODE_DATA(nid); + struct lruvec *lruvec = get_lruvec(memcg, nid); + + if (!lruvec) + continue; + + spin_lock_irq(&pgdat->lru_lock); + + VM_WARN_ON_ONCE(!seq_is_valid(lruvec)); + VM_WARN_ON_ONCE(!state_is_valid(lruvec)); + + lruvec->lrugen.enabled = enabled; + + while (!(enabled ? fill_evictable(lruvec) : drain_evictable(lruvec))) { + spin_unlock_irq(&pgdat->lru_lock); + cond_resched(); + spin_lock_irq(&pgdat->lru_lock); + } + + spin_unlock_irq(&pgdat->lru_lock); + } + + cond_resched(); + } while ((memcg = mem_cgroup_iter(NULL, memcg, NULL))); +unlock: + mutex_unlock(&state_mutex); + put_online_mems(); + cpus_read_unlock(); + cgroup_unlock(); +} + +/****************************************************************************** + * sysfs interface + ******************************************************************************/ + +static ssize_t show_enabled(struct kobject *kobj, struct kobj_attribute *attr, char *buf) +{ + unsigned int caps = 0; + + if (get_cap(LRU_GEN_CORE)) + caps |= BIT(LRU_GEN_CORE); + + if (arch_has_hw_pte_young() && get_cap(LRU_GEN_MM_WALK)) + caps |= BIT(LRU_GEN_MM_WALK); + + if (IS_ENABLED(CONFIG_ARCH_HAS_NONLEAF_PMD_YOUNG) && get_cap(LRU_GEN_NONLEAF_YOUNG)) + caps |= BIT(LRU_GEN_NONLEAF_YOUNG); + + return snprintf(buf, PAGE_SIZE, "0x%04x\n", caps); +} + +static ssize_t store_enabled(struct kobject *kobj, struct kobj_attribute *attr, + const char *buf, size_t len) +{ + int i; + unsigned int caps; + + if (tolower(*buf) == 'n') + caps = 0; + else if (tolower(*buf) == 'y') + caps = -1; + else if (kstrtouint(buf, 0, &caps)) + return -EINVAL; + + for (i = 0; i < NR_LRU_GEN_CAPS; i++) { + bool enabled = caps & BIT(i); + + if (i == LRU_GEN_CORE) + lru_gen_change_state(enabled); + else if (enabled) + static_branch_enable(&lru_gen_caps[i]); + else + static_branch_disable(&lru_gen_caps[i]); + } + + return len; +} + +static struct kobj_attribute lru_gen_enabled_attr = __ATTR( + enabled, 0644, show_enabled, store_enabled +); + +static struct attribute *lru_gen_attrs[] = { + &lru_gen_enabled_attr.attr, + NULL +}; + +static struct attribute_group lru_gen_attr_group = { + .name = "lru_gen", + .attrs = lru_gen_attrs, +}; + /****************************************************************************** * initialization ******************************************************************************/ @@ -4651,6 +4866,7 @@ void lru_gen_init_lruvec(struct lruvec *lruvec) struct lru_gen_struct *lrugen = &lruvec->lrugen; lrugen->max_seq = MIN_NR_GENS + 1; + lrugen->enabled = lru_gen_enabled(); for_each_gen_type_zone(gen, type, zone) INIT_LIST_HEAD(&lrugen->lists[gen][type][zone]); @@ -4690,6 +4906,9 @@ static int __init init_lru_gen(void) BUILD_BUG_ON(MIN_NR_GENS + 1 >= MAX_NR_GENS); BUILD_BUG_ON(BIT(LRU_GEN_WIDTH) <= MAX_NR_GENS); + if (sysfs_create_group(mm_kobj, &lru_gen_attr_group)) + pr_err("lru_gen: failed to create sysfs group\n"); + return 0; }; late_initcall(init_lru_gen); From e25fab9eea63dbb2a89ddfb5749c431d2f98694f Mon Sep 17 00:00:00 2001 From: Yu Zhao Date: Sun, 18 Sep 2022 02:00:08 -0600 Subject: [PATCH 572/698] UPSTREAM: mm: multi-gen LRU: thrashing prevention MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add /sys/kernel/mm/lru_gen/min_ttl_ms for thrashing prevention, as requested by many desktop users [1]. When set to value N, it prevents the working set of N milliseconds from getting evicted. The OOM killer is triggered if this working set cannot be kept in memory. Based on the average human detectable lag (~100ms), N=1000 usually eliminates intolerable lags due to thrashing. Larger values l(CR) N=3000 make lags less noticeable at the risk of premature OOM kills. Compared with the size-based approach [2], this time-based approach has the following advantages: 1. It is easier to configure because it is agnostic to applications and memory sizes. 2. It is more reliable because it is directly wired to the OOM killer. Moto-CRs-Fixed:(CR) [1] https://lore.kernel.org/r/Ydza%2FzXKY9ATRoh6@google.com/ [2] https://lore.kernel.org/r/20101028191523.GA14972@google.com/ Link: https://lkml.kernel.org/r/20220918080010.2920238-12-yuzhao@google.com Change-Id: I52c14154a55c3e131d6e43fc623b3030cfa435ec Signed-off-by: Yu Zhao Acked-by: Brian Geffon Acked-by: Jan Alexander Steffens (heftig) Acked-by: Oleksandr Natalenko Acked-by: Steven Barrett Acked-by: Suleiman Souhlal Tested-by: Daniel Byrne Tested-by: Donald Carr Tested-by: Holger Hoffstätte Tested-by: Konstantin Kharlamov Tested-by: Shuang Zhai Tested-by: Sofia Trinh Tested-by: Vaibhav Jain Cc: Andi Kleen Cc: Aneesh Kumar K.V Cc: Barry Song Cc: Catalin Marinas Cc: Dave Hansen Cc: Hillf Danton Cc: Jens Axboe Cc: Johannes Weiner Cc: Jonathan Corbet Cc: Linus Torvalds Cc: Matthew Wilcox Cc: Mel Gorman Cc: Miaohe Lin Cc: Michael Larabel Cc: Michal Hocko Cc: M(CR) Rapoport Cc: M(CR) Rapoport Cc: Peter Zijlstra Cc: Qi Zheng Cc: Tejun Heo Cc: Vlastimil Babka Cc: Will Deacon Signed-off-by: Andrew Morton (cherry picked from commit 1332a809d95a4fc763cabe5ecb6d4fb6a6d941b2) Bug: 261052246 Signed-off-by: Kalesh Singh Reviewed-on: https://gerrit.mot.com/2491804 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- include/linux/mmzone.h | 2 ++ mm/vmscan.c | 74 ++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 73 insertions(+), 3 deletions(-) diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index 5a9c5192155b..4529fa06dad7 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -416,6 +416,8 @@ struct lru_gen_struct { unsigned long max_seq; /* the eviction increments the oldest generation numbers */ unsigned long min_seq[ANON_AND_FILE]; + /* the birth time of each generation in jiffies */ + unsigned long timestamps[MAX_NR_GENS]; /* the multi-gen LRU lists, lazily sorted on eviction */ struct list_head lists[MAX_NR_GENS][ANON_AND_FILE][MAX_NR_ZONES]; /* the multi-gen LRU sizes, eventually consistent */ diff --git a/mm/vmscan.c b/mm/vmscan.c index 8304d81ab3ac..69c516cfd2c4 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -3875,6 +3875,7 @@ static void inc_max_seq(struct lruvec *lruvec, bool can_swap) for (type = 0; type < ANON_AND_FILE; type++) reset_ctrl_pos(lruvec, type, false); + WRITE_ONCE(lrugen->timestamps[next], jiffies); /* make sure preceding modifications appear */ smp_store_release(&lrugen->max_seq, lrugen->max_seq + 1); @@ -4002,7 +4003,7 @@ static bool should_run_aging(struct lruvec *lruvec, unsigned long max_seq, unsig return false; } -static void age_lruvec(struct lruvec *lruvec, struct scan_control *sc) +static bool age_lruvec(struct lruvec *lruvec, struct scan_control *sc, unsigned long min_ttl) { bool need_aging; unsigned long nr_to_scan; @@ -4015,16 +4016,36 @@ static void age_lruvec(struct lruvec *lruvec, struct scan_control *sc) VM_WARN_ON_ONCE(sc->memcg_low_reclaim); if (prot == MEMCG_PROT_MIN) - return; + return false; need_aging = should_run_aging(lruvec, max_seq, min_seq, sc, swappiness, &nr_to_scan); + + if (min_ttl) { + int gen = lru_gen_from_seq(min_seq[LRU_GEN_FILE]); + unsigned long birth = READ_ONCE(lruvec->lrugen.timestamps[gen]); + + if (time_is_after_jiffies(birth + min_ttl)) + return false; + + /* the size is likely too small to be helpful */ + if (!nr_to_scan && sc->priority != DEF_PRIORITY) + return false; + } + if (need_aging) try_to_inc_max_seq(lruvec, max_seq, sc, swappiness); + + return true; } +/* to protect the working set of the last N jiffies */ +static unsigned long lru_gen_min_ttl __read_mostly; + static void lru_gen_age_node(struct pglist_data *pgdat, struct scan_control *sc) { struct mem_cgroup *memcg; + bool success = false; + unsigned long min_ttl = READ_ONCE(lru_gen_min_ttl); VM_WARN_ON_ONCE(!current_is_kswapd()); @@ -4047,12 +4068,32 @@ static void lru_gen_age_node(struct pglist_data *pgdat, struct scan_control *sc) do { struct lruvec *lruvec = mem_cgroup_lruvec(pgdat, memcg); - age_lruvec(lruvec, sc); + if (age_lruvec(lruvec, sc, min_ttl)) + success = true; cond_resched(); } while ((memcg = mem_cgroup_iter(NULL, memcg, NULL))); clear_mm_walk(); + + /* check the order to exclude compaction-induced reclaim */ + if (success || !min_ttl || sc->order) + return; + + /* + * The main goal is to OOM kill if every generation from all memcgs is + * younger than min_ttl. However, another possibility is all memcgs are + * either below min or empty. + */ + if (mutex_trylock(&oom_lock)) { + struct oom_control oc = { + .gfp_mask = sc->gfp_mask, + }; + + out_of_memory(&oc); + + mutex_unlock(&oom_lock); + } } /* @@ -4799,6 +4840,28 @@ unlock: * sysfs interface ******************************************************************************/ +static ssize_t show_min_ttl(struct kobject *kobj, struct kobj_attribute *attr, char *buf) +{ + return sprintf(buf, "%u\n", jiffies_to_msecs(READ_ONCE(lru_gen_min_ttl))); +} + +static ssize_t store_min_ttl(struct kobject *kobj, struct kobj_attribute *attr, + const char *buf, size_t len) +{ + unsigned int msecs; + + if (kstrtouint(buf, 0, &msecs)) + return -EINVAL; + + WRITE_ONCE(lru_gen_min_ttl, msecs_to_jiffies(msecs)); + + return len; +} + +static struct kobj_attribute lru_gen_min_ttl_attr = __ATTR( + min_ttl_ms, 0644, show_min_ttl, store_min_ttl +); + static ssize_t show_enabled(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { unsigned int caps = 0; @@ -4847,6 +4910,7 @@ static struct kobj_attribute lru_gen_enabled_attr = __ATTR( ); static struct attribute *lru_gen_attrs[] = { + &lru_gen_min_ttl_attr.attr, &lru_gen_enabled_attr.attr, NULL }; @@ -4862,12 +4926,16 @@ static struct attribute_group lru_gen_attr_group = { void lru_gen_init_lruvec(struct lruvec *lruvec) { + int i; int gen, type, zone; struct lru_gen_struct *lrugen = &lruvec->lrugen; lrugen->max_seq = MIN_NR_GENS + 1; lrugen->enabled = lru_gen_enabled(); + for (i = 0; i <= MIN_NR_GENS + 1; i++) + lrugen->timestamps[i] = jiffies; + for_each_gen_type_zone(gen, type, zone) INIT_LIST_HEAD(&lrugen->lists[gen][type][zone]); From 682c2dab8624aec7e7aa7b789b43fe6e445d7b68 Mon Sep 17 00:00:00 2001 From: Yu Zhao Date: Sun, 18 Sep 2022 02:00:09 -0600 Subject: [PATCH 573/698] BACKPORT: mm: multi-gen LRU: debugfs interface MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add /sys/kernel/debug/lru_gen for working set estimation and proactive reclaim. These techniques are commonly used to optimize job scheduling (bin packing) in data centers [1][2]. Compared with the page table-based approach and the PFN-based approach, this lruvec-based approach has the following advantages: 1. It offers better choices because it is aware of memcgs, NUMA nodes, shared mappings and unmapped page cache. 2. It is more scalable because it is O(nr_hot_pages), whereas the PFN-based approach is O(nr_total_pages). Add /sys/kernel/debug/lru_gen_full for debugging. Moto-CRs-Fixed:(CR) [1] https://dl.acm.org/doi/10.1145/3297858.3304053 [2] https://dl.acm.org/doi/10.1145/3503222.3507731 Link: https://lkml.kernel.org/r/20220918080010.2920238-13-yuzhao@google.com Change-Id: I2d07e743e7ed139fb2ba16d5f2c1a5f32f238ccc Signed-off-by: Yu Zhao Reviewed-by: Qi Zheng Acked-by: Brian Geffon Acked-by: Jan Alexander Steffens (heftig) Acked-by: Oleksandr Natalenko Acked-by: Steven Barrett Acked-by: Suleiman Souhlal Tested-by: Daniel Byrne Tested-by: Donald Carr Tested-by: Holger Hoffstätte Tested-by: Konstantin Kharlamov Tested-by: Shuang Zhai Tested-by: Sofia Trinh Tested-by: Vaibhav Jain Cc: Andi Kleen Cc: Aneesh Kumar K.V Cc: Barry Song Cc: Catalin Marinas Cc: Dave Hansen Cc: Hillf Danton Cc: Jens Axboe Cc: Johannes Weiner Cc: Jonathan Corbet Cc: Linus Torvalds Cc: Matthew Wilcox Cc: Mel Gorman Cc: Miaohe Lin Cc: Michael Larabel Cc: Michal Hocko Cc: M(CR) Rapoport Cc: M(CR) Rapoport Cc: Peter Zijlstra Cc: Tejun Heo Cc: Vlastimil Babka Cc: Will Deacon Signed-off-by: Andrew Morton (cherry picked from commit d6c3af7d8a2ba5602c28841248c551a712ac50f5) Bug: 261052246 Signed-off-by: Kalesh Singh Reviewed-on: https://gerrit.mot.com/2491805 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- include/linux/nodemask.h | 1 + mm/vmscan.c | 411 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 402 insertions(+), 10 deletions(-) diff --git a/include/linux/nodemask.h b/include/linux/nodemask.h index a8d79f5b9a52..8df4329c6480 100644 --- a/include/linux/nodemask.h +++ b/include/linux/nodemask.h @@ -484,6 +484,7 @@ static inline int num_node_state(enum node_states state) #define first_online_node 0 #define first_memory_node 0 #define next_online_node(nid) (MAX_NUMNODES) +#define next_memory_node(nid) (MAX_NUMNODES) #define nr_node_ids 1U #define nr_online_nodes 1U diff --git a/mm/vmscan.c b/mm/vmscan.c index 69c516cfd2c4..8d262097f95d 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -54,6 +54,7 @@ #include #include #include +#include #include #include @@ -3778,12 +3779,40 @@ static void clear_mm_walk(void) kfree(walk); } -static void inc_min_seq(struct lruvec *lruvec, int type) +static bool inc_min_seq(struct lruvec *lruvec, int type, bool can_swap) { + int zone; + int remaining = MAX_LRU_BATCH; struct lru_gen_struct *lrugen = &lruvec->lrugen; + int new_gen, old_gen = lru_gen_from_seq(lrugen->min_seq[type]); + if (type == LRU_GEN_ANON && !can_swap) + goto done; + + /* prevent cold/hot inversion if force_scan is true */ + for (zone = 0; zone < MAX_NR_ZONES; zone++) { + struct list_head *head = &lrugen->lists[old_gen][type][zone]; + + while (!list_empty(head)) { + struct page *page = lru_to_page(head); + + VM_WARN_ON_ONCE_PAGE(PageUnevictable(page), page); + VM_WARN_ON_ONCE_PAGE(PageActive(page), page); + VM_WARN_ON_ONCE_PAGE(page_is_file_cache(page) != type, page); + VM_WARN_ON_ONCE_PAGE(page_zonenum(page) != zone, page); + + new_gen = page_inc_gen(lruvec, page, false); + list_move_tail(&page->lru, &lrugen->lists[new_gen][type][zone]); + + if (!--remaining) + return false; + } + } +done: reset_ctrl_pos(lruvec, type, true); WRITE_ONCE(lrugen->min_seq[type], lrugen->min_seq[type] + 1); + + return true; } static bool try_to_inc_min_seq(struct lruvec *lruvec, bool can_swap) @@ -3829,7 +3858,7 @@ next: return success; } -static void inc_max_seq(struct lruvec *lruvec, bool can_swap) +static void inc_max_seq(struct lruvec *lruvec, bool can_swap, bool force_scan) { int prev, next; int type, zone; @@ -3844,9 +3873,13 @@ static void inc_max_seq(struct lruvec *lruvec, bool can_swap) if (get_nr_gens(lruvec, type) != MAX_NR_GENS) continue; - VM_WARN_ON_ONCE(type == LRU_GEN_FILE || can_swap); + VM_WARN_ON_ONCE(!force_scan && (type == LRU_GEN_FILE || can_swap)); - inc_min_seq(lruvec, type); + while (!inc_min_seq(lruvec, type, can_swap)) { + spin_unlock_irq(&pgdat->lru_lock); + cond_resched(); + spin_lock_irq(&pgdat->lru_lock); + } } /* @@ -3883,7 +3916,7 @@ static void inc_max_seq(struct lruvec *lruvec, bool can_swap) } static bool try_to_inc_max_seq(struct lruvec *lruvec, unsigned long max_seq, - struct scan_control *sc, bool can_swap) + struct scan_control *sc, bool can_swap, bool force_scan) { bool success; struct lru_gen_mm_walk *walk; @@ -3904,7 +3937,7 @@ static bool try_to_inc_max_seq(struct lruvec *lruvec, unsigned long max_seq, * handful of PTEs. Spreading the work out over a period of time usually * is less efficient, but it avoids bursty page faults. */ - if (!(arch_has_hw_pte_young() && get_cap(LRU_GEN_MM_WALK))) { + if (!force_scan && !(arch_has_hw_pte_young() && get_cap(LRU_GEN_MM_WALK))) { success = iterate_mm_list_nowalk(lruvec, max_seq); goto done; } @@ -3918,7 +3951,7 @@ static bool try_to_inc_max_seq(struct lruvec *lruvec, unsigned long max_seq, walk->lruvec = lruvec; walk->max_seq = max_seq; walk->can_swap = can_swap; - walk->force_scan = false; + walk->force_scan = force_scan; do { success = iterate_mm_list(lruvec, walk, &mm); @@ -3938,7 +3971,7 @@ done: VM_WARN_ON_ONCE(max_seq != READ_ONCE(lrugen->max_seq)); - inc_max_seq(lruvec, can_swap); + inc_max_seq(lruvec, can_swap, force_scan); /* either this sees any waiters or they will see updated max_seq */ if (wq_has_sleeper(&lruvec->mm_state.wait)) wake_up_all(&lruvec->mm_state.wait); @@ -4033,7 +4066,7 @@ static bool age_lruvec(struct lruvec *lruvec, struct scan_control *sc, unsigned } if (need_aging) - try_to_inc_max_seq(lruvec, max_seq, sc, swappiness); + try_to_inc_max_seq(lruvec, max_seq, sc, swappiness, false); return true; } @@ -4581,7 +4614,7 @@ static unsigned long get_nr_to_scan(struct lruvec *lruvec, struct scan_control * if (current_is_kswapd()) return 0; - if (try_to_inc_max_seq(lruvec, max_seq, sc, can_swap)) + if (try_to_inc_max_seq(lruvec, max_seq, sc, can_swap, false)) return nr_to_scan; done: return min_seq[!can_swap] + MIN_NR_GENS <= max_seq ? nr_to_scan : 0; @@ -4920,6 +4953,361 @@ static struct attribute_group lru_gen_attr_group = { .attrs = lru_gen_attrs, }; +/****************************************************************************** + * debugfs interface + ******************************************************************************/ + +static void *lru_gen_seq_start(struct seq_file *m, loff_t *pos) +{ + struct mem_cgroup *memcg; + loff_t nr_to_skip = *pos; + + m->private = kvmalloc(PATH_MAX, GFP_KERNEL); + if (!m->private) + return ERR_PTR(-ENOMEM); + + memcg = mem_cgroup_iter(NULL, NULL, NULL); + do { + int nid; + + for_each_node_state(nid, N_MEMORY) { + if (!nr_to_skip--) + return get_lruvec(memcg, nid); + } + } while ((memcg = mem_cgroup_iter(NULL, memcg, NULL))); + + return NULL; +} + +static void lru_gen_seq_stop(struct seq_file *m, void *v) +{ + if (!IS_ERR_OR_NULL(v)) + mem_cgroup_iter_break(NULL, lruvec_memcg(v)); + + kvfree(m->private); + m->private = NULL; +} + +static void *lru_gen_seq_next(struct seq_file *m, void *v, loff_t *pos) +{ + int nid = lruvec_pgdat(v)->node_id; + struct mem_cgroup *memcg = lruvec_memcg(v); + + ++*pos; + + nid = next_memory_node(nid); + if (nid == MAX_NUMNODES) { + memcg = mem_cgroup_iter(NULL, memcg, NULL); + if (!memcg) + return NULL; + + nid = first_memory_node; + } + + return get_lruvec(memcg, nid); +} + +static void lru_gen_seq_show_full(struct seq_file *m, struct lruvec *lruvec, + unsigned long max_seq, unsigned long *min_seq, + unsigned long seq) +{ + int i; + int type, tier; + int hist = lru_hist_from_seq(seq); + struct lru_gen_struct *lrugen = &lruvec->lrugen; + + for (tier = 0; tier < MAX_NR_TIERS; tier++) { + seq_printf(m, " %10d", tier); + for (type = 0; type < ANON_AND_FILE; type++) { + const char *s = " "; + unsigned long n[3] = {}; + + if (seq == max_seq) { + s = "RT "; + n[0] = READ_ONCE(lrugen->avg_refaulted[type][tier]); + n[1] = READ_ONCE(lrugen->avg_total[type][tier]); + } else if (seq == min_seq[type] || NR_HIST_GENS > 1) { + s = "rep"; + n[0] = atomic_long_read(&lrugen->refaulted[hist][type][tier]); + n[1] = atomic_long_read(&lrugen->evicted[hist][type][tier]); + if (tier) + n[2] = READ_ONCE(lrugen->protected[hist][type][tier - 1]); + } + + for (i = 0; i < 3; i++) + seq_printf(m, " %10lu%c", n[i], s[i]); + } + seq_putc(m, '\n'); + } + + seq_puts(m, " "); + for (i = 0; i < NR_MM_STATS; i++) { + const char *s = " "; + unsigned long n = 0; + + if (seq == max_seq && NR_HIST_GENS == 1) { + s = "LOYNFA"; + n = READ_ONCE(lruvec->mm_state.stats[hist][i]); + } else if (seq != max_seq && NR_HIST_GENS > 1) { + s = "loynfa"; + n = READ_ONCE(lruvec->mm_state.stats[hist][i]); + } + + seq_printf(m, " %10lu%c", n, s[i]); + } + seq_putc(m, '\n'); +} + +static int lru_gen_seq_show(struct seq_file *m, void *v) +{ + unsigned long seq; + bool full = !debugfs_real_fops(m->file)->write; + struct lruvec *lruvec = v; + struct lru_gen_struct *lrugen = &lruvec->lrugen; + int nid = lruvec_pgdat(lruvec)->node_id; + struct mem_cgroup *memcg = lruvec_memcg(lruvec); + DEFINE_MAX_SEQ(lruvec); + DEFINE_MIN_SEQ(lruvec); + + if (nid == first_memory_node) { + const char *path = memcg ? m->private : ""; + +#ifdef CONFIG_MEMCG + if (memcg) + cgroup_path(memcg->css.cgroup, m->private, PATH_MAX); +#endif + seq_printf(m, "memcg %5hu %s\n", mem_cgroup_id(memcg), path); + } + + seq_printf(m, " node %5d\n", nid); + + if (!full) + seq = min_seq[LRU_GEN_ANON]; + else if (max_seq >= MAX_NR_GENS) + seq = max_seq - MAX_NR_GENS + 1; + else + seq = 0; + + for (; seq <= max_seq; seq++) { + int type, zone; + int gen = lru_gen_from_seq(seq); + unsigned long birth = READ_ONCE(lruvec->lrugen.timestamps[gen]); + + seq_printf(m, " %10lu %10u", seq, jiffies_to_msecs(jiffies - birth)); + + for (type = 0; type < ANON_AND_FILE; type++) { + unsigned long size = 0; + char mark = full && seq < min_seq[type] ? 'x' : ' '; + + for (zone = 0; zone < MAX_NR_ZONES; zone++) + size += max(READ_ONCE(lrugen->nr_pages[gen][type][zone]), 0L); + + seq_printf(m, " %10lu%c", size, mark); + } + + seq_putc(m, '\n'); + + if (full) + lru_gen_seq_show_full(m, lruvec, max_seq, min_seq, seq); + } + + return 0; +} + +static const struct seq_operations lru_gen_seq_ops = { + .start = lru_gen_seq_start, + .stop = lru_gen_seq_stop, + .next = lru_gen_seq_next, + .show = lru_gen_seq_show, +}; + +static int run_aging(struct lruvec *lruvec, unsigned long seq, struct scan_control *sc, + bool can_swap, bool force_scan) +{ + DEFINE_MAX_SEQ(lruvec); + DEFINE_MIN_SEQ(lruvec); + + if (seq < max_seq) + return 0; + + if (seq > max_seq) + return -EINVAL; + + if (!force_scan && min_seq[!can_swap] + MAX_NR_GENS - 1 <= max_seq) + return -ERANGE; + + try_to_inc_max_seq(lruvec, max_seq, sc, can_swap, force_scan); + + return 0; +} + +static int run_eviction(struct lruvec *lruvec, unsigned long seq, struct scan_control *sc, + int swappiness, unsigned long nr_to_reclaim) +{ + DEFINE_MAX_SEQ(lruvec); + + if (seq + MIN_NR_GENS > max_seq) + return -EINVAL; + + sc->nr_reclaimed = 0; + + while (!signal_pending(current)) { + DEFINE_MIN_SEQ(lruvec); + + if (seq < min_seq[!swappiness]) + return 0; + + if (sc->nr_reclaimed >= nr_to_reclaim) + return 0; + + if (!evict_pages(lruvec, sc, swappiness, NULL)) + return 0; + + cond_resched(); + } + + return -EINTR; +} + +static int run_cmd(char cmd, int memcg_id, int nid, unsigned long seq, + struct scan_control *sc, int swappiness, unsigned long opt) +{ + struct lruvec *lruvec; + int err = -EINVAL; + struct mem_cgroup *memcg = NULL; + + if (nid < 0 || nid >= MAX_NUMNODES || !node_state(nid, N_MEMORY)) + return -EINVAL; + + if (!mem_cgroup_disabled()) { + rcu_read_lock(); + memcg = mem_cgroup_from_id(memcg_id); +#ifdef CONFIG_MEMCG + if (memcg && !css_tryget(&memcg->css)) + memcg = NULL; +#endif + rcu_read_unlock(); + + if (!memcg) + return -EINVAL; + } + + if (memcg_id != mem_cgroup_id(memcg)) + goto done; + + lruvec = get_lruvec(memcg, nid); + + if (swappiness < 0) + swappiness = get_swappiness(lruvec, sc); + else if (swappiness > 200) + goto done; + + switch (cmd) { + case '+': + err = run_aging(lruvec, seq, sc, swappiness, opt); + break; + case '-': + err = run_eviction(lruvec, seq, sc, swappiness, opt); + break; + } +done: + mem_cgroup_put(memcg); + + return err; +} + +static ssize_t lru_gen_seq_write(struct file *file, const char __user *src, + size_t len, loff_t *pos) +{ + void *buf; + char *cur, *next; + unsigned int flags; + struct blk_plug plug; + int err = -EINVAL; + struct scan_control sc = { + .may_writepage = true, + .may_unmap = true, + .may_swap = true, + .reclaim_idx = MAX_NR_ZONES - 1, + .gfp_mask = GFP_KERNEL, + }; + + buf = kvmalloc(len + 1, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + if (copy_from_user(buf, src, len)) { + kvfree(buf); + return -EFAULT; + } + + set_task_reclaim_state(current, &sc.reclaim_state); + flags = memalloc_noreclaim_save(); + blk_start_plug(&plug); + if (!set_mm_walk(NULL)) { + err = -ENOMEM; + goto done; + } + + next = buf; + next[len] = '\0'; + + while ((cur = strsep(&next, ",;\n"))) { + int n; + int end; + char cmd; + unsigned int memcg_id; + unsigned int nid; + unsigned long seq; + unsigned int swappiness = -1; + unsigned long opt = -1; + + cur = skip_spaces(cur); + if (!*cur) + continue; + + n = sscanf(cur, "%c %u %u %lu %n %u %n %lu %n", &cmd, &memcg_id, &nid, + &seq, &end, &swappiness, &end, &opt, &end); + if (n < 4 || cur[end]) { + err = -EINVAL; + break; + } + + err = run_cmd(cmd, memcg_id, nid, seq, &sc, swappiness, opt); + if (err) + break; + } +done: + clear_mm_walk(); + blk_finish_plug(&plug); + memalloc_noreclaim_restore(flags); + set_task_reclaim_state(current, NULL); + + kvfree(buf); + + return err ? : len; +} + +static int lru_gen_seq_open(struct inode *inode, struct file *file) +{ + return seq_open(file, &lru_gen_seq_ops); +} + +static const struct file_operations lru_gen_rw_fops = { + .open = lru_gen_seq_open, + .read = seq_read, + .write = lru_gen_seq_write, + .llseek = seq_lseek, + .release = seq_release, +}; + +static const struct file_operations lru_gen_ro_fops = { + .open = lru_gen_seq_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; + /****************************************************************************** * initialization ******************************************************************************/ @@ -4977,6 +5365,9 @@ static int __init init_lru_gen(void) if (sysfs_create_group(mm_kobj, &lru_gen_attr_group)) pr_err("lru_gen: failed to create sysfs group\n"); + debugfs_create_file("lru_gen", 0644, NULL, NULL, &lru_gen_rw_fops); + debugfs_create_file("lru_gen_full", 0444, NULL, NULL, &lru_gen_ro_fops); + return 0; }; late_initcall(init_lru_gen); From fe02aa7695a3509170386dcba91da2e76bdeccd5 Mon Sep 17 00:00:00 2001 From: Yu Zhao Date: Sun, 18 Sep 2022 02:00:10 -0600 Subject: [PATCH 574/698] UPSTREAM: mm: multi-gen LRU: admin guide MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add an admin guide. Moto-CRs-Fixed:(CR) Link: https://lkml.kernel.org/r/20220918080010.2920238-14-yuzhao@google.com Change-Id: Ia4dba47e8231eda4f0e76fb8969df7291a9bfe7c Signed-off-by: Yu Zhao Acked-by: Brian Geffon Acked-by: Jan Alexander Steffens (heftig) Acked-by: Oleksandr Natalenko Acked-by: Steven Barrett Acked-by: Suleiman Souhlal Acked-by: M(CR) Rapoport Tested-by: Daniel Byrne Tested-by: Donald Carr Tested-by: Holger Hoffstätte Tested-by: Konstantin Kharlamov Tested-by: Shuang Zhai Tested-by: Sofia Trinh Tested-by: Vaibhav Jain Cc: Andi Kleen Cc: Aneesh Kumar K.V Cc: Barry Song Cc: Catalin Marinas Cc: Dave Hansen Cc: Hillf Danton Cc: Jens Axboe Cc: Johannes Weiner Cc: Jonathan Corbet Cc: Linus Torvalds Cc: Matthew Wilcox Cc: Mel Gorman Cc: Miaohe Lin Cc: Michael Larabel Cc: Michal Hocko Cc: M(CR) Rapoport Cc: Peter Zijlstra Cc: Qi Zheng Cc: Tejun Heo Cc: Vlastimil Babka Cc: Will Deacon Signed-off-by: Andrew Morton (cherry picked from commit 07017acb06012d250fb68930e809257e6694d324) Bug: 261052246 Signed-off-by: Kalesh Singh Reviewed-on: https://gerrit.mot.com/2491806 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- Documentation/admin-guide/mm/index.rst | 1 + Documentation/admin-guide/mm/multigen_lru.rst | 162 ++++++++++++++++++ mm/Kconfig | 3 +- mm/vmscan.c | 4 + 4 files changed, 169 insertions(+), 1 deletion(-) create mode 100644 Documentation/admin-guide/mm/multigen_lru.rst diff --git a/Documentation/admin-guide/mm/index.rst b/Documentation/admin-guide/mm/index.rst index 11db46448354..59dfa5892f8f 100644 --- a/Documentation/admin-guide/mm/index.rst +++ b/Documentation/admin-guide/mm/index.rst @@ -31,6 +31,7 @@ the Linux memory management. idle_page_tracking ksm memory-hotplug + multigen_lru numa_memory_policy numaperf pagemap diff --git a/Documentation/admin-guide/mm/multigen_lru.rst b/Documentation/admin-guide/mm/multigen_lru.rst new file mode 100644 index 000000000000..33e068830497 --- /dev/null +++ b/Documentation/admin-guide/mm/multigen_lru.rst @@ -0,0 +1,162 @@ +.. SPDX-License-Identifier: GPL-2.0 + +============= +Multi-Gen LRU +============= +The multi-gen LRU is an alternative LRU implementation that optimizes +page reclaim and improves performance under memory pressure. Page +reclaim decides the kernel's caching policy and ability to overcommit +memory. It directly impacts the kswapd CPU usage and RAM efficiency. + +Quick start +=========== +Build the kernel with the following configurations. + +* ``CONFIG_LRU_GEN=y`` +* ``CONFIG_LRU_GEN_ENABLED=y`` + +All set! + +Runtime options +=============== +``/sys/kernel/mm/lru_gen/`` contains stable ABIs described in the +following subsections. + +Kill switch +----------- +``enabled`` accepts different values to enable or disable the +following components. Its default value depends on +``CONFIG_LRU_GEN_ENABLED``. All the components should be enabled +unless some of them have unforeseen side effects. Writing to +``enabled`` has no effect when a component is not supported by the +hardware, and valid values will be accepted even when the main switch +is off. + +====== =============================================================== +Values Components +====== =============================================================== +0x0001 The main switch for the multi-gen LRU. +0x0002 Clearing the accessed bit in leaf page table entries in large + batches, when MMU sets it (e.g., on x86). This behavior can + theoretically worsen lock contention (mmap_lock). If it is + disabled, the multi-gen LRU will suffer a minor performance + degradation for workloads that contiguously map hot pages, + whose accessed bits can be otherwise cleared by fewer larger + batches. +0x0004 Clearing the accessed bit in non-leaf page table entries as + well, when MMU sets it (e.g., on x86). This behavior was not + verified on x86 varieties other than Intel and AMD. If it is + disabled, the multi-gen LRU will suffer a negligible + performance degradation. +[yYnN] Apply to all the components above. +====== =============================================================== + +E.g., +:: + + echo y >/sys/kernel/mm/lru_gen/enabled + cat /sys/kernel/mm/lru_gen/enabled + 0x0007 + echo 5 >/sys/kernel/mm/lru_gen/enabled + cat /sys/kernel/mm/lru_gen/enabled + 0x0005 + +Thrashing prevention +-------------------- +Personal computers are more sensitive to thrashing because it can +cause janks (lags when rendering UI) and negatively impact user +experience. The multi-gen LRU offers thrashing prevention to the +majority of laptop and desktop users who do not have ``oomd``. + +Users can write ``N`` to ``min_ttl_ms`` to prevent the working set of +``N`` milliseconds from getting evicted. The OOM killer is triggered +if this working set cannot be kept in memory. In other words, this +option works as an adjustable pressure relief valve, and when open, it +terminates applications that are hopefully not being used. + +Based on the average human detectable lag (~100ms), ``N=1000`` usually +eliminates intolerable janks due to thrashing. Larger values like +``N=3000`` make janks less noticeable at the risk of premature OOM +kills. + +The default value ``0`` means disabled. + +Experimental features +===================== +``/sys/kernel/debug/lru_gen`` accepts commands described in the +following subsections. Multiple command lines are supported, so does +concatenation with delimiters ``,`` and ``;``. + +``/sys/kernel/debug/lru_gen_full`` provides additional stats for +debugging. ``CONFIG_LRU_GEN_STATS=y`` keeps historical stats from +evicted generations in this file. + +Working set estimation +---------------------- +Working set estimation measures how much memory an application needs +in a given time interval, and it is usually done with little impact on +the performance of the application. E.g., data centers want to +optimize job scheduling (bin packing) to improve memory utilizations. +When a new job comes in, the job scheduler needs to find out whether +each server it manages can allocate a certain amount of memory for +this new job before it can pick a candidate. To do so, the job +scheduler needs to estimate the working sets of the existing jobs. + +When it is read, ``lru_gen`` returns a histogram of numbers of pages +accessed over different time intervals for each memcg and node. +``MAX_NR_GENS`` decides the number of bins for each histogram. The +histograms are noncumulative. +:: + + memcg memcg_id memcg_path + node node_id + min_gen_nr age_in_ms nr_anon_pages nr_file_pages + ... + max_gen_nr age_in_ms nr_anon_pages nr_file_pages + +Each bin contains an estimated number of pages that have been accessed +within ``age_in_ms``. E.g., ``min_gen_nr`` contains the coldest pages +and ``max_gen_nr`` contains the hottest pages, since ``age_in_ms`` of +the former is the largest and that of the latter is the smallest. + +Users can write the following command to ``lru_gen`` to create a new +generation ``max_gen_nr+1``: + + ``+ memcg_id node_id max_gen_nr [can_swap [force_scan]]`` + +``can_swap`` defaults to the swap setting and, if it is set to ``1``, +it forces the scan of anon pages when swap is off, and vice versa. +``force_scan`` defaults to ``1`` and, if it is set to ``0``, it +employs heuristics to reduce the overhead, which is likely to reduce +the coverage as well. + +A typical use case is that a job scheduler runs this command at a +certain time interval to create new generations, and it ranks the +servers it manages based on the sizes of their cold pages defined by +this time interval. + +Proactive reclaim +----------------- +Proactive reclaim induces page reclaim when there is no memory +pressure. It usually targets cold pages only. E.g., when a new job +comes in, the job scheduler wants to proactively reclaim cold pages on +the server it selected, to improve the chance of successfully landing +this new job. + +Users can write the following command to ``lru_gen`` to evict +generations less than or equal to ``min_gen_nr``. + + ``- memcg_id node_id min_gen_nr [swappiness [nr_to_reclaim]]`` + +``min_gen_nr`` should be less than ``max_gen_nr-1``, since +``max_gen_nr`` and ``max_gen_nr-1`` are not fully aged (equivalent to +the active list) and therefore cannot be evicted. ``swappiness`` +overrides the default value in ``/proc/sys/vm/swappiness``. +``nr_to_reclaim`` limits the number of pages to evict. + +A typical use case is that a job scheduler runs this command before it +tries to land a new job on a server. If it fails to materialize enough +cold pages because of the overestimation, it retries on the next +server according to the ranking result obtained from the working set +estimation step. This less forceful approach limits the impacts on the +existing jobs. diff --git a/mm/Kconfig b/mm/Kconfig index b96975666710..8dc2a49d4509 100644 --- a/mm/Kconfig +++ b/mm/Kconfig @@ -863,7 +863,8 @@ config LRU_GEN # make sure page->flags has enough spare bits depends on 64BIT || !SPARSEMEM || SPARSEMEM_VMEMMAP help - A high performance LRU implementation to overcommit memory. + A high performance LRU implementation to overcommit memory. See + Documentation/admin-guide/mm/multigen_lru.rst for details. config LRU_GEN_ENABLED bool "Enable by default" diff --git a/mm/vmscan.c b/mm/vmscan.c index 8d262097f95d..ba1b7ce2cd7c 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -4878,6 +4878,7 @@ static ssize_t show_min_ttl(struct kobject *kobj, struct kobj_attribute *attr, c return sprintf(buf, "%u\n", jiffies_to_msecs(READ_ONCE(lru_gen_min_ttl))); } +/* see Documentation/admin-guide/mm/multigen_lru.rst for details */ static ssize_t store_min_ttl(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t len) { @@ -4911,6 +4912,7 @@ static ssize_t show_enabled(struct kobject *kobj, struct kobj_attribute *attr, c return snprintf(buf, PAGE_SIZE, "0x%04x\n", caps); } +/* see Documentation/admin-guide/mm/multigen_lru.rst for details */ static ssize_t store_enabled(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t len) { @@ -5058,6 +5060,7 @@ static void lru_gen_seq_show_full(struct seq_file *m, struct lruvec *lruvec, seq_putc(m, '\n'); } +/* see Documentation/admin-guide/mm/multigen_lru.rst for details */ static int lru_gen_seq_show(struct seq_file *m, void *v) { unsigned long seq; @@ -5216,6 +5219,7 @@ done: return err; } +/* see Documentation/admin-guide/mm/multigen_lru.rst for details */ static ssize_t lru_gen_seq_write(struct file *file, const char __user *src, size_t len, loff_t *pos) { From 5c800a5f151011ff792fc8b4016dcc8cb31c8aa7 Mon Sep 17 00:00:00 2001 From: Yu Zhao Date: Sun, 18 Sep 2022 02:00:11 -0600 Subject: [PATCH 575/698] BACKPORT: mm: multi-gen LRU: design doc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a design doc. Moto-CRs-Fixed:(CR) Link: https://lkml.kernel.org/r/20220918080010.2920238-15-yuzhao@google.com Change-Id: I78c0956fb9f3b34d9faf96ecdef31fe0c5aeb184 Signed-off-by: Yu Zhao Acked-by: Brian Geffon Acked-by: Jan Alexander Steffens (heftig) Acked-by: Oleksandr Natalenko Acked-by: Steven Barrett Acked-by: Suleiman Souhlal Tested-by: Daniel Byrne Tested-by: Donald Carr Tested-by: Holger Hoffstätte Tested-by: Konstantin Kharlamov Tested-by: Shuang Zhai Tested-by: Sofia Trinh Tested-by: Vaibhav Jain Cc: Andi Kleen Cc: Aneesh Kumar K.V Cc: Barry Song Cc: Catalin Marinas Cc: Dave Hansen Cc: Hillf Danton Cc: Jens Axboe Cc: Johannes Weiner Cc: Jonathan Corbet Cc: Linus Torvalds Cc: Matthew Wilcox Cc: Mel Gorman Cc: Miaohe Lin Cc: Michael Larabel Cc: Michal Hocko Cc: M(CR) Rapoport Cc: M(CR) Rapoport Cc: Peter Zijlstra Cc: Qi Zheng Cc: Tejun Heo Cc: Vlastimil Babka Cc: Will Deacon Signed-off-by: Andrew Morton (cherry picked from commit 8be976a0937a18118424dd2505925081d9192fd5) [ Kalesh Singh - Fix trivial conflicts in Documentation/vm/index.rst ] Bug: 261052246 Signed-off-by: Kalesh Singh Reviewed-on: https://gerrit.mot.com/2491807 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- Documentation/vm/index.rst | 1 + Documentation/vm/multigen_lru.rst | 159 ++++++++++++++++++++++++++++++ 2 files changed, 160 insertions(+) create mode 100644 Documentation/vm/multigen_lru.rst diff --git a/Documentation/vm/index.rst b/Documentation/vm/index.rst index e8d943b21cf9..3a1bbc37e309 100644 --- a/Documentation/vm/index.rst +++ b/Documentation/vm/index.rst @@ -39,6 +39,7 @@ descriptions of data structures and algorithms. ksm memory-model mmu_notifier + multigen_lru numa overcommit-accounting page_migration diff --git a/Documentation/vm/multigen_lru.rst b/Documentation/vm/multigen_lru.rst new file mode 100644 index 000000000000..d7062c6a8946 --- /dev/null +++ b/Documentation/vm/multigen_lru.rst @@ -0,0 +1,159 @@ +.. SPDX-License-Identifier: GPL-2.0 + +============= +Multi-Gen LRU +============= +The multi-gen LRU is an alternative LRU implementation that optimizes +page reclaim and improves performance under memory pressure. Page +reclaim decides the kernel's caching policy and ability to overcommit +memory. It directly impacts the kswapd CPU usage and RAM efficiency. + +Design overview +=============== +Objectives +---------- +The design objectives are: + +* Good representation of access recency +* Try to profit from spatial locality +* Fast paths to make obvious choices +* Simple self-correcting heuristics + +The representation of access recency is at the core of all LRU +implementations. In the multi-gen LRU, each generation represents a +group of pages with similar access recency. Generations establish a +(time-based) common frame of reference and therefore help make better +choices, e.g., between different memcgs on a computer or different +computers in a data center (for job scheduling). + +Exploiting spatial locality improves efficiency when gathering the +accessed bit. A rmap walk targets a single page and does not try to +profit from discovering a young PTE. A page table walk can sweep all +the young PTEs in an address space, but the address space can be too +sparse to make a profit. The key is to optimize both methods and use +them in combination. + +Fast paths reduce code complexity and runtime overhead. Unmapped pages +do not require TLB flushes; clean pages do not require writeback. +These facts are only helpful when other conditions, e.g., access +recency, are similar. With generations as a common frame of reference, +additional factors stand out. But obvious choices might not be good +choices; thus self-correction is necessary. + +The benefits of simple self-correcting heuristics are self-evident. +Again, with generations as a common frame of reference, this becomes +attainable. Specifically, pages in the same generation can be +categorized based on additional factors, and a feedback loop can +statistically compare the refault percentages across those categories +and infer which of them are better choices. + +Assumptions +----------- +The protection of hot pages and the selection of cold pages are based +on page access channels and patterns. There are two access channels: + +* Accesses through page tables +* Accesses through file descriptors + +The protection of the former channel is by design stronger because: + +1. The uncertainty in determining the access patterns of the former + channel is higher due to the approximation of the accessed bit. +2. The cost of evicting the former channel is higher due to the TLB + flushes required and the likelihood of encountering the dirty bit. +3. The penalty of underprotecting the former channel is higher because + applications usually do not prepare themselves for major page + faults like they do for blocked I/O. E.g., GUI applications + commonly use dedicated I/O threads to avoid blocking rendering + threads. + +There are also two access patterns: + +* Accesses exhibiting temporal locality +* Accesses not exhibiting temporal locality + +For the reasons listed above, the former channel is assumed to follow +the former pattern unless ``VM_SEQ_READ`` or ``VM_RAND_READ`` is +present, and the latter channel is assumed to follow the latter +pattern unless outlying refaults have been observed. + +Workflow overview +================= +Evictable pages are divided into multiple generations for each +``lruvec``. The youngest generation number is stored in +``lrugen->max_seq`` for both anon and file types as they are aged on +an equal footing. The oldest generation numbers are stored in +``lrugen->min_seq[]`` separately for anon and file types as clean file +pages can be evicted regardless of swap constraints. These three +variables are monotonically increasing. + +Generation numbers are truncated into ``order_base_2(MAX_NR_GENS+1)`` +bits in order to fit into the gen counter in ``folio->flags``. Each +truncated generation number is an index to ``lrugen->lists[]``. The +sliding window technique is used to track at least ``MIN_NR_GENS`` and +at most ``MAX_NR_GENS`` generations. The gen counter stores a value +within ``[1, MAX_NR_GENS]`` while a page is on one of +``lrugen->lists[]``; otherwise it stores zero. + +Each generation is divided into multiple tiers. A page accessed ``N`` +times through file descriptors is in tier ``order_base_2(N)``. Unlike +generations, tiers do not have dedicated ``lrugen->lists[]``. In +contrast to moving across generations, which requires the LRU lock, +moving across tiers only involves atomic operations on +``folio->flags`` and therefore has a negligible cost. A feedback loop +modeled after the PID controller monitors refaults over all the tiers +from anon and file types and decides which tiers from which types to +evict or protect. + +There are two conceptually independent procedures: the aging and the +eviction. They form a closed-loop system, i.e., the page reclaim. + +Aging +----- +The aging produces young generations. Given an ``lruvec``, it +increments ``max_seq`` when ``max_seq-min_seq+1`` approaches +``MIN_NR_GENS``. The aging promotes hot pages to the youngest +generation when it finds them accessed through page tables; the +demotion of cold pages happens consequently when it increments +``max_seq``. The aging uses page table walks and rmap walks to find +young PTEs. For the former, it iterates ``lruvec_memcg()->mm_list`` +and calls ``walk_page_range()`` with each ``mm_struct`` on this list +to scan PTEs, and after each iteration, it increments ``max_seq``. For +the latter, when the eviction walks the rmap and finds a young PTE, +the aging scans the adjacent PTEs. For both, on finding a young PTE, +the aging clears the accessed bit and updates the gen counter of the +page mapped by this PTE to ``(max_seq%MAX_NR_GENS)+1``. + +Eviction +-------- +The eviction consumes old generations. Given an ``lruvec``, it +increments ``min_seq`` when ``lrugen->lists[]`` indexed by +``min_seq%MAX_NR_GENS`` becomes empty. To select a type and a tier to +evict from, it first compares ``min_seq[]`` to select the older type. +If both types are equally old, it selects the one whose first tier has +a lower refault percentage. The first tier contains single-use +unmapped clean pages, which are the best bet. The eviction sorts a +page according to its gen counter if the aging has found this page +accessed through page tables and updated its gen counter. It also +moves a page to the next generation, i.e., ``min_seq+1``, if this page +was accessed multiple times through file descriptors and the feedback +loop has detected outlying refaults from the tier this page is in. To +this end, the feedback loop uses the first tier as the baseline, for +the reason stated earlier. + +Summary +------- +The multi-gen LRU can be disassembled into the following parts: + +* Generations +* Rmap walks +* Page table walks +* Bloom filters +* PID controller + +The aging and the eviction form a producer-consumer model; +specifically, the latter drives the former by the sliding window over +generations. Within the aging, rmap walks drive page table walks by +inserting hot densely populated page tables to the Bloom filters. +Within the eviction, the PID controller uses refaults as the feedback +to select types to evict and tiers to protect. From 7e039a2e3dfe1e5b6ec6aa133897b6fca0b3405f Mon Sep 17 00:00:00 2001 From: William Liu Date: Tue, 18 Apr 2023 16:42:41 +0800 Subject: [PATCH 576/698] configs:Enable mglru MGLRU feature could provide better Memory usage and avoid less LMK killing Change-Id: Iab8af4f931124898bd8cd45574aa9aa89f209573 Signed-off-by: William Liu Reviewed-on: https://gerrit.mot.com/2580285 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi-bangkk.config | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-bangkk.config b/arch/arm64/configs/vendor/ext_config/moto-holi-bangkk.config index 9c9a7fa94347..44e605efbf30 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-bangkk.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-bangkk.config @@ -40,3 +40,5 @@ CONFIG_QUP0_SE2_AP=y CONFIG_CAMERA_FLASH_IIC_COMPATIBLE=y CONFIG_EROFS_FS_PCPU_KTHREAD=y CONFIG_EROFS_FS_PCPU_KTHREAD_HIPRI=y +CONFIG_LRU_GEN=y +CONFIG_LRU_GEN_ENABLED=y From b47bc15a5d2f46fe39dc5a9812963889bf5fac86 Mon Sep 17 00:00:00 2001 From: William Liu Date: Mon, 15 May 2023 13:21:28 +0800 Subject: [PATCH 577/698] Revert "configs:Enable mglru" This reverts commit 9886c4f4f002b51392741d0b299d1b707c05c68c. This change breaks the GKI abi interface, need Google to submit the Same configuration in GKI image first, then we can enable it later Change-Id: I3c58864ec567371ead43eee2a49056461393de43 Reviewed-on: https://gerrit.mot.com/2606885 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi-bangkk.config | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-bangkk.config b/arch/arm64/configs/vendor/ext_config/moto-holi-bangkk.config index 44e605efbf30..9c9a7fa94347 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-bangkk.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-bangkk.config @@ -40,5 +40,3 @@ CONFIG_QUP0_SE2_AP=y CONFIG_CAMERA_FLASH_IIC_COMPATIBLE=y CONFIG_EROFS_FS_PCPU_KTHREAD=y CONFIG_EROFS_FS_PCPU_KTHREAD_HIPRI=y -CONFIG_LRU_GEN=y -CONFIG_LRU_GEN_ENABLED=y From 74ab74e06b48207d0181048785a7e405c79c3ecb Mon Sep 17 00:00:00 2001 From: xiewen3 Date: Tue, 16 May 2023 22:39:44 +0800 Subject: [PATCH 578/698] LUR: Revert "BACKPORT: mm: multi-gen LRU: design doc" The LRU function is not compatible with GKI, causing GKI to fail to start, so revert. This reverts commit 932a09f2bd726ba07f940fb9840b5eaead870180. Change-Id: I41f90ae7376d956b07eb509c25a6306aea38c2f2 Reviewed-on: https://gerrit.mot.com/2609754 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- Documentation/vm/index.rst | 1 - Documentation/vm/multigen_lru.rst | 159 ------------------------------ 2 files changed, 160 deletions(-) delete mode 100644 Documentation/vm/multigen_lru.rst diff --git a/Documentation/vm/index.rst b/Documentation/vm/index.rst index 3a1bbc37e309..e8d943b21cf9 100644 --- a/Documentation/vm/index.rst +++ b/Documentation/vm/index.rst @@ -39,7 +39,6 @@ descriptions of data structures and algorithms. ksm memory-model mmu_notifier - multigen_lru numa overcommit-accounting page_migration diff --git a/Documentation/vm/multigen_lru.rst b/Documentation/vm/multigen_lru.rst deleted file mode 100644 index d7062c6a8946..000000000000 --- a/Documentation/vm/multigen_lru.rst +++ /dev/null @@ -1,159 +0,0 @@ -.. SPDX-License-Identifier: GPL-2.0 - -============= -Multi-Gen LRU -============= -The multi-gen LRU is an alternative LRU implementation that optimizes -page reclaim and improves performance under memory pressure. Page -reclaim decides the kernel's caching policy and ability to overcommit -memory. It directly impacts the kswapd CPU usage and RAM efficiency. - -Design overview -=============== -Objectives ----------- -The design objectives are: - -* Good representation of access recency -* Try to profit from spatial locality -* Fast paths to make obvious choices -* Simple self-correcting heuristics - -The representation of access recency is at the core of all LRU -implementations. In the multi-gen LRU, each generation represents a -group of pages with similar access recency. Generations establish a -(time-based) common frame of reference and therefore help make better -choices, e.g., between different memcgs on a computer or different -computers in a data center (for job scheduling). - -Exploiting spatial locality improves efficiency when gathering the -accessed bit. A rmap walk targets a single page and does not try to -profit from discovering a young PTE. A page table walk can sweep all -the young PTEs in an address space, but the address space can be too -sparse to make a profit. The key is to optimize both methods and use -them in combination. - -Fast paths reduce code complexity and runtime overhead. Unmapped pages -do not require TLB flushes; clean pages do not require writeback. -These facts are only helpful when other conditions, e.g., access -recency, are similar. With generations as a common frame of reference, -additional factors stand out. But obvious choices might not be good -choices; thus self-correction is necessary. - -The benefits of simple self-correcting heuristics are self-evident. -Again, with generations as a common frame of reference, this becomes -attainable. Specifically, pages in the same generation can be -categorized based on additional factors, and a feedback loop can -statistically compare the refault percentages across those categories -and infer which of them are better choices. - -Assumptions ------------ -The protection of hot pages and the selection of cold pages are based -on page access channels and patterns. There are two access channels: - -* Accesses through page tables -* Accesses through file descriptors - -The protection of the former channel is by design stronger because: - -1. The uncertainty in determining the access patterns of the former - channel is higher due to the approximation of the accessed bit. -2. The cost of evicting the former channel is higher due to the TLB - flushes required and the likelihood of encountering the dirty bit. -3. The penalty of underprotecting the former channel is higher because - applications usually do not prepare themselves for major page - faults like they do for blocked I/O. E.g., GUI applications - commonly use dedicated I/O threads to avoid blocking rendering - threads. - -There are also two access patterns: - -* Accesses exhibiting temporal locality -* Accesses not exhibiting temporal locality - -For the reasons listed above, the former channel is assumed to follow -the former pattern unless ``VM_SEQ_READ`` or ``VM_RAND_READ`` is -present, and the latter channel is assumed to follow the latter -pattern unless outlying refaults have been observed. - -Workflow overview -================= -Evictable pages are divided into multiple generations for each -``lruvec``. The youngest generation number is stored in -``lrugen->max_seq`` for both anon and file types as they are aged on -an equal footing. The oldest generation numbers are stored in -``lrugen->min_seq[]`` separately for anon and file types as clean file -pages can be evicted regardless of swap constraints. These three -variables are monotonically increasing. - -Generation numbers are truncated into ``order_base_2(MAX_NR_GENS+1)`` -bits in order to fit into the gen counter in ``folio->flags``. Each -truncated generation number is an index to ``lrugen->lists[]``. The -sliding window technique is used to track at least ``MIN_NR_GENS`` and -at most ``MAX_NR_GENS`` generations. The gen counter stores a value -within ``[1, MAX_NR_GENS]`` while a page is on one of -``lrugen->lists[]``; otherwise it stores zero. - -Each generation is divided into multiple tiers. A page accessed ``N`` -times through file descriptors is in tier ``order_base_2(N)``. Unlike -generations, tiers do not have dedicated ``lrugen->lists[]``. In -contrast to moving across generations, which requires the LRU lock, -moving across tiers only involves atomic operations on -``folio->flags`` and therefore has a negligible cost. A feedback loop -modeled after the PID controller monitors refaults over all the tiers -from anon and file types and decides which tiers from which types to -evict or protect. - -There are two conceptually independent procedures: the aging and the -eviction. They form a closed-loop system, i.e., the page reclaim. - -Aging ------ -The aging produces young generations. Given an ``lruvec``, it -increments ``max_seq`` when ``max_seq-min_seq+1`` approaches -``MIN_NR_GENS``. The aging promotes hot pages to the youngest -generation when it finds them accessed through page tables; the -demotion of cold pages happens consequently when it increments -``max_seq``. The aging uses page table walks and rmap walks to find -young PTEs. For the former, it iterates ``lruvec_memcg()->mm_list`` -and calls ``walk_page_range()`` with each ``mm_struct`` on this list -to scan PTEs, and after each iteration, it increments ``max_seq``. For -the latter, when the eviction walks the rmap and finds a young PTE, -the aging scans the adjacent PTEs. For both, on finding a young PTE, -the aging clears the accessed bit and updates the gen counter of the -page mapped by this PTE to ``(max_seq%MAX_NR_GENS)+1``. - -Eviction --------- -The eviction consumes old generations. Given an ``lruvec``, it -increments ``min_seq`` when ``lrugen->lists[]`` indexed by -``min_seq%MAX_NR_GENS`` becomes empty. To select a type and a tier to -evict from, it first compares ``min_seq[]`` to select the older type. -If both types are equally old, it selects the one whose first tier has -a lower refault percentage. The first tier contains single-use -unmapped clean pages, which are the best bet. The eviction sorts a -page according to its gen counter if the aging has found this page -accessed through page tables and updated its gen counter. It also -moves a page to the next generation, i.e., ``min_seq+1``, if this page -was accessed multiple times through file descriptors and the feedback -loop has detected outlying refaults from the tier this page is in. To -this end, the feedback loop uses the first tier as the baseline, for -the reason stated earlier. - -Summary -------- -The multi-gen LRU can be disassembled into the following parts: - -* Generations -* Rmap walks -* Page table walks -* Bloom filters -* PID controller - -The aging and the eviction form a producer-consumer model; -specifically, the latter drives the former by the sliding window over -generations. Within the aging, rmap walks drive page table walks by -inserting hot densely populated page tables to the Bloom filters. -Within the eviction, the PID controller uses refaults as the feedback -to select types to evict and tiers to protect. From c85538727651f7ea1cb151987d2a034a0913ee26 Mon Sep 17 00:00:00 2001 From: xiewen3 Date: Tue, 16 May 2023 22:40:37 +0800 Subject: [PATCH 579/698] LUR: Revert "UPSTREAM: mm: multi-gen LRU: admin guide" The LRU function is not compatible with GKI, causing GKI to fail to start, so revert. This reverts commit cafd97d5b6d857ea0631ea3b4afc12fd995dbde7. Change-Id: I397fabfd5b0b47f54e7e9ef0ef4562980786893a Reviewed-on: https://gerrit.mot.com/2609755 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- Documentation/admin-guide/mm/index.rst | 1 - Documentation/admin-guide/mm/multigen_lru.rst | 162 ------------------ mm/Kconfig | 3 +- mm/vmscan.c | 4 - 4 files changed, 1 insertion(+), 169 deletions(-) delete mode 100644 Documentation/admin-guide/mm/multigen_lru.rst diff --git a/Documentation/admin-guide/mm/index.rst b/Documentation/admin-guide/mm/index.rst index 59dfa5892f8f..11db46448354 100644 --- a/Documentation/admin-guide/mm/index.rst +++ b/Documentation/admin-guide/mm/index.rst @@ -31,7 +31,6 @@ the Linux memory management. idle_page_tracking ksm memory-hotplug - multigen_lru numa_memory_policy numaperf pagemap diff --git a/Documentation/admin-guide/mm/multigen_lru.rst b/Documentation/admin-guide/mm/multigen_lru.rst deleted file mode 100644 index 33e068830497..000000000000 --- a/Documentation/admin-guide/mm/multigen_lru.rst +++ /dev/null @@ -1,162 +0,0 @@ -.. SPDX-License-Identifier: GPL-2.0 - -============= -Multi-Gen LRU -============= -The multi-gen LRU is an alternative LRU implementation that optimizes -page reclaim and improves performance under memory pressure. Page -reclaim decides the kernel's caching policy and ability to overcommit -memory. It directly impacts the kswapd CPU usage and RAM efficiency. - -Quick start -=========== -Build the kernel with the following configurations. - -* ``CONFIG_LRU_GEN=y`` -* ``CONFIG_LRU_GEN_ENABLED=y`` - -All set! - -Runtime options -=============== -``/sys/kernel/mm/lru_gen/`` contains stable ABIs described in the -following subsections. - -Kill switch ------------ -``enabled`` accepts different values to enable or disable the -following components. Its default value depends on -``CONFIG_LRU_GEN_ENABLED``. All the components should be enabled -unless some of them have unforeseen side effects. Writing to -``enabled`` has no effect when a component is not supported by the -hardware, and valid values will be accepted even when the main switch -is off. - -====== =============================================================== -Values Components -====== =============================================================== -0x0001 The main switch for the multi-gen LRU. -0x0002 Clearing the accessed bit in leaf page table entries in large - batches, when MMU sets it (e.g., on x86). This behavior can - theoretically worsen lock contention (mmap_lock). If it is - disabled, the multi-gen LRU will suffer a minor performance - degradation for workloads that contiguously map hot pages, - whose accessed bits can be otherwise cleared by fewer larger - batches. -0x0004 Clearing the accessed bit in non-leaf page table entries as - well, when MMU sets it (e.g., on x86). This behavior was not - verified on x86 varieties other than Intel and AMD. If it is - disabled, the multi-gen LRU will suffer a negligible - performance degradation. -[yYnN] Apply to all the components above. -====== =============================================================== - -E.g., -:: - - echo y >/sys/kernel/mm/lru_gen/enabled - cat /sys/kernel/mm/lru_gen/enabled - 0x0007 - echo 5 >/sys/kernel/mm/lru_gen/enabled - cat /sys/kernel/mm/lru_gen/enabled - 0x0005 - -Thrashing prevention --------------------- -Personal computers are more sensitive to thrashing because it can -cause janks (lags when rendering UI) and negatively impact user -experience. The multi-gen LRU offers thrashing prevention to the -majority of laptop and desktop users who do not have ``oomd``. - -Users can write ``N`` to ``min_ttl_ms`` to prevent the working set of -``N`` milliseconds from getting evicted. The OOM killer is triggered -if this working set cannot be kept in memory. In other words, this -option works as an adjustable pressure relief valve, and when open, it -terminates applications that are hopefully not being used. - -Based on the average human detectable lag (~100ms), ``N=1000`` usually -eliminates intolerable janks due to thrashing. Larger values like -``N=3000`` make janks less noticeable at the risk of premature OOM -kills. - -The default value ``0`` means disabled. - -Experimental features -===================== -``/sys/kernel/debug/lru_gen`` accepts commands described in the -following subsections. Multiple command lines are supported, so does -concatenation with delimiters ``,`` and ``;``. - -``/sys/kernel/debug/lru_gen_full`` provides additional stats for -debugging. ``CONFIG_LRU_GEN_STATS=y`` keeps historical stats from -evicted generations in this file. - -Working set estimation ----------------------- -Working set estimation measures how much memory an application needs -in a given time interval, and it is usually done with little impact on -the performance of the application. E.g., data centers want to -optimize job scheduling (bin packing) to improve memory utilizations. -When a new job comes in, the job scheduler needs to find out whether -each server it manages can allocate a certain amount of memory for -this new job before it can pick a candidate. To do so, the job -scheduler needs to estimate the working sets of the existing jobs. - -When it is read, ``lru_gen`` returns a histogram of numbers of pages -accessed over different time intervals for each memcg and node. -``MAX_NR_GENS`` decides the number of bins for each histogram. The -histograms are noncumulative. -:: - - memcg memcg_id memcg_path - node node_id - min_gen_nr age_in_ms nr_anon_pages nr_file_pages - ... - max_gen_nr age_in_ms nr_anon_pages nr_file_pages - -Each bin contains an estimated number of pages that have been accessed -within ``age_in_ms``. E.g., ``min_gen_nr`` contains the coldest pages -and ``max_gen_nr`` contains the hottest pages, since ``age_in_ms`` of -the former is the largest and that of the latter is the smallest. - -Users can write the following command to ``lru_gen`` to create a new -generation ``max_gen_nr+1``: - - ``+ memcg_id node_id max_gen_nr [can_swap [force_scan]]`` - -``can_swap`` defaults to the swap setting and, if it is set to ``1``, -it forces the scan of anon pages when swap is off, and vice versa. -``force_scan`` defaults to ``1`` and, if it is set to ``0``, it -employs heuristics to reduce the overhead, which is likely to reduce -the coverage as well. - -A typical use case is that a job scheduler runs this command at a -certain time interval to create new generations, and it ranks the -servers it manages based on the sizes of their cold pages defined by -this time interval. - -Proactive reclaim ------------------ -Proactive reclaim induces page reclaim when there is no memory -pressure. It usually targets cold pages only. E.g., when a new job -comes in, the job scheduler wants to proactively reclaim cold pages on -the server it selected, to improve the chance of successfully landing -this new job. - -Users can write the following command to ``lru_gen`` to evict -generations less than or equal to ``min_gen_nr``. - - ``- memcg_id node_id min_gen_nr [swappiness [nr_to_reclaim]]`` - -``min_gen_nr`` should be less than ``max_gen_nr-1``, since -``max_gen_nr`` and ``max_gen_nr-1`` are not fully aged (equivalent to -the active list) and therefore cannot be evicted. ``swappiness`` -overrides the default value in ``/proc/sys/vm/swappiness``. -``nr_to_reclaim`` limits the number of pages to evict. - -A typical use case is that a job scheduler runs this command before it -tries to land a new job on a server. If it fails to materialize enough -cold pages because of the overestimation, it retries on the next -server according to the ranking result obtained from the working set -estimation step. This less forceful approach limits the impacts on the -existing jobs. diff --git a/mm/Kconfig b/mm/Kconfig index 8dc2a49d4509..b96975666710 100644 --- a/mm/Kconfig +++ b/mm/Kconfig @@ -863,8 +863,7 @@ config LRU_GEN # make sure page->flags has enough spare bits depends on 64BIT || !SPARSEMEM || SPARSEMEM_VMEMMAP help - A high performance LRU implementation to overcommit memory. See - Documentation/admin-guide/mm/multigen_lru.rst for details. + A high performance LRU implementation to overcommit memory. config LRU_GEN_ENABLED bool "Enable by default" diff --git a/mm/vmscan.c b/mm/vmscan.c index ba1b7ce2cd7c..8d262097f95d 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -4878,7 +4878,6 @@ static ssize_t show_min_ttl(struct kobject *kobj, struct kobj_attribute *attr, c return sprintf(buf, "%u\n", jiffies_to_msecs(READ_ONCE(lru_gen_min_ttl))); } -/* see Documentation/admin-guide/mm/multigen_lru.rst for details */ static ssize_t store_min_ttl(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t len) { @@ -4912,7 +4911,6 @@ static ssize_t show_enabled(struct kobject *kobj, struct kobj_attribute *attr, c return snprintf(buf, PAGE_SIZE, "0x%04x\n", caps); } -/* see Documentation/admin-guide/mm/multigen_lru.rst for details */ static ssize_t store_enabled(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t len) { @@ -5060,7 +5058,6 @@ static void lru_gen_seq_show_full(struct seq_file *m, struct lruvec *lruvec, seq_putc(m, '\n'); } -/* see Documentation/admin-guide/mm/multigen_lru.rst for details */ static int lru_gen_seq_show(struct seq_file *m, void *v) { unsigned long seq; @@ -5219,7 +5216,6 @@ done: return err; } -/* see Documentation/admin-guide/mm/multigen_lru.rst for details */ static ssize_t lru_gen_seq_write(struct file *file, const char __user *src, size_t len, loff_t *pos) { From edf7d67c68b15c220870f1c24e9564311d3ea792 Mon Sep 17 00:00:00 2001 From: xiewen3 Date: Tue, 16 May 2023 22:41:35 +0800 Subject: [PATCH 580/698] LUR: Revert "BACKPORT: mm: multi-gen LRU: debugfs interface" The LRU function is not compatible with GKI, causing GKI to fail to start, so revert. This reverts commit d4695923186a42934135af0890d4880969af65af. Change-Id: Ide8be264420e2a6e505b9c35ac4298f9e06b6b7b Reviewed-on: https://gerrit.mot.com/2609756 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- include/linux/nodemask.h | 1 - mm/vmscan.c | 411 +-------------------------------------- 2 files changed, 10 insertions(+), 402 deletions(-) diff --git a/include/linux/nodemask.h b/include/linux/nodemask.h index 8df4329c6480..a8d79f5b9a52 100644 --- a/include/linux/nodemask.h +++ b/include/linux/nodemask.h @@ -484,7 +484,6 @@ static inline int num_node_state(enum node_states state) #define first_online_node 0 #define first_memory_node 0 #define next_online_node(nid) (MAX_NUMNODES) -#define next_memory_node(nid) (MAX_NUMNODES) #define nr_node_ids 1U #define nr_online_nodes 1U diff --git a/mm/vmscan.c b/mm/vmscan.c index 8d262097f95d..69c516cfd2c4 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -54,7 +54,6 @@ #include #include #include -#include #include #include @@ -3779,40 +3778,12 @@ static void clear_mm_walk(void) kfree(walk); } -static bool inc_min_seq(struct lruvec *lruvec, int type, bool can_swap) +static void inc_min_seq(struct lruvec *lruvec, int type) { - int zone; - int remaining = MAX_LRU_BATCH; struct lru_gen_struct *lrugen = &lruvec->lrugen; - int new_gen, old_gen = lru_gen_from_seq(lrugen->min_seq[type]); - if (type == LRU_GEN_ANON && !can_swap) - goto done; - - /* prevent cold/hot inversion if force_scan is true */ - for (zone = 0; zone < MAX_NR_ZONES; zone++) { - struct list_head *head = &lrugen->lists[old_gen][type][zone]; - - while (!list_empty(head)) { - struct page *page = lru_to_page(head); - - VM_WARN_ON_ONCE_PAGE(PageUnevictable(page), page); - VM_WARN_ON_ONCE_PAGE(PageActive(page), page); - VM_WARN_ON_ONCE_PAGE(page_is_file_cache(page) != type, page); - VM_WARN_ON_ONCE_PAGE(page_zonenum(page) != zone, page); - - new_gen = page_inc_gen(lruvec, page, false); - list_move_tail(&page->lru, &lrugen->lists[new_gen][type][zone]); - - if (!--remaining) - return false; - } - } -done: reset_ctrl_pos(lruvec, type, true); WRITE_ONCE(lrugen->min_seq[type], lrugen->min_seq[type] + 1); - - return true; } static bool try_to_inc_min_seq(struct lruvec *lruvec, bool can_swap) @@ -3858,7 +3829,7 @@ next: return success; } -static void inc_max_seq(struct lruvec *lruvec, bool can_swap, bool force_scan) +static void inc_max_seq(struct lruvec *lruvec, bool can_swap) { int prev, next; int type, zone; @@ -3873,13 +3844,9 @@ static void inc_max_seq(struct lruvec *lruvec, bool can_swap, bool force_scan) if (get_nr_gens(lruvec, type) != MAX_NR_GENS) continue; - VM_WARN_ON_ONCE(!force_scan && (type == LRU_GEN_FILE || can_swap)); + VM_WARN_ON_ONCE(type == LRU_GEN_FILE || can_swap); - while (!inc_min_seq(lruvec, type, can_swap)) { - spin_unlock_irq(&pgdat->lru_lock); - cond_resched(); - spin_lock_irq(&pgdat->lru_lock); - } + inc_min_seq(lruvec, type); } /* @@ -3916,7 +3883,7 @@ static void inc_max_seq(struct lruvec *lruvec, bool can_swap, bool force_scan) } static bool try_to_inc_max_seq(struct lruvec *lruvec, unsigned long max_seq, - struct scan_control *sc, bool can_swap, bool force_scan) + struct scan_control *sc, bool can_swap) { bool success; struct lru_gen_mm_walk *walk; @@ -3937,7 +3904,7 @@ static bool try_to_inc_max_seq(struct lruvec *lruvec, unsigned long max_seq, * handful of PTEs. Spreading the work out over a period of time usually * is less efficient, but it avoids bursty page faults. */ - if (!force_scan && !(arch_has_hw_pte_young() && get_cap(LRU_GEN_MM_WALK))) { + if (!(arch_has_hw_pte_young() && get_cap(LRU_GEN_MM_WALK))) { success = iterate_mm_list_nowalk(lruvec, max_seq); goto done; } @@ -3951,7 +3918,7 @@ static bool try_to_inc_max_seq(struct lruvec *lruvec, unsigned long max_seq, walk->lruvec = lruvec; walk->max_seq = max_seq; walk->can_swap = can_swap; - walk->force_scan = force_scan; + walk->force_scan = false; do { success = iterate_mm_list(lruvec, walk, &mm); @@ -3971,7 +3938,7 @@ done: VM_WARN_ON_ONCE(max_seq != READ_ONCE(lrugen->max_seq)); - inc_max_seq(lruvec, can_swap, force_scan); + inc_max_seq(lruvec, can_swap); /* either this sees any waiters or they will see updated max_seq */ if (wq_has_sleeper(&lruvec->mm_state.wait)) wake_up_all(&lruvec->mm_state.wait); @@ -4066,7 +4033,7 @@ static bool age_lruvec(struct lruvec *lruvec, struct scan_control *sc, unsigned } if (need_aging) - try_to_inc_max_seq(lruvec, max_seq, sc, swappiness, false); + try_to_inc_max_seq(lruvec, max_seq, sc, swappiness); return true; } @@ -4614,7 +4581,7 @@ static unsigned long get_nr_to_scan(struct lruvec *lruvec, struct scan_control * if (current_is_kswapd()) return 0; - if (try_to_inc_max_seq(lruvec, max_seq, sc, can_swap, false)) + if (try_to_inc_max_seq(lruvec, max_seq, sc, can_swap)) return nr_to_scan; done: return min_seq[!can_swap] + MIN_NR_GENS <= max_seq ? nr_to_scan : 0; @@ -4953,361 +4920,6 @@ static struct attribute_group lru_gen_attr_group = { .attrs = lru_gen_attrs, }; -/****************************************************************************** - * debugfs interface - ******************************************************************************/ - -static void *lru_gen_seq_start(struct seq_file *m, loff_t *pos) -{ - struct mem_cgroup *memcg; - loff_t nr_to_skip = *pos; - - m->private = kvmalloc(PATH_MAX, GFP_KERNEL); - if (!m->private) - return ERR_PTR(-ENOMEM); - - memcg = mem_cgroup_iter(NULL, NULL, NULL); - do { - int nid; - - for_each_node_state(nid, N_MEMORY) { - if (!nr_to_skip--) - return get_lruvec(memcg, nid); - } - } while ((memcg = mem_cgroup_iter(NULL, memcg, NULL))); - - return NULL; -} - -static void lru_gen_seq_stop(struct seq_file *m, void *v) -{ - if (!IS_ERR_OR_NULL(v)) - mem_cgroup_iter_break(NULL, lruvec_memcg(v)); - - kvfree(m->private); - m->private = NULL; -} - -static void *lru_gen_seq_next(struct seq_file *m, void *v, loff_t *pos) -{ - int nid = lruvec_pgdat(v)->node_id; - struct mem_cgroup *memcg = lruvec_memcg(v); - - ++*pos; - - nid = next_memory_node(nid); - if (nid == MAX_NUMNODES) { - memcg = mem_cgroup_iter(NULL, memcg, NULL); - if (!memcg) - return NULL; - - nid = first_memory_node; - } - - return get_lruvec(memcg, nid); -} - -static void lru_gen_seq_show_full(struct seq_file *m, struct lruvec *lruvec, - unsigned long max_seq, unsigned long *min_seq, - unsigned long seq) -{ - int i; - int type, tier; - int hist = lru_hist_from_seq(seq); - struct lru_gen_struct *lrugen = &lruvec->lrugen; - - for (tier = 0; tier < MAX_NR_TIERS; tier++) { - seq_printf(m, " %10d", tier); - for (type = 0; type < ANON_AND_FILE; type++) { - const char *s = " "; - unsigned long n[3] = {}; - - if (seq == max_seq) { - s = "RT "; - n[0] = READ_ONCE(lrugen->avg_refaulted[type][tier]); - n[1] = READ_ONCE(lrugen->avg_total[type][tier]); - } else if (seq == min_seq[type] || NR_HIST_GENS > 1) { - s = "rep"; - n[0] = atomic_long_read(&lrugen->refaulted[hist][type][tier]); - n[1] = atomic_long_read(&lrugen->evicted[hist][type][tier]); - if (tier) - n[2] = READ_ONCE(lrugen->protected[hist][type][tier - 1]); - } - - for (i = 0; i < 3; i++) - seq_printf(m, " %10lu%c", n[i], s[i]); - } - seq_putc(m, '\n'); - } - - seq_puts(m, " "); - for (i = 0; i < NR_MM_STATS; i++) { - const char *s = " "; - unsigned long n = 0; - - if (seq == max_seq && NR_HIST_GENS == 1) { - s = "LOYNFA"; - n = READ_ONCE(lruvec->mm_state.stats[hist][i]); - } else if (seq != max_seq && NR_HIST_GENS > 1) { - s = "loynfa"; - n = READ_ONCE(lruvec->mm_state.stats[hist][i]); - } - - seq_printf(m, " %10lu%c", n, s[i]); - } - seq_putc(m, '\n'); -} - -static int lru_gen_seq_show(struct seq_file *m, void *v) -{ - unsigned long seq; - bool full = !debugfs_real_fops(m->file)->write; - struct lruvec *lruvec = v; - struct lru_gen_struct *lrugen = &lruvec->lrugen; - int nid = lruvec_pgdat(lruvec)->node_id; - struct mem_cgroup *memcg = lruvec_memcg(lruvec); - DEFINE_MAX_SEQ(lruvec); - DEFINE_MIN_SEQ(lruvec); - - if (nid == first_memory_node) { - const char *path = memcg ? m->private : ""; - -#ifdef CONFIG_MEMCG - if (memcg) - cgroup_path(memcg->css.cgroup, m->private, PATH_MAX); -#endif - seq_printf(m, "memcg %5hu %s\n", mem_cgroup_id(memcg), path); - } - - seq_printf(m, " node %5d\n", nid); - - if (!full) - seq = min_seq[LRU_GEN_ANON]; - else if (max_seq >= MAX_NR_GENS) - seq = max_seq - MAX_NR_GENS + 1; - else - seq = 0; - - for (; seq <= max_seq; seq++) { - int type, zone; - int gen = lru_gen_from_seq(seq); - unsigned long birth = READ_ONCE(lruvec->lrugen.timestamps[gen]); - - seq_printf(m, " %10lu %10u", seq, jiffies_to_msecs(jiffies - birth)); - - for (type = 0; type < ANON_AND_FILE; type++) { - unsigned long size = 0; - char mark = full && seq < min_seq[type] ? 'x' : ' '; - - for (zone = 0; zone < MAX_NR_ZONES; zone++) - size += max(READ_ONCE(lrugen->nr_pages[gen][type][zone]), 0L); - - seq_printf(m, " %10lu%c", size, mark); - } - - seq_putc(m, '\n'); - - if (full) - lru_gen_seq_show_full(m, lruvec, max_seq, min_seq, seq); - } - - return 0; -} - -static const struct seq_operations lru_gen_seq_ops = { - .start = lru_gen_seq_start, - .stop = lru_gen_seq_stop, - .next = lru_gen_seq_next, - .show = lru_gen_seq_show, -}; - -static int run_aging(struct lruvec *lruvec, unsigned long seq, struct scan_control *sc, - bool can_swap, bool force_scan) -{ - DEFINE_MAX_SEQ(lruvec); - DEFINE_MIN_SEQ(lruvec); - - if (seq < max_seq) - return 0; - - if (seq > max_seq) - return -EINVAL; - - if (!force_scan && min_seq[!can_swap] + MAX_NR_GENS - 1 <= max_seq) - return -ERANGE; - - try_to_inc_max_seq(lruvec, max_seq, sc, can_swap, force_scan); - - return 0; -} - -static int run_eviction(struct lruvec *lruvec, unsigned long seq, struct scan_control *sc, - int swappiness, unsigned long nr_to_reclaim) -{ - DEFINE_MAX_SEQ(lruvec); - - if (seq + MIN_NR_GENS > max_seq) - return -EINVAL; - - sc->nr_reclaimed = 0; - - while (!signal_pending(current)) { - DEFINE_MIN_SEQ(lruvec); - - if (seq < min_seq[!swappiness]) - return 0; - - if (sc->nr_reclaimed >= nr_to_reclaim) - return 0; - - if (!evict_pages(lruvec, sc, swappiness, NULL)) - return 0; - - cond_resched(); - } - - return -EINTR; -} - -static int run_cmd(char cmd, int memcg_id, int nid, unsigned long seq, - struct scan_control *sc, int swappiness, unsigned long opt) -{ - struct lruvec *lruvec; - int err = -EINVAL; - struct mem_cgroup *memcg = NULL; - - if (nid < 0 || nid >= MAX_NUMNODES || !node_state(nid, N_MEMORY)) - return -EINVAL; - - if (!mem_cgroup_disabled()) { - rcu_read_lock(); - memcg = mem_cgroup_from_id(memcg_id); -#ifdef CONFIG_MEMCG - if (memcg && !css_tryget(&memcg->css)) - memcg = NULL; -#endif - rcu_read_unlock(); - - if (!memcg) - return -EINVAL; - } - - if (memcg_id != mem_cgroup_id(memcg)) - goto done; - - lruvec = get_lruvec(memcg, nid); - - if (swappiness < 0) - swappiness = get_swappiness(lruvec, sc); - else if (swappiness > 200) - goto done; - - switch (cmd) { - case '+': - err = run_aging(lruvec, seq, sc, swappiness, opt); - break; - case '-': - err = run_eviction(lruvec, seq, sc, swappiness, opt); - break; - } -done: - mem_cgroup_put(memcg); - - return err; -} - -static ssize_t lru_gen_seq_write(struct file *file, const char __user *src, - size_t len, loff_t *pos) -{ - void *buf; - char *cur, *next; - unsigned int flags; - struct blk_plug plug; - int err = -EINVAL; - struct scan_control sc = { - .may_writepage = true, - .may_unmap = true, - .may_swap = true, - .reclaim_idx = MAX_NR_ZONES - 1, - .gfp_mask = GFP_KERNEL, - }; - - buf = kvmalloc(len + 1, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - if (copy_from_user(buf, src, len)) { - kvfree(buf); - return -EFAULT; - } - - set_task_reclaim_state(current, &sc.reclaim_state); - flags = memalloc_noreclaim_save(); - blk_start_plug(&plug); - if (!set_mm_walk(NULL)) { - err = -ENOMEM; - goto done; - } - - next = buf; - next[len] = '\0'; - - while ((cur = strsep(&next, ",;\n"))) { - int n; - int end; - char cmd; - unsigned int memcg_id; - unsigned int nid; - unsigned long seq; - unsigned int swappiness = -1; - unsigned long opt = -1; - - cur = skip_spaces(cur); - if (!*cur) - continue; - - n = sscanf(cur, "%c %u %u %lu %n %u %n %lu %n", &cmd, &memcg_id, &nid, - &seq, &end, &swappiness, &end, &opt, &end); - if (n < 4 || cur[end]) { - err = -EINVAL; - break; - } - - err = run_cmd(cmd, memcg_id, nid, seq, &sc, swappiness, opt); - if (err) - break; - } -done: - clear_mm_walk(); - blk_finish_plug(&plug); - memalloc_noreclaim_restore(flags); - set_task_reclaim_state(current, NULL); - - kvfree(buf); - - return err ? : len; -} - -static int lru_gen_seq_open(struct inode *inode, struct file *file) -{ - return seq_open(file, &lru_gen_seq_ops); -} - -static const struct file_operations lru_gen_rw_fops = { - .open = lru_gen_seq_open, - .read = seq_read, - .write = lru_gen_seq_write, - .llseek = seq_lseek, - .release = seq_release, -}; - -static const struct file_operations lru_gen_ro_fops = { - .open = lru_gen_seq_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release, -}; - /****************************************************************************** * initialization ******************************************************************************/ @@ -5365,9 +4977,6 @@ static int __init init_lru_gen(void) if (sysfs_create_group(mm_kobj, &lru_gen_attr_group)) pr_err("lru_gen: failed to create sysfs group\n"); - debugfs_create_file("lru_gen", 0644, NULL, NULL, &lru_gen_rw_fops); - debugfs_create_file("lru_gen_full", 0444, NULL, NULL, &lru_gen_ro_fops); - return 0; }; late_initcall(init_lru_gen); From 87feb49d9e028ad6c200763f56d07056724ead0e Mon Sep 17 00:00:00 2001 From: xiewen3 Date: Tue, 16 May 2023 22:42:40 +0800 Subject: [PATCH 581/698] LUR: Revert "UPSTREAM: mm: multi-gen LRU: thrashing prevention" The LRU function is not compatible with GKI, causing GKI to fail to start, so revert. This reverts commit 6e3eMontana0d3ac358919e87e47e5c8f2c4d66a1526. Change-Id: Ife5ed05ffbd20122a589c5d4d6a0c17cb1a11adb Reviewed-on: https://gerrit.mot.com/2609757 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- include/linux/mmzone.h | 2 -- mm/vmscan.c | 74 ++---------------------------------------- 2 files changed, 3 insertions(+), 73 deletions(-) diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index 4529fa06dad7..5a9c5192155b 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -416,8 +416,6 @@ struct lru_gen_struct { unsigned long max_seq; /* the eviction increments the oldest generation numbers */ unsigned long min_seq[ANON_AND_FILE]; - /* the birth time of each generation in jiffies */ - unsigned long timestamps[MAX_NR_GENS]; /* the multi-gen LRU lists, lazily sorted on eviction */ struct list_head lists[MAX_NR_GENS][ANON_AND_FILE][MAX_NR_ZONES]; /* the multi-gen LRU sizes, eventually consistent */ diff --git a/mm/vmscan.c b/mm/vmscan.c index 69c516cfd2c4..8304d81ab3ac 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -3875,7 +3875,6 @@ static void inc_max_seq(struct lruvec *lruvec, bool can_swap) for (type = 0; type < ANON_AND_FILE; type++) reset_ctrl_pos(lruvec, type, false); - WRITE_ONCE(lrugen->timestamps[next], jiffies); /* make sure preceding modifications appear */ smp_store_release(&lrugen->max_seq, lrugen->max_seq + 1); @@ -4003,7 +4002,7 @@ static bool should_run_aging(struct lruvec *lruvec, unsigned long max_seq, unsig return false; } -static bool age_lruvec(struct lruvec *lruvec, struct scan_control *sc, unsigned long min_ttl) +static void age_lruvec(struct lruvec *lruvec, struct scan_control *sc) { bool need_aging; unsigned long nr_to_scan; @@ -4016,36 +4015,16 @@ static bool age_lruvec(struct lruvec *lruvec, struct scan_control *sc, unsigned VM_WARN_ON_ONCE(sc->memcg_low_reclaim); if (prot == MEMCG_PROT_MIN) - return false; + return; need_aging = should_run_aging(lruvec, max_seq, min_seq, sc, swappiness, &nr_to_scan); - - if (min_ttl) { - int gen = lru_gen_from_seq(min_seq[LRU_GEN_FILE]); - unsigned long birth = READ_ONCE(lruvec->lrugen.timestamps[gen]); - - if (time_is_after_jiffies(birth + min_ttl)) - return false; - - /* the size is likely too small to be helpful */ - if (!nr_to_scan && sc->priority != DEF_PRIORITY) - return false; - } - if (need_aging) try_to_inc_max_seq(lruvec, max_seq, sc, swappiness); - - return true; } -/* to protect the working set of the last N jiffies */ -static unsigned long lru_gen_min_ttl __read_mostly; - static void lru_gen_age_node(struct pglist_data *pgdat, struct scan_control *sc) { struct mem_cgroup *memcg; - bool success = false; - unsigned long min_ttl = READ_ONCE(lru_gen_min_ttl); VM_WARN_ON_ONCE(!current_is_kswapd()); @@ -4068,32 +4047,12 @@ static void lru_gen_age_node(struct pglist_data *pgdat, struct scan_control *sc) do { struct lruvec *lruvec = mem_cgroup_lruvec(pgdat, memcg); - if (age_lruvec(lruvec, sc, min_ttl)) - success = true; + age_lruvec(lruvec, sc); cond_resched(); } while ((memcg = mem_cgroup_iter(NULL, memcg, NULL))); clear_mm_walk(); - - /* check the order to exclude compaction-induced reclaim */ - if (success || !min_ttl || sc->order) - return; - - /* - * The main goal is to OOM kill if every generation from all memcgs is - * younger than min_ttl. However, another possibility is all memcgs are - * either below min or empty. - */ - if (mutex_trylock(&oom_lock)) { - struct oom_control oc = { - .gfp_mask = sc->gfp_mask, - }; - - out_of_memory(&oc); - - mutex_unlock(&oom_lock); - } } /* @@ -4840,28 +4799,6 @@ unlock: * sysfs interface ******************************************************************************/ -static ssize_t show_min_ttl(struct kobject *kobj, struct kobj_attribute *attr, char *buf) -{ - return sprintf(buf, "%u\n", jiffies_to_msecs(READ_ONCE(lru_gen_min_ttl))); -} - -static ssize_t store_min_ttl(struct kobject *kobj, struct kobj_attribute *attr, - const char *buf, size_t len) -{ - unsigned int msecs; - - if (kstrtouint(buf, 0, &msecs)) - return -EINVAL; - - WRITE_ONCE(lru_gen_min_ttl, msecs_to_jiffies(msecs)); - - return len; -} - -static struct kobj_attribute lru_gen_min_ttl_attr = __ATTR( - min_ttl_ms, 0644, show_min_ttl, store_min_ttl -); - static ssize_t show_enabled(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { unsigned int caps = 0; @@ -4910,7 +4847,6 @@ static struct kobj_attribute lru_gen_enabled_attr = __ATTR( ); static struct attribute *lru_gen_attrs[] = { - &lru_gen_min_ttl_attr.attr, &lru_gen_enabled_attr.attr, NULL }; @@ -4926,16 +4862,12 @@ static struct attribute_group lru_gen_attr_group = { void lru_gen_init_lruvec(struct lruvec *lruvec) { - int i; int gen, type, zone; struct lru_gen_struct *lrugen = &lruvec->lrugen; lrugen->max_seq = MIN_NR_GENS + 1; lrugen->enabled = lru_gen_enabled(); - for (i = 0; i <= MIN_NR_GENS + 1; i++) - lrugen->timestamps[i] = jiffies; - for_each_gen_type_zone(gen, type, zone) INIT_LIST_HEAD(&lrugen->lists[gen][type][zone]); From c33afa41e2458d502e418adab085a1e0389be3fa Mon Sep 17 00:00:00 2001 From: xiewen3 Date: Tue, 16 May 2023 22:44:48 +0800 Subject: [PATCH 582/698] LUR: Revert "BACKPORT: mm: multi-gen LRU: optimize multiple memcgs" The LRU function is not compatible with GKI, causing GKI to fail to start, so revert. This reverts commit 1fe9a1daa5a17c0e3cd2580827620d7acf83a3ce. Change-Id: Ia0615a681415489bad60d6e6929e5e79d888d999 Reviewed-on: https://gerrit.mot.com/2609759 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- mm/vmscan.c | 104 +++++----------------------------------------------- 1 file changed, 9 insertions(+), 95 deletions(-) diff --git a/mm/vmscan.c b/mm/vmscan.c index 8304d81ab3ac..3c68054373d9 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -107,12 +107,6 @@ struct scan_control { /* One of the zones is ready for compaction */ unsigned int compaction_ready:1; -#ifdef CONFIG_LRU_GEN - /* help kswapd make better choices among multiple memcgs */ - unsigned int memcgs_need_aging:1; - unsigned long last_reclaimed; -#endif - /* Allocation order */ s8 order; @@ -4028,19 +4022,6 @@ static void lru_gen_age_node(struct pglist_data *pgdat, struct scan_control *sc) VM_WARN_ON_ONCE(!current_is_kswapd()); - sc->last_reclaimed = sc->nr_reclaimed; - - /* - * To reduce the chance of going into the aging path, which can be - * costly, optimistically skip it if the flag below was cleared in the - * eviction path. This improves the overall performance when multiple - * memcgs are available. - */ - if (!sc->memcgs_need_aging) { - sc->memcgs_need_aging = true; - return; - } - set_mm_walk(pgdat); memcg = mem_cgroup_iter(NULL, NULL, NULL); @@ -4447,8 +4428,7 @@ static int isolate_pages(struct lruvec *lruvec, struct scan_control *sc, int swa return scanned; } -static int evict_pages(struct lruvec *lruvec, struct scan_control *sc, int swappiness, - bool *need_swapping) +static int evict_pages(struct lruvec *lruvec, struct scan_control *sc, int swappiness) { int type; int scanned; @@ -4510,9 +4490,6 @@ static int evict_pages(struct lruvec *lruvec, struct scan_control *sc, int swapp sc->nr_reclaimed += reclaimed; - if (need_swapping && type == LRU_GEN_ANON) - *need_swapping = true; - return scanned; } @@ -4522,14 +4499,15 @@ static int evict_pages(struct lruvec *lruvec, struct scan_control *sc, int swapp * reclaim. */ static unsigned long get_nr_to_scan(struct lruvec *lruvec, struct scan_control *sc, - bool can_swap, bool *need_aging) + bool can_swap) { + bool need_aging; unsigned long nr_to_scan; DEFINE_MAX_SEQ(lruvec); DEFINE_MIN_SEQ(lruvec); - *need_aging = should_run_aging(lruvec, max_seq, min_seq, sc, can_swap, &nr_to_scan); - if (!*need_aging) + need_aging = should_run_aging(lruvec, max_seq, min_seq, sc, can_swap, &nr_to_scan); + if (!need_aging) return nr_to_scan; /* skip the aging path at the default priority */ @@ -4546,67 +4524,10 @@ done: return min_seq[!can_swap] + MIN_NR_GENS <= max_seq ? nr_to_scan : 0; } -static bool should_abort_scan(struct lruvec *lruvec, unsigned long seq, - struct scan_control *sc, bool need_swapping) -{ - int i; - DEFINE_MAX_SEQ(lruvec); - - if (!current_is_kswapd()) { - /* age each memcg at most once to ensure fairness */ - if (max_seq - seq > 1) - return true; - - /* over-swapping can increase allocation latency */ - if (sc->nr_reclaimed >= sc->nr_to_reclaim && need_swapping) - return true; - - /* give this thread a chance to exit and free its memory */ - if (fatal_signal_pending(current)) { - sc->nr_reclaimed += MIN_LRU_BATCH; - return true; - } - - if (!global_reclaim(sc)) - return false; - } else if (sc->nr_reclaimed - sc->last_reclaimed < sc->nr_to_reclaim) - return false; - - /* keep scanning at low priorities to ensure fairness */ - if (sc->priority > DEF_PRIORITY - 2) - return false; - - /* - * A minimum amount of work was done under global memory pressure. For - * kswapd, it may be overshooting. For direct reclaim, the allocation - * may succeed if all suitable zones are somewhat safe. In either case, - * it's better to stop now, and restart later if necessary. - */ - for (i = 0; i <= sc->reclaim_idx; i++) { - unsigned long wmark; - struct zone *zone = lruvec_pgdat(lruvec)->node_zones + i; - - if (!managed_zone(zone)) - continue; - - wmark = current_is_kswapd() ? high_wmark_pages(zone) : low_wmark_pages(zone); - if (wmark > zone_page_state(zone, NR_FREE_PAGES)) - return false; - } - - sc->nr_reclaimed += MIN_LRU_BATCH; - - return true; -} - static void lru_gen_shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc) { struct blk_plug plug; - bool need_aging = false; - bool need_swapping = false; unsigned long scanned = 0; - unsigned long reclaimed = sc->nr_reclaimed; - DEFINE_MAX_SEQ(lruvec); lru_add_drain(); @@ -4626,28 +4547,21 @@ static void lru_gen_shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc else swappiness = 0; - nr_to_scan = get_nr_to_scan(lruvec, sc, swappiness, &need_aging); + nr_to_scan = get_nr_to_scan(lruvec, sc, swappiness); if (!nr_to_scan) - goto done; + break; - delta = evict_pages(lruvec, sc, swappiness, &need_swapping); + delta = evict_pages(lruvec, sc, swappiness); if (!delta) - goto done; + break; scanned += delta; if (scanned >= nr_to_scan) break; - if (should_abort_scan(lruvec, max_seq, sc, need_swapping)) - break; - cond_resched(); } - /* see the comment in lru_gen_age_node() */ - if (sc->nr_reclaimed - reclaimed >= MIN_LRU_BATCH && !need_aging) - sc->memcgs_need_aging = false; -done: clear_mm_walk(); blk_finish_plug(&plug); From bff8c1b3e76640c2a9db783d4e1fb804a916a2cd Mon Sep 17 00:00:00 2001 From: xiewen3 Date: Tue, 16 May 2023 22:43:43 +0800 Subject: [PATCH 583/698] LUR: Revert "BACKPORT: mm: multi-gen LRU: kill switch" The LRU function is not compatible with GKI, causing GKI to fail to start, so revert. This reverts commit 16dc2574dd742a5a27f2588601d5b646175f45ba. Change-Id: Idfece6dedd466ebc4f58ebfccd9ba9f59494466e Reviewed-on: https://gerrit.mot.com/2609758 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- include/linux/cgroup.h | 15 +-- include/linux/mm_inline.h | 15 +-- include/linux/mmzone.h | 9 -- kernel/cgroup/cgroup-internal.h | 1 + mm/Kconfig | 6 - mm/vmscan.c | 229 +------------------------------- 6 files changed, 9 insertions(+), 266 deletions(-) diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h index 3933ddd082e9..bf290358507c 100644 --- a/include/linux/cgroup.h +++ b/include/linux/cgroup.h @@ -428,18 +428,6 @@ static inline void cgroup_put(struct cgroup *cgrp) css_put(&cgrp->self); } -extern struct mutex cgroup_mutex; - -static inline void cgroup_lock(void) -{ - mutex_lock(&cgroup_mutex); -} - -static inline void cgroup_unlock(void) -{ - mutex_unlock(&cgroup_mutex); -} - /** * task_css_set_check - obtain a task's css_set with extra access conditions * @task: the task to obtain css_set for @@ -454,6 +442,7 @@ static inline void cgroup_unlock(void) * as locks used during the cgroup_subsys::attach() methods. */ #ifdef CONFIG_PROVE_RCU +extern struct mutex cgroup_mutex; extern spinlock_t css_set_lock; #define task_css_set_check(task, __c) \ rcu_dereference_check((task)->cgroups, \ @@ -718,8 +707,6 @@ struct cgroup; static inline void css_get(struct cgroup_subsys_state *css) {} static inline void css_put(struct cgroup_subsys_state *css) {} -static inline void cgroup_lock(void) {} -static inline void cgroup_unlock(void) {} static inline int cgroup_attach_task_all(struct task_struct *from, struct task_struct *t) { return 0; } static inline int cgroupstats_build(struct cgroupstats *stats, diff --git a/include/linux/mm_inline.h b/include/linux/mm_inline.h index 663dc926dbac..64b33e79165b 100644 --- a/include/linux/mm_inline.h +++ b/include/linux/mm_inline.h @@ -105,21 +105,10 @@ static __always_inline enum lru_list page_lru(struct page *page) #ifdef CONFIG_LRU_GEN -#ifdef CONFIG_LRU_GEN_ENABLED static inline bool lru_gen_enabled(void) { - DECLARE_STATIC_KEY_TRUE(lru_gen_caps[NR_LRU_GEN_CAPS]); - - return static_branch_likely(&lru_gen_caps[LRU_GEN_CORE]); + return true; } -#else -static inline bool lru_gen_enabled(void) -{ - DECLARE_STATIC_KEY_FALSE(lru_gen_caps[NR_LRU_GEN_CAPS]); - - return static_branch_unlikely(&lru_gen_caps[LRU_GEN_CORE]); -} -#endif static inline bool lru_gen_in_fault(void) { @@ -232,7 +221,7 @@ static inline bool lru_gen_add_page(struct lruvec *lruvec, struct page *page, bo VM_WARN_ON_ONCE_PAGE(gen != -1, page); - if (PageUnevictable(page) || !lrugen->enabled) + if (PageUnevictable(page)) return false; /* * There are three common cases for this page: diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index 5a9c5192155b..f4fb963c963e 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -381,13 +381,6 @@ enum { LRU_GEN_FILE, }; -enum { - LRU_GEN_CORE, - LRU_GEN_MM_WALK, - LRU_GEN_NONLEAF_YOUNG, - NR_LRU_GEN_CAPS -}; - #define MIN_LRU_BATCH BITS_PER_LONG #define MAX_LRU_BATCH (MIN_LRU_BATCH * 64) @@ -429,8 +422,6 @@ struct lru_gen_struct { /* can be modified without holding the LRU lock */ atomic_long_t evicted[NR_HIST_GENS][ANON_AND_FILE][MAX_NR_TIERS]; atomic_long_t refaulted[NR_HIST_GENS][ANON_AND_FILE][MAX_NR_TIERS]; - /* whether the multi-gen LRU is enabled */ - bool enabled; }; enum { diff --git a/kernel/cgroup/cgroup-internal.h b/kernel/cgroup/cgroup-internal.h index ec985923f7c8..803989eae99e 100644 --- a/kernel/cgroup/cgroup-internal.h +++ b/kernel/cgroup/cgroup-internal.h @@ -165,6 +165,7 @@ struct cgroup_mgctx { #define DEFINE_CGROUP_MGCTX(name) \ struct cgroup_mgctx name = CGROUP_MGCTX_INIT(name) +extern struct mutex cgroup_mutex; extern spinlock_t css_set_lock; extern struct cgroup_subsys *cgroup_subsys[]; extern struct list_head cgroup_roots; diff --git a/mm/Kconfig b/mm/Kconfig index b96975666710..5f7638bc90e4 100644 --- a/mm/Kconfig +++ b/mm/Kconfig @@ -865,12 +865,6 @@ config LRU_GEN help A high performance LRU implementation to overcommit memory. -config LRU_GEN_ENABLED - bool "Enable by default" - depends on LRU_GEN - help - This option enables the multi-gen LRU by default. - config LRU_GEN_STATS bool "Full stats for debugging" depends on LRU_GEN diff --git a/mm/vmscan.c b/mm/vmscan.c index 3c68054373d9..cdf2aded13e9 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -53,7 +53,6 @@ #include #include #include -#include #include #include @@ -2641,14 +2640,6 @@ out: #ifdef CONFIG_LRU_GEN -#ifdef CONFIG_LRU_GEN_ENABLED -DEFINE_STATIC_KEY_ARRAY_TRUE(lru_gen_caps, NR_LRU_GEN_CAPS); -#define get_cap(cap) static_branch_likely(&lru_gen_caps[cap]) -#else -DEFINE_STATIC_KEY_ARRAY_FALSE(lru_gen_caps, NR_LRU_GEN_CAPS); -#define get_cap(cap) static_branch_unlikely(&lru_gen_caps[cap]) -#endif - /****************************************************************************** * shorthand helpers ******************************************************************************/ @@ -3527,8 +3518,7 @@ static void walk_pmd_range_locked(pud_t *pud, unsigned long next, struct vm_area goto next; if (!pmd_trans_huge(pmd[i])) { - if (IS_ENABLED(CONFIG_ARCH_HAS_NONLEAF_PMD_YOUNG) && - get_cap(LRU_GEN_NONLEAF_YOUNG)) + if (IS_ENABLED(CONFIG_ARCH_HAS_NONLEAF_PMD_YOUNG)) pmdp_test_and_clear_young(vma, addr, pmd + i); goto next; } @@ -3627,12 +3617,10 @@ restart: walk->mm_stats[MM_NONLEAF_TOTAL]++; #ifdef CONFIG_ARCH_HAS_NONLEAF_PMD_YOUNG - if (get_cap(LRU_GEN_NONLEAF_YOUNG)) { - if (!pmd_young(val)) - continue; + if (!pmd_young(val)) + continue; - walk_pmd_range_locked(pud, addr, vma, args, bitmap, &pos); - } + walk_pmd_range_locked(pud, addr, vma, args, bitmap, &pos); #endif if (!walk->force_scan && !test_bloom_filter(walk->lruvec, walk->max_seq, pmd + i)) continue; @@ -3897,7 +3885,7 @@ static bool try_to_inc_max_seq(struct lruvec *lruvec, unsigned long max_seq, * handful of PTEs. Spreading the work out over a period of time usually * is less efficient, but it avoids bursty page faults. */ - if (!(arch_has_hw_pte_young() && get_cap(LRU_GEN_MM_WALK))) { + if (!arch_has_hw_pte_young()) { success = iterate_mm_list_nowalk(lruvec, max_seq); goto done; } @@ -4567,209 +4555,6 @@ static void lru_gen_shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc blk_finish_plug(&plug); } -/****************************************************************************** - * state change - ******************************************************************************/ - -static bool __maybe_unused state_is_valid(struct lruvec *lruvec) -{ - struct lru_gen_struct *lrugen = &lruvec->lrugen; - - if (lrugen->enabled) { - enum lru_list lru; - - for_each_evictable_lru(lru) { - if (!list_empty(&lruvec->lists[lru])) - return false; - } - } else { - int gen, type, zone; - - for_each_gen_type_zone(gen, type, zone) { - if (!list_empty(&lrugen->lists[gen][type][zone])) - return false; - } - } - - return true; -} - -static bool fill_evictable(struct lruvec *lruvec) -{ - enum lru_list lru; - int remaining = MAX_LRU_BATCH; - - for_each_evictable_lru(lru) { - int type = is_file_lru(lru); - bool active = is_active_lru(lru); - struct list_head *head = &lruvec->lists[lru]; - - while (!list_empty(head)) { - bool success; - struct page *page = lru_to_page(head); - - VM_WARN_ON_ONCE_PAGE(PageUnevictable(page), page); - VM_WARN_ON_ONCE_PAGE(PageActive(page) != active, page); - VM_WARN_ON_ONCE_PAGE(page_is_file_cache(page) != type, page); - VM_WARN_ON_ONCE_PAGE(page_lru_gen(page) != -1, page); - - del_page_from_lru_list(page, lruvec); - success = lru_gen_add_page(lruvec, page, false); - VM_WARN_ON_ONCE(!success); - - if (!--remaining) - return false; - } - } - - return true; -} - -static bool drain_evictable(struct lruvec *lruvec) -{ - int gen, type, zone; - int remaining = MAX_LRU_BATCH; - - for_each_gen_type_zone(gen, type, zone) { - struct list_head *head = &lruvec->lrugen.lists[gen][type][zone]; - - while (!list_empty(head)) { - bool success; - struct page *page = lru_to_page(head); - - VM_WARN_ON_ONCE_PAGE(PageUnevictable(page), page); - VM_WARN_ON_ONCE_PAGE(PageActive(page), page); - VM_WARN_ON_ONCE_PAGE(page_is_file_cache(page) != type, page); - VM_WARN_ON_ONCE_PAGE(page_zonenum(page) != zone, page); - - success = lru_gen_del_page(lruvec, page, false); - VM_WARN_ON_ONCE(!success); - add_page_to_lru_list(page, lruvec); - - if (!--remaining) - return false; - } - } - - return true; -} - -static void lru_gen_change_state(bool enabled) -{ - static DEFINE_MUTEX(state_mutex); - - struct mem_cgroup *memcg; - - cgroup_lock(); - cpus_read_lock(); - get_online_mems(); - mutex_lock(&state_mutex); - - if (enabled == lru_gen_enabled()) - goto unlock; - - if (enabled) - static_branch_enable_cpuslocked(&lru_gen_caps[LRU_GEN_CORE]); - else - static_branch_disable_cpuslocked(&lru_gen_caps[LRU_GEN_CORE]); - - memcg = mem_cgroup_iter(NULL, NULL, NULL); - do { - int nid; - - for_each_node(nid) { - struct pglist_data *pgdat = NODE_DATA(nid); - struct lruvec *lruvec = get_lruvec(memcg, nid); - - if (!lruvec) - continue; - - spin_lock_irq(&pgdat->lru_lock); - - VM_WARN_ON_ONCE(!seq_is_valid(lruvec)); - VM_WARN_ON_ONCE(!state_is_valid(lruvec)); - - lruvec->lrugen.enabled = enabled; - - while (!(enabled ? fill_evictable(lruvec) : drain_evictable(lruvec))) { - spin_unlock_irq(&pgdat->lru_lock); - cond_resched(); - spin_lock_irq(&pgdat->lru_lock); - } - - spin_unlock_irq(&pgdat->lru_lock); - } - - cond_resched(); - } while ((memcg = mem_cgroup_iter(NULL, memcg, NULL))); -unlock: - mutex_unlock(&state_mutex); - put_online_mems(); - cpus_read_unlock(); - cgroup_unlock(); -} - -/****************************************************************************** - * sysfs interface - ******************************************************************************/ - -static ssize_t show_enabled(struct kobject *kobj, struct kobj_attribute *attr, char *buf) -{ - unsigned int caps = 0; - - if (get_cap(LRU_GEN_CORE)) - caps |= BIT(LRU_GEN_CORE); - - if (arch_has_hw_pte_young() && get_cap(LRU_GEN_MM_WALK)) - caps |= BIT(LRU_GEN_MM_WALK); - - if (IS_ENABLED(CONFIG_ARCH_HAS_NONLEAF_PMD_YOUNG) && get_cap(LRU_GEN_NONLEAF_YOUNG)) - caps |= BIT(LRU_GEN_NONLEAF_YOUNG); - - return snprintf(buf, PAGE_SIZE, "0x%04x\n", caps); -} - -static ssize_t store_enabled(struct kobject *kobj, struct kobj_attribute *attr, - const char *buf, size_t len) -{ - int i; - unsigned int caps; - - if (tolower(*buf) == 'n') - caps = 0; - else if (tolower(*buf) == 'y') - caps = -1; - else if (kstrtouint(buf, 0, &caps)) - return -EINVAL; - - for (i = 0; i < NR_LRU_GEN_CAPS; i++) { - bool enabled = caps & BIT(i); - - if (i == LRU_GEN_CORE) - lru_gen_change_state(enabled); - else if (enabled) - static_branch_enable(&lru_gen_caps[i]); - else - static_branch_disable(&lru_gen_caps[i]); - } - - return len; -} - -static struct kobj_attribute lru_gen_enabled_attr = __ATTR( - enabled, 0644, show_enabled, store_enabled -); - -static struct attribute *lru_gen_attrs[] = { - &lru_gen_enabled_attr.attr, - NULL -}; - -static struct attribute_group lru_gen_attr_group = { - .name = "lru_gen", - .attrs = lru_gen_attrs, -}; - /****************************************************************************** * initialization ******************************************************************************/ @@ -4780,7 +4565,6 @@ void lru_gen_init_lruvec(struct lruvec *lruvec) struct lru_gen_struct *lrugen = &lruvec->lrugen; lrugen->max_seq = MIN_NR_GENS + 1; - lrugen->enabled = lru_gen_enabled(); for_each_gen_type_zone(gen, type, zone) INIT_LIST_HEAD(&lrugen->lists[gen][type][zone]); @@ -4820,9 +4604,6 @@ static int __init init_lru_gen(void) BUILD_BUG_ON(MIN_NR_GENS + 1 >= MAX_NR_GENS); BUILD_BUG_ON(BIT(LRU_GEN_WIDTH) <= MAX_NR_GENS); - if (sysfs_create_group(mm_kobj, &lru_gen_attr_group)) - pr_err("lru_gen: failed to create sysfs group\n"); - return 0; }; late_initcall(init_lru_gen); From 09002348efa99b5c5fbd2788c7bc2fea558bcf6c Mon Sep 17 00:00:00 2001 From: xiewen3 Date: Tue, 16 May 2023 22:45:54 +0800 Subject: [PATCH 584/698] LUR: Revert "BACKPORT: mm: multi-gen LRU: support page table walks" The LRU function is not compatible with GKI, causing GKI to fail to start, so revert. This reverts commit 343d9750c00d2df4b962a32e2e1a8472b0fc09d5. Change-Id: I9149a4752ca1b2501c85d37ba75507e42fc8b9bf Reviewed-on: https://gerrit.mot.com/2609760 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- fs/exec.c | 2 - include/linux/memcontrol.h | 5 - include/linux/mm.h | 5 - include/linux/mm_types.h | 78 --- include/linux/mmzone.h | 56 +- include/linux/swap.h | 4 - kernel/exit.c | 1 - kernel/fork.c | 9 - kernel/sched/core.c | 1 - mm/memcontrol.c | 25 - mm/memory.c | 5 + mm/vmscan.c | 1011 +----------------------------------- 12 files changed, 22 insertions(+), 1180 deletions(-) diff --git a/fs/exec.c b/fs/exec.c index 1969aa7eee21..6860cd572e17 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -1047,7 +1047,6 @@ static int exec_mmap(struct mm_struct *mm) active_mm = tsk->active_mm; tsk->active_mm = mm; tsk->mm = mm; - lru_gen_add_mm(mm); /* * This prevents preemption while active_mm is being loaded and * it and mm are being updated, which could cause problems for @@ -1063,7 +1062,6 @@ static int exec_mmap(struct mm_struct *mm) tsk->mm->vmacache_seqnum = 0; vmacache_flush(tsk); task_unlock(tsk); - lru_gen_use_mm(mm); if (old_mm) { up_read(&old_mm->mmap_sem); BUG_ON(active_mm != old_mm); diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h index e796f3440fc3..45709b7bef1a 100644 --- a/include/linux/memcontrol.h +++ b/include/linux/memcontrol.h @@ -334,11 +334,6 @@ struct mem_cgroup { struct deferred_split deferred_split_queue; #endif -#ifdef CONFIG_LRU_GEN - /* per-memcg mm_struct list */ - struct lru_gen_mm_list mm_list; -#endif - struct mem_cgroup_per_node *nodeinfo[0]; /* WARNING: nodeinfo must be the last member here */ }; diff --git a/include/linux/mm.h b/include/linux/mm.h index 080da96a4566..0389ca4f7c3f 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -584,11 +584,6 @@ static inline bool vma_is_anonymous(struct vm_area_struct *vma) return !vma->vm_ops; } -static inline bool vma_is_accessible(struct vm_area_struct *vma) -{ - return vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE); -} - #ifdef CONFIG_SHMEM /* * The vma_is_shmem is not inline because it is used only by slow diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h index 0cfd5bd73d1d..32f9f55f2868 100644 --- a/include/linux/mm_types.h +++ b/include/linux/mm_types.h @@ -546,24 +546,6 @@ struct mm_struct { atomic_long_t hugetlb_usage; #endif struct work_struct async_put_work; -#ifdef CONFIG_LRU_GEN - struct { - /* this mm_struct is on lru_gen_mm_list */ - struct list_head list; - /* - * Set when switching to this mm_struct, as a hint of - * whether it has been used since the last time per-node - * page table walkers cleared the corresponding bits. - */ - unsigned long bitmap; -#ifdef CONFIG_MEMCG - /* points to the memcg of "owner" above */ - struct mem_cgroup *memcg; -#endif - } lru_gen; -#endif /* CONFIG_LRU_GEN */ - - ANDROID_KABI_RESERVE(1); ANDROID_VENDOR_DATA(1); } __randomize_layout; @@ -591,66 +573,6 @@ static inline cpumask_t *mm_cpumask(struct mm_struct *mm) return (struct cpumask *)&mm->cpu_bitmap; } -#ifdef CONFIG_LRU_GEN - -struct lru_gen_mm_list { - /* mm_struct list for page table walkers */ - struct list_head fifo; - /* protects the list above */ - spinlock_t lock; -}; - -void lru_gen_add_mm(struct mm_struct *mm); -void lru_gen_del_mm(struct mm_struct *mm); -#ifdef CONFIG_MEMCG -void lru_gen_migrate_mm(struct mm_struct *mm); -#endif - -static inline void lru_gen_init_mm(struct mm_struct *mm) -{ - INIT_LIST_HEAD(&mm->lru_gen.list); - mm->lru_gen.bitmap = 0; -#ifdef CONFIG_MEMCG - mm->lru_gen.memcg = NULL; -#endif -} - -static inline void lru_gen_use_mm(struct mm_struct *mm) -{ - /* - * When the bitmap is set, page reclaim knows this mm_struct has been - * used since the last time it cleared the bitmap. So it might be worth - * walking the page tables of this mm_struct to clear the accessed bit. - */ - WRITE_ONCE(mm->lru_gen.bitmap, -1); -} - -#else /* !CONFIG_LRU_GEN */ - -static inline void lru_gen_add_mm(struct mm_struct *mm) -{ -} - -static inline void lru_gen_del_mm(struct mm_struct *mm) -{ -} - -#ifdef CONFIG_MEMCG -static inline void lru_gen_migrate_mm(struct mm_struct *mm) -{ -} -#endif - -static inline void lru_gen_init_mm(struct mm_struct *mm) -{ -} - -static inline void lru_gen_use_mm(struct mm_struct *mm) -{ -} - -#endif /* CONFIG_LRU_GEN */ - struct mmu_gather; extern void tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned long start, unsigned long end); diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index f4fb963c963e..4d6a1cff0e70 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -402,7 +402,7 @@ enum { * min_seq behind. * * The number of pages in each generation is eventually consistent and therefore - * can be transiently negative when reset_batch_size() is pending. + * can be transiently negative. */ struct lru_gen_struct { /* the aging increments the youngest generation number */ @@ -424,53 +424,6 @@ struct lru_gen_struct { atomic_long_t refaulted[NR_HIST_GENS][ANON_AND_FILE][MAX_NR_TIERS]; }; -enum { - MM_LEAF_TOTAL, /* total leaf entries */ - MM_LEAF_OLD, /* old leaf entries */ - MM_LEAF_YOUNG, /* young leaf entries */ - MM_NONLEAF_TOTAL, /* total non-leaf entries */ - MM_NONLEAF_FOUND, /* non-leaf entries found in Bloom filters */ - MM_NONLEAF_ADDED, /* non-leaf entries added to Bloom filters */ - NR_MM_STATS -}; - -/* double-buffering Bloom filters */ -#define NR_BLOOM_FILTERS 2 - -struct lru_gen_mm_state { - /* set to max_seq after each iteration */ - unsigned long seq; - /* where the current iteration continues (inclusive) */ - struct list_head *head; - /* where the last iteration ended (exclusive) */ - struct list_head *tail; - /* to wait for the last page table walker to finish */ - struct wait_queue_head wait; - /* Bloom filters flip after each iteration */ - unsigned long *filters[NR_BLOOM_FILTERS]; - /* the mm stats for debugging */ - unsigned long stats[NR_HIST_GENS][NR_MM_STATS]; - /* the number of concurrent page table walkers */ - int nr_walkers; -}; - -struct lru_gen_mm_walk { - /* the lruvec under reclaim */ - struct lruvec *lruvec; - /* unstable max_seq from lru_gen_struct */ - unsigned long max_seq; - /* the next address within an mm to scan */ - unsigned long next_addr; - /* to batch promoted pages */ - int nr_pages[MAX_NR_GENS][ANON_AND_FILE][MAX_NR_ZONES]; - /* to batch the mm stats */ - int mm_stats[NR_MM_STATS]; - /* total batched items */ - int batched; - bool can_swap; - bool force_scan; -}; - void lru_gen_init_lruvec(struct lruvec *lruvec); void lru_gen_look_around(struct page_vma_mapped_walk *pvmw); @@ -511,8 +464,6 @@ struct lruvec { #ifdef CONFIG_LRU_GEN /* evictable pages divided into generations */ struct lru_gen_struct lrugen; - /* to concurrently iterate lru_gen_mm_list */ - struct lru_gen_mm_state mm_state; #endif #ifdef CONFIG_MEMCG struct pglist_data *pgdat; @@ -1003,11 +954,6 @@ typedef struct pglist_data { unsigned long flags; -#ifdef CONFIG_LRU_GEN - /* kswap mm walk data */ - struct lru_gen_mm_walk mm_walk; -#endif - ZONE_PADDING(_pad2_) /* Per-node vmstats */ diff --git a/include/linux/swap.h b/include/linux/swap.h index df8c42d861d1..0cc833d21ce2 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h @@ -130,10 +130,6 @@ union swap_header { */ struct reclaim_state { unsigned long reclaimed_slab; -#ifdef CONFIG_LRU_GEN - /* per-thread mm walk data */ - struct lru_gen_mm_walk *mm_walk; -#endif }; #ifdef __KERNEL__ diff --git a/kernel/exit.c b/kernel/exit.c index 5cb9e73cd231..f286f432869d 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -470,7 +470,6 @@ assign_new_owner: goto retry; } WRITE_ONCE(mm->owner, c); - lru_gen_migrate_mm(mm); task_unlock(c); put_task_struct(c); } diff --git a/kernel/fork.c b/kernel/fork.c index 742672fb434d..74f6f5e26ee4 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -1104,7 +1104,6 @@ static struct mm_struct *mm_init(struct mm_struct *mm, struct task_struct *p, goto fail_nocontext; mm->user_ns = get_user_ns(user_ns); - lru_gen_init_mm(mm); return mm; fail_nocontext: @@ -1147,7 +1146,6 @@ static inline void __mmput(struct mm_struct *mm) } if (mm->binfmt) module_put(mm->binfmt->module); - lru_gen_del_mm(mm); mmdrop(mm); } @@ -2459,13 +2457,6 @@ long _do_fork(struct kernel_clone_args *args) get_task_struct(p); } - if (IS_ENABLED(CONFIG_LRU_GEN) && !(clone_flags & CLONE_VM)) { - /* lock the task to synchronize with memcg migration */ - task_lock(p); - lru_gen_add_mm(p->mm); - task_unlock(p); - } - wake_up_new_task(p); /* forking complete and child started to run, tell ptracer */ diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 240c885a4a63..82c12f4d588d 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -3614,7 +3614,6 @@ context_switch(struct rq *rq, struct task_struct *prev, * finish_task_switch()'s mmdrop(). */ switch_mm_irqs_off(prev->active_mm, next->mm, next); - lru_gen_use_mm(next->mm); if (!prev->mm) { // from kernel /* will mmdrop() in finish_task_switch(). */ diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 07550b3145e4..e9caf18e133c 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -6072,30 +6072,6 @@ static void mem_cgroup_move_task(void) } #endif -#ifdef CONFIG_LRU_GEN -static void mem_cgroup_attach(struct cgroup_taskset *tset) -{ - struct task_struct *task; - struct cgroup_subsys_state *css; - - /* find the first leader if there is any */ - cgroup_taskset_for_each_leader(task, css, tset) - break; - - if (!task) - return; - - task_lock(task); - if (task->mm && READ_ONCE(task->mm->owner) == task) - lru_gen_migrate_mm(task->mm); - task_unlock(task); -} -#else -static void mem_cgroup_attach(struct cgroup_taskset *tset) -{ -} -#endif /* CONFIG_LRU_GEN */ - /* * Cgroup retains root cgroups across [un]mount cycles making it necessary * to verify whether we're attached to the default hierarchy on each mount @@ -6396,7 +6372,6 @@ struct cgroup_subsys memory_cgrp_subsys = { .css_free = mem_cgroup_css_free, .css_reset = mem_cgroup_css_reset, .can_attach = mem_cgroup_can_attach, - .attach = mem_cgroup_attach, .cancel_attach = mem_cgroup_cancel_attach, .post_attach = mem_cgroup_move_task, .bind = mem_cgroup_bind, diff --git a/mm/memory.c b/mm/memory.c index 95c5937f2050..63d684cf3f8d 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -4158,6 +4158,11 @@ static inline vm_fault_t wp_huge_pmd(struct vm_fault *vmf, pmd_t orig_pmd) return VM_FAULT_FALLBACK; } +static inline bool vma_is_accessible(struct vm_area_struct *vma) +{ + return vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE); +} + static vm_fault_t create_huge_pud(struct vm_fault *vmf) { #ifdef CONFIG_TRANSPARENT_HUGEPAGE diff --git a/mm/vmscan.c b/mm/vmscan.c index cdf2aded13e9..c6e98e805bf5 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -51,8 +51,6 @@ #include #include #include -#include -#include #include #include @@ -2660,7 +2658,7 @@ out: for ((type) = 0; (type) < ANON_AND_FILE; (type)++) \ for ((zone) = 0; (zone) < MAX_NR_ZONES; (zone)++) -static struct lruvec *get_lruvec(struct mem_cgroup *memcg, int nid) +static struct lruvec __maybe_unused *get_lruvec(struct mem_cgroup *memcg, int nid) { struct pglist_data *pgdat = NODE_DATA(nid); @@ -2703,371 +2701,6 @@ static bool __maybe_unused seq_is_valid(struct lruvec *lruvec) get_nr_gens(lruvec, LRU_GEN_ANON) <= MAX_NR_GENS; } -/****************************************************************************** - * mm_struct list - ******************************************************************************/ - -static struct lru_gen_mm_list *get_mm_list(struct mem_cgroup *memcg) -{ - static struct lru_gen_mm_list mm_list = { - .fifo = LIST_HEAD_INIT(mm_list.fifo), - .lock = __SPIN_LOCK_UNLOCKED(mm_list.lock), - }; - -#ifdef CONFIG_MEMCG - if (memcg) - return &memcg->mm_list; -#endif - VM_WARN_ON_ONCE(!mem_cgroup_disabled()); - - return &mm_list; -} - -void lru_gen_add_mm(struct mm_struct *mm) -{ - int nid; - struct mem_cgroup *memcg = get_mem_cgroup_from_mm(mm); - struct lru_gen_mm_list *mm_list = get_mm_list(memcg); - - VM_WARN_ON_ONCE(!list_empty(&mm->lru_gen.list)); -#ifdef CONFIG_MEMCG - VM_WARN_ON_ONCE(mm->lru_gen.memcg); - mm->lru_gen.memcg = memcg; -#endif - spin_lock(&mm_list->lock); - - for_each_node_state(nid, N_MEMORY) { - struct lruvec *lruvec = get_lruvec(memcg, nid); - - if (!lruvec) - continue; - - /* the first addition since the last iteration */ - if (lruvec->mm_state.tail == &mm_list->fifo) - lruvec->mm_state.tail = &mm->lru_gen.list; - } - - list_add_tail(&mm->lru_gen.list, &mm_list->fifo); - - spin_unlock(&mm_list->lock); -} - -void lru_gen_del_mm(struct mm_struct *mm) -{ - int nid; - struct lru_gen_mm_list *mm_list; - struct mem_cgroup *memcg = NULL; - - if (list_empty(&mm->lru_gen.list)) - return; - -#ifdef CONFIG_MEMCG - memcg = mm->lru_gen.memcg; -#endif - mm_list = get_mm_list(memcg); - - spin_lock(&mm_list->lock); - - for_each_node(nid) { - struct lruvec *lruvec = get_lruvec(memcg, nid); - - if (!lruvec) - continue; - - /* where the last iteration ended (exclusive) */ - if (lruvec->mm_state.tail == &mm->lru_gen.list) - lruvec->mm_state.tail = lruvec->mm_state.tail->next; - - /* where the current iteration continues (inclusive) */ - if (lruvec->mm_state.head != &mm->lru_gen.list) - continue; - - lruvec->mm_state.head = lruvec->mm_state.head->next; - /* the deletion ends the current iteration */ - if (lruvec->mm_state.head == &mm_list->fifo) - WRITE_ONCE(lruvec->mm_state.seq, lruvec->mm_state.seq + 1); - } - - list_del_init(&mm->lru_gen.list); - - spin_unlock(&mm_list->lock); - -#ifdef CONFIG_MEMCG - mem_cgroup_put(mm->lru_gen.memcg); - mm->lru_gen.memcg = NULL; -#endif -} - -#ifdef CONFIG_MEMCG -void lru_gen_migrate_mm(struct mm_struct *mm) -{ - struct mem_cgroup *memcg; - struct task_struct *task = rcu_dereference_protected(mm->owner, true); - - VM_WARN_ON_ONCE(task->mm != mm); - lockdep_assert_held(&task->alloc_lock); - - /* for mm_update_next_owner() */ - if (mem_cgroup_disabled()) - return; - - rcu_read_lock(); - memcg = mem_cgroup_from_task(task); - rcu_read_unlock(); - if (memcg == mm->lru_gen.memcg) - return; - - VM_WARN_ON_ONCE(!mm->lru_gen.memcg); - VM_WARN_ON_ONCE(list_empty(&mm->lru_gen.list)); - - lru_gen_del_mm(mm); - lru_gen_add_mm(mm); -} -#endif - -/* - * Bloom filters with m=1<<15, k=2 and the false positive rates of ~1/5 when - * n=10,000 and ~1/2 when n=20,000, where, conventionally, m is the number of - * bits in a bitmap, k is the number of hash functions and n is the number of - * inserted items. - * - * Page table walkers use one of the two filters to reduce their search space. - * To get rid of non-leaf entries that no longer have enough leaf entries, the - * aging uses the double-buffering technique to flip to the other filter each - * time it produces a new generation. For non-leaf entries that have enough - * leaf entries, the aging carries them over to the next generation in - * walk_pmd_range(); the eviction also report them when walking the rmap - * in lru_gen_look_around(). - * - * For future optimizations: - * 1. It's not necessary to keep both filters all the time. The spare one can be - * freed after the RCU grace period and reallocated if needed again. - * 2. And when reallocating, it's worth scaling its size according to the number - * of inserted entries in the other filter, to reduce the memory overhead on - * small systems and false positives on large systems. - * 3. Jenkins' hash function is an alternative to Knuth's. - */ -#define BLOOM_FILTER_SHIFT 15 - -static inline int filter_gen_from_seq(unsigned long seq) -{ - return seq % NR_BLOOM_FILTERS; -} - -static void get_item_key(void *item, int *key) -{ - u32 hash = hash_ptr(item, BLOOM_FILTER_SHIFT * 2); - - BUILD_BUG_ON(BLOOM_FILTER_SHIFT * 2 > BITS_PER_TYPE(u32)); - - key[0] = hash & (BIT(BLOOM_FILTER_SHIFT) - 1); - key[1] = hash >> BLOOM_FILTER_SHIFT; -} - -static void reset_bloom_filter(struct lruvec *lruvec, unsigned long seq) -{ - unsigned long *filter; - int gen = filter_gen_from_seq(seq); - - filter = lruvec->mm_state.filters[gen]; - if (filter) { - bitmap_clear(filter, 0, BIT(BLOOM_FILTER_SHIFT)); - return; - } - - filter = bitmap_zalloc(BIT(BLOOM_FILTER_SHIFT), - __GFP_HIGH | __GFP_NOMEMALLOC | __GFP_NOWARN); - WRITE_ONCE(lruvec->mm_state.filters[gen], filter); -} - -static void update_bloom_filter(struct lruvec *lruvec, unsigned long seq, void *item) -{ - int key[2]; - unsigned long *filter; - int gen = filter_gen_from_seq(seq); - - filter = READ_ONCE(lruvec->mm_state.filters[gen]); - if (!filter) - return; - - get_item_key(item, key); - - if (!test_bit(key[0], filter)) - set_bit(key[0], filter); - if (!test_bit(key[1], filter)) - set_bit(key[1], filter); -} - -static bool test_bloom_filter(struct lruvec *lruvec, unsigned long seq, void *item) -{ - int key[2]; - unsigned long *filter; - int gen = filter_gen_from_seq(seq); - - filter = READ_ONCE(lruvec->mm_state.filters[gen]); - if (!filter) - return true; - - get_item_key(item, key); - - return test_bit(key[0], filter) && test_bit(key[1], filter); -} - -static void reset_mm_stats(struct lruvec *lruvec, struct lru_gen_mm_walk *walk, bool last) -{ - int i; - int hist; - - lockdep_assert_held(&get_mm_list(lruvec_memcg(lruvec))->lock); - - if (walk) { - hist = lru_hist_from_seq(walk->max_seq); - - for (i = 0; i < NR_MM_STATS; i++) { - WRITE_ONCE(lruvec->mm_state.stats[hist][i], - lruvec->mm_state.stats[hist][i] + walk->mm_stats[i]); - walk->mm_stats[i] = 0; - } - } - - if (NR_HIST_GENS > 1 && last) { - hist = lru_hist_from_seq(lruvec->mm_state.seq + 1); - - for (i = 0; i < NR_MM_STATS; i++) - WRITE_ONCE(lruvec->mm_state.stats[hist][i], 0); - } -} - -static bool should_skip_mm(struct mm_struct *mm, struct lru_gen_mm_walk *walk) -{ - int type; - unsigned long size = 0; - struct pglist_data *pgdat = lruvec_pgdat(walk->lruvec); - int key = pgdat->node_id % BITS_PER_TYPE(mm->lru_gen.bitmap); - - if (!walk->force_scan && !test_bit(key, &mm->lru_gen.bitmap)) - return true; - - clear_bit(key, &mm->lru_gen.bitmap); - - for (type = !walk->can_swap; type < ANON_AND_FILE; type++) { - size += type ? get_mm_counter(mm, MM_FILEPAGES) : - get_mm_counter(mm, MM_ANONPAGES) + - get_mm_counter(mm, MM_SHMEMPAGES); - } - - if (size < MIN_LRU_BATCH) - return true; - - return !mmget_not_zero(mm); -} - -static bool iterate_mm_list(struct lruvec *lruvec, struct lru_gen_mm_walk *walk, - struct mm_struct **iter) -{ - bool first = false; - bool last = true; - struct mm_struct *mm = NULL; - struct mem_cgroup *memcg = lruvec_memcg(lruvec); - struct lru_gen_mm_list *mm_list = get_mm_list(memcg); - struct lru_gen_mm_state *mm_state = &lruvec->mm_state; - - /* - * There are four interesting cases for this page table walker: - * 1. It tries to start a new iteration of mm_list with a stale max_seq; - * there is nothing left to do. - * 2. It's the first of the current generation, and it needs to reset - * the Bloom filter for the next generation. - * 3. It reaches the end of mm_list, and it needs to increment - * mm_state->seq; the iteration is done. - * 4. It's the last of the current generation, and it needs to reset the - * mm stats counters for the next generation. - */ - spin_lock(&mm_list->lock); - - VM_WARN_ON_ONCE(mm_state->seq + 1 < walk->max_seq); - VM_WARN_ON_ONCE(*iter && mm_state->seq > walk->max_seq); - VM_WARN_ON_ONCE(*iter && !mm_state->nr_walkers); - - if (walk->max_seq <= mm_state->seq) { - if (!*iter) - last = false; - goto done; - } - - if (!mm_state->nr_walkers) { - VM_WARN_ON_ONCE(mm_state->head && mm_state->head != &mm_list->fifo); - - mm_state->head = mm_list->fifo.next; - first = true; - } - - while (!mm && mm_state->head != &mm_list->fifo) { - mm = list_entry(mm_state->head, struct mm_struct, lru_gen.list); - - mm_state->head = mm_state->head->next; - - /* force scan for those added after the last iteration */ - if (!mm_state->tail || mm_state->tail == &mm->lru_gen.list) { - mm_state->tail = mm_state->head; - walk->force_scan = true; - } - - if (should_skip_mm(mm, walk)) - mm = NULL; - } - - if (mm_state->head == &mm_list->fifo) - WRITE_ONCE(mm_state->seq, mm_state->seq + 1); -done: - if (*iter && !mm) - mm_state->nr_walkers--; - if (!*iter && mm) - mm_state->nr_walkers++; - - if (mm_state->nr_walkers) - last = false; - - if (*iter || last) - reset_mm_stats(lruvec, walk, last); - - spin_unlock(&mm_list->lock); - - if (mm && first) - reset_bloom_filter(lruvec, walk->max_seq + 1); - - if (*iter) - mmput_async(*iter); - - *iter = mm; - - return last; -} - -static bool iterate_mm_list_nowalk(struct lruvec *lruvec, unsigned long max_seq) -{ - bool success = false; - struct mem_cgroup *memcg = lruvec_memcg(lruvec); - struct lru_gen_mm_list *mm_list = get_mm_list(memcg); - struct lru_gen_mm_state *mm_state = &lruvec->mm_state; - - spin_lock(&mm_list->lock); - - VM_WARN_ON_ONCE(mm_state->seq + 1 < max_seq); - - if (max_seq > mm_state->seq && !mm_state->nr_walkers) { - VM_WARN_ON_ONCE(mm_state->head && mm_state->head != &mm_list->fifo); - - WRITE_ONCE(mm_state->seq, mm_state->seq + 1); - reset_mm_stats(lruvec, NULL, true); - success = true; - } - - spin_unlock(&mm_list->lock); - - return success; -} - /****************************************************************************** * refault feedback loop ******************************************************************************/ @@ -3222,118 +2855,6 @@ static int page_inc_gen(struct lruvec *lruvec, struct page *page, bool reclaimin return new_gen; } -static void update_batch_size(struct lru_gen_mm_walk *walk, struct page *page, - int old_gen, int new_gen) -{ - int type = page_is_file_cache(page); - int zone = page_zonenum(page); - int delta = hpage_nr_pages(page); - - VM_WARN_ON_ONCE(old_gen >= MAX_NR_GENS); - VM_WARN_ON_ONCE(new_gen >= MAX_NR_GENS); - - walk->batched++; - - walk->nr_pages[old_gen][type][zone] -= delta; - walk->nr_pages[new_gen][type][zone] += delta; -} - -static void reset_batch_size(struct lruvec *lruvec, struct lru_gen_mm_walk *walk) -{ - int gen, type, zone; - struct lru_gen_struct *lrugen = &lruvec->lrugen; - - walk->batched = 0; - - for_each_gen_type_zone(gen, type, zone) { - enum lru_list lru = type * LRU_INACTIVE_FILE; - int delta = walk->nr_pages[gen][type][zone]; - - if (!delta) - continue; - - walk->nr_pages[gen][type][zone] = 0; - WRITE_ONCE(lrugen->nr_pages[gen][type][zone], - lrugen->nr_pages[gen][type][zone] + delta); - - if (lru_gen_is_active(lruvec, gen)) - lru += LRU_ACTIVE; - __update_lru_size(lruvec, lru, zone, delta); - } -} - -static int should_skip_vma(unsigned long start, unsigned long end, struct mm_walk *args) -{ - struct address_space *mapping; - struct vm_area_struct *vma = args->vma; - struct lru_gen_mm_walk *walk = args->private; - - if (!vma_is_accessible(vma)) - return true; - - if (is_vm_hugetlb_page(vma)) - return true; - - if (vma->vm_flags & (VM_LOCKED | VM_SPECIAL | VM_SEQ_READ | VM_RAND_READ)) - return true; - - if (vma == get_gate_vma(vma->vm_mm)) - return true; - - if (vma_is_anonymous(vma)) - return !walk->can_swap; - - if (WARN_ON_ONCE(!vma->vm_file || !vma->vm_file->f_mapping)) - return true; - - mapping = vma->vm_file->f_mapping; - if (mapping_unevictable(mapping)) - return true; - - if (shmem_mapping(mapping)) - return !walk->can_swap; - - /* to exclude special mappings like dax, etc. */ - return !mapping->a_ops->readpage; -} - -/* - * Some userspace memory allocators map many single-page VMAs. Instead of - * returning back to the PGD table for each of such VMAs, finish an entire PMD - * table to reduce zigzags and improve cache performance. - */ -static bool get_next_vma(unsigned long mask, unsigned long size, struct mm_walk *args, - unsigned long *vm_start, unsigned long *vm_end) -{ - unsigned long start = round_up(*vm_end, size); - unsigned long end = (start | ~mask) + 1; - - VM_WARN_ON_ONCE(mask & size); - VM_WARN_ON_ONCE((start & mask) != (*vm_start & mask)); - - while (args->vma) { - if (start >= args->vma->vm_end) { - args->vma = args->vma->vm_next; - continue; - } - - if (end && end <= args->vma->vm_start) - return false; - - if (should_skip_vma(args->vma->vm_start, args->vma->vm_end, args)) { - args->vma = args->vma->vm_next; - continue; - } - - *vm_start = max(start, args->vma->vm_start); - *vm_end = min(end - 1, args->vma->vm_end - 1) + 1; - - return true; - } - - return false; -} - static unsigned long get_pte_pfn(pte_t pte, struct vm_area_struct *vma, unsigned long addr) { unsigned long pfn = pte_pfn(pte); @@ -3352,28 +2873,8 @@ static unsigned long get_pte_pfn(pte_t pte, struct vm_area_struct *vma, unsigned return pfn; } -#if defined(CONFIG_TRANSPARENT_HUGEPAGE) || defined(CONFIG_ARCH_HAS_NONLEAF_PMD_YOUNG) -static unsigned long get_pmd_pfn(pmd_t pmd, struct vm_area_struct *vma, unsigned long addr) -{ - unsigned long pfn = pmd_pfn(pmd); - - VM_WARN_ON_ONCE(addr < vma->vm_start || addr >= vma->vm_end); - - if (!pmd_present(pmd) || is_huge_zero_pmd(pmd)) - return -1; - - if (WARN_ON_ONCE(pmd_devmap(pmd))) - return -1; - - if (WARN_ON_ONCE(!pfn_valid(pfn))) - return -1; - - return pfn; -} -#endif - static struct page *get_pfn_page(unsigned long pfn, struct mem_cgroup *memcg, - struct pglist_data *pgdat, bool can_swap) + struct pglist_data *pgdat) { struct page *page; @@ -3388,378 +2889,9 @@ static struct page *get_pfn_page(unsigned long pfn, struct mem_cgroup *memcg, if (page_memcg_rcu(page) != memcg) return NULL; - /* file VMAs can contain anon pages from COW */ - if (!page_is_file_cache(page) && !can_swap) - return NULL; - return page; } -static bool suitable_to_scan(int total, int young) -{ - int n = clamp_t(int, cache_line_size() / sizeof(pte_t), 2, 8); - - /* suitable if the average number of young PTEs per cacheline is >=1 */ - return young * n >= total; -} - -static bool walk_pte_range(pmd_t *pmd, unsigned long start, unsigned long end, - struct mm_walk *args) -{ - int i; - pte_t *pte; - spinlock_t *ptl; - unsigned long addr; - int total = 0; - int young = 0; - struct lru_gen_mm_walk *walk = args->private; - struct mem_cgroup *memcg = lruvec_memcg(walk->lruvec); - struct pglist_data *pgdat = lruvec_pgdat(walk->lruvec); - int old_gen, new_gen = lru_gen_from_seq(walk->max_seq); - - VM_WARN_ON_ONCE(pmd_leaf(*pmd)); - - ptl = pte_lockptr(args->mm, pmd); - if (!spin_trylock(ptl)) - return false; - - arch_enter_lazy_mmu_mode(); - - pte = pte_offset_map(pmd, start & PMD_MASK); -restart: - for (i = pte_index(start), addr = start; addr != end; i++, addr += PAGE_SIZE) { - unsigned long pfn; - struct page *page; - - total++; - walk->mm_stats[MM_LEAF_TOTAL]++; - - pfn = get_pte_pfn(pte[i], args->vma, addr); - if (pfn == -1) - continue; - - if (!pte_young(pte[i])) { - walk->mm_stats[MM_LEAF_OLD]++; - continue; - } - - page = get_pfn_page(pfn, memcg, pgdat, walk->can_swap); - if (!page) - continue; - - if (!ptep_test_and_clear_young(args->vma, addr, pte + i)) - VM_WARN_ON_ONCE(true); - - young++; - walk->mm_stats[MM_LEAF_YOUNG]++; - - if (pte_dirty(pte[i]) && !PageDirty(page) && - !(PageAnon(page) && PageSwapBacked(page) && - !PageSwapCache(page))) - set_page_dirty(page); - - old_gen = page_update_gen(page, new_gen); - if (old_gen >= 0 && old_gen != new_gen) - update_batch_size(walk, page, old_gen, new_gen); - } - - if (i < PTRS_PER_PTE && get_next_vma(PMD_MASK, PAGE_SIZE, args, &start, &end)) - goto restart; - - pte_unmap(pte); - - arch_leave_lazy_mmu_mode(); - spin_unlock(ptl); - - return suitable_to_scan(total, young); -} - -#if defined(CONFIG_TRANSPARENT_HUGEPAGE) || defined(CONFIG_ARCH_HAS_NONLEAF_PMD_YOUNG) -static void walk_pmd_range_locked(pud_t *pud, unsigned long next, struct vm_area_struct *vma, - struct mm_walk *args, unsigned long *bitmap, unsigned long *start) -{ - int i; - pmd_t *pmd; - spinlock_t *ptl; - struct lru_gen_mm_walk *walk = args->private; - struct mem_cgroup *memcg = lruvec_memcg(walk->lruvec); - struct pglist_data *pgdat = lruvec_pgdat(walk->lruvec); - int old_gen, new_gen = lru_gen_from_seq(walk->max_seq); - - VM_WARN_ON_ONCE(pud_leaf(*pud)); - - /* try to batch at most 1+MIN_LRU_BATCH+1 entries */ - if (*start == -1) { - *start = next; - return; - } - - i = next == -1 ? 0 : ((next - *start) >> PMD_SHIFT) & (PTRS_PER_PMD - 1); - if (i && i <= MIN_LRU_BATCH) { - __set_bit(i - 1, bitmap); - return; - } - - pmd = pmd_offset(pud, *start); - - ptl = pmd_lockptr(args->mm, pmd); - if (!spin_trylock(ptl)) - goto done; - - arch_enter_lazy_mmu_mode(); - - do { - unsigned long pfn; - struct page *page; - unsigned long addr = i ? (*start & PMD_MASK) + i * PMD_SIZE : *start; - - pfn = get_pmd_pfn(pmd[i], vma, addr); - if (pfn == -1) - goto next; - - if (!pmd_trans_huge(pmd[i])) { - if (IS_ENABLED(CONFIG_ARCH_HAS_NONLEAF_PMD_YOUNG)) - pmdp_test_and_clear_young(vma, addr, pmd + i); - goto next; - } - - page = get_pfn_page(pfn, memcg, pgdat, walk->can_swap); - if (!page) - goto next; - - if (!pmdp_test_and_clear_young(vma, addr, pmd + i)) - goto next; - - walk->mm_stats[MM_LEAF_YOUNG]++; - - if (pmd_dirty(pmd[i]) && !PageDirty(page) && - !(PageAnon(page) && PageSwapBacked(page) && - !PageSwapCache(page))) - set_page_dirty(page); - - old_gen = page_update_gen(page, new_gen); - if (old_gen >= 0 && old_gen != new_gen) - update_batch_size(walk, page, old_gen, new_gen); -next: - i = i > MIN_LRU_BATCH ? 0 : find_next_bit(bitmap, MIN_LRU_BATCH, i) + 1; - } while (i <= MIN_LRU_BATCH); - - arch_leave_lazy_mmu_mode(); - spin_unlock(ptl); -done: - *start = -1; - bitmap_zero(bitmap, MIN_LRU_BATCH); -} -#else -static void walk_pmd_range_locked(pud_t *pud, unsigned long next, struct vm_area_struct *vma, - struct mm_walk *args, unsigned long *bitmap, unsigned long *start) -{ -} -#endif - -static void walk_pmd_range(pud_t *pud, unsigned long start, unsigned long end, - struct mm_walk *args) -{ - int i; - pmd_t *pmd; - unsigned long next; - unsigned long addr; - struct vm_area_struct *vma; - unsigned long pos = -1; - struct lru_gen_mm_walk *walk = args->private; - unsigned long bitmap[BITS_TO_LONGS(MIN_LRU_BATCH)] = {}; - - VM_WARN_ON_ONCE(pud_leaf(*pud)); - - /* - * Finish an entire PMD in two passes: the first only reaches to PTE - * tables to avoid taking the PMD lock; the second, if necessary, takes - * the PMD lock to clear the accessed bit in PMD entries. - */ - pmd = pmd_offset(pud, start & PUD_MASK); -restart: - /* walk_pte_range() may call get_next_vma() */ - vma = args->vma; - i = (start >> PMD_SHIFT) & (PTRS_PER_PMD - 1); - for (addr = start; addr != end; i++, addr = next) { - pmd_t val = pmd_read_atomic(pmd + i); - - /* for pmd_read_atomic() */ - barrier(); - - next = pmd_addr_end(addr, end); - - if (!pmd_present(val) || is_huge_zero_pmd(val)) { - walk->mm_stats[MM_LEAF_TOTAL]++; - continue; - } - -#ifdef CONFIG_TRANSPARENT_HUGEPAGE - if (pmd_trans_huge(val)) { - unsigned long pfn = pmd_pfn(val); - struct pglist_data *pgdat = lruvec_pgdat(walk->lruvec); - - walk->mm_stats[MM_LEAF_TOTAL]++; - - if (!pmd_young(val)) { - walk->mm_stats[MM_LEAF_OLD]++; - continue; - } - - /* try to avoid unnecessary memory loads */ - if (pfn < pgdat->node_start_pfn || pfn >= pgdat_end_pfn(pgdat)) - continue; - - walk_pmd_range_locked(pud, addr, vma, args, bitmap, &pos); - continue; - } -#endif - walk->mm_stats[MM_NONLEAF_TOTAL]++; - -#ifdef CONFIG_ARCH_HAS_NONLEAF_PMD_YOUNG - if (!pmd_young(val)) - continue; - - walk_pmd_range_locked(pud, addr, vma, args, bitmap, &pos); -#endif - if (!walk->force_scan && !test_bloom_filter(walk->lruvec, walk->max_seq, pmd + i)) - continue; - - walk->mm_stats[MM_NONLEAF_FOUND]++; - - if (!walk_pte_range(&val, addr, next, args)) - continue; - - walk->mm_stats[MM_NONLEAF_ADDED]++; - - /* carry over to the next generation */ - update_bloom_filter(walk->lruvec, walk->max_seq + 1, pmd + i); - } - - walk_pmd_range_locked(pud, -1, vma, args, bitmap, &pos); - - if (i < PTRS_PER_PMD && get_next_vma(PUD_MASK, PMD_SIZE, args, &start, &end)) - goto restart; -} - -static int walk_pud_range(p4d_t *p4d, unsigned long start, unsigned long end, - struct mm_walk *args) -{ - int i; - pud_t *pud; - unsigned long addr; - unsigned long next; - struct lru_gen_mm_walk *walk = args->private; - - VM_WARN_ON_ONCE(p4d_leaf(*p4d)); - - pud = pud_offset(p4d, start & P4D_MASK); -restart: - i = (start >> PUD_SHIFT) & (PTRS_PER_PUD - 1); - for (addr = start; addr != end; i++, addr = next) { - pud_t val = READ_ONCE(pud[i]); - - next = pud_addr_end(addr, end); - - if (!pud_present(val) || WARN_ON_ONCE(pud_leaf(val))) - continue; - - walk_pmd_range(&val, addr, next, args); - - /* a racy check to curtail the waiting time */ - if (wq_has_sleeper(&walk->lruvec->mm_state.wait)) - return 1; - - if (need_resched() || walk->batched >= MAX_LRU_BATCH) { - end = (addr | ~PUD_MASK) + 1; - goto done; - } - } - - if (i < PTRS_PER_PUD && get_next_vma(P4D_MASK, PUD_SIZE, args, &start, &end)) - goto restart; - - end = round_up(end, P4D_SIZE); -done: - if (!end || !args->vma) - return 1; - - walk->next_addr = max(end, args->vma->vm_start); - - return -EAGAIN; -} - -static void walk_mm(struct lruvec *lruvec, struct mm_struct *mm, struct lru_gen_mm_walk *walk) -{ - static const struct mm_walk_ops mm_walk_ops = { - .test_walk = should_skip_vma, - .p4d_entry = walk_pud_range, - }; - - int err; - struct mem_cgroup *memcg = lruvec_memcg(lruvec); - struct pglist_data *pgdat = lruvec_pgdat(lruvec); - - walk->next_addr = FIRST_USER_ADDRESS; - - do { - err = -EBUSY; - - /* page_update_gen() requires stable page_memcg() */ - if (!mem_cgroup_trylock_pages(memcg)) - break; - - /* the caller might be holding the lock for write */ - if (mmap_read_trylock(mm)) { - err = walk_page_range(mm, walk->next_addr, ULONG_MAX, &mm_walk_ops, walk); - - mmap_read_unlock(mm); - } - - mem_cgroup_unlock_pages(); - - if (walk->batched) { - spin_lock_irq(&pgdat->lru_lock); - reset_batch_size(lruvec, walk); - spin_unlock_irq(&pgdat->lru_lock); - } - - cond_resched(); - } while (err == -EAGAIN); -} - -static struct lru_gen_mm_walk *set_mm_walk(struct pglist_data *pgdat) -{ - struct lru_gen_mm_walk *walk = current->reclaim_state->mm_walk; - - if (pgdat && current_is_kswapd()) { - VM_WARN_ON_ONCE(walk); - - walk = &pgdat->mm_walk; - } else if (!pgdat && !walk) { - VM_WARN_ON_ONCE(current_is_kswapd()); - - walk = kzalloc(sizeof(*walk), __GFP_HIGH | __GFP_NOMEMALLOC | __GFP_NOWARN); - } - - current->reclaim_state->mm_walk = walk; - - return walk; -} - -static void clear_mm_walk(void) -{ - struct lru_gen_mm_walk *walk = current->reclaim_state->mm_walk; - - VM_WARN_ON_ONCE(walk && memchr_inv(walk->nr_pages, 0, sizeof(walk->nr_pages))); - VM_WARN_ON_ONCE(walk && memchr_inv(walk->mm_stats, 0, sizeof(walk->mm_stats))); - - current->reclaim_state->mm_walk = NULL; - - if (!current_is_kswapd()) - kfree(walk); -} - static void inc_min_seq(struct lruvec *lruvec, int type) { struct lru_gen_struct *lrugen = &lruvec->lrugen; @@ -3811,7 +2943,7 @@ next: return success; } -static void inc_max_seq(struct lruvec *lruvec, bool can_swap) +static void inc_max_seq(struct lruvec *lruvec, unsigned long max_seq, bool can_swap) { int prev, next; int type, zone; @@ -3822,6 +2954,9 @@ static void inc_max_seq(struct lruvec *lruvec, bool can_swap) VM_WARN_ON_ONCE(!seq_is_valid(lruvec)); + if (max_seq != lrugen->max_seq) + goto unlock; + for (type = ANON_AND_FILE - 1; type >= 0; type--) { if (get_nr_gens(lruvec, type) != MAX_NR_GENS) continue; @@ -3859,74 +2994,10 @@ static void inc_max_seq(struct lruvec *lruvec, bool can_swap) /* make sure preceding modifications appear */ smp_store_release(&lrugen->max_seq, lrugen->max_seq + 1); - +unlock: spin_unlock_irq(&pgdat->lru_lock); } -static bool try_to_inc_max_seq(struct lruvec *lruvec, unsigned long max_seq, - struct scan_control *sc, bool can_swap) -{ - bool success; - struct lru_gen_mm_walk *walk; - struct mm_struct *mm = NULL; - struct lru_gen_struct *lrugen = &lruvec->lrugen; - - VM_WARN_ON_ONCE(max_seq > READ_ONCE(lrugen->max_seq)); - - /* see the comment in iterate_mm_list() */ - if (max_seq <= READ_ONCE(lruvec->mm_state.seq)) { - success = false; - goto done; - } - - /* - * If the hardware doesn't automatically set the accessed bit, fallback - * to lru_gen_look_around(), which only clears the accessed bit in a - * handful of PTEs. Spreading the work out over a period of time usually - * is less efficient, but it avoids bursty page faults. - */ - if (!arch_has_hw_pte_young()) { - success = iterate_mm_list_nowalk(lruvec, max_seq); - goto done; - } - - walk = set_mm_walk(NULL); - if (!walk) { - success = iterate_mm_list_nowalk(lruvec, max_seq); - goto done; - } - - walk->lruvec = lruvec; - walk->max_seq = max_seq; - walk->can_swap = can_swap; - walk->force_scan = false; - - do { - success = iterate_mm_list(lruvec, walk, &mm); - if (mm) - walk_mm(lruvec, mm, walk); - - cond_resched(); - } while (mm); -done: - if (!success) { - if (sc->priority <= DEF_PRIORITY - 2) - wait_event_killable(lruvec->mm_state.wait, - max_seq < READ_ONCE(lrugen->max_seq)); - - return max_seq < READ_ONCE(lrugen->max_seq); - } - - VM_WARN_ON_ONCE(max_seq != READ_ONCE(lrugen->max_seq)); - - inc_max_seq(lruvec, can_swap); - /* either this sees any waiters or they will see updated max_seq */ - if (wq_has_sleeper(&lruvec->mm_state.wait)) - wake_up_all(&lruvec->mm_state.wait); - - return true; -} - static bool should_run_aging(struct lruvec *lruvec, unsigned long max_seq, unsigned long *min_seq, struct scan_control *sc, bool can_swap, unsigned long *nr_to_scan) { @@ -4001,7 +3072,7 @@ static void age_lruvec(struct lruvec *lruvec, struct scan_control *sc) need_aging = should_run_aging(lruvec, max_seq, min_seq, sc, swappiness, &nr_to_scan); if (need_aging) - try_to_inc_max_seq(lruvec, max_seq, sc, swappiness); + inc_max_seq(lruvec, max_seq, swappiness); } static void lru_gen_age_node(struct pglist_data *pgdat, struct scan_control *sc) @@ -4010,8 +3081,6 @@ static void lru_gen_age_node(struct pglist_data *pgdat, struct scan_control *sc) VM_WARN_ON_ONCE(!current_is_kswapd()); - set_mm_walk(pgdat); - memcg = mem_cgroup_iter(NULL, NULL, NULL); do { struct lruvec *lruvec = mem_cgroup_lruvec(pgdat, memcg); @@ -4020,16 +3089,11 @@ static void lru_gen_age_node(struct pglist_data *pgdat, struct scan_control *sc) cond_resched(); } while ((memcg = mem_cgroup_iter(NULL, memcg, NULL))); - - clear_mm_walk(); } /* * This function exploits spatial locality when shrink_page_list() walks the - * rmap. It scans the adjacent PTEs of a young PTE and promotes hot pages. If - * the scan was done cacheline efficiently, it adds the PMD entry pointing to - * the PTE table to the Bloom filter. This forms a feedback loop between the - * eviction and the aging. + * rmap. It scans the adjacent PTEs of a young PTE and promotes hot pages. */ void lru_gen_look_around(struct page_vma_mapped_walk *pvmw) { @@ -4038,8 +3102,6 @@ void lru_gen_look_around(struct page_vma_mapped_walk *pvmw) unsigned long start; unsigned long end; unsigned long addr; - struct lru_gen_mm_walk *walk; - int young = 0; unsigned long bitmap[BITS_TO_LONGS(MIN_LRU_BATCH)] = {}; struct page *page = pvmw->page; struct mem_cgroup *memcg = page_memcg(page); @@ -4054,9 +3116,6 @@ void lru_gen_look_around(struct page_vma_mapped_walk *pvmw) if (spin_is_contended(pvmw->ptl)) return; - /* avoid taking the LRU lock under the PTL when possible */ - walk = current->reclaim_state ? current->reclaim_state->mm_walk : NULL; - start = max(pvmw->address & PMD_MASK, pvmw->vma->vm_start); end = min(pvmw->address | ~PMD_MASK, pvmw->vma->vm_end - 1) + 1; @@ -4086,15 +3145,13 @@ void lru_gen_look_around(struct page_vma_mapped_walk *pvmw) if (!pte_young(pte[i])) continue; - page = get_pfn_page(pfn, memcg, pgdat, !walk || walk->can_swap); + page = get_pfn_page(pfn, memcg, pgdat); if (!page) continue; if (!ptep_test_and_clear_young(pvmw->vma, addr, pte + i)) VM_WARN_ON_ONCE(true); - young++; - if (pte_dirty(pte[i]) && !PageDirty(page) && !(PageAnon(page) && PageSwapBacked(page) && !PageSwapCache(page))) @@ -4110,11 +3167,7 @@ void lru_gen_look_around(struct page_vma_mapped_walk *pvmw) arch_leave_lazy_mmu_mode(); rcu_read_unlock(); - /* feedback from rmap walkers to page table walkers */ - if (suitable_to_scan(i, young)) - update_bloom_filter(lruvec, max_seq, pvmw->pmd); - - if (!walk && bitmap_weight(bitmap, MIN_LRU_BATCH) < PAGEVEC_SIZE) { + if (bitmap_weight(bitmap, MIN_LRU_BATCH) < PAGEVEC_SIZE) { for_each_set_bit(i, bitmap, MIN_LRU_BATCH) { page = pte_page(pte[i]); activate_page(page); @@ -4126,10 +3179,8 @@ void lru_gen_look_around(struct page_vma_mapped_walk *pvmw) if (!mem_cgroup_trylock_pages(memcg)) return; - if (!walk) { - spin_lock_irq(&pgdat->lru_lock); - new_gen = lru_gen_from_seq(lruvec->lrugen.max_seq); - } + spin_lock_irq(&pgdat->lru_lock); + new_gen = lru_gen_from_seq(lruvec->lrugen.max_seq); for_each_set_bit(i, bitmap, MIN_LRU_BATCH) { page = compound_head(pte_page(pte[i])); @@ -4140,14 +3191,10 @@ void lru_gen_look_around(struct page_vma_mapped_walk *pvmw) if (old_gen < 0 || old_gen == new_gen) continue; - if (walk) - update_batch_size(walk, page, old_gen, new_gen); - else - lru_gen_update_size(lruvec, page, old_gen, new_gen); + lru_gen_update_size(lruvec, page, old_gen, new_gen); } - if (!walk) - spin_unlock_irq(&pgdat->lru_lock); + spin_unlock_irq(&pgdat->lru_lock); mem_cgroup_unlock_pages(); } @@ -4425,7 +3472,6 @@ static int evict_pages(struct lruvec *lruvec, struct scan_control *sc, int swapp struct page *page; enum vm_event_item item; struct reclaim_stat stat; - struct lru_gen_mm_walk *walk; struct mem_cgroup *memcg = lruvec_memcg(lruvec); struct pglist_data *pgdat = lruvec_pgdat(lruvec); @@ -4462,10 +3508,6 @@ static int evict_pages(struct lruvec *lruvec, struct scan_control *sc, int swapp move_pages_to_lru(lruvec, &list); - walk = current->reclaim_state->mm_walk; - if (walk && walk->batched) - reset_batch_size(lruvec, walk); - item = current_is_kswapd() ? PGSTEAL_KSWAPD : PGSTEAL_DIRECT; if (global_reclaim(sc)) __count_vm_events(item, reclaimed); @@ -4481,11 +3523,6 @@ static int evict_pages(struct lruvec *lruvec, struct scan_control *sc, int swapp return scanned; } -/* - * For future optimizations: - * 1. Defer try_to_inc_max_seq() to workqueues to reduce latency for memcg - * reclaim. - */ static unsigned long get_nr_to_scan(struct lruvec *lruvec, struct scan_control *sc, bool can_swap) { @@ -4506,8 +3543,7 @@ static unsigned long get_nr_to_scan(struct lruvec *lruvec, struct scan_control * if (current_is_kswapd()) return 0; - if (try_to_inc_max_seq(lruvec, max_seq, sc, can_swap)) - return nr_to_scan; + inc_max_seq(lruvec, max_seq, can_swap); done: return min_seq[!can_swap] + MIN_NR_GENS <= max_seq ? nr_to_scan : 0; } @@ -4521,8 +3557,6 @@ static void lru_gen_shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc blk_start_plug(&plug); - set_mm_walk(lruvec_pgdat(lruvec)); - while (true) { int delta; int swappiness; @@ -4550,8 +3584,6 @@ static void lru_gen_shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc cond_resched(); } - clear_mm_walk(); - blk_finish_plug(&plug); } @@ -4568,21 +3600,15 @@ void lru_gen_init_lruvec(struct lruvec *lruvec) for_each_gen_type_zone(gen, type, zone) INIT_LIST_HEAD(&lrugen->lists[gen][type][zone]); - - lruvec->mm_state.seq = MIN_NR_GENS; - init_waitqueue_head(&lruvec->mm_state.wait); } #ifdef CONFIG_MEMCG void lru_gen_init_memcg(struct mem_cgroup *memcg) { - INIT_LIST_HEAD(&memcg->mm_list.fifo); - spin_lock_init(&memcg->mm_list.lock); } void lru_gen_exit_memcg(struct mem_cgroup *memcg) { - int i; int nid; for_each_node(nid) { @@ -4590,11 +3616,6 @@ void lru_gen_exit_memcg(struct mem_cgroup *memcg) VM_WARN_ON_ONCE(memchr_inv(lruvec->lrugen.nr_pages, 0, sizeof(lruvec->lrugen.nr_pages))); - - for (i = 0; i < NR_BLOOM_FILTERS; i++) { - bitmap_free(lruvec->mm_state.filters[i]); - lruvec->mm_state.filters[i] = NULL; - } } } #endif From eeca9bffa701e038b2a984775346916428684d7e Mon Sep 17 00:00:00 2001 From: xiewen3 Date: Tue, 16 May 2023 22:47:13 +0800 Subject: [PATCH 585/698] LUR: Revert "BACKPORT: mm: multi-gen LRU: exploit locality in rmap" The LRU function is not compatible with GKI, causing GKI to fail to start, so revert. This reverts commit 574d1e5ff72493a5b3b7b1a47251418e81aa1369. Change-Id: I909f487156f7da759b5531bec06a74b729e3b392 Reviewed-on: https://gerrit.mot.com/2609761 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- include/linux/memcontrol.h | 29 ------ include/linux/mmzone.h | 6 -- mm/internal.h | 1 - mm/rmap.c | 7 -- mm/vmscan.c | 186 ------------------------------------- 5 files changed, 229 deletions(-) diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h index 45709b7bef1a..a1b04d916526 100644 --- a/include/linux/memcontrol.h +++ b/include/linux/memcontrol.h @@ -659,23 +659,6 @@ static inline unsigned long memcg_page_state_local(struct mem_cgroup *memcg, void __mod_memcg_state(struct mem_cgroup *memcg, int idx, int val); -/* try to stablize page_memcg() for all the pages in a memcg */ -static inline bool mem_cgroup_trylock_pages(struct mem_cgroup *memcg) -{ - rcu_read_lock(); - - if (mem_cgroup_disabled() || !atomic_read(&memcg->moving_account)) - return true; - - rcu_read_unlock(); - return false; -} - -static inline void mem_cgroup_unlock_pages(void) -{ - rcu_read_unlock(); -} - /* idx can be of type enum memcg_stat_item or node_stat_item */ static inline void mod_memcg_state(struct mem_cgroup *memcg, int idx, int val) @@ -1076,18 +1059,6 @@ static inline void unlock_page_memcg(struct page *page) { } -static inline bool mem_cgroup_trylock_pages(struct mem_cgroup *memcg) -{ - /* to match page_memcg_rcu() */ - rcu_read_lock(); - return true; -} - -static inline void mem_cgroup_unlock_pages(void) -{ - rcu_read_unlock(); -} - static inline void mem_cgroup_handle_over_high(void) { } diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index 4d6a1cff0e70..2721b50970fe 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -366,7 +366,6 @@ struct zone_reclaim_stat { #ifndef __GENERATING_BOUNDS_H struct lruvec; -struct page_vma_mapped_walk; #define LRU_GEN_MASK ((BIT(LRU_GEN_WIDTH) - 1) << LRU_GEN_PGOFF) #define LRU_REFS_MASK ((BIT(LRU_REFS_WIDTH) - 1) << LRU_REFS_PGOFF) @@ -425,7 +424,6 @@ struct lru_gen_struct { }; void lru_gen_init_lruvec(struct lruvec *lruvec); -void lru_gen_look_around(struct page_vma_mapped_walk *pvmw); #ifdef CONFIG_MEMCG void lru_gen_init_memcg(struct mem_cgroup *memcg); @@ -438,10 +436,6 @@ static inline void lru_gen_init_lruvec(struct lruvec *lruvec) { } -static inline void lru_gen_look_around(struct page_vma_mapped_walk *pvmw) -{ -} - #ifdef CONFIG_MEMCG static inline void lru_gen_init_memcg(struct mem_cgroup *memcg) { diff --git a/mm/internal.h b/mm/internal.h index f14974189fbf..6504edd8a447 100644 --- a/mm/internal.h +++ b/mm/internal.h @@ -35,7 +35,6 @@ void page_writeback_init(void); vm_fault_t do_swap_page(struct vm_fault *vmf); -void activate_page(struct page *page); #ifdef CONFIG_SPECULATIVE_PAGE_FAULT extern struct vm_area_struct *get_vma(struct mm_struct *mm, diff --git a/mm/rmap.c b/mm/rmap.c index 46416f1dc6fa..2b5886600b38 100644 --- a/mm/rmap.c +++ b/mm/rmap.c @@ -66,7 +66,6 @@ #include #include #include -#include #include @@ -782,12 +781,6 @@ static bool page_referenced_one(struct page *page, struct vm_area_struct *vma, } if (pvmw.pte) { - if (lru_gen_enabled() && pte_young(*pvmw.pte) && - !(vma->vm_flags & (VM_SEQ_READ | VM_RAND_READ))) { - lru_gen_look_around(&pvmw); - referenced++; - } - if (ptep_clear_flush_young_notify(vma, address, pvmw.pte)) { /* diff --git a/mm/vmscan.c b/mm/vmscan.c index c6e98e805bf5..7cf42b2eaee2 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -1190,11 +1190,6 @@ static unsigned long shrink_page_list(struct list_head *page_list, if (!sc->may_unmap && page_mapped(page)) goto keep_locked; - /* page_update_gen() tried to promote this page? */ - if (lru_gen_enabled() && !ignore_references && - page_mapped(page) && PageReferenced(page)) - goto keep_locked; - may_enter_fs = (sc->gfp_mask & __GFP_FS) || (PageSwapCache(page) && (sc->gfp_mask & __GFP_IO)); @@ -2798,31 +2793,6 @@ static bool positive_ctrl_err(struct ctrl_pos *sp, struct ctrl_pos *pv) * the aging ******************************************************************************/ -/* promote pages accessed through page tables */ -static int page_update_gen(struct page *page, int gen) -{ - unsigned long new_flags, old_flags; - - VM_WARN_ON_ONCE(gen >= MAX_NR_GENS); - VM_WARN_ON_ONCE(!rcu_read_lock_held()); - - do { - old_flags = READ_ONCE(page->flags); - - /* lru_gen_del_page() has isolated this page? */ - if (!(old_flags & LRU_GEN_MASK)) { - /* for shrink_page_list() */ - new_flags = old_flags | BIT(PG_referenced); - continue; - } - - new_flags = old_flags & ~(LRU_GEN_MASK | LRU_REFS_MASK | LRU_REFS_FLAGS); - new_flags |= (gen + 1UL) << LRU_GEN_PGOFF; - } while (cmpxchg(&page->flags, old_flags, new_flags) != old_flags); - - return ((old_flags & LRU_GEN_MASK) >> LRU_GEN_PGOFF) - 1; -} - /* protect pages accessed multiple times through file descriptors */ static int page_inc_gen(struct lruvec *lruvec, struct page *page, bool reclaiming) { @@ -2836,11 +2806,6 @@ static int page_inc_gen(struct lruvec *lruvec, struct page *page, bool reclaimin VM_WARN_ON_ONCE_PAGE(!(old_flags & LRU_GEN_MASK), page); - new_gen = ((old_flags & LRU_GEN_MASK) >> LRU_GEN_PGOFF) - 1; - /* page_update_gen() has promoted this page? */ - if (new_gen >= 0 && new_gen != old_gen) - return new_gen; - new_gen = (old_gen + 1) % MAX_NR_GENS; new_flags = old_flags & ~(LRU_GEN_MASK | LRU_REFS_MASK | LRU_REFS_FLAGS); @@ -2855,43 +2820,6 @@ static int page_inc_gen(struct lruvec *lruvec, struct page *page, bool reclaimin return new_gen; } -static unsigned long get_pte_pfn(pte_t pte, struct vm_area_struct *vma, unsigned long addr) -{ - unsigned long pfn = pte_pfn(pte); - - VM_WARN_ON_ONCE(addr < vma->vm_start || addr >= vma->vm_end); - - if (!pte_present(pte) || is_zero_pfn(pfn)) - return -1; - - if (WARN_ON_ONCE(pte_devmap(pte) || pte_special(pte))) - return -1; - - if (WARN_ON_ONCE(!pfn_valid(pfn))) - return -1; - - return pfn; -} - -static struct page *get_pfn_page(unsigned long pfn, struct mem_cgroup *memcg, - struct pglist_data *pgdat) -{ - struct page *page; - - /* try to avoid unnecessary memory loads */ - if (pfn < pgdat->node_start_pfn || pfn >= pgdat_end_pfn(pgdat)) - return NULL; - - page = compound_head(pfn_to_page(pfn)); - if (page_to_nid(page) != pgdat->node_id) - return NULL; - - if (page_memcg_rcu(page) != memcg) - return NULL; - - return page; -} - static void inc_min_seq(struct lruvec *lruvec, int type) { struct lru_gen_struct *lrugen = &lruvec->lrugen; @@ -3091,114 +3019,6 @@ static void lru_gen_age_node(struct pglist_data *pgdat, struct scan_control *sc) } while ((memcg = mem_cgroup_iter(NULL, memcg, NULL))); } -/* - * This function exploits spatial locality when shrink_page_list() walks the - * rmap. It scans the adjacent PTEs of a young PTE and promotes hot pages. - */ -void lru_gen_look_around(struct page_vma_mapped_walk *pvmw) -{ - int i; - pte_t *pte; - unsigned long start; - unsigned long end; - unsigned long addr; - unsigned long bitmap[BITS_TO_LONGS(MIN_LRU_BATCH)] = {}; - struct page *page = pvmw->page; - struct mem_cgroup *memcg = page_memcg(page); - struct pglist_data *pgdat = page_pgdat(page); - struct lruvec *lruvec = mem_cgroup_lruvec(pgdat, memcg); - DEFINE_MAX_SEQ(lruvec); - int old_gen, new_gen = lru_gen_from_seq(max_seq); - - lockdep_assert_held(pvmw->ptl); - VM_WARN_ON_ONCE_PAGE(PageLRU(page), page); - - if (spin_is_contended(pvmw->ptl)) - return; - - start = max(pvmw->address & PMD_MASK, pvmw->vma->vm_start); - end = min(pvmw->address | ~PMD_MASK, pvmw->vma->vm_end - 1) + 1; - - if (end - start > MIN_LRU_BATCH * PAGE_SIZE) { - if (pvmw->address - start < MIN_LRU_BATCH * PAGE_SIZE / 2) - end = start + MIN_LRU_BATCH * PAGE_SIZE; - else if (end - pvmw->address < MIN_LRU_BATCH * PAGE_SIZE / 2) - start = end - MIN_LRU_BATCH * PAGE_SIZE; - else { - start = pvmw->address - MIN_LRU_BATCH * PAGE_SIZE / 2; - end = pvmw->address + MIN_LRU_BATCH * PAGE_SIZE / 2; - } - } - - pte = pvmw->pte - (pvmw->address - start) / PAGE_SIZE; - - rcu_read_lock(); - arch_enter_lazy_mmu_mode(); - - for (i = 0, addr = start; addr != end; i++, addr += PAGE_SIZE) { - unsigned long pfn; - - pfn = get_pte_pfn(pte[i], pvmw->vma, addr); - if (pfn == -1) - continue; - - if (!pte_young(pte[i])) - continue; - - page = get_pfn_page(pfn, memcg, pgdat); - if (!page) - continue; - - if (!ptep_test_and_clear_young(pvmw->vma, addr, pte + i)) - VM_WARN_ON_ONCE(true); - - if (pte_dirty(pte[i]) && !PageDirty(page) && - !(PageAnon(page) && PageSwapBacked(page) && - !PageSwapCache(page))) - set_page_dirty(page); - - old_gen = page_lru_gen(page); - if (old_gen < 0) - SetPageReferenced(page); - else if (old_gen != new_gen) - __set_bit(i, bitmap); - } - - arch_leave_lazy_mmu_mode(); - rcu_read_unlock(); - - if (bitmap_weight(bitmap, MIN_LRU_BATCH) < PAGEVEC_SIZE) { - for_each_set_bit(i, bitmap, MIN_LRU_BATCH) { - page = pte_page(pte[i]); - activate_page(page); - } - return; - } - - /* page_update_gen() requires stable page_memcg() */ - if (!mem_cgroup_trylock_pages(memcg)) - return; - - spin_lock_irq(&pgdat->lru_lock); - new_gen = lru_gen_from_seq(lruvec->lrugen.max_seq); - - for_each_set_bit(i, bitmap, MIN_LRU_BATCH) { - page = compound_head(pte_page(pte[i])); - if (page_memcg_rcu(page) != memcg) - continue; - - old_gen = page_update_gen(page, new_gen); - if (old_gen < 0 || old_gen == new_gen) - continue; - - lru_gen_update_size(lruvec, page, old_gen, new_gen); - } - - spin_unlock_irq(&pgdat->lru_lock); - - mem_cgroup_unlock_pages(); -} - /****************************************************************************** * the eviction ******************************************************************************/ @@ -3235,12 +3055,6 @@ static bool sort_page(struct lruvec *lruvec, struct page *page, int tier_idx) return true; } - /* promoted */ - if (gen != lru_gen_from_seq(lrugen->min_seq[type])) { - list_move(&page->lru, &lrugen->lists[gen][type][zone]); - return true; - } - /* protected */ if (tier > tier_idx) { int hist = lru_hist_from_seq(lrugen->min_seq[type]); From a246d9f08af298a7c4dc5538c9e83fb50fba7e6e Mon Sep 17 00:00:00 2001 From: xiewen3 Date: Tue, 16 May 2023 22:48:58 +0800 Subject: [PATCH 586/698] LUR: Revert "BACKPORT: mm: multi-gen LRU: minimal implementation" The LRU function is not compatible with GKI, causing GKI to fail to start, so revert. This reverts commit bdab47a49135e8ded0e5158717bc3a29dbf79e8c. Change-Id: I48190e01afcb59dae18d87a1ca785fcec73b2730 Reviewed-on: https://gerrit.mot.com/2609762 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- include/linux/mm_inline.h | 36 -- include/linux/mmzone.h | 44 -- include/linux/page-flags-layout.h | 5 +- kernel/bounds.c | 2 - mm/Kconfig | 11 - mm/memory.c | 19 +- mm/swap.c | 41 -- mm/swap_state.c | 9 +- mm/vmscan.c | 780 +----------------------------- mm/workingset.c | 114 +---- 10 files changed, 14 insertions(+), 1047 deletions(-) diff --git a/include/linux/mm_inline.h b/include/linux/mm_inline.h index 64b33e79165b..1d0414b49e66 100644 --- a/include/linux/mm_inline.h +++ b/include/linux/mm_inline.h @@ -120,33 +120,6 @@ static inline int lru_gen_from_seq(unsigned long seq) return seq % MAX_NR_GENS; } -static inline int lru_hist_from_seq(unsigned long seq) -{ - return seq % NR_HIST_GENS; -} - -static inline int lru_tier_from_refs(int refs) -{ - VM_WARN_ON_ONCE(refs > BIT(LRU_REFS_WIDTH)); - - /* see the comment in page_lru_refs() */ - return order_base_2(refs + 1); -} - -static inline int page_lru_refs(struct page *page) -{ - unsigned long flags = READ_ONCE(page->flags); - bool workingset = flags & BIT(PG_workingset); - - /* - * Return the number of accesses beyond PG_referenced, i.e., N-1 if the - * total number of accesses is N>1, since N=0,1 both map to the first - * tier. lru_tier_from_refs() will account for this off-by-one. Also see - * the comment on MAX_NR_TIERS. - */ - return ((flags & LRU_REFS_MASK) >> LRU_REFS_PGOFF) + workingset; -} - static inline int page_lru_gen(struct page *page) { unsigned long flags = READ_ONCE(page->flags); @@ -199,15 +172,6 @@ static inline void lru_gen_update_size(struct lruvec *lruvec, struct page *page, __update_lru_size(lruvec, lru, zone, -delta); return; } - - /* promotion */ - if (!lru_gen_is_active(lruvec, old_gen) && lru_gen_is_active(lruvec, new_gen)) { - __update_lru_size(lruvec, lru, zone, -delta); - __update_lru_size(lruvec, lru + LRU_ACTIVE, zone, delta); - } - - /* demotion requires isolation, e.g., lru_deactivate_fn() */ - VM_WARN_ON_ONCE(lru_gen_is_active(lruvec, old_gen) && !lru_gen_is_active(lruvec, new_gen)); } static inline bool lru_gen_add_page(struct lruvec *lruvec, struct page *page, bool reclaiming) diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index 2721b50970fe..b4aa67cfbf41 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -341,28 +341,6 @@ struct zone_reclaim_stat { #define MIN_NR_GENS 2U #define MAX_NR_GENS 4U -/* - * Each generation is divided into multiple tiers. A page accessed N times - * through file descriptors is in tier order_base_2(N). A page in the first tier - * (N=0,1) is marked by PG_referenced unless it was faulted in through page - * tables or read ahead. A page in any other tier (N>1) is marked by - * PG_referenced and PG_workingset. This implies a minimum of two tiers is - * supported without using additional bits in page->flags. - * - * In contrast to moving across generations which requires the LRU lock, moving - * across tiers only involves atomic operations on page->flags and therefore - * has a negligible cost in the buffered access path. In the eviction path, - * comparisons of refaulted/(evicted+protected) from the first tier and the - * rest infer whether pages accessed multiple times through file descriptors - * are statistically hot and thus worth protecting. - * - * MAX_NR_TIERS is set to 4 so that the multi-gen LRU can support twice the - * number of categories of the active/inactive LRU when keeping track of - * accesses through file descriptors. This uses MAX_NR_TIERS-2 spare bits in - * page->flags. - */ -#define MAX_NR_TIERS 4U - #ifndef __GENERATING_BOUNDS_H struct lruvec; @@ -370,9 +348,6 @@ struct lruvec; #define LRU_GEN_MASK ((BIT(LRU_GEN_WIDTH) - 1) << LRU_GEN_PGOFF) #define LRU_REFS_MASK ((BIT(LRU_REFS_WIDTH) - 1) << LRU_REFS_PGOFF) -void *lru_gen_eviction(struct page *page); -void lru_gen_refault(struct page *page, void *shadow); - #ifdef CONFIG_LRU_GEN enum { @@ -380,16 +355,6 @@ enum { LRU_GEN_FILE, }; -#define MIN_LRU_BATCH BITS_PER_LONG -#define MAX_LRU_BATCH (MIN_LRU_BATCH * 64) - -/* whether to keep historical stats from evicted generations */ -#ifdef CONFIG_LRU_GEN_STATS -#define NR_HIST_GENS MAX_NR_GENS -#else -#define NR_HIST_GENS 1U -#endif - /* * The youngest generation number is stored in max_seq for both anon and file * types as they are aged on an equal footing. The oldest generation numbers are @@ -412,15 +377,6 @@ struct lru_gen_struct { struct list_head lists[MAX_NR_GENS][ANON_AND_FILE][MAX_NR_ZONES]; /* the multi-gen LRU sizes, eventually consistent */ long nr_pages[MAX_NR_GENS][ANON_AND_FILE][MAX_NR_ZONES]; - /* the exponential moving average of refaulted */ - unsigned long avg_refaulted[ANON_AND_FILE][MAX_NR_TIERS]; - /* the exponential moving average of evicted+protected */ - unsigned long avg_total[ANON_AND_FILE][MAX_NR_TIERS]; - /* the first tier doesn't need protection, hence the minus one */ - unsigned long protected[NR_HIST_GENS][ANON_AND_FILE][MAX_NR_TIERS - 1]; - /* can be modified without holding the LRU lock */ - atomic_long_t evicted[NR_HIST_GENS][ANON_AND_FILE][MAX_NR_TIERS]; - atomic_long_t refaulted[NR_HIST_GENS][ANON_AND_FILE][MAX_NR_TIERS]; }; void lru_gen_init_lruvec(struct lruvec *lruvec); diff --git a/include/linux/page-flags-layout.h b/include/linux/page-flags-layout.h index f89a37da49d2..18b0bff4550a 100644 --- a/include/linux/page-flags-layout.h +++ b/include/linux/page-flags-layout.h @@ -96,10 +96,7 @@ #error "Not enough bits in page flags" #endif -/* see the comment on MAX_NR_TIERS */ -#define LRU_REFS_WIDTH min(__LRU_REFS_WIDTH, BITS_PER_LONG - NR_PAGEFLAGS - \ - ZONES_WIDTH - LRU_GEN_WIDTH - SECTIONS_WIDTH - \ - NODES_WIDTH - KASAN_TAG_WIDTH - LAST_CPUPID_WIDTH) +#define LRU_REFS_WIDTH 0 /* * We are going to use the flags for the page to node mapping if its in diff --git a/kernel/bounds.c b/kernel/bounds.c index b529182e8b04..5ee60777d8e4 100644 --- a/kernel/bounds.c +++ b/kernel/bounds.c @@ -24,10 +24,8 @@ int main(void) DEFINE(SPINLOCK_SIZE, sizeof(spinlock_t)); #ifdef CONFIG_LRU_GEN DEFINE(LRU_GEN_WIDTH, order_base_2(MAX_NR_GENS + 1)); - DEFINE(__LRU_REFS_WIDTH, MAX_NR_TIERS - 2); #else DEFINE(LRU_GEN_WIDTH, 0); - DEFINE(__LRU_REFS_WIDTH, 0); #endif /* End of constants */ diff --git a/mm/Kconfig b/mm/Kconfig index 5f7638bc90e4..57de0038609e 100644 --- a/mm/Kconfig +++ b/mm/Kconfig @@ -856,7 +856,6 @@ config OOM_TASK_PRIORITY_ADJ_LIMIT With this parameter you can limit the OOM killer to first kill tasks with an oom_score_adj value above a certain threshold before considering tasks with a lower oom_score_adj value. -# multi-gen LRU { config LRU_GEN bool "Multi-Gen LRU" depends on MMU @@ -865,16 +864,6 @@ config LRU_GEN help A high performance LRU implementation to overcommit memory. -config LRU_GEN_STATS - bool "Full stats for debugging" - depends on LRU_GEN - help - Do not enable this option unless you plan to look at historical stats - from evicted generations for debugging purpose. - - This option has a per-memcg and per-node memory overhead. -# } - endmenu config PROCESS_RECLAIM diff --git a/mm/memory.c b/mm/memory.c index 63d684cf3f8d..cd892d43d03f 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -71,8 +71,6 @@ #include #include #include -#include -#include #include @@ -3019,19 +3017,6 @@ void unmap_mapping_range(struct address_space *mapping, } EXPORT_SYMBOL(unmap_mapping_range); -static void lru_gen_swap_refault(struct page *page, swp_entry_t entry) -{ - if (lru_gen_enabled()) { - void *item; - struct address_space *mapping = swap_address_space(entry); - pgoff_t index = swp_offset(entry); - - item = xa_load(&mapping->i_pages, index); - if (xa_is_value(item)) - lru_gen_refault(page, item); - } -} - /* * We enter with non-exclusive mmap_sem (to exclude vma changes, * but allow concurrent faults), and pte mapped but not yet locked. @@ -3112,7 +3097,6 @@ vm_fault_t do_swap_page(struct vm_fault *vmf) __SetPageLocked(page); __SetPageSwapBacked(page); set_page_private(page, entry.val); - lru_gen_swap_refault(page, entry); lru_cache_add_anon(page); swap_readpage(page, true); } @@ -3246,8 +3230,7 @@ vm_fault_t do_swap_page(struct vm_fault *vmf) } else { do_page_add_anon_rmap(page, vma, vmf->address, exclusive); mem_cgroup_commit_charge(page, memcg, true, false); - if (!lru_gen_enabled()) - activate_page(page); + activate_page(page); } swap_free(entry); diff --git a/mm/swap.c b/mm/swap.c index 9003e635e255..3cd3d1ec8f4c 100644 --- a/mm/swap.c +++ b/mm/swap.c @@ -357,41 +357,6 @@ static void __lru_cache_activate_page(struct page *page) put_cpu_var(lru_add_pvec); } -#ifdef CONFIG_LRU_GEN -static void page_inc_refs(struct page *page) -{ - unsigned long new_flags, old_flags; - - if (PageUnevictable(page)) - return; - - if (!PageReferenced(page)) { - SetPageReferenced(page); - return; - } - - if (!PageWorkingset(page)) { - SetPageWorkingset(page); - return; - } - - /* see the comment on MAX_NR_TIERS */ - do { - old_flags = READ_ONCE(page->flags); - new_flags = old_flags & LRU_REFS_MASK; - if (new_flags == LRU_REFS_MASK) - break; - - new_flags += BIT(LRU_REFS_PGOFF); - new_flags |= old_flags & ~LRU_REFS_MASK; - } while (cmpxchg(&page->flags, old_flags, new_flags) != old_flags); -} -#else -static void page_inc_refs(struct page *page) -{ -} -#endif /* CONFIG_LRU_GEN */ - /* * Mark a page as having seen activity. * @@ -405,12 +370,6 @@ static void page_inc_refs(struct page *page) void mark_page_accessed(struct page *page) { page = compound_head(page); - - if (lru_gen_enabled()) { - page_inc_refs(page); - return; - } - if (!PageActive(page) && !PageUnevictable(page) && PageReferenced(page)) { diff --git a/mm/swap_state.c b/mm/swap_state.c index 505e54000952..e8bd52bb23b1 100644 --- a/mm/swap_state.c +++ b/mm/swap_state.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include "internal.h" @@ -410,7 +409,6 @@ struct page *__read_swap_cache_async(swp_entry_t entry, gfp_t gfp_mask, struct page *found_page = NULL, *new_page = NULL; struct swap_info_struct *si; int err; - void *shadow; *new_page_allocated = false; do { @@ -467,13 +465,10 @@ struct page *__read_swap_cache_async(swp_entry_t entry, gfp_t gfp_mask, __SetPageLocked(new_page); __SetPageSwapBacked(new_page); err = add_to_swap_cache(new_page, entry, - gfp_mask & GFP_RECLAIM_MASK, &shadow); + gfp_mask & GFP_RECLAIM_MASK, NULL); if (likely(!err)) { /* Initiate read into locked page */ - if (!lru_gen_enabled()) - SetPageWorkingset(new_page); - else if (shadow) - lru_gen_refault(new_page, shadow); + SetPageWorkingset(new_page); lru_cache_add_anon(new_page); *new_page_allocated = true; return new_page; diff --git a/mm/vmscan.c b/mm/vmscan.c index 7cf42b2eaee2..8db231e0b758 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -923,7 +923,6 @@ static int __remove_mapping(struct address_space *mapping, struct page *page, { unsigned long flags; int refcount; - void *shadow = NULL; BUG_ON(!PageLocked(page)); BUG_ON(mapping != page_mapping(page)); @@ -965,11 +964,8 @@ static int __remove_mapping(struct address_space *mapping, struct page *page, if (PageSwapCache(page)) { swp_entry_t swap = { .val = page_private(page) }; - - if (lru_gen_enabled()) - shadow = lru_gen_eviction(page); mem_cgroup_swapout(page, swap); - __delete_from_swap_cache(page, swap, shadow); + __delete_from_swap_cache(page, swap, NULL); xa_unlock_irqrestore(&mapping->i_pages, flags); put_swap_page(page, swap); } else { @@ -2637,17 +2633,6 @@ out: * shorthand helpers ******************************************************************************/ -#define LRU_REFS_FLAGS (BIT(PG_referenced) | BIT(PG_workingset)) - -#define DEFINE_MAX_SEQ(lruvec) \ - unsigned long max_seq = READ_ONCE((lruvec)->lrugen.max_seq) - -#define DEFINE_MIN_SEQ(lruvec) \ - unsigned long min_seq[ANON_AND_FILE] = { \ - READ_ONCE((lruvec)->lrugen.min_seq[LRU_GEN_ANON]), \ - READ_ONCE((lruvec)->lrugen.min_seq[LRU_GEN_FILE]), \ - } - #define for_each_gen_type_zone(gen, type, zone) \ for ((gen) = 0; (gen) < MAX_NR_GENS; (gen)++) \ for ((type) = 0; (type) < ANON_AND_FILE; (type)++) \ @@ -2673,734 +2658,6 @@ static struct lruvec __maybe_unused *get_lruvec(struct mem_cgroup *memcg, int ni return pgdat ? &pgdat->lruvec : NULL; } -static int get_swappiness(struct lruvec *lruvec, struct scan_control *sc) -{ - struct mem_cgroup *memcg = lruvec_memcg(lruvec); - - if (mem_cgroup_get_nr_swap_pages(memcg) < MIN_LRU_BATCH) - return 0; - - return mem_cgroup_swappiness(memcg); -} - -static int get_nr_gens(struct lruvec *lruvec, int type) -{ - return lruvec->lrugen.max_seq - lruvec->lrugen.min_seq[type] + 1; -} - -static bool __maybe_unused seq_is_valid(struct lruvec *lruvec) -{ - /* see the comment on lru_gen_struct */ - return get_nr_gens(lruvec, LRU_GEN_FILE) >= MIN_NR_GENS && - get_nr_gens(lruvec, LRU_GEN_FILE) <= get_nr_gens(lruvec, LRU_GEN_ANON) && - get_nr_gens(lruvec, LRU_GEN_ANON) <= MAX_NR_GENS; -} - -/****************************************************************************** - * refault feedback loop - ******************************************************************************/ - -/* - * A feedback loop based on Proportional-Integral-Derivative (PID) controller. - * - * The P term is refaulted/(evicted+protected) from a tier in the generation - * currently being evicted; the I term is the exponential moving average of the - * P term over the generations previously evicted, using the smoothing factor - * 1/2; the D term isn't supported. - * - * The setpoint (SP) is always the first tier of one type; the process variable - * (PV) is either any tier of the other type or any other tier of the same - * type. - * - * The error is the difference between the SP and the PV; the correction is to - * turn off protection when SP>PV or turn on protection when SPlrugen; - int hist = lru_hist_from_seq(lrugen->min_seq[type]); - - pos->refaulted = lrugen->avg_refaulted[type][tier] + - atomic_long_read(&lrugen->refaulted[hist][type][tier]); - pos->total = lrugen->avg_total[type][tier] + - atomic_long_read(&lrugen->evicted[hist][type][tier]); - if (tier) - pos->total += lrugen->protected[hist][type][tier - 1]; - pos->gain = gain; -} - -static void reset_ctrl_pos(struct lruvec *lruvec, int type, bool carryover) -{ - int hist, tier; - struct lru_gen_struct *lrugen = &lruvec->lrugen; - bool clear = carryover ? NR_HIST_GENS == 1 : NR_HIST_GENS > 1; - unsigned long seq = carryover ? lrugen->min_seq[type] : lrugen->max_seq + 1; - - lockdep_assert_held(&lruvec_pgdat(lruvec)->lru_lock); - - if (!carryover && !clear) - return; - - hist = lru_hist_from_seq(seq); - - for (tier = 0; tier < MAX_NR_TIERS; tier++) { - if (carryover) { - unsigned long sum; - - sum = lrugen->avg_refaulted[type][tier] + - atomic_long_read(&lrugen->refaulted[hist][type][tier]); - WRITE_ONCE(lrugen->avg_refaulted[type][tier], sum / 2); - - sum = lrugen->avg_total[type][tier] + - atomic_long_read(&lrugen->evicted[hist][type][tier]); - if (tier) - sum += lrugen->protected[hist][type][tier - 1]; - WRITE_ONCE(lrugen->avg_total[type][tier], sum / 2); - } - - if (clear) { - atomic_long_set(&lrugen->refaulted[hist][type][tier], 0); - atomic_long_set(&lrugen->evicted[hist][type][tier], 0); - if (tier) - WRITE_ONCE(lrugen->protected[hist][type][tier - 1], 0); - } - } -} - -static bool positive_ctrl_err(struct ctrl_pos *sp, struct ctrl_pos *pv) -{ - /* - * Return true if the PV has a limited number of refaults or a lower - * refaulted/total than the SP. - */ - return pv->refaulted < MIN_LRU_BATCH || - pv->refaulted * (sp->total + MIN_LRU_BATCH) * sp->gain <= - (sp->refaulted + 1) * pv->total * pv->gain; -} - -/****************************************************************************** - * the aging - ******************************************************************************/ - -/* protect pages accessed multiple times through file descriptors */ -static int page_inc_gen(struct lruvec *lruvec, struct page *page, bool reclaiming) -{ - int type = page_is_file_cache(page); - struct lru_gen_struct *lrugen = &lruvec->lrugen; - int new_gen, old_gen = lru_gen_from_seq(lrugen->min_seq[type]); - unsigned long new_flags, old_flags; - - do { - old_flags = READ_ONCE(page->flags); - - VM_WARN_ON_ONCE_PAGE(!(old_flags & LRU_GEN_MASK), page); - - new_gen = (old_gen + 1) % MAX_NR_GENS; - - new_flags = old_flags & ~(LRU_GEN_MASK | LRU_REFS_MASK | LRU_REFS_FLAGS); - new_flags |= (new_gen + 1UL) << LRU_GEN_PGOFF; - /* for end_page_writeback() */ - if (reclaiming) - new_flags |= BIT(PG_reclaim); - } while (cmpxchg(&page->flags, old_flags, new_flags) != old_flags); - - lru_gen_update_size(lruvec, page, old_gen, new_gen); - - return new_gen; -} - -static void inc_min_seq(struct lruvec *lruvec, int type) -{ - struct lru_gen_struct *lrugen = &lruvec->lrugen; - - reset_ctrl_pos(lruvec, type, true); - WRITE_ONCE(lrugen->min_seq[type], lrugen->min_seq[type] + 1); -} - -static bool try_to_inc_min_seq(struct lruvec *lruvec, bool can_swap) -{ - int gen, type, zone; - bool success = false; - struct lru_gen_struct *lrugen = &lruvec->lrugen; - DEFINE_MIN_SEQ(lruvec); - - VM_WARN_ON_ONCE(!seq_is_valid(lruvec)); - - /* find the oldest populated generation */ - for (type = !can_swap; type < ANON_AND_FILE; type++) { - while (min_seq[type] + MIN_NR_GENS <= lrugen->max_seq) { - gen = lru_gen_from_seq(min_seq[type]); - - for (zone = 0; zone < MAX_NR_ZONES; zone++) { - if (!list_empty(&lrugen->lists[gen][type][zone])) - goto next; - } - - min_seq[type]++; - } -next: - ; - } - - /* see the comment on lru_gen_struct */ - if (can_swap) { - min_seq[LRU_GEN_ANON] = min(min_seq[LRU_GEN_ANON], min_seq[LRU_GEN_FILE]); - min_seq[LRU_GEN_FILE] = max(min_seq[LRU_GEN_ANON], lrugen->min_seq[LRU_GEN_FILE]); - } - - for (type = !can_swap; type < ANON_AND_FILE; type++) { - if (min_seq[type] == lrugen->min_seq[type]) - continue; - - reset_ctrl_pos(lruvec, type, true); - WRITE_ONCE(lrugen->min_seq[type], min_seq[type]); - success = true; - } - - return success; -} - -static void inc_max_seq(struct lruvec *lruvec, unsigned long max_seq, bool can_swap) -{ - int prev, next; - int type, zone; - struct lru_gen_struct *lrugen = &lruvec->lrugen; - struct pglist_data *pgdat = lruvec_pgdat(lruvec); - - spin_lock_irq(&pgdat->lru_lock); - - VM_WARN_ON_ONCE(!seq_is_valid(lruvec)); - - if (max_seq != lrugen->max_seq) - goto unlock; - - for (type = ANON_AND_FILE - 1; type >= 0; type--) { - if (get_nr_gens(lruvec, type) != MAX_NR_GENS) - continue; - - VM_WARN_ON_ONCE(type == LRU_GEN_FILE || can_swap); - - inc_min_seq(lruvec, type); - } - - /* - * Update the active/inactive LRU sizes for compatibility. Both sides of - * the current max_seq need to be covered, since max_seq+1 can overlap - * with min_seq[LRU_GEN_ANON] if swapping is constrained. And if they do - * overlap, cold/hot inversion happens. - */ - prev = lru_gen_from_seq(lrugen->max_seq - 1); - next = lru_gen_from_seq(lrugen->max_seq + 1); - - for (type = 0; type < ANON_AND_FILE; type++) { - for (zone = 0; zone < MAX_NR_ZONES; zone++) { - enum lru_list lru = type * LRU_INACTIVE_FILE; - long delta = lrugen->nr_pages[prev][type][zone] - - lrugen->nr_pages[next][type][zone]; - - if (!delta) - continue; - - __update_lru_size(lruvec, lru, zone, delta); - __update_lru_size(lruvec, lru + LRU_ACTIVE, zone, -delta); - } - } - - for (type = 0; type < ANON_AND_FILE; type++) - reset_ctrl_pos(lruvec, type, false); - - /* make sure preceding modifications appear */ - smp_store_release(&lrugen->max_seq, lrugen->max_seq + 1); -unlock: - spin_unlock_irq(&pgdat->lru_lock); -} - -static bool should_run_aging(struct lruvec *lruvec, unsigned long max_seq, unsigned long *min_seq, - struct scan_control *sc, bool can_swap, unsigned long *nr_to_scan) -{ - int gen, type, zone; - unsigned long old = 0; - unsigned long young = 0; - unsigned long total = 0; - struct lru_gen_struct *lrugen = &lruvec->lrugen; - struct mem_cgroup *memcg = lruvec_memcg(lruvec); - - for (type = !can_swap; type < ANON_AND_FILE; type++) { - unsigned long seq; - - for (seq = min_seq[type]; seq <= max_seq; seq++) { - unsigned long size = 0; - - gen = lru_gen_from_seq(seq); - - for (zone = 0; zone < MAX_NR_ZONES; zone++) - size += max(READ_ONCE(lrugen->nr_pages[gen][type][zone]), 0L); - - total += size; - if (seq == max_seq) - young += size; - else if (seq + MIN_NR_GENS == max_seq) - old += size; - } - } - - /* try to scrape all its memory if this memcg was deleted */ - *nr_to_scan = mem_cgroup_online(memcg) ? (total >> sc->priority) : total; - - /* - * The aging tries to be lazy to reduce the overhead, while the eviction - * stalls when the number of generations reaches MIN_NR_GENS. Hence, the - * ideal number of generations is MIN_NR_GENS+1. - */ - if (min_seq[!can_swap] + MIN_NR_GENS > max_seq) - return true; - if (min_seq[!can_swap] + MIN_NR_GENS < max_seq) - return false; - - /* - * It's also ideal to spread pages out evenly, i.e., 1/(MIN_NR_GENS+1) - * of the total number of pages for each generation. A reasonable range - * for this average portion is [1/MIN_NR_GENS, 1/(MIN_NR_GENS+2)]. The - * aging cares about the upper bound of hot pages, while the eviction - * cares about the lower bound of cold pages. - */ - if (young * MIN_NR_GENS > total) - return true; - if (old * (MIN_NR_GENS + 2) < total) - return true; - - return false; -} - -static void age_lruvec(struct lruvec *lruvec, struct scan_control *sc) -{ - bool need_aging; - unsigned long nr_to_scan; - int swappiness = get_swappiness(lruvec, sc); - struct mem_cgroup *memcg = lruvec_memcg(lruvec); - enum mem_cgroup_protection prot = mem_cgroup_protected(NULL, memcg); - DEFINE_MAX_SEQ(lruvec); - DEFINE_MIN_SEQ(lruvec); - - VM_WARN_ON_ONCE(sc->memcg_low_reclaim); - - if (prot == MEMCG_PROT_MIN) - return; - - need_aging = should_run_aging(lruvec, max_seq, min_seq, sc, swappiness, &nr_to_scan); - if (need_aging) - inc_max_seq(lruvec, max_seq, swappiness); -} - -static void lru_gen_age_node(struct pglist_data *pgdat, struct scan_control *sc) -{ - struct mem_cgroup *memcg; - - VM_WARN_ON_ONCE(!current_is_kswapd()); - - memcg = mem_cgroup_iter(NULL, NULL, NULL); - do { - struct lruvec *lruvec = mem_cgroup_lruvec(pgdat, memcg); - - age_lruvec(lruvec, sc); - - cond_resched(); - } while ((memcg = mem_cgroup_iter(NULL, memcg, NULL))); -} - -/****************************************************************************** - * the eviction - ******************************************************************************/ - -static bool sort_page(struct lruvec *lruvec, struct page *page, int tier_idx) -{ - bool success; - int gen = page_lru_gen(page); - int type = page_is_file_cache(page); - int zone = page_zonenum(page); - int delta = hpage_nr_pages(page); - int refs = page_lru_refs(page); - int tier = lru_tier_from_refs(refs); - struct lru_gen_struct *lrugen = &lruvec->lrugen; - - VM_WARN_ON_ONCE_PAGE(gen >= MAX_NR_GENS, page); - - /* unevictable */ - if (!page_evictable(page)) { - success = lru_gen_del_page(lruvec, page, true); - VM_WARN_ON_ONCE_PAGE(!success, page); - SetPageUnevictable(page); - add_page_to_lru_list(page, lruvec); - __count_vm_events(UNEVICTABLE_PGCULLED, delta); - return true; - } - - /* dirty lazyfree */ - if (type == LRU_GEN_FILE && PageAnon(page) && PageDirty(page)) { - success = lru_gen_del_page(lruvec, page, true); - VM_WARN_ON_ONCE_PAGE(!success, page); - SetPageSwapBacked(page); - add_page_to_lru_list_tail(page, lruvec); - return true; - } - - /* protected */ - if (tier > tier_idx) { - int hist = lru_hist_from_seq(lrugen->min_seq[type]); - - gen = page_inc_gen(lruvec, page, false); - list_move_tail(&page->lru, &lrugen->lists[gen][type][zone]); - - WRITE_ONCE(lrugen->protected[hist][type][tier - 1], - lrugen->protected[hist][type][tier - 1] + delta); - __mod_lruvec_state(lruvec, WORKINGSET_ACTIVATE, delta); - return true; - } - - /* waiting for writeback */ - if (PageLocked(page) || PageWriteback(page) || - (type == LRU_GEN_FILE && PageDirty(page))) { - gen = page_inc_gen(lruvec, page, true); - list_move(&page->lru, &lrugen->lists[gen][type][zone]); - return true; - } - - return false; -} - -static bool isolate_page(struct lruvec *lruvec, struct page *page, struct scan_control *sc) -{ - bool success; - - /* unmapping inhibited */ - if (!sc->may_unmap && page_mapped(page)) - return false; - - /* swapping inhibited */ - if (!(sc->may_writepage && (sc->gfp_mask & __GFP_IO)) && - (PageDirty(page) || - (PageAnon(page) && !PageSwapCache(page)))) - return false; - - /* raced with release_pages() */ - if (!get_page_unless_zero(page)) - return false; - - ClearPageLRU(page); - - /* see the comment on MAX_NR_TIERS */ - if (!PageReferenced(page)) - set_mask_bits(&page->flags, LRU_REFS_MASK | LRU_REFS_FLAGS, 0); - - /* for shrink_page_list() */ - ClearPageReclaim(page); - ClearPageReferenced(page); - - success = lru_gen_del_page(lruvec, page, true); - VM_WARN_ON_ONCE_PAGE(!success, page); - - return true; -} - -static int scan_pages(struct lruvec *lruvec, struct scan_control *sc, - int type, int tier, struct list_head *list) -{ - int gen, zone; - enum vm_event_item item; - int sorted = 0; - int scanned = 0; - int isolated = 0; - int remaining = MAX_LRU_BATCH; - struct lru_gen_struct *lrugen = &lruvec->lrugen; - struct mem_cgroup *memcg = lruvec_memcg(lruvec); - - VM_WARN_ON_ONCE(!list_empty(list)); - - if (get_nr_gens(lruvec, type) == MIN_NR_GENS) - return 0; - - gen = lru_gen_from_seq(lrugen->min_seq[type]); - - for (zone = sc->reclaim_idx; zone >= 0; zone--) { - LIST_HEAD(moved); - int skipped = 0; - struct list_head *head = &lrugen->lists[gen][type][zone]; - - while (!list_empty(head)) { - struct page *page = lru_to_page(head); - int delta = hpage_nr_pages(page); - - VM_WARN_ON_ONCE_PAGE(PageUnevictable(page), page); - VM_WARN_ON_ONCE_PAGE(PageActive(page), page); - VM_WARN_ON_ONCE_PAGE(page_is_file_cache(page) != type, page); - VM_WARN_ON_ONCE_PAGE(page_zonenum(page) != zone, page); - - scanned += delta; - - if (sort_page(lruvec, page, tier)) - sorted += delta; - else if (isolate_page(lruvec, page, sc)) { - list_add(&page->lru, list); - isolated += delta; - } else { - list_move(&page->lru, &moved); - skipped += delta; - } - - if (!--remaining || max(isolated, skipped) >= MIN_LRU_BATCH) - break; - } - - if (skipped) { - list_splice(&moved, head); - __count_zid_vm_events(PGSCAN_SKIP, zone, skipped); - } - - if (!remaining || isolated >= MIN_LRU_BATCH) - break; - } - - item = current_is_kswapd() ? PGSCAN_KSWAPD : PGSCAN_DIRECT; - if (global_reclaim(sc)) { - __count_vm_events(item, isolated); - __count_vm_events(PGREFILL, sorted); - } - __count_memcg_events(memcg, item, isolated); - __count_memcg_events(memcg, PGREFILL, sorted); - - /* - * There might not be eligible pages due to reclaim_idx, may_unmap and - * may_writepage. Check the remaining to prevent livelock if it's not - * making progress. - */ - return isolated || !remaining ? scanned : 0; -} - -static int get_tier_idx(struct lruvec *lruvec, int type) -{ - int tier; - struct ctrl_pos sp, pv; - - /* - * To leave a margin for fluctuations, use a larger gain factor (1:2). - * This value is chosen because any other tier would have at least twice - * as many refaults as the first tier. - */ - read_ctrl_pos(lruvec, type, 0, 1, &sp); - for (tier = 1; tier < MAX_NR_TIERS; tier++) { - read_ctrl_pos(lruvec, type, tier, 2, &pv); - if (!positive_ctrl_err(&sp, &pv)) - break; - } - - return tier - 1; -} - -static int get_type_to_scan(struct lruvec *lruvec, int swappiness, int *tier_idx) -{ - int type, tier; - struct ctrl_pos sp, pv; - int gain[ANON_AND_FILE] = { swappiness, 200 - swappiness }; - - /* - * Compare the first tier of anon with that of file to determine which - * type to scan. Also need to compare other tiers of the selected type - * with the first tier of the other type to determine the last tier (of - * the selected type) to evict. - */ - read_ctrl_pos(lruvec, LRU_GEN_ANON, 0, gain[LRU_GEN_ANON], &sp); - read_ctrl_pos(lruvec, LRU_GEN_FILE, 0, gain[LRU_GEN_FILE], &pv); - type = positive_ctrl_err(&sp, &pv); - - read_ctrl_pos(lruvec, !type, 0, gain[!type], &sp); - for (tier = 1; tier < MAX_NR_TIERS; tier++) { - read_ctrl_pos(lruvec, type, tier, gain[type], &pv); - if (!positive_ctrl_err(&sp, &pv)) - break; - } - - *tier_idx = tier - 1; - - return type; -} - -static int isolate_pages(struct lruvec *lruvec, struct scan_control *sc, int swappiness, - int *type_scanned, struct list_head *list) -{ - int i; - int type; - int scanned; - int tier = -1; - DEFINE_MIN_SEQ(lruvec); - - /* - * Try to make the obvious choice first. When anon and file are both - * available from the same generation, interpret swappiness 1 as file - * first and 200 as anon first. - */ - if (!swappiness) - type = LRU_GEN_FILE; - else if (min_seq[LRU_GEN_ANON] < min_seq[LRU_GEN_FILE]) - type = LRU_GEN_ANON; - else if (swappiness == 1) - type = LRU_GEN_FILE; - else if (swappiness == 200) - type = LRU_GEN_ANON; - else - type = get_type_to_scan(lruvec, swappiness, &tier); - - for (i = !swappiness; i < ANON_AND_FILE; i++) { - if (tier < 0) - tier = get_tier_idx(lruvec, type); - - scanned = scan_pages(lruvec, sc, type, tier, list); - if (scanned) - break; - - type = !type; - tier = -1; - } - - *type_scanned = type; - - return scanned; -} - -static int evict_pages(struct lruvec *lruvec, struct scan_control *sc, int swappiness) -{ - int type; - int scanned; - int reclaimed; - LIST_HEAD(list); - struct page *page; - enum vm_event_item item; - struct reclaim_stat stat; - struct mem_cgroup *memcg = lruvec_memcg(lruvec); - struct pglist_data *pgdat = lruvec_pgdat(lruvec); - - spin_lock_irq(&pgdat->lru_lock); - - scanned = isolate_pages(lruvec, sc, swappiness, &type, &list); - - scanned += try_to_inc_min_seq(lruvec, swappiness); - - if (get_nr_gens(lruvec, !swappiness) == MIN_NR_GENS) - scanned = 0; - - spin_unlock_irq(&pgdat->lru_lock); - - if (list_empty(&list)) - return scanned; - - reclaimed = shrink_page_list(&list, pgdat, sc, 0, &stat, false); - - list_for_each_entry(page, &list, lru) { - /* restore LRU_REFS_FLAGS cleared by isolate_page() */ - if (PageWorkingset(page)) - SetPageReferenced(page); - - /* don't add rejected pages to the oldest generation */ - if (PageReclaim(page) && - (PageDirty(page) || PageWriteback(page))) - ClearPageActive(page); - else - SetPageActive(page); - } - - spin_lock_irq(&pgdat->lru_lock); - - move_pages_to_lru(lruvec, &list); - - item = current_is_kswapd() ? PGSTEAL_KSWAPD : PGSTEAL_DIRECT; - if (global_reclaim(sc)) - __count_vm_events(item, reclaimed); - __count_memcg_events(memcg, item, reclaimed); - - spin_unlock_irq(&pgdat->lru_lock); - - mem_cgroup_uncharge_list(&list); - free_unref_page_list(&list); - - sc->nr_reclaimed += reclaimed; - - return scanned; -} - -static unsigned long get_nr_to_scan(struct lruvec *lruvec, struct scan_control *sc, - bool can_swap) -{ - bool need_aging; - unsigned long nr_to_scan; - DEFINE_MAX_SEQ(lruvec); - DEFINE_MIN_SEQ(lruvec); - - need_aging = should_run_aging(lruvec, max_seq, min_seq, sc, can_swap, &nr_to_scan); - if (!need_aging) - return nr_to_scan; - - /* skip the aging path at the default priority */ - if (sc->priority == DEF_PRIORITY) - goto done; - - /* leave the work to lru_gen_age_node() */ - if (current_is_kswapd()) - return 0; - - inc_max_seq(lruvec, max_seq, can_swap); -done: - return min_seq[!can_swap] + MIN_NR_GENS <= max_seq ? nr_to_scan : 0; -} - -static void lru_gen_shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc) -{ - struct blk_plug plug; - unsigned long scanned = 0; - - lru_add_drain(); - - blk_start_plug(&plug); - - while (true) { - int delta; - int swappiness; - unsigned long nr_to_scan; - - if (sc->may_swap) - swappiness = get_swappiness(lruvec, sc); - else if (global_reclaim(sc) && get_swappiness(lruvec, sc)) - swappiness = 1; - else - swappiness = 0; - - nr_to_scan = get_nr_to_scan(lruvec, sc, swappiness); - if (!nr_to_scan) - break; - - delta = evict_pages(lruvec, sc, swappiness); - if (!delta) - break; - - scanned += delta; - if (scanned >= nr_to_scan) - break; - - cond_resched(); - } - - blk_finish_plug(&plug); -} - /****************************************************************************** * initialization ******************************************************************************/ @@ -3443,16 +2700,6 @@ static int __init init_lru_gen(void) }; late_initcall(init_lru_gen); -#else /* !CONFIG_LRU_GEN */ - -static void lru_gen_age_node(struct pglist_data *pgdat, struct scan_control *sc) -{ -} - -static void lru_gen_shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc) -{ -} - #endif /* CONFIG_LRU_GEN */ /* @@ -3471,11 +2718,6 @@ static void shrink_node_memcg(struct pglist_data *pgdat, struct mem_cgroup *memc struct blk_plug plug; bool scan_adjusted; - if (lru_gen_enabled()) { - lru_gen_shrink_lruvec(lruvec, sc); - return; - } - get_scan_count(lruvec, memcg, sc, nr, lru_pages); /* Record the original scan target for proportional adjustments later */ @@ -3950,9 +3192,6 @@ static void snapshot_refaults(struct mem_cgroup *root_memcg, pg_data_t *pgdat) { struct mem_cgroup *memcg; - if (lru_gen_enabled()) - return; - memcg = mem_cgroup_iter(root_memcg, NULL, NULL); do { unsigned long refaults; @@ -4310,15 +3549,11 @@ unsigned long try_to_free_mem_cgroup_pages(struct mem_cgroup *memcg, } #endif -static void kswapd_age_node(struct pglist_data *pgdat, struct scan_control *sc) +static void age_active_anon(struct pglist_data *pgdat, + struct scan_control *sc) { struct mem_cgroup *memcg; - if (lru_gen_enabled()) { - lru_gen_age_node(pgdat, sc); - return; - } - if (!total_swap_pages) return; @@ -4598,11 +3833,12 @@ restart: sc.may_swap = !nr_boost_reclaim; /* - * Do some background aging, to give pages a chance to be - * referenced before reclaiming. All pages are rotated - * regardless of classzone as this is about consistent aging. + * Do some background aging of the anon list, to give + * pages a chance to be referenced before reclaiming. All + * pages are rotated regardless of classzone as this is + * about consistent aging. */ - kswapd_age_node(pgdat, &sc); + age_active_anon(pgdat, &sc); /* * If we're getting trouble reclaiming, start doing writepage diff --git a/mm/workingset.c b/mm/workingset.c index 3f422d514ff6..b51d8eace8a0 100644 --- a/mm/workingset.c +++ b/mm/workingset.c @@ -7,7 +7,6 @@ #include #include -#include #include #include #include @@ -185,6 +184,7 @@ static unsigned int bucket_order __read_mostly; static void *pack_shadow(int memcgid, pg_data_t *pgdat, unsigned long eviction, bool workingset) { + eviction >>= bucket_order; eviction &= EVICTION_MASK; eviction = (eviction << MEM_CGROUP_ID_SHIFT) | memcgid; eviction = (eviction << NODES_SHIFT) | pgdat->node_id; @@ -209,110 +209,10 @@ static void unpack_shadow(void *shadow, int *memcgidp, pg_data_t **pgdat, *memcgidp = memcgid; *pgdat = NODE_DATA(nid); - *evictionp = entry; + *evictionp = entry << bucket_order; *workingsetp = workingset; } -#ifdef CONFIG_LRU_GEN - -void *lru_gen_eviction(struct page *page) -{ - int hist; - unsigned long token; - unsigned long min_seq; - struct lruvec *lruvec; - struct lru_gen_struct *lrugen; - int type = page_is_file_cache(page); - int delta = hpage_nr_pages(page); - int refs = page_lru_refs(page); - int tier = lru_tier_from_refs(refs); - struct mem_cgroup *memcg = page_memcg(page); - struct pglist_data *pgdat = page_pgdat(page); - - if (!mem_cgroup_disabled() && !memcg) - return NULL; - - BUILD_BUG_ON(LRU_GEN_WIDTH + LRU_REFS_WIDTH > BITS_PER_LONG - EVICTION_SHIFT); - - lruvec = mem_cgroup_lruvec(pgdat, memcg); - lrugen = &lruvec->lrugen; - min_seq = READ_ONCE(lrugen->min_seq[type]); - token = (min_seq << LRU_REFS_WIDTH) | max(refs - 1, 0); - - hist = lru_hist_from_seq(min_seq); - atomic_long_add(delta, &lrugen->evicted[hist][type][tier]); - - return pack_shadow(mem_cgroup_id(memcg), pgdat, token, refs); -} - -void lru_gen_refault(struct page *page, void *shadow) -{ - int hist, tier, refs; - int memcg_id; - bool workingset; - unsigned long token; - unsigned long min_seq; - struct lruvec *lruvec; - struct lru_gen_struct *lrugen; - struct mem_cgroup *memcg; - struct pglist_data *pgdat; - int type = page_is_file_cache(page); - int delta = hpage_nr_pages(page); - - unpack_shadow(shadow, &memcg_id, &pgdat, &token, &workingset); - - if (pgdat != page_pgdat(page)) - return; - - rcu_read_lock(); - - memcg = page_memcg_rcu(page); - if ((!mem_cgroup_disabled() && !memcg) || memcg_id != mem_cgroup_id(memcg)) - goto unlock; - - lruvec = mem_cgroup_lruvec(pgdat, memcg); - lrugen = &lruvec->lrugen; - - min_seq = READ_ONCE(lrugen->min_seq[type]); - if ((token >> LRU_REFS_WIDTH) != (min_seq & (EVICTION_MASK >> LRU_REFS_WIDTH))) - goto unlock; - - hist = lru_hist_from_seq(min_seq); - /* see the comment in page_lru_refs() */ - refs = (token & (BIT(LRU_REFS_WIDTH) - 1)) + workingset; - tier = lru_tier_from_refs(refs); - - atomic_long_add(delta, &lrugen->refaulted[hist][type][tier]); - mod_lruvec_state(lruvec, WORKINGSET_REFAULT, delta); - - /* - * Count the following two cases as stalls: - * 1. For pages accessed through page tables, hotter pages pushed out - * hot pages which refaulted immediately. - * 2. For pages accessed multiple times through file descriptors, - * numbers of accesses might have been out of the range. - */ - if (lru_gen_in_fault() || refs == BIT(LRU_REFS_WIDTH)) { - SetPageWorkingset(page); - mod_lruvec_state(lruvec, WORKINGSET_RESTORE, delta); - } -unlock: - rcu_read_unlock(); -} - -#else /* !CONFIG_LRU_GEN */ - -void *lru_gen_eviction(struct page *page) -{ - return NULL; -} - -void lru_gen_refault(struct page *page, void *shadow) -{ -} - -#endif /* CONFIG_LRU_GEN */ - /** * workingset_eviction - note the eviction of a page from memory * @page: the page being evicted @@ -328,9 +228,6 @@ void *workingset_eviction(struct page *page) unsigned long eviction; struct lruvec *lruvec; - if (lru_gen_enabled()) - return lru_gen_eviction(page); - /* Page is fully exclusive and pins page->mem_cgroup */ VM_BUG_ON_PAGE(PageLRU(page), page); VM_BUG_ON_PAGE(page_count(page), page); @@ -338,7 +235,6 @@ void *workingset_eviction(struct page *page) lruvec = mem_cgroup_lruvec(pgdat, memcg); eviction = atomic_long_inc_return(&lruvec->inactive_age); - eviction >>= bucket_order; return pack_shadow(memcgid, pgdat, eviction, PageWorkingset(page)); } @@ -362,13 +258,7 @@ void workingset_refault(struct page *page, void *shadow) bool workingset; int memcgid; - if (lru_gen_enabled()) { - lru_gen_refault(page, shadow); - return; - } - unpack_shadow(shadow, &memcgid, &pgdat, &eviction, &workingset); - eviction <<= bucket_order; rcu_read_lock(); /* From 0c15b26b726ce490ffc0003f136ec5439754259c Mon Sep 17 00:00:00 2001 From: xiewen3 Date: Tue, 16 May 2023 22:50:54 +0800 Subject: [PATCH 587/698] LUR: Revert "BACKPORT: mm: multi-gen LRU: groundwork" The LRU function is not compatible with GKI, causing GKI to fail to start, so revert. This reverts commit 82f8143939a9ab52528733433ebfb8f22df2224d. Change-Id: I7df728d1ad77b59070a61fb90575fdf348532e2a Reviewed-on: https://gerrit.mot.com/2609763 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- fs/fuse/dev.c | 3 +- include/linux/mm.h | 2 - include/linux/mm_inline.h | 177 +----------------------------- include/linux/mmzone.h | 100 ----------------- include/linux/page-flags-layout.h | 13 +-- include/linux/page-flags.h | 4 +- include/linux/sched.h | 4 - kernel/bounds.c | 5 - mm/Kconfig | 7 -- mm/huge_memory.c | 3 +- mm/memcontrol.c | 2 - mm/memory.c | 24 ---- mm/mm_init.c | 7 +- mm/mmzone.c | 2 - mm/swap.c | 10 +- mm/vmscan.c | 75 ------------- 16 files changed, 14 insertions(+), 424 deletions(-) diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index d1cae08ba1cb..a4b663f50701 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -776,8 +776,7 @@ static int fuse_check_page(struct page *page) 1 << PG_active | 1 << PG_workingset | 1 << PG_reclaim | - 1 << PG_waiters | - LRU_GEN_MASK | LRU_REFS_MASK))) { + 1 << PG_waiters))) { pr_warn("trying to steal weird page\n"); pr_warn(" page=%p index=%li flags=%08lx, count=%i, mapcount=%i, mapping=%p\n", page, page->index, page->flags, page_count(page), page_mapcount(page), page->mapping); return 1; diff --git a/include/linux/mm.h b/include/linux/mm.h index 0389ca4f7c3f..5114ec750e19 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -966,8 +966,6 @@ vm_fault_t finish_mkwrite_fault(struct vm_fault *vmf); #define ZONES_PGOFF (NODES_PGOFF - ZONES_WIDTH) #define LAST_CPUPID_PGOFF (ZONES_PGOFF - LAST_CPUPID_WIDTH) #define KASAN_TAG_PGOFF (LAST_CPUPID_PGOFF - KASAN_TAG_WIDTH) -#define LRU_GEN_PGOFF (KASAN_TAG_PGOFF - LRU_GEN_WIDTH) -#define LRU_REFS_PGOFF (LRU_GEN_PGOFF - LRU_REFS_WIDTH) /* * Define the bit shifts to access each section. For non-existent diff --git a/include/linux/mm_inline.h b/include/linux/mm_inline.h index 1d0414b49e66..24dbfcfe4a6d 100644 --- a/include/linux/mm_inline.h +++ b/include/linux/mm_inline.h @@ -25,13 +25,10 @@ static inline int page_is_file_cache(struct page *page) static __always_inline void __update_lru_size(struct lruvec *lruvec, enum lru_list lru, enum zone_type zid, - long nr_pages) + int nr_pages) { struct pglist_data *pgdat = lruvec_pgdat(lruvec); - lockdep_assert_held(&pgdat->lru_lock); - WARN_ON_ONCE(nr_pages != (int)nr_pages); - __mod_lruvec_state(lruvec, NR_LRU_BASE + lru, nr_pages); __mod_zone_page_state(&pgdat->node_zones[zid], NR_ZONE_LRU_BASE + lru, nr_pages); @@ -103,177 +100,11 @@ static __always_inline enum lru_list page_lru(struct page *page) return lru; } -#ifdef CONFIG_LRU_GEN - -static inline bool lru_gen_enabled(void) -{ - return true; -} - -static inline bool lru_gen_in_fault(void) -{ - return current->in_lru_fault; -} - -static inline int lru_gen_from_seq(unsigned long seq) -{ - return seq % MAX_NR_GENS; -} - -static inline int page_lru_gen(struct page *page) -{ - unsigned long flags = READ_ONCE(page->flags); - - return ((flags & LRU_GEN_MASK) >> LRU_GEN_PGOFF) - 1; -} - -static inline bool lru_gen_is_active(struct lruvec *lruvec, int gen) -{ - unsigned long max_seq = lruvec->lrugen.max_seq; - - VM_WARN_ON_ONCE(gen >= MAX_NR_GENS); - - /* see the comment on MIN_NR_GENS */ - return gen == lru_gen_from_seq(max_seq) || gen == lru_gen_from_seq(max_seq - 1); -} - -static inline void lru_gen_update_size(struct lruvec *lruvec, struct page *page, - int old_gen, int new_gen) -{ - int type = page_is_file_cache(page); - int zone = page_zonenum(page); - int delta = hpage_nr_pages(page); - enum lru_list lru = type * LRU_INACTIVE_FILE; - struct lru_gen_struct *lrugen = &lruvec->lrugen; - - VM_WARN_ON_ONCE(old_gen != -1 && old_gen >= MAX_NR_GENS); - VM_WARN_ON_ONCE(new_gen != -1 && new_gen >= MAX_NR_GENS); - VM_WARN_ON_ONCE(old_gen == -1 && new_gen == -1); - - if (old_gen >= 0) - WRITE_ONCE(lrugen->nr_pages[old_gen][type][zone], - lrugen->nr_pages[old_gen][type][zone] - delta); - if (new_gen >= 0) - WRITE_ONCE(lrugen->nr_pages[new_gen][type][zone], - lrugen->nr_pages[new_gen][type][zone] + delta); - - /* addition */ - if (old_gen < 0) { - if (lru_gen_is_active(lruvec, new_gen)) - lru += LRU_ACTIVE; - __update_lru_size(lruvec, lru, zone, delta); - return; - } - - /* deletion */ - if (new_gen < 0) { - if (lru_gen_is_active(lruvec, old_gen)) - lru += LRU_ACTIVE; - __update_lru_size(lruvec, lru, zone, -delta); - return; - } -} - -static inline bool lru_gen_add_page(struct lruvec *lruvec, struct page *page, bool reclaiming) -{ - unsigned long seq; - unsigned long flags; - int gen = page_lru_gen(page); - int type = page_is_file_cache(page); - int zone = page_zonenum(page); - struct lru_gen_struct *lrugen = &lruvec->lrugen; - - VM_WARN_ON_ONCE_PAGE(gen != -1, page); - - if (PageUnevictable(page)) - return false; - /* - * There are three common cases for this page: - * 1. If it's hot, e.g., freshly faulted in or previously hot and - * migrated, add it to the youngest generation. - * 2. If it's cold but can't be evicted immediately, i.e., an anon page - * not in swapcache or a dirty page pending writeback, add it to the - * second oldest generation. - * 3. Everything else (clean, cold) is added to the oldest generation. - */ - if (PageActive(page)) - seq = lrugen->max_seq; - else if ((type == LRU_GEN_ANON && !PageSwapCache(page)) || - (PageReclaim(page) && - (PageDirty(page) || PageWriteback(page)))) - seq = lrugen->min_seq[type] + 1; - else - seq = lrugen->min_seq[type]; - - gen = lru_gen_from_seq(seq); - flags = (gen + 1UL) << LRU_GEN_PGOFF; - /* see the comment on MIN_NR_GENS about PG_active */ - set_mask_bits(&page->flags, LRU_GEN_MASK | BIT(PG_active), flags); - - lru_gen_update_size(lruvec, page, -1, gen); - /* for rotate_reclaimable_page() */ - if (reclaiming) - list_add_tail(&page->lru, &lrugen->lists[gen][type][zone]); - else - list_add(&page->lru, &lrugen->lists[gen][type][zone]); - - return true; -} - -static inline bool lru_gen_del_page(struct lruvec *lruvec, struct page *page, bool reclaiming) -{ - unsigned long flags; - int gen = page_lru_gen(page); - - if (gen < 0) - return false; - - VM_WARN_ON_ONCE_PAGE(PageActive(page), page); - VM_WARN_ON_ONCE_PAGE(PageUnevictable(page), page); - - /* for migrate_page_states() */ - flags = !reclaiming && lru_gen_is_active(lruvec, gen) ? BIT(PG_active) : 0; - flags = set_mask_bits(&page->flags, LRU_GEN_MASK, flags); - gen = ((flags & LRU_GEN_MASK) >> LRU_GEN_PGOFF) - 1; - - lru_gen_update_size(lruvec, page, gen, -1); - list_del(&page->lru); - - return true; -} - -#else /* !CONFIG_LRU_GEN */ - -static inline bool lru_gen_enabled(void) -{ - return false; -} - -static inline bool lru_gen_in_fault(void) -{ - return false; -} - -static inline bool lru_gen_add_page(struct lruvec *lruvec, struct page *page, bool reclaiming) -{ - return false; -} - -static inline bool lru_gen_del_page(struct lruvec *lruvec, struct page *page, bool reclaiming) -{ - return false; -} - -#endif /* CONFIG_LRU_GEN */ - static __always_inline void add_page_to_lru_list(struct page *page, struct lruvec *lruvec) { enum lru_list lru = page_lru(page); - if (lru_gen_add_page(lruvec, page, false)) - return; - update_lru_size(lruvec, lru, page_zonenum(page), hpage_nr_pages(page)); list_add(&page->lru, &lruvec->lists[lru]); } @@ -283,9 +114,6 @@ static __always_inline void add_page_to_lru_list_tail(struct page *page, { enum lru_list lru = page_lru(page); - if (lru_gen_add_page(lruvec, page, true)) - return; - update_lru_size(lruvec, lru, page_zonenum(page), hpage_nr_pages(page)); list_add_tail(&page->lru, &lruvec->lists[lru]); } @@ -293,9 +121,6 @@ static __always_inline void add_page_to_lru_list_tail(struct page *page, static __always_inline void del_page_from_lru_list(struct page *page, struct lruvec *lruvec) { - if (lru_gen_del_page(lruvec, page, false)) - return; - list_del(&page->lru); update_lru_size(lruvec, page_lru(page), page_zonenum(page), -hpage_nr_pages(page)); diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index b4aa67cfbf41..97f9d4576d2e 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -308,102 +308,6 @@ struct zone_reclaim_stat { unsigned long recent_scanned[ANON_AND_FILE]; }; -#endif /* !__GENERATING_BOUNDS_H */ - -/* - * Evictable pages are divided into multiple generations. The youngest and the - * oldest generation numbers, max_seq and min_seq, are monotonically increasing. - * They form a sliding window of a variable size [MIN_NR_GENS, MAX_NR_GENS]. An - * offset within MAX_NR_GENS, i.e., gen, indexes the LRU list of the - * corresponding generation. The gen counter in page->flags stores gen+1 while - * a page is on one of lrugen->lists[]. Otherwise it stores 0. - * - * A page is added to the youngest generation on faulting. The aging needs to - * check the accessed bit at least twice before handing this page over to the - * eviction. The first check takes care of the accessed bit set on the initial - * fault; the second check makes sure this page hasn't been used since then. - * This process, AKA second chance, requires a minimum of two generations, - * hence MIN_NR_GENS. And to maintain ABI compatibility with the active/inactive - * LRU, e.g., /proc/vmstat, these two generations are considered active; the - * rest of generations, if they exist, are considered inactive. See - * lru_gen_is_active(). - * - * PG_active is always cleared while a page is on one of lrugen->lists[] so that - * the aging needs not to worry about it. And it's set again when a page - * considered active is isolated for non-reclaiming purposes, e.g., migration. - * See lru_gen_add_page() and lru_gen_del_page(). - * - * MAX_NR_GENS is set to 4 so that the multi-gen LRU can support twice the - * number of categories of the active/inactive LRU when keeping track of - * accesses through page tables. This requires order_base_2(MAX_NR_GENS+1) bits - * in page->flags. - */ -#define MIN_NR_GENS 2U -#define MAX_NR_GENS 4U - -#ifndef __GENERATING_BOUNDS_H - -struct lruvec; - -#define LRU_GEN_MASK ((BIT(LRU_GEN_WIDTH) - 1) << LRU_GEN_PGOFF) -#define LRU_REFS_MASK ((BIT(LRU_REFS_WIDTH) - 1) << LRU_REFS_PGOFF) - -#ifdef CONFIG_LRU_GEN - -enum { - LRU_GEN_ANON, - LRU_GEN_FILE, -}; - -/* - * The youngest generation number is stored in max_seq for both anon and file - * types as they are aged on an equal footing. The oldest generation numbers are - * stored in min_seq[] separately for anon and file types as clean file pages - * can be evicted regardless of swap constraints. - * - * Normally anon and file min_seq are in sync. But if swapping is constrained, - * e.g., out of swap space, file min_seq is allowed to advance and leave anon - * min_seq behind. - * - * The number of pages in each generation is eventually consistent and therefore - * can be transiently negative. - */ -struct lru_gen_struct { - /* the aging increments the youngest generation number */ - unsigned long max_seq; - /* the eviction increments the oldest generation numbers */ - unsigned long min_seq[ANON_AND_FILE]; - /* the multi-gen LRU lists, lazily sorted on eviction */ - struct list_head lists[MAX_NR_GENS][ANON_AND_FILE][MAX_NR_ZONES]; - /* the multi-gen LRU sizes, eventually consistent */ - long nr_pages[MAX_NR_GENS][ANON_AND_FILE][MAX_NR_ZONES]; -}; - -void lru_gen_init_lruvec(struct lruvec *lruvec); - -#ifdef CONFIG_MEMCG -void lru_gen_init_memcg(struct mem_cgroup *memcg); -void lru_gen_exit_memcg(struct mem_cgroup *memcg); -#endif - -#else /* !CONFIG_LRU_GEN */ - -static inline void lru_gen_init_lruvec(struct lruvec *lruvec) -{ -} - -#ifdef CONFIG_MEMCG -static inline void lru_gen_init_memcg(struct mem_cgroup *memcg) -{ -} - -static inline void lru_gen_exit_memcg(struct mem_cgroup *memcg) -{ -} -#endif - -#endif /* CONFIG_LRU_GEN */ - struct lruvec { struct list_head lists[NR_LRU_LISTS]; struct zone_reclaim_stat reclaim_stat; @@ -411,10 +315,6 @@ struct lruvec { atomic_long_t inactive_age; /* Refaults at the time of last reclaim cycle */ unsigned long refaults; -#ifdef CONFIG_LRU_GEN - /* evictable pages divided into generations */ - struct lru_gen_struct lrugen; -#endif #ifdef CONFIG_MEMCG struct pglist_data *pgdat; #endif diff --git a/include/linux/page-flags-layout.h b/include/linux/page-flags-layout.h index 18b0bff4550a..71283739ffd2 100644 --- a/include/linux/page-flags-layout.h +++ b/include/linux/page-flags-layout.h @@ -56,8 +56,7 @@ #define ZONES_WIDTH ZONES_SHIFT -#if ZONES_WIDTH + LRU_GEN_WIDTH + SECTIONS_WIDTH + NODES_SHIFT \ - <= BITS_PER_LONG - NR_PAGEFLAGS +#if SECTIONS_WIDTH+ZONES_WIDTH+NODES_SHIFT <= BITS_PER_LONG - NR_PAGEFLAGS #define NODES_WIDTH NODES_SHIFT #else #ifdef CONFIG_SPARSEMEM_VMEMMAP @@ -84,20 +83,18 @@ #define KASAN_TAG_WIDTH 0 #endif -#if ZONES_WIDTH + LRU_GEN_WIDTH + SECTIONS_WIDTH + NODES_WIDTH + \ - KASAN_TAG_WIDTH + LAST_CPUPID_SHIFT <= BITS_PER_LONG - NR_PAGEFLAGS +#if SECTIONS_WIDTH+ZONES_WIDTH+NODES_SHIFT+LAST_CPUPID_SHIFT+KASAN_TAG_WIDTH \ + <= BITS_PER_LONG - NR_PAGEFLAGS #define LAST_CPUPID_WIDTH LAST_CPUPID_SHIFT #else #define LAST_CPUPID_WIDTH 0 #endif -#if ZONES_WIDTH + LRU_GEN_WIDTH + SECTIONS_WIDTH + NODES_WIDTH + \ - KASAN_TAG_WIDTH + LAST_CPUPID_WIDTH > BITS_PER_LONG - NR_PAGEFLAGS +#if SECTIONS_WIDTH+NODES_WIDTH+ZONES_WIDTH+LAST_CPUPID_WIDTH+KASAN_TAG_WIDTH \ + > BITS_PER_LONG - NR_PAGEFLAGS #error "Not enough bits in page flags" #endif -#define LRU_REFS_WIDTH 0 - /* * We are going to use the flags for the page to node mapping if its in * there. This includes the case where there is no node, so it is implicit. diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h index 6c57922d8fb4..77de28bfefb0 100644 --- a/include/linux/page-flags.h +++ b/include/linux/page-flags.h @@ -827,7 +827,7 @@ static inline void ClearPageSlabPfmemalloc(struct page *page) 1UL << PG_private | 1UL << PG_private_2 | \ 1UL << PG_writeback | 1UL << PG_reserved | \ 1UL << PG_slab | 1UL << PG_active | \ - 1UL << PG_unevictable | __PG_MLOCKED | LRU_GEN_MASK) + 1UL << PG_unevictable | __PG_MLOCKED) /* * Flags checked when a page is prepped for return by the page allocator. @@ -838,7 +838,7 @@ static inline void ClearPageSlabPfmemalloc(struct page *page) * alloc-free cycle to prevent from reusing the page. */ #define PAGE_FLAGS_CHECK_AT_PREP \ - ((((1UL << NR_PAGEFLAGS) - 1) & ~__PG_HWPOISON) | LRU_GEN_MASK | LRU_REFS_MASK) + (((1UL << NR_PAGEFLAGS) - 1) & ~__PG_HWPOISON) #define PAGE_FLAGS_PRIVATE \ (1UL << PG_private | 1UL << PG_private_2) diff --git a/include/linux/sched.h b/include/linux/sched.h index bbd5c55774ed..e18e03b541b2 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -946,10 +946,6 @@ struct task_struct { #ifdef CONFIG_MEMCG unsigned in_user_fault:1; #endif -#ifdef CONFIG_LRU_GEN - /* whether the LRU algorithm may apply to this access */ - unsigned in_lru_fault:1; -#endif #ifdef CONFIG_COMPAT_BRK unsigned brk_randomized:1; #endif diff --git a/kernel/bounds.c b/kernel/bounds.c index 5ee60777d8e4..9795d75b09b2 100644 --- a/kernel/bounds.c +++ b/kernel/bounds.c @@ -22,11 +22,6 @@ int main(void) DEFINE(NR_CPUS_BITS, ilog2(CONFIG_NR_CPUS)); #endif DEFINE(SPINLOCK_SIZE, sizeof(spinlock_t)); -#ifdef CONFIG_LRU_GEN - DEFINE(LRU_GEN_WIDTH, order_base_2(MAX_NR_GENS + 1)); -#else - DEFINE(LRU_GEN_WIDTH, 0); -#endif /* End of constants */ return 0; diff --git a/mm/Kconfig b/mm/Kconfig index 57de0038609e..fe6c22bc562c 100644 --- a/mm/Kconfig +++ b/mm/Kconfig @@ -856,13 +856,6 @@ config OOM_TASK_PRIORITY_ADJ_LIMIT With this parameter you can limit the OOM killer to first kill tasks with an oom_score_adj value above a certain threshold before considering tasks with a lower oom_score_adj value. -config LRU_GEN - bool "Multi-Gen LRU" - depends on MMU - # make sure page->flags has enough spare bits - depends on 64BIT || !SPARSEMEM || SPARSEMEM_VMEMMAP - help - A high performance LRU implementation to overcommit memory. endmenu diff --git a/mm/huge_memory.c b/mm/huge_memory.c index db1ff286b144..e86ae9ed9685 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -2509,8 +2509,7 @@ static void __split_huge_page_tail(struct page *head, int tail, (1L << PG_workingset) | (1L << PG_locked) | (1L << PG_unevictable) | - (1L << PG_dirty) | - LRU_GEN_MASK | LRU_REFS_MASK)); + (1L << PG_dirty))); /* ->mapping in first tail page is compound_mapcount */ VM_BUG_ON_PAGE(tail > 2 && page_tail->mapping != TAIL_MAPPING, diff --git a/mm/memcontrol.c b/mm/memcontrol.c index e9caf18e133c..9171eccfd971 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -5107,7 +5107,6 @@ static void __mem_cgroup_free(struct mem_cgroup *memcg) static void mem_cgroup_free(struct mem_cgroup *memcg) { - lru_gen_exit_memcg(memcg); memcg_wb_domain_exit(memcg); /* * Flush percpu vmstats and vmevents to guarantee the value correctness @@ -5180,7 +5179,6 @@ static struct mem_cgroup *mem_cgroup_alloc(void) memcg->deferred_split_queue.split_queue_len = 0; #endif idr_replace(&mem_cgroup_idr, memcg, memcg->id.id); - lru_gen_init_memcg(memcg); return memcg; fail: mem_cgroup_id_remove(memcg); diff --git a/mm/memory.c b/mm/memory.c index cd892d43d03f..175ea2765182 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -4617,26 +4617,6 @@ bool can_reuse_spf_vma(struct vm_area_struct *vma, unsigned long address) return ret; } #endif /* CONFIG_SPECULATIVE_PAGE_FAULT */ -#ifdef CONFIG_LRU_GEN -static void lru_gen_enter_fault(struct vm_area_struct *vma) -{ - /* the LRU algorithm doesn't apply to sequential or random reads */ - current->in_lru_fault = !(vma->vm_flags & (VM_SEQ_READ | VM_RAND_READ)); -} - -static void lru_gen_exit_fault(void) -{ - current->in_lru_fault = false; -} -#else -static void lru_gen_enter_fault(struct vm_area_struct *vma) -{ -} - -static void lru_gen_exit_fault(void) -{ -} -#endif /* CONFIG_LRU_GEN */ /* * By the time we get here, we already hold the mm semaphore @@ -4669,15 +4649,11 @@ vm_fault_t handle_mm_fault(struct vm_area_struct *vma, unsigned long address, if (flags & FAULT_FLAG_USER) mem_cgroup_enter_user_fault(); - lru_gen_enter_fault(vma); - if (unlikely(is_vm_hugetlb_page(vma))) ret = hugetlb_fault(vma->vm_mm, vma, address, flags); else ret = __handle_mm_fault(vma, address, flags); - lru_gen_exit_fault(); - if (flags & FAULT_FLAG_USER) { mem_cgroup_exit_user_fault(); /* diff --git a/mm/mm_init.c b/mm/mm_init.c index f4d9f66051d1..5c918388de99 100644 --- a/mm/mm_init.c +++ b/mm/mm_init.c @@ -67,16 +67,13 @@ void __init mminit_verify_pageflags_layout(void) unsigned long or_mask, add_mask; shift = 8 * sizeof(unsigned long); - width = shift - SECTIONS_WIDTH - NODES_WIDTH - ZONES_WIDTH - - LAST_CPUPID_SHIFT - LRU_GEN_WIDTH - LRU_REFS_WIDTH; + width = shift - SECTIONS_WIDTH - NODES_WIDTH - ZONES_WIDTH - LAST_CPUPID_SHIFT; mminit_dprintk(MMINIT_TRACE, "pageflags_layout_widths", - "Section %d Node %d Zone %d Lastcpupid %d Gen %d Tier %d Flags %d\n", + "Section %d Node %d Zone %d Lastcpupid %d Flags %d\n", SECTIONS_WIDTH, NODES_WIDTH, ZONES_WIDTH, LAST_CPUPID_WIDTH, - LRU_GEN_WIDTH, - LRU_REFS_WIDTH, NR_PAGEFLAGS); mminit_dprintk(MMINIT_TRACE, "pageflags_layout_shifts", "Section %d Node %d Zone %d Lastcpupid %d\n", diff --git a/mm/mmzone.c b/mm/mmzone.c index d76ca549e424..f337831affc2 100644 --- a/mm/mmzone.c +++ b/mm/mmzone.c @@ -80,8 +80,6 @@ void lruvec_init(struct lruvec *lruvec) for_each_lru(lru) INIT_LIST_HEAD(&lruvec->lists[lru]); - - lru_gen_init_lruvec(lruvec); } #if defined(CONFIG_NUMA_BALANCING) && !defined(LAST_CPUPID_NOT_IN_PAGE_FLAGS) diff --git a/mm/swap.c b/mm/swap.c index 3cd3d1ec8f4c..34bedd0e7619 100644 --- a/mm/swap.c +++ b/mm/swap.c @@ -436,12 +436,6 @@ void lru_cache_add(struct page *page) { VM_BUG_ON_PAGE(PageActive(page) && PageUnevictable(page), page); VM_BUG_ON_PAGE(PageLRU(page), page); - - /* see the comment in lru_gen_add_page() */ - if (lru_gen_enabled() && !PageUnevictable(page) && - lru_gen_in_fault() && !(current->flags & PF_MEMALLOC)) - SetPageActive(page); - __lru_cache_add(page); } @@ -544,7 +538,7 @@ static void lru_deactivate_file_fn(struct page *page, struct lruvec *lruvec, static void lru_deactivate_fn(struct page *page, struct lruvec *lruvec, void *arg) { - if (PageLRU(page) && !PageUnevictable(page) && (PageActive(page) || lru_gen_enabled())) { + if (PageLRU(page) && PageActive(page) && !PageUnevictable(page)) { int file = page_is_file_cache(page); del_page_from_lru_list(page, lruvec); @@ -653,7 +647,7 @@ void deactivate_file_page(struct page *page) */ void deactivate_page(struct page *page) { - if (PageLRU(page) && !PageUnevictable(page) && (PageActive(page) || lru_gen_enabled())) { + if (PageLRU(page) && PageActive(page) && !PageUnevictable(page)) { struct pagevec *pvec = &get_cpu_var(lru_deactivate_pvecs); get_page(page); diff --git a/mm/vmscan.c b/mm/vmscan.c index 8db231e0b758..084f48f95afd 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -2627,81 +2627,6 @@ out: } } -#ifdef CONFIG_LRU_GEN - -/****************************************************************************** - * shorthand helpers - ******************************************************************************/ - -#define for_each_gen_type_zone(gen, type, zone) \ - for ((gen) = 0; (gen) < MAX_NR_GENS; (gen)++) \ - for ((type) = 0; (type) < ANON_AND_FILE; (type)++) \ - for ((zone) = 0; (zone) < MAX_NR_ZONES; (zone)++) - -static struct lruvec __maybe_unused *get_lruvec(struct mem_cgroup *memcg, int nid) -{ - struct pglist_data *pgdat = NODE_DATA(nid); - -#ifdef CONFIG_MEMCG - if (memcg) { - struct lruvec *lruvec = &memcg->nodeinfo[nid]->lruvec; - - /* for hotadd_new_pgdat() */ - if (!lruvec->pgdat) - lruvec->pgdat = pgdat; - - return lruvec; - } -#endif - VM_WARN_ON_ONCE(!mem_cgroup_disabled()); - - return pgdat ? &pgdat->lruvec : NULL; -} - -/****************************************************************************** - * initialization - ******************************************************************************/ - -void lru_gen_init_lruvec(struct lruvec *lruvec) -{ - int gen, type, zone; - struct lru_gen_struct *lrugen = &lruvec->lrugen; - - lrugen->max_seq = MIN_NR_GENS + 1; - - for_each_gen_type_zone(gen, type, zone) - INIT_LIST_HEAD(&lrugen->lists[gen][type][zone]); -} - -#ifdef CONFIG_MEMCG -void lru_gen_init_memcg(struct mem_cgroup *memcg) -{ -} - -void lru_gen_exit_memcg(struct mem_cgroup *memcg) -{ - int nid; - - for_each_node(nid) { - struct lruvec *lruvec = get_lruvec(memcg, nid); - - VM_WARN_ON_ONCE(memchr_inv(lruvec->lrugen.nr_pages, 0, - sizeof(lruvec->lrugen.nr_pages))); - } -} -#endif - -static int __init init_lru_gen(void) -{ - BUILD_BUG_ON(MIN_NR_GENS + 1 >= MAX_NR_GENS); - BUILD_BUG_ON(BIT(LRU_GEN_WIDTH) <= MAX_NR_GENS); - - return 0; -}; -late_initcall(init_lru_gen); - -#endif /* CONFIG_LRU_GEN */ - /* * This is a basic per-node page freer. Used by both kswapd and direct reclaim. */ From 4acb10e29463c57790d22645d096e1fad326a4f7 Mon Sep 17 00:00:00 2001 From: xiewen3 Date: Tue, 16 May 2023 22:51:54 +0800 Subject: [PATCH 588/698] LUR: Revert "BACKPORT: mm: x86: add CONFIG_ARCH_HAS_NONLEAF_PMD_YOUNG" The LRU function is not compatible with GKI, causing GKI to fail to start, so revert. This reverts commit 1db11940f2946d87b1333667fd99503475728e9e. Change-Id: I5156f15cde7c0f7d1b38e392b2a36d4b85e3f447 Reviewed-on: https://gerrit.mot.com/2609764 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- arch/Kconfig | 8 -------- arch/x86/Kconfig | 1 - arch/x86/include/asm/pgtable.h | 3 +-- arch/x86/mm/pgtable.c | 5 +---- include/asm-generic/pgtable.h | 4 ++-- 5 files changed, 4 insertions(+), 17 deletions(-) diff --git a/arch/Kconfig b/arch/Kconfig index e7d5df0a8186..136a633b28a7 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -1071,14 +1071,6 @@ config RELR config ARCH_HAS_MEM_ENCRYPT bool -config ARCH_HAS_NONLEAF_PMD_YOUNG - bool - help - Architectures that select this option are capable of setting the - accessed bit in non-leaf PMD entries when using them as part of linear - address translations. Page table walkers that clear the accessed bit - may use this capability to reduce their search space. - source "kernel/gcov/Kconfig" source "scripts/gcc-plugins/Kconfig" diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 295518328228..63fd3706316d 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -74,7 +74,6 @@ config X86 select ARCH_HAS_PMEM_API if X86_64 select ARCH_HAS_PTE_DEVMAP if X86_64 select ARCH_HAS_PTE_SPECIAL - select ARCH_HAS_NONLEAF_PMD_YOUNG if PGTABLE_LEVELS > 2 select ARCH_HAS_UACCESS_FLUSHCACHE if X86_64 select ARCH_HAS_UACCESS_MCSAFE if X86_64 && X86_MCE select ARCH_HAS_SET_MEMORY diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h index 91dc85dfa1f9..0c6e2b758857 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h @@ -844,8 +844,7 @@ static inline pte_t *pte_offset_kernel(pmd_t *pmd, unsigned long address) static inline int pmd_bad(pmd_t pmd) { - return (pmd_flags(pmd) & ~(_PAGE_USER | _PAGE_ACCESSED)) != - (_KERNPG_TABLE & ~_PAGE_ACCESSED); + return (pmd_flags(pmd) & ~_PAGE_USER) != _KERNPG_TABLE; } static inline unsigned long pages_to_mb(unsigned long npg) diff --git a/arch/x86/mm/pgtable.c b/arch/x86/mm/pgtable.c index 18e63df7ee76..7982f13807aa 100644 --- a/arch/x86/mm/pgtable.c +++ b/arch/x86/mm/pgtable.c @@ -543,7 +543,7 @@ int ptep_test_and_clear_young(struct vm_area_struct *vma, return ret; } -#if defined(CONFIG_TRANSPARENT_HUGEPAGE) || defined(CONFIG_ARCH_HAS_NONLEAF_PMD_YOUNG) +#ifdef CONFIG_TRANSPARENT_HUGEPAGE int pmdp_test_and_clear_young(struct vm_area_struct *vma, unsigned long addr, pmd_t *pmdp) { @@ -555,9 +555,6 @@ int pmdp_test_and_clear_young(struct vm_area_struct *vma, return ret; } -#endif - -#ifdef CONFIG_TRANSPARENT_HUGEPAGE int pudp_test_and_clear_young(struct vm_area_struct *vma, unsigned long addr, pud_t *pudp) { diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h index ac0be045e487..3ac04e08b568 100644 --- a/include/asm-generic/pgtable.h +++ b/include/asm-generic/pgtable.h @@ -74,7 +74,7 @@ static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, #endif #ifndef __HAVE_ARCH_PMDP_TEST_AND_CLEAR_YOUNG -#if defined(CONFIG_TRANSPARENT_HUGEPAGE) || defined(CONFIG_ARCH_HAS_NONLEAF_PMD_YOUNG) +#ifdef CONFIG_TRANSPARENT_HUGEPAGE static inline int pmdp_test_and_clear_young(struct vm_area_struct *vma, unsigned long address, pmd_t *pmdp) @@ -95,7 +95,7 @@ static inline int pmdp_test_and_clear_young(struct vm_area_struct *vma, BUILD_BUG(); return 0; } -#endif /* CONFIG_TRANSPARENT_HUGEPAGE || CONFIG_ARCH_HAS_NONLEAF_PMD_YOUNG */ +#endif /* CONFIG_TRANSPARENT_HUGEPAGE */ #endif #ifndef __HAVE_ARCH_PTEP_CLEAR_YOUNG_FLUSH From b40b2cd6826f0f6281ec84c5c62d091033a5d21c Mon Sep 17 00:00:00 2001 From: xiewen3 Date: Tue, 16 May 2023 22:53:44 +0800 Subject: [PATCH 589/698] LUR: Revert "BACKPORT: mm: x86, arm64: add arch_has_hw_pte_young()" The LRU function is not compatible with GKI, causing GKI to fail to start, so revert. This reverts commit 5adf37f31d207aac909d816b51be3d92a9d2c8ca. Change-Id: I92db4936ceae197ccab03de584ccc9637d4d065d Reviewed-on: https://gerrit.mot.com/2609765 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- arch/arm64/include/asm/pgtable.h | 8 +++++++- arch/x86/include/asm/pgtable.h | 6 +++--- include/asm-generic/pgtable.h | 13 ------------- mm/memory.c | 14 +++++++++++++- 4 files changed, 23 insertions(+), 18 deletions(-) diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h index 6a1976149af4..4f48704996dc 100644 --- a/arch/arm64/include/asm/pgtable.h +++ b/arch/arm64/include/asm/pgtable.h @@ -894,7 +894,13 @@ static inline void update_mmu_cache(struct vm_area_struct *vma, * page after fork() + CoW for pfn mappings. We don't always have a * hardware-managed access flag on arm64. */ -#define arch_has_hw_pte_young cpu_has_hw_af +static inline bool arch_faults_on_old_pte(void) +{ + WARN_ON(preemptible()); + + return !cpu_has_hw_af(); +} +#define arch_faults_on_old_pte arch_faults_on_old_pte #endif /* !__ASSEMBLY__ */ diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h index 0c6e2b758857..d711bc431a2c 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h @@ -1472,10 +1472,10 @@ static inline bool arch_has_pfn_modify_check(void) return boot_cpu_has_bug(X86_BUG_L1TF); } -#define arch_has_hw_pte_young arch_has_hw_pte_young -static inline bool arch_has_hw_pte_young(void) +#define arch_faults_on_old_pte arch_faults_on_old_pte +static inline bool arch_faults_on_old_pte(void) { - return true; + return false; } #include diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h index 3ac04e08b568..f5895a174b3b 100644 --- a/include/asm-generic/pgtable.h +++ b/include/asm-generic/pgtable.h @@ -121,19 +121,6 @@ static inline int pmdp_clear_flush_young(struct vm_area_struct *vma, #endif /* CONFIG_TRANSPARENT_HUGEPAGE */ #endif -#ifndef arch_has_hw_pte_young -/* - * Return whether the accessed bit is supported on the local CPU. - * - * This stub assumes accessing through an old PTE triggers a page fault. - * Architectures that automatically set the access bit should overwrite it. - */ -static inline bool arch_has_hw_pte_young(void) -{ - return false; -} -#endif - #ifndef __HAVE_ARCH_PTEP_GET_AND_CLEAR static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long address, diff --git a/mm/memory.c b/mm/memory.c index 175ea2765182..609e32cfbb0e 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -120,6 +120,18 @@ int randomize_va_space __read_mostly = 2; #endif +#ifndef arch_faults_on_old_pte +static inline bool arch_faults_on_old_pte(void) +{ + /* + * Those arches which don't have hw access flag feature need to + * implement their own helper. By default, "true" means pagefault + * will be hit on old pte. + */ + return true; +} +#endif + static int __init disable_randmaps(char *s) { randomize_va_space = 0; @@ -2359,7 +2371,7 @@ static inline bool cow_user_page(struct page *dst, struct page *src, * On architectures with software "accessed" bits, we would * take a double page fault, so mark it accessed here. */ - if (!arch_has_hw_pte_young() && !pte_young(vmf->orig_pte)) { + if (arch_faults_on_old_pte() && !pte_young(vmf->orig_pte)) { pte_t entry; vmf->pte = pte_offset_map_lock(mm, vmf->pmd, addr, &vmf->ptl); From e784526c5148215151c08b8993d951e2a11a70ca Mon Sep 17 00:00:00 2001 From: xiewen3 Date: Tue, 16 May 2023 22:54:06 +0800 Subject: [PATCH 590/698] LUR: Revert "BACKPORT: mm: VM_BUG_ON lru page flags" The LRU function is not compatible with GKI, causing GKI to fail to start, so revert. This reverts commit 99ec8c955ce7d24ae76309db23e6920a7a920466. Change-Id: I471a06616d85d9e4216ee38f9145d2dd7b333b4a Reviewed-on: https://gerrit.mot.com/2609766 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- include/linux/mm_inline.h | 4 ---- mm/swap.c | 2 ++ mm/vmscan.c | 1 + 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/include/linux/mm_inline.h b/include/linux/mm_inline.h index 24dbfcfe4a6d..3cdbd538aa5f 100644 --- a/include/linux/mm_inline.h +++ b/include/linux/mm_inline.h @@ -65,8 +65,6 @@ static inline enum lru_list page_lru_base_type(struct page *page) */ static __always_inline void __clear_page_lru_flags(struct page *page) { - VM_BUG_ON_PAGE(!PageLRU(page), page); - __ClearPageLRU(page); /* this shouldn't happen, so leave the flags to bad_page() */ @@ -88,8 +86,6 @@ static __always_inline enum lru_list page_lru(struct page *page) { enum lru_list lru; - VM_BUG_ON_PAGE(PageActive(page) && PageUnevictable(page), page); - if (PageUnevictable(page)) lru = LRU_UNEVICTABLE; else { diff --git a/mm/swap.c b/mm/swap.c index 34bedd0e7619..dda66aeb7b11 100644 --- a/mm/swap.c +++ b/mm/swap.c @@ -66,6 +66,7 @@ static void __page_cache_release(struct page *page) spin_lock_irqsave(&pgdat->lru_lock, flags); lruvec = mem_cgroup_page_lruvec(page, pgdat); + VM_BUG_ON_PAGE(!PageLRU(page), page); del_page_from_lru_list(page, lruvec); __clear_page_lru_flags(page); spin_unlock_irqrestore(&pgdat->lru_lock, flags); @@ -817,6 +818,7 @@ void release_pages(struct page **pages, int nr) } lruvec = mem_cgroup_page_lruvec(page, locked_pgdat); + VM_BUG_ON_PAGE(!PageLRU(page), page); del_page_from_lru_list(page, lruvec); __clear_page_lru_flags(page); } diff --git a/mm/vmscan.c b/mm/vmscan.c index 084f48f95afd..8c32f6d7a317 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -4562,6 +4562,7 @@ void check_move_unevictable_pages(struct pagevec *pvec) continue; if (page_evictable(page)) { + VM_BUG_ON_PAGE(PageActive(page), page); del_page_from_lru_list(page, lruvec); ClearPageUnevictable(page); add_page_to_lru_list(page, lruvec); From ae7ee7d38695325685088bef934ae0aad3d5362c Mon Sep 17 00:00:00 2001 From: xiewen3 Date: Tue, 16 May 2023 22:55:49 +0800 Subject: [PATCH 591/698] LUR: Revert "BACKPORT: mm: add __clear_page_lru_flags() to replace page_off_lru()" The LRU function is not compatible with GKI, causing GKI to fail to start, so revert. This reverts commit 83ef32c2525938d7dc08c40f8c770c66fd6cd331. Change-Id: I2bb041d8430290af3a9e2a8e9c08bf07177fa6a8 Reviewed-on: https://gerrit.mot.com/2609767 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- include/linux/mm_inline.h | 28 ++++++++++++++++++---------- mm/swap.c | 6 ++++-- mm/vmscan.c | 3 ++- 3 files changed, 24 insertions(+), 13 deletions(-) diff --git a/include/linux/mm_inline.h b/include/linux/mm_inline.h index 3cdbd538aa5f..04872cd8fb1c 100644 --- a/include/linux/mm_inline.h +++ b/include/linux/mm_inline.h @@ -60,19 +60,27 @@ static inline enum lru_list page_lru_base_type(struct page *page) } /** - * __clear_page_lru_flags - clear page lru flags before releasing a page - * @page: the page that was on lru and now has a zero reference + * page_off_lru - which LRU list was page on? clearing its lru flags. + * @page: the page to test + * + * Returns the LRU list a page was on, as an index into the array of LRU + * lists; and clears its Unevictable or Active flags, ready for freeing. */ -static __always_inline void __clear_page_lru_flags(struct page *page) +static __always_inline enum lru_list page_off_lru(struct page *page) { - __ClearPageLRU(page); + enum lru_list lru; - /* this shouldn't happen, so leave the flags to bad_page() */ - if (PageActive(page) && PageUnevictable(page)) - return; - - __ClearPageActive(page); - __ClearPageUnevictable(page); + if (PageUnevictable(page)) { + __ClearPageUnevictable(page); + lru = LRU_UNEVICTABLE; + } else { + lru = page_lru_base_type(page); + if (PageActive(page)) { + __ClearPageActive(page); + lru += LRU_ACTIVE; + } + } + return lru; } /** diff --git a/mm/swap.c b/mm/swap.c index dda66aeb7b11..26e2dd8cf33e 100644 --- a/mm/swap.c +++ b/mm/swap.c @@ -67,8 +67,9 @@ static void __page_cache_release(struct page *page) spin_lock_irqsave(&pgdat->lru_lock, flags); lruvec = mem_cgroup_page_lruvec(page, pgdat); VM_BUG_ON_PAGE(!PageLRU(page), page); + __ClearPageLRU(page); del_page_from_lru_list(page, lruvec); - __clear_page_lru_flags(page); + page_off_lru(page); spin_unlock_irqrestore(&pgdat->lru_lock, flags); } __ClearPageWaiters(page); @@ -819,8 +820,9 @@ void release_pages(struct page **pages, int nr) lruvec = mem_cgroup_page_lruvec(page, locked_pgdat); VM_BUG_ON_PAGE(!PageLRU(page), page); + __ClearPageLRU(page); del_page_from_lru_list(page, lruvec); - __clear_page_lru_flags(page); + page_off_lru(page); } __ClearPageWaiters(page); diff --git a/mm/vmscan.c b/mm/vmscan.c index 8c32f6d7a317..677b408b154d 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -1965,8 +1965,9 @@ static unsigned noinline_for_stack move_pages_to_lru(struct lruvec *lruvec, add_page_to_lru_list(page, lruvec); if (put_page_testzero(page)) { + __ClearPageLRU(page); del_page_from_lru_list(page, lruvec); - __clear_page_lru_flags(page); + __ClearPageActive(page); if (unlikely(PageCompound(page))) { spin_unlock_irq(&pgdat->lru_lock); From e3010ff43e40787ca84946cf06e419b84463b61b Mon Sep 17 00:00:00 2001 From: xiewen3 Date: Tue, 16 May 2023 22:56:22 +0800 Subject: [PATCH 592/698] LUR: Revert "BACKPORT: mm/swap.c: don't pass "enum lru_list" to del_page_from_lru_list()" The LRU function is not compatible with GKI, causing GKI to fail to start, so revert. This reverts commit 77a295298e69ff1fbb68fad4646684c70163fb54. Change-Id: Ic13bafb6fa8bf383caf27a77cce12f8217536334 Reviewed-on: https://gerrit.mot.com/2609768 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- include/linux/mm_inline.h | 5 ++--- mm/compaction.c | 2 +- mm/memcontrol.c | 2 +- mm/mlock.c | 2 +- mm/swap.c | 23 +++++++++++++---------- mm/vmscan.c | 9 ++++++--- 6 files changed, 24 insertions(+), 19 deletions(-) diff --git a/include/linux/mm_inline.h b/include/linux/mm_inline.h index 04872cd8fb1c..d01a06dae3b7 100644 --- a/include/linux/mm_inline.h +++ b/include/linux/mm_inline.h @@ -123,11 +123,10 @@ static __always_inline void add_page_to_lru_list_tail(struct page *page, } static __always_inline void del_page_from_lru_list(struct page *page, - struct lruvec *lruvec) + struct lruvec *lruvec, enum lru_list lru) { list_del(&page->lru); - update_lru_size(lruvec, page_lru(page), page_zonenum(page), - -hpage_nr_pages(page)); + update_lru_size(lruvec, lru, page_zonenum(page), -hpage_nr_pages(page)); } #endif diff --git a/mm/compaction.c b/mm/compaction.c index 195dce9221c2..2293de8dffe5 100644 --- a/mm/compaction.c +++ b/mm/compaction.c @@ -984,7 +984,7 @@ isolate_migratepages_block(struct compact_control *cc, unsigned long low_pfn, VM_BUG_ON_PAGE(PageCompound(page), page); /* Successfully isolated */ - del_page_from_lru_list(page, lruvec); + del_page_from_lru_list(page, lruvec, page_lru(page)); inc_node_page_state(page, NR_ISOLATED_ANON + page_is_file_cache(page)); diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 9171eccfd971..d464f39389a2 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -2741,7 +2741,7 @@ static void lock_page_lru(struct page *page, int *isolated) lruvec = mem_cgroup_page_lruvec(page, pgdat); ClearPageLRU(page); - del_page_from_lru_list(page, lruvec); + del_page_from_lru_list(page, lruvec, page_lru(page)); *isolated = 1; } else *isolated = 0; diff --git a/mm/mlock.c b/mm/mlock.c index 94a4828072a7..395bf08f86d8 100644 --- a/mm/mlock.c +++ b/mm/mlock.c @@ -115,7 +115,7 @@ static bool __munlock_isolate_lru_page(struct page *page, bool getpage) if (getpage) get_page(page); ClearPageLRU(page); - del_page_from_lru_list(page, lruvec); + del_page_from_lru_list(page, lruvec, page_lru(page)); return true; } diff --git a/mm/swap.c b/mm/swap.c index 26e2dd8cf33e..1be4213f4807 100644 --- a/mm/swap.c +++ b/mm/swap.c @@ -68,8 +68,7 @@ static void __page_cache_release(struct page *page) lruvec = mem_cgroup_page_lruvec(page, pgdat); VM_BUG_ON_PAGE(!PageLRU(page), page); __ClearPageLRU(page); - del_page_from_lru_list(page, lruvec); - page_off_lru(page); + del_page_from_lru_list(page, lruvec, page_off_lru(page)); spin_unlock_irqrestore(&pgdat->lru_lock, flags); } __ClearPageWaiters(page); @@ -223,7 +222,7 @@ static void pagevec_move_tail_fn(struct page *page, struct lruvec *lruvec, int *pgmoved = arg; if (PageLRU(page) && !PageUnevictable(page)) { - del_page_from_lru_list(page, lruvec); + del_page_from_lru_list(page, lruvec, page_lru(page)); ClearPageActive(page); add_page_to_lru_list_tail(page, lruvec); (*pgmoved)++; @@ -278,8 +277,9 @@ static void __activate_page(struct page *page, struct lruvec *lruvec, { if (PageLRU(page) && !PageActive(page) && !PageUnevictable(page)) { int file = page_is_file_cache(page); + int lru = page_lru_base_type(page); - del_page_from_lru_list(page, lruvec); + del_page_from_lru_list(page, lruvec, lru); SetPageActive(page); add_page_to_lru_list(page, lruvec); trace_mm_lru_activate(page); @@ -495,7 +495,7 @@ void __lru_cache_add_active_or_unevictable(struct page *page, static void lru_deactivate_file_fn(struct page *page, struct lruvec *lruvec, void *arg) { - int file; + int lru, file; bool active; if (!PageLRU(page)) @@ -510,8 +510,9 @@ static void lru_deactivate_file_fn(struct page *page, struct lruvec *lruvec, active = PageActive(page); file = page_is_file_cache(page); + lru = page_lru_base_type(page); - del_page_from_lru_list(page, lruvec); + del_page_from_lru_list(page, lruvec, lru + active); ClearPageActive(page); ClearPageReferenced(page); @@ -542,8 +543,9 @@ static void lru_deactivate_fn(struct page *page, struct lruvec *lruvec, { if (PageLRU(page) && PageActive(page) && !PageUnevictable(page)) { int file = page_is_file_cache(page); + int lru = page_lru_base_type(page); - del_page_from_lru_list(page, lruvec); + del_page_from_lru_list(page, lruvec, lru + LRU_ACTIVE); ClearPageActive(page); ClearPageReferenced(page); add_page_to_lru_list(page, lruvec); @@ -558,8 +560,10 @@ static void lru_lazyfree_fn(struct page *page, struct lruvec *lruvec, { if (PageLRU(page) && PageAnon(page) && PageSwapBacked(page) && !PageSwapCache(page) && !PageUnevictable(page)) { + bool active = PageActive(page); - del_page_from_lru_list(page, lruvec); + del_page_from_lru_list(page, lruvec, + LRU_INACTIVE_ANON + active); ClearPageActive(page); ClearPageReferenced(page); /* @@ -821,8 +825,7 @@ void release_pages(struct page **pages, int nr) lruvec = mem_cgroup_page_lruvec(page, locked_pgdat); VM_BUG_ON_PAGE(!PageLRU(page), page); __ClearPageLRU(page); - del_page_from_lru_list(page, lruvec); - page_off_lru(page); + del_page_from_lru_list(page, lruvec, page_off_lru(page)); } __ClearPageWaiters(page); diff --git a/mm/vmscan.c b/mm/vmscan.c index 677b408b154d..214e43dd38c3 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -1874,9 +1874,10 @@ int isolate_lru_page(struct page *page) spin_lock_irq(&pgdat->lru_lock); lruvec = mem_cgroup_page_lruvec(page, pgdat); if (PageLRU(page)) { + int lru = page_lru(page); get_page(page); ClearPageLRU(page); - del_page_from_lru_list(page, lruvec); + del_page_from_lru_list(page, lruvec, lru); ret = 0; } spin_unlock_irq(&pgdat->lru_lock); @@ -1948,6 +1949,7 @@ static unsigned noinline_for_stack move_pages_to_lru(struct lruvec *lruvec, int nr_pages, nr_moved = 0; LIST_HEAD(pages_to_free); struct page *page; + enum lru_list lru; while (!list_empty(list)) { page = lru_to_page(list); @@ -1962,12 +1964,13 @@ static unsigned noinline_for_stack move_pages_to_lru(struct lruvec *lruvec, lruvec = mem_cgroup_page_lruvec(page, pgdat); SetPageLRU(page); + lru = page_lru(page); add_page_to_lru_list(page, lruvec); if (put_page_testzero(page)) { __ClearPageLRU(page); - del_page_from_lru_list(page, lruvec); __ClearPageActive(page); + del_page_from_lru_list(page, lruvec, lru); if (unlikely(PageCompound(page))) { spin_unlock_irq(&pgdat->lru_lock); @@ -4564,8 +4567,8 @@ void check_move_unevictable_pages(struct pagevec *pvec) if (page_evictable(page)) { VM_BUG_ON_PAGE(PageActive(page), page); - del_page_from_lru_list(page, lruvec); ClearPageUnevictable(page); + del_page_from_lru_list(page, lruvec, LRU_UNEVICTABLE); add_page_to_lru_list(page, lruvec); pgrescued++; } From efefa59fcb2622986e5000e8338f2ecf8e3f8777 Mon Sep 17 00:00:00 2001 From: xiewen3 Date: Tue, 16 May 2023 22:57:10 +0800 Subject: [PATCH 593/698] LUR: Revert "BACKPORT: mm/swap.c: don't pass "enum lru_list" to trace_mm_lru_insertion()" The LRU function is not compatible with GKI, causing GKI to fail to start, so revert. This reverts commit 819585d2b096f203fabe95cef72a6accd1ef28df. Change-Id: I739c6ebcc0d2ece0470c37fc942815eeeb5f4c42 Reviewed-on: https://gerrit.mot.com/2609769 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- include/trace/events/pagemap.h | 11 +++++++---- mm/swap.c | 5 ++++- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/include/trace/events/pagemap.h b/include/trace/events/pagemap.h index e1735fe7c76a..8fd1babae761 100644 --- a/include/trace/events/pagemap.h +++ b/include/trace/events/pagemap.h @@ -27,21 +27,24 @@ TRACE_EVENT(mm_lru_insertion, - TP_PROTO(struct page *page), + TP_PROTO( + struct page *page, + int lru + ), - TP_ARGS(page), + TP_ARGS(page, lru), TP_STRUCT__entry( __field(struct page *, page ) __field(unsigned long, pfn ) - __field(enum lru_list, lru ) + __field(int, lru ) __field(unsigned long, flags ) ), TP_fast_assign( __entry->page = page; __entry->pfn = page_to_pfn(page); - __entry->lru = page_lru(page); + __entry->lru = lru; __entry->flags = trace_pagemap_flags(page); ), diff --git a/mm/swap.c b/mm/swap.c index 1be4213f4807..e4616bde21e1 100644 --- a/mm/swap.c +++ b/mm/swap.c @@ -901,6 +901,7 @@ void lru_add_page_tail(struct page *page, struct page *page_tail, static void __pagevec_lru_add_fn(struct page *page, struct lruvec *lruvec, void *arg) { + enum lru_list lru; int was_unevictable = TestClearPageUnevictable(page); VM_BUG_ON_PAGE(PageLRU(page), page); @@ -935,11 +936,13 @@ static void __pagevec_lru_add_fn(struct page *page, struct lruvec *lruvec, smp_mb(); if (page_evictable(page)) { + lru = page_lru(page); update_page_reclaim_stat(lruvec, page_is_file_cache(page), PageActive(page)); if (was_unevictable) count_vm_event(UNEVICTABLE_PGRESCUED); } else { + lru = LRU_UNEVICTABLE; ClearPageActive(page); SetPageUnevictable(page); if (!was_unevictable) @@ -947,7 +950,7 @@ static void __pagevec_lru_add_fn(struct page *page, struct lruvec *lruvec, } add_page_to_lru_list(page, lruvec); - trace_mm_lru_insertion(page); + trace_mm_lru_insertion(page, lru); } /* From 15869d4f255e862e2e91ad7b6bb502d791bf7a20 Mon Sep 17 00:00:00 2001 From: xiewen3 Date: Tue, 16 May 2023 22:57:54 +0800 Subject: [PATCH 594/698] LUR: Revert "BACKPORT: mm: don't pass "enum lru_list" to lru list addition functions" The LRU function is not compatible with GKI, causing GKI to fail to start, so revert. This reverts commit 34909e452db7c4eacb96d5faa4a070d4bf26985b. Change-Id: I79aa270fe5e4620bde28824d7c90f3c38d491e67 Reviewed-on: https://gerrit.mot.com/2609770 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- include/linux/mm_inline.h | 8 ++------ mm/memcontrol.c | 2 +- mm/swap.c | 18 ++++++++++-------- mm/vmscan.c | 6 ++++-- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/include/linux/mm_inline.h b/include/linux/mm_inline.h index d01a06dae3b7..85e526fb0d1f 100644 --- a/include/linux/mm_inline.h +++ b/include/linux/mm_inline.h @@ -105,19 +105,15 @@ static __always_inline enum lru_list page_lru(struct page *page) } static __always_inline void add_page_to_lru_list(struct page *page, - struct lruvec *lruvec) + struct lruvec *lruvec, enum lru_list lru) { - enum lru_list lru = page_lru(page); - update_lru_size(lruvec, lru, page_zonenum(page), hpage_nr_pages(page)); list_add(&page->lru, &lruvec->lists[lru]); } static __always_inline void add_page_to_lru_list_tail(struct page *page, - struct lruvec *lruvec) + struct lruvec *lruvec, enum lru_list lru) { - enum lru_list lru = page_lru(page); - update_lru_size(lruvec, lru, page_zonenum(page), hpage_nr_pages(page)); list_add_tail(&page->lru, &lruvec->lists[lru]); } diff --git a/mm/memcontrol.c b/mm/memcontrol.c index d464f39389a2..0140629b7cb2 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -2757,7 +2757,7 @@ static void unlock_page_lru(struct page *page, int isolated) lruvec = mem_cgroup_page_lruvec(page, pgdat); VM_BUG_ON_PAGE(PageLRU(page), page); SetPageLRU(page); - add_page_to_lru_list(page, lruvec); + add_page_to_lru_list(page, lruvec, page_lru(page)); } spin_unlock_irq(&pgdat->lru_lock); } diff --git a/mm/swap.c b/mm/swap.c index e4616bde21e1..8362cfde85aa 100644 --- a/mm/swap.c +++ b/mm/swap.c @@ -224,7 +224,7 @@ static void pagevec_move_tail_fn(struct page *page, struct lruvec *lruvec, if (PageLRU(page) && !PageUnevictable(page)) { del_page_from_lru_list(page, lruvec, page_lru(page)); ClearPageActive(page); - add_page_to_lru_list_tail(page, lruvec); + add_page_to_lru_list_tail(page, lruvec, page_lru(page)); (*pgmoved)++; } } @@ -281,7 +281,8 @@ static void __activate_page(struct page *page, struct lruvec *lruvec, del_page_from_lru_list(page, lruvec, lru); SetPageActive(page); - add_page_to_lru_list(page, lruvec); + lru += LRU_ACTIVE; + add_page_to_lru_list(page, lruvec, lru); trace_mm_lru_activate(page); __count_vm_event(PGACTIVATE); @@ -522,14 +523,14 @@ static void lru_deactivate_file_fn(struct page *page, struct lruvec *lruvec, * It can make readahead confusing. But race window * is _really_ small and it's non-critical problem. */ - add_page_to_lru_list(page, lruvec); + add_page_to_lru_list(page, lruvec, lru); SetPageReclaim(page); } else { /* * The page's writeback ends up during pagevec * We moves tha page into tail of inactive. */ - add_page_to_lru_list_tail(page, lruvec); + add_page_to_lru_list_tail(page, lruvec, lru); __count_vm_event(PGROTATED); } @@ -548,7 +549,7 @@ static void lru_deactivate_fn(struct page *page, struct lruvec *lruvec, del_page_from_lru_list(page, lruvec, lru + LRU_ACTIVE); ClearPageActive(page); ClearPageReferenced(page); - add_page_to_lru_list(page, lruvec); + add_page_to_lru_list(page, lruvec, lru); __count_vm_events(PGDEACTIVATE, hpage_nr_pages(page)); update_page_reclaim_stat(lruvec, file, 0); @@ -572,7 +573,7 @@ static void lru_lazyfree_fn(struct page *page, struct lruvec *lruvec, * pages */ ClearPageSwapBacked(page); - add_page_to_lru_list(page, lruvec); + add_page_to_lru_list(page, lruvec, LRU_INACTIVE_FILE); __count_vm_events(PGLAZYFREE, hpage_nr_pages(page)); count_memcg_page_event(page, PGLAZYFREE); @@ -890,7 +891,8 @@ void lru_add_page_tail(struct page *page, struct page *page_tail, * Put page_tail on the list at the correct position * so they all end up in order. */ - add_page_to_lru_list_tail(page_tail, lruvec); + add_page_to_lru_list_tail(page_tail, lruvec, + page_lru(page_tail)); } if (!PageUnevictable(page)) @@ -949,7 +951,7 @@ static void __pagevec_lru_add_fn(struct page *page, struct lruvec *lruvec, count_vm_event(UNEVICTABLE_PGCULLED); } - add_page_to_lru_list(page, lruvec); + add_page_to_lru_list(page, lruvec, lru); trace_mm_lru_insertion(page, lru); } diff --git a/mm/vmscan.c b/mm/vmscan.c index 214e43dd38c3..e2b824d0f847 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -1965,7 +1965,7 @@ static unsigned noinline_for_stack move_pages_to_lru(struct lruvec *lruvec, SetPageLRU(page); lru = page_lru(page); - add_page_to_lru_list(page, lruvec); + add_page_to_lru_list(page, lruvec, lru); if (put_page_testzero(page)) { __ClearPageLRU(page); @@ -4566,10 +4566,12 @@ void check_move_unevictable_pages(struct pagevec *pvec) continue; if (page_evictable(page)) { + enum lru_list lru = page_lru_base_type(page); + VM_BUG_ON_PAGE(PageActive(page), page); ClearPageUnevictable(page); del_page_from_lru_list(page, lruvec, LRU_UNEVICTABLE); - add_page_to_lru_list(page, lruvec); + add_page_to_lru_list(page, lruvec, lru); pgrescued++; } } From fb82224f34a80c955eb72518fcb81cbd3a749512 Mon Sep 17 00:00:00 2001 From: xiewen3 Date: Tue, 16 May 2023 22:58:50 +0800 Subject: [PATCH 595/698] LUR: Revert "BACKPORT: include/linux/mm_inline.h: shuffle lru list addition and deletion functions" The LRU function is not compatible with GKI, causing GKI to fail to start, so revert. This reverts commit 462f77e105f8d43417955974dc9fb1082a10027a. Change-Id: I2ee54fd0fed9660e2473a41474ab79836c9a4945 Reviewed-on: https://gerrit.mot.com/2609771 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- include/linux/mm_inline.h | 43 +++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/include/linux/mm_inline.h b/include/linux/mm_inline.h index 85e526fb0d1f..6f2fef7b0784 100644 --- a/include/linux/mm_inline.h +++ b/include/linux/mm_inline.h @@ -44,6 +44,27 @@ static __always_inline void update_lru_size(struct lruvec *lruvec, #endif } +static __always_inline void add_page_to_lru_list(struct page *page, + struct lruvec *lruvec, enum lru_list lru) +{ + update_lru_size(lruvec, lru, page_zonenum(page), hpage_nr_pages(page)); + list_add(&page->lru, &lruvec->lists[lru]); +} + +static __always_inline void add_page_to_lru_list_tail(struct page *page, + struct lruvec *lruvec, enum lru_list lru) +{ + update_lru_size(lruvec, lru, page_zonenum(page), hpage_nr_pages(page)); + list_add_tail(&page->lru, &lruvec->lists[lru]); +} + +static __always_inline void del_page_from_lru_list(struct page *page, + struct lruvec *lruvec, enum lru_list lru) +{ + list_del(&page->lru); + update_lru_size(lruvec, lru, page_zonenum(page), -hpage_nr_pages(page)); +} + /** * page_lru_base_type - which LRU list type should a page be on? * @page: the page to test @@ -103,26 +124,4 @@ static __always_inline enum lru_list page_lru(struct page *page) } return lru; } - -static __always_inline void add_page_to_lru_list(struct page *page, - struct lruvec *lruvec, enum lru_list lru) -{ - update_lru_size(lruvec, lru, page_zonenum(page), hpage_nr_pages(page)); - list_add(&page->lru, &lruvec->lists[lru]); -} - -static __always_inline void add_page_to_lru_list_tail(struct page *page, - struct lruvec *lruvec, enum lru_list lru) -{ - update_lru_size(lruvec, lru, page_zonenum(page), hpage_nr_pages(page)); - list_add_tail(&page->lru, &lruvec->lists[lru]); -} - -static __always_inline void del_page_from_lru_list(struct page *page, - struct lruvec *lruvec, enum lru_list lru) -{ - list_del(&page->lru); - update_lru_size(lruvec, lru, page_zonenum(page), -hpage_nr_pages(page)); -} - #endif From 30837c89d8df0ed7d86a7a7352f763d4e8e7ac2a Mon Sep 17 00:00:00 2001 From: xiewen3 Date: Tue, 16 May 2023 22:59:33 +0800 Subject: [PATCH 596/698] LUR: Revert "BACKPORT: mm/vmscan.c: use add_page_to_lru_list()" The LRU function is not compatible with GKI, causing GKI to fail to start, so revert. This reverts commit 15a8f8af8670c68474abf476ef1d3017ef8e1Montana. Change-Id: I3129823e1c05d84cc5616e30b16c906e973e36e3 Reviewed-on: https://gerrit.mot.com/2609772 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- mm/vmscan.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/mm/vmscan.c b/mm/vmscan.c index e2b824d0f847..cc14927c44ee 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -1954,8 +1954,8 @@ static unsigned noinline_for_stack move_pages_to_lru(struct lruvec *lruvec, while (!list_empty(list)) { page = lru_to_page(list); VM_BUG_ON_PAGE(PageLRU(page), page); - list_del(&page->lru); if (unlikely(!page_evictable(page))) { + list_del(&page->lru); spin_unlock_irq(&pgdat->lru_lock); putback_lru_page(page); spin_lock_irq(&pgdat->lru_lock); @@ -1965,7 +1965,10 @@ static unsigned noinline_for_stack move_pages_to_lru(struct lruvec *lruvec, SetPageLRU(page); lru = page_lru(page); - add_page_to_lru_list(page, lruvec, lru); + + nr_pages = hpage_nr_pages(page); + update_lru_size(lruvec, lru, page_zonenum(page), nr_pages); + list_move(&page->lru, &lruvec->lists[lru]); if (put_page_testzero(page)) { __ClearPageLRU(page); @@ -1979,7 +1982,6 @@ static unsigned noinline_for_stack move_pages_to_lru(struct lruvec *lruvec, } else list_add(&page->lru, &pages_to_free); } else { - nr_pages = hpage_nr_pages(page); nr_moved += nr_pages; } } From 0850000858bd070d7b8fdb02d65147cb9f8e8c40 Mon Sep 17 00:00:00 2001 From: xiewen3 Date: Tue, 16 May 2023 23:00:13 +0800 Subject: [PATCH 597/698] LUR: Revert "BACKPORT: mm: use self-explanatory macros rather than "2"" The LRU function is not compatible with GKI, causing GKI to fail to start, so revert. This reverts commit 4e6324f47996243c54f49591465a0743d586127d. Change-Id: Iae8f79f63d50424acce595fedcd6ccc01df02d21 Reviewed-on: https://gerrit.mot.com/2609773 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- include/linux/mmzone.h | 12 ++++-------- mm/vmscan.c | 4 +++- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index 97f9d4576d2e..6f2a15015435 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -293,8 +293,6 @@ static inline int is_active_lru(enum lru_list lru) return (lru == LRU_ACTIVE_ANON || lru == LRU_ACTIVE_FILE); } -#define ANON_AND_FILE 2 - struct zone_reclaim_stat { /* * The pageout code in vmscan.c keeps track of how many of the @@ -304,8 +302,8 @@ struct zone_reclaim_stat { * * The anon LRU stats live in [0], file LRU stats in [1] */ - unsigned long recent_rotated[ANON_AND_FILE]; - unsigned long recent_scanned[ANON_AND_FILE]; + unsigned long recent_rotated[2]; + unsigned long recent_scanned[2]; }; struct lruvec { @@ -427,8 +425,6 @@ enum zone_type { #ifndef __GENERATING_BOUNDS_H -#define ASYNC_AND_SYNC 2 - struct zone { /* Read-mostly fields */ @@ -552,8 +548,8 @@ struct zone { #if defined CONFIG_COMPACTION || defined CONFIG_CMA /* pfn where compaction free scanner should start */ unsigned long compact_cached_free_pfn; - /* pfn where compaction migration scanner should start */ - unsigned long compact_cached_migrate_pfn[ASYNC_AND_SYNC]; + /* pfn where async and sync compaction migration scanner should start */ + unsigned long compact_cached_migrate_pfn[2]; unsigned long compact_init_migrate_pfn; unsigned long compact_init_free_pfn; #endif diff --git a/mm/vmscan.c b/mm/vmscan.c index cc14927c44ee..46261548525b 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -2375,7 +2375,7 @@ static void get_scan_count(struct lruvec *lruvec, struct mem_cgroup *memcg, { int swappiness = mem_cgroup_swappiness(memcg); struct zone_reclaim_stat *reclaim_stat = &lruvec->reclaim_stat; - u64 fraction[ANON_AND_FILE]; + u64 fraction[2]; u64 denominator = 0; /* gcc */ struct pglist_data *pgdat = lruvec_pgdat(lruvec); unsigned long anon_prio, file_prio; @@ -2487,6 +2487,8 @@ static void get_scan_count(struct lruvec *lruvec, struct mem_cgroup *memcg, * Because workloads change over time (and to avoid overflow) * we keep these statistics as a floating average, which ends * up weighing recent references more than old ones. + * + * anon in [0], file in [1] */ anon = lruvec_lru_size(lruvec, LRU_ACTIVE_ANON, MAX_NR_ZONES) + From f8a0095395a7b88c0c2ff61809dbab53ab8bec0d Mon Sep 17 00:00:00 2001 From: xiewen3 Date: Tue, 16 May 2023 23:00:56 +0800 Subject: [PATCH 598/698] LUR: Revert "BACKPORT: mm: remove superfluous __ClearPageActive()" The LRU function is not compatible with GKI, causing GKI to fail to start, so revert. This reverts commit 5f225d9450f42612a0056e7fec13cfe5e828caac. Change-Id: Ic0e6dca9a27428421d8ad29517a497133138ee3b Reviewed-on: https://gerrit.mot.com/2609774 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- mm/memremap.c | 2 ++ mm/swap.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/mm/memremap.c b/mm/memremap.c index b268b184eab3..c51c6bd2fe34 100644 --- a/mm/memremap.c +++ b/mm/memremap.c @@ -419,6 +419,8 @@ void __put_devmap_managed_page(struct page *page) * holds a reference on the page. */ if (count == 1) { + /* Clear Active bit in case of parallel mark_page_accessed */ + __ClearPageActive(page); __ClearPageWaiters(page); mem_cgroup_uncharge(page); diff --git a/mm/swap.c b/mm/swap.c index 8362cfde85aa..159174565497 100644 --- a/mm/swap.c +++ b/mm/swap.c @@ -829,6 +829,8 @@ void release_pages(struct page **pages, int nr) del_page_from_lru_list(page, lruvec, page_off_lru(page)); } + /* Clear Active bit in case of parallel mark_page_accessed */ + __ClearPageActive(page); __ClearPageWaiters(page); list_add(&page->lru, &pages_to_free); From 7a008015a508f72b675e9e5c7770249a81400fbc Mon Sep 17 00:00:00 2001 From: xiewen3 Date: Tue, 16 May 2023 23:01:44 +0800 Subject: [PATCH 599/698] LUR: Revert "BACKPORT: mm/swapcache: support to handle the shadow entries" The LRU function is not compatible with GKI, causing GKI to fail to start, so revert. This reverts commit 1968691ba29356ec6e407f6691ccd3fc5b16f38b. Change-Id: I410b200e5c30b6aa189c424ae9afd6c9288c3e40 Reviewed-on: https://gerrit.mot.com/2609775 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- include/linux/swap.h | 18 ++++---------- mm/shmem.c | 2 +- mm/swap_state.c | 59 ++++++-------------------------------------- mm/swapfile.c | 2 -- mm/vmscan.c | 2 +- 5 files changed, 14 insertions(+), 69 deletions(-) diff --git a/include/linux/swap.h b/include/linux/swap.h index 0cc833d21ce2..bb50a6d0eee4 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h @@ -415,13 +415,10 @@ extern struct address_space *swapper_spaces[]; extern unsigned long total_swapcache_pages(void); extern void show_swap_cache_info(void); extern int add_to_swap(struct page *page); -extern int add_to_swap_cache(struct page *page, swp_entry_t entry, - gfp_t gfp, void **shadowp); -extern void __delete_from_swap_cache(struct page *page, - swp_entry_t entry, void *shadow); +extern int add_to_swap_cache(struct page *, swp_entry_t, gfp_t); +extern int __add_to_swap_cache(struct page *page, swp_entry_t entry); +extern void __delete_from_swap_cache(struct page *, swp_entry_t entry); extern void delete_from_swap_cache(struct page *); -extern void clear_shadow_from_swap_cache(int type, unsigned long begin, - unsigned long end); extern void free_page_and_swap_cache(struct page *); extern void free_pages_and_swap_cache(struct page **, int); extern struct page *lookup_swap_cache(swp_entry_t entry, @@ -576,13 +573,13 @@ static inline int add_to_swap(struct page *page) } static inline int add_to_swap_cache(struct page *page, swp_entry_t entry, - gfp_t gfp_mask, void **shadowp) + gfp_t gfp_mask) { return -1; } static inline void __delete_from_swap_cache(struct page *page, - swp_entry_t entry, void *shadow) + swp_entry_t entry) { } @@ -590,11 +587,6 @@ static inline void delete_from_swap_cache(struct page *page) { } -static inline void clear_shadow_from_swap_cache(int type, unsigned long begin, - unsigned long end) -{ -} - static inline int page_swapcount(struct page *page) { return 0; diff --git a/mm/shmem.c b/mm/shmem.c index a5b110795c54..28deb63c21a7 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -1374,7 +1374,7 @@ static int shmem_writepage(struct page *page, struct writeback_control *wbc) if (list_empty(&info->swaplist)) list_add(&info->swaplist, &shmem_swaplist); - if (add_to_swap_cache(page, swap, GFP_ATOMIC, NULL) == 0) { + if (add_to_swap_cache(page, swap, GFP_ATOMIC) == 0) { spin_lock_irq(&info->lock); shmem_recalc_inode(inode); info->swapped++; diff --git a/mm/swap_state.c b/mm/swap_state.c index e8bd52bb23b1..16709312e949 100644 --- a/mm/swap_state.c +++ b/mm/swap_state.c @@ -112,14 +112,12 @@ void show_swap_cache_info(void) * add_to_swap_cache resembles add_to_page_cache_locked on swapper_space, * but sets SwapCache flag and private instead of mapping and index. */ -int add_to_swap_cache(struct page *page, swp_entry_t entry, - gfp_t gfp, void **shadowp) +int add_to_swap_cache(struct page *page, swp_entry_t entry, gfp_t gfp) { struct address_space *address_space = swap_address_space(entry); pgoff_t idx = swp_offset(entry); XA_STATE_ORDER(xas, &address_space->i_pages, idx, compound_order(page)); - unsigned long i, nr = hpage_nr_pages(page); - void *old; + unsigned long i, nr = compound_nr(page); VM_BUG_ON_PAGE(!PageLocked(page), page); VM_BUG_ON_PAGE(PageSwapCache(page), page); @@ -129,25 +127,16 @@ int add_to_swap_cache(struct page *page, swp_entry_t entry, SetPageSwapCache(page); do { - unsigned long nr_shadows = 0; - xas_lock_irq(&xas); xas_create_range(&xas); if (xas_error(&xas)) goto unlock; for (i = 0; i < nr; i++) { VM_BUG_ON_PAGE(xas.xa_index != idx + i, page); - old = xas_load(&xas); - if (xa_is_value(old)) { - nr_shadows++; - if (shadowp) - *shadowp = old; - } set_page_private(page + i, entry.val + i); xas_store(&xas, page); xas_next(&xas); } - address_space->nrexceptional -= nr_shadows; address_space->nrpages += nr; __mod_node_page_state(page_pgdat(page), NR_FILE_PAGES, nr); ADD_CACHE_INFO(add_total, nr); @@ -167,8 +156,7 @@ unlock: * This must be called only on pages that have * been verified to be in the swap cache. */ -void __delete_from_swap_cache(struct page *page, - swp_entry_t entry, void *shadow) +void __delete_from_swap_cache(struct page *page, swp_entry_t entry) { struct address_space *address_space = swap_address_space(entry); int i, nr = hpage_nr_pages(page); @@ -180,14 +168,12 @@ void __delete_from_swap_cache(struct page *page, VM_BUG_ON_PAGE(PageWriteback(page), page); for (i = 0; i < nr; i++) { - void *entry = xas_store(&xas, shadow); + void *entry = xas_store(&xas, NULL); VM_BUG_ON_PAGE(entry != page, entry); set_page_private(page + i, 0); xas_next(&xas); } ClearPageSwapCache(page); - if (shadow) - address_space->nrexceptional += nr; address_space->nrpages -= nr; __mod_node_page_state(page_pgdat(page), NR_FILE_PAGES, -nr); ADD_CACHE_INFO(del_total, nr); @@ -224,7 +210,7 @@ int add_to_swap(struct page *page) * Add it to the swap cache. */ err = add_to_swap_cache(page, entry, - __GFP_HIGH|__GFP_NOMEMALLOC|__GFP_NOWARN, NULL); + __GFP_HIGH|__GFP_NOMEMALLOC|__GFP_NOWARN); if (err) /* * add_to_swap_cache() doesn't return -EEXIST, so we can safely @@ -262,44 +248,13 @@ void delete_from_swap_cache(struct page *page) struct address_space *address_space = swap_address_space(entry); xa_lock_irq(&address_space->i_pages); - __delete_from_swap_cache(page, entry, NULL); + __delete_from_swap_cache(page, entry); xa_unlock_irq(&address_space->i_pages); put_swap_page(page, entry); page_ref_sub(page, hpage_nr_pages(page)); } -void clear_shadow_from_swap_cache(int type, unsigned long begin, - unsigned long end) -{ - unsigned long curr = begin; - void *old; - - for (;;) { - unsigned long nr_shadows = 0; - swp_entry_t entry = swp_entry(type, curr); - struct address_space *address_space = swap_address_space(entry); - XA_STATE(xas, &address_space->i_pages, curr); - - xa_lock_irq(&address_space->i_pages); - xas_for_each(&xas, old, end) { - if (!xa_is_value(old)) - continue; - xas_store(&xas, NULL); - nr_shadows++; - } - address_space->nrexceptional -= nr_shadows; - xa_unlock_irq(&address_space->i_pages); - - /* search the next swapcache until we meet end */ - curr >>= SWAP_ADDRESS_SPACE_SHIFT; - curr++; - curr <<= SWAP_ADDRESS_SPACE_SHIFT; - if (curr > end) - break; - } -} - /* * If we are the only user, then try to free up the swap cache. * @@ -465,7 +420,7 @@ struct page *__read_swap_cache_async(swp_entry_t entry, gfp_t gfp_mask, __SetPageLocked(new_page); __SetPageSwapBacked(new_page); err = add_to_swap_cache(new_page, entry, - gfp_mask & GFP_RECLAIM_MASK, NULL); + gfp_mask & GFP_RECLAIM_MASK); if (likely(!err)) { /* Initiate read into locked page */ SetPageWorkingset(new_page); diff --git a/mm/swapfile.c b/mm/swapfile.c index 0a1485f4b59c..f0f77c750c56 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -716,7 +716,6 @@ static void add_to_avail_list(struct swap_info_struct *p) static void swap_range_free(struct swap_info_struct *si, unsigned long offset, unsigned int nr_entries) { - unsigned long begin = offset; unsigned long end = offset + nr_entries - 1; void (*swap_slot_free_notify)(struct block_device *, unsigned long); @@ -742,7 +741,6 @@ static void swap_range_free(struct swap_info_struct *si, unsigned long offset, swap_slot_free_notify(si->bdev, offset); offset++; } - clear_shadow_from_swap_cache(si->type, begin, end); } static int scan_swap_map_slots(struct swap_info_struct *si, diff --git a/mm/vmscan.c b/mm/vmscan.c index 46261548525b..3cae1a1866f1 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -965,7 +965,7 @@ static int __remove_mapping(struct address_space *mapping, struct page *page, if (PageSwapCache(page)) { swp_entry_t swap = { .val = page_private(page) }; mem_cgroup_swapout(page, swap); - __delete_from_swap_cache(page, swap, NULL); + __delete_from_swap_cache(page, swap); xa_unlock_irqrestore(&mapping->i_pages, flags); put_swap_page(page, swap); } else { From a281a3400d6573eaa763da21ce16438d6728414b Mon Sep 17 00:00:00 2001 From: xiewen3 Date: Tue, 16 May 2023 23:02:51 +0800 Subject: [PATCH 600/698] LUR: Revert "UPSTREAM: mm/vmscan.c: use update_lru_size() in update_lru_sizes()" The LRU function is not compatible with GKI, causing GKI to fail to start, so revert. This reverts commit 78201f9570128320c849f6a527e1a55b9e2585ed. Change-Id: I74fcb0d3720b84bc82e36f15846b3518aac136c8 Reviewed-on: https://gerrit.mot.com/2609776 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- mm/vmscan.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/mm/vmscan.c b/mm/vmscan.c index 3cae1a1866f1..90ef9c46e2f3 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -1722,7 +1722,10 @@ static __always_inline void update_lru_sizes(struct lruvec *lruvec, if (!nr_zone_taken[zid]) continue; - update_lru_size(lruvec, lru, zid, -nr_zone_taken[zid]); + __update_lru_size(lruvec, lru, zid, -nr_zone_taken[zid]); +#ifdef CONFIG_MEMCG + mem_cgroup_update_lru_size(lruvec, lru, zid, -nr_zone_taken[zid]); +#endif } } From 1826331646caf33a46698e33731a36ad53a66489 Mon Sep 17 00:00:00 2001 From: xiewen3 Date: Tue, 16 May 2023 23:03:32 +0800 Subject: [PATCH 601/698] LUR: Revert "BACKPORT: mm/hmm: do not call hmm_vma_walk_hole() while holding a spinlock" The LRU function is not compatible with GKI, causing GKI to fail to start, so revert. This reverts commit ac70c47ff84f406637d773c2314e89b3a911bbbe. Change-Id: Id782c9e6c84871051ad605dfdbd8213d2e0fab87 Reviewed-on: https://gerrit.mot.com/2609777 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- mm/hmm.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/mm/hmm.c b/mm/hmm.c index 795faf021085..231de978d647 100644 --- a/mm/hmm.c +++ b/mm/hmm.c @@ -671,8 +671,8 @@ static int hmm_vma_walk_pud(pud_t *pudp, unsigned long start, unsigned long end, pud = READ_ONCE(*pudp); if (pud_none(pud)) { - spin_unlock(ptl); - return hmm_vma_walk_hole(start, end, walk); + ret = hmm_vma_walk_hole(start, end, walk); + goto out_unlock; } if (pud_huge(pud) && pud_devmap(pud)) { @@ -681,8 +681,8 @@ static int hmm_vma_walk_pud(pud_t *pudp, unsigned long start, unsigned long end, bool fault, write_fault; if (!pud_present(pud)) { - spin_unlock(ptl); - return hmm_vma_walk_hole(start, end, walk); + ret = hmm_vma_walk_hole(start, end, walk); + goto out_unlock; } i = (addr - range->start) >> PAGE_SHIFT; @@ -693,9 +693,9 @@ static int hmm_vma_walk_pud(pud_t *pudp, unsigned long start, unsigned long end, hmm_range_need_fault(hmm_vma_walk, pfns, npages, cpu_flags, &fault, &write_fault); if (fault || write_fault) { - spin_unlock(ptl); - return hmm_vma_walk_hole_(addr, end, fault, write_fault, - walk); + ret = hmm_vma_walk_hole_(addr, end, fault, + write_fault, walk); + goto out_unlock; } pfn = pud_pfn(pud) + ((addr & ~PUD_MASK) >> PAGE_SHIFT); From 56fc3e3ac8c27b5bec8dd4008f90793f460a4f37 Mon Sep 17 00:00:00 2001 From: xiewen3 Date: Tue, 16 May 2023 23:04:25 +0800 Subject: [PATCH 602/698] LUR: Revert "BACKPORT: mm: pagewalk: add p4d_entry() and pgd_entry()" The LRU function is not compatible with GKI, causing GKI to fail to start, so revert. This reverts commit 943fbd81c3d0bc996fd50856d9cab91213f62b7a. Change-Id: I63b8b71aa039e709d27377f0134163a6398b8368 Reviewed-on: https://gerrit.mot.com/2609778 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- include/linux/pagewalk.h | 34 +++++------------------ mm/hmm.c | 58 ++++++++++++++++++---------------------- mm/pagewalk.c | 50 +++++++++++----------------------- 3 files changed, 47 insertions(+), 95 deletions(-) diff --git a/include/linux/pagewalk.h b/include/linux/pagewalk.h index ed30c86195b0..bddd9759bab9 100644 --- a/include/linux/pagewalk.h +++ b/include/linux/pagewalk.h @@ -8,15 +8,15 @@ struct mm_walk; /** * mm_walk_ops - callbacks for walk_page_range - * @pgd_entry: if set, called for each non-empty PGD (top-level) entry - * @p4d_entry: if set, called for each non-empty P4D entry - * @pud_entry: if set, called for each non-empty PUD entry - * @pmd_entry: if set, called for each non-empty PMD entry + * @pud_entry: if set, called for each non-empty PUD (2nd-level) entry + * this handler should only handle pud_trans_huge() puds. + * the pmd_entry or pte_entry callbacks will be used for + * regular PUDs. + * @pmd_entry: if set, called for each non-empty PMD (3rd-level) entry * this handler is required to be able to handle * pmd_trans_huge() pmds. They may simply choose to * split_huge_page() instead of handling it explicitly. - * @pte_entry: if set, called for each non-empty PTE (lowest-level) - * entry + * @pte_entry: if set, called for each non-empty PTE (4th-level) entry * @pte_hole: if set, called for each hole at all levels * @hugetlb_entry: if set, called for each hugetlb entry * @test_walk: caller specific callback function to determine whether @@ -24,15 +24,8 @@ struct mm_walk; * "do page table walk over the current vma", returning * a negative value means "abort current page table walk * right now" and returning 1 means "skip the current vma" - * - * p?d_entry callbacks are called even if those levels are folded on a - * particular architecture/configuration. */ struct mm_walk_ops { - int (*pgd_entry)(pgd_t *pgd, unsigned long addr, - unsigned long next, struct mm_walk *walk); - int (*p4d_entry)(p4d_t *p4d, unsigned long addr, - unsigned long next, struct mm_walk *walk); int (*pud_entry)(pud_t *pud, unsigned long addr, unsigned long next, struct mm_walk *walk); int (*pmd_entry)(pmd_t *pmd, unsigned long addr, @@ -48,25 +41,11 @@ struct mm_walk_ops { struct mm_walk *walk); }; -/* - * Action for pud_entry / pmd_entry callbacks. - * ACTION_SUBTREE is the default - */ -enum page_walk_action { - /* Descend to next level, splitting huge pages if needed and possible */ - ACTION_SUBTREE = 0, - /* Continue to next entry at this level (ignoring any subtree) */ - ACTION_CONTINUE = 1, - /* Call again for this entry */ - ACTION_AGAIN = 2 -}; - /** * mm_walk - walk_page_range data * @ops: operation to call during the walk * @mm: mm_struct representing the target process of page table walk * @vma: vma currently walked (NULL if walking outside vmas) - * @action: next action to perform (see enum page_walk_action) * @private: private data for callbacks' usage * * (see the comment on walk_page_range() for more details) @@ -75,7 +54,6 @@ struct mm_walk { const struct mm_walk_ops *ops; struct mm_struct *mm; struct vm_area_struct *vma; - enum page_walk_action action; void *private; }; diff --git a/mm/hmm.c b/mm/hmm.c index 231de978d647..902f5fa6bf93 100644 --- a/mm/hmm.c +++ b/mm/hmm.c @@ -658,32 +658,23 @@ static int hmm_vma_walk_pud(pud_t *pudp, unsigned long start, unsigned long end, { struct hmm_vma_walk *hmm_vma_walk = walk->private; struct hmm_range *range = hmm_vma_walk->range; - unsigned long addr = start; + unsigned long addr = start, next; + pmd_t *pmdp; pud_t pud; - int ret = 0; - spinlock_t *ptl = pud_trans_huge_lock(pudp, walk->vma); - - if (!ptl) - return 0; - - /* Normally we don't want to split the huge page */ - walk->action = ACTION_CONTINUE; + int ret; +again: pud = READ_ONCE(*pudp); - if (pud_none(pud)) { - ret = hmm_vma_walk_hole(start, end, walk); - goto out_unlock; - } + if (pud_none(pud)) + return hmm_vma_walk_hole(start, end, walk); if (pud_huge(pud) && pud_devmap(pud)) { unsigned long i, npages, pfn; uint64_t *pfns, cpu_flags; bool fault, write_fault; - if (!pud_present(pud)) { - ret = hmm_vma_walk_hole(start, end, walk); - goto out_unlock; - } + if (!pud_present(pud)) + return hmm_vma_walk_hole(start, end, walk); i = (addr - range->start) >> PAGE_SHIFT; npages = (end - addr) >> PAGE_SHIFT; @@ -692,20 +683,16 @@ static int hmm_vma_walk_pud(pud_t *pudp, unsigned long start, unsigned long end, cpu_flags = pud_to_hmm_pfn_flags(range, pud); hmm_range_need_fault(hmm_vma_walk, pfns, npages, cpu_flags, &fault, &write_fault); - if (fault || write_fault) { - ret = hmm_vma_walk_hole_(addr, end, fault, - write_fault, walk); - goto out_unlock; - } + if (fault || write_fault) + return hmm_vma_walk_hole_(addr, end, fault, + write_fault, walk); pfn = pud_pfn(pud) + ((addr & ~PUD_MASK) >> PAGE_SHIFT); for (i = 0; i < npages; ++i, ++pfn) { hmm_vma_walk->pgmap = get_dev_pagemap(pfn, hmm_vma_walk->pgmap); - if (unlikely(!hmm_vma_walk->pgmap)) { - ret = -EBUSY; - goto out_unlock; - } + if (unlikely(!hmm_vma_walk->pgmap)) + return -EBUSY; pfns[i] = hmm_device_entry_from_pfn(range, pfn) | cpu_flags; } @@ -714,15 +701,22 @@ static int hmm_vma_walk_pud(pud_t *pudp, unsigned long start, unsigned long end, hmm_vma_walk->pgmap = NULL; } hmm_vma_walk->last = end; - goto out_unlock; + return 0; } - /* Ask for the PUD to be split */ - walk->action = ACTION_SUBTREE; + split_huge_pud(walk->vma, pudp, addr); + if (pud_none(*pudp)) + goto again; -out_unlock: - spin_unlock(ptl); - return ret; + pmdp = pmd_offset(pudp, addr); + do { + next = pmd_addr_end(addr, end); + ret = hmm_vma_walk_pmd(pmdp, addr, next, walk); + if (ret) + return ret; + } while (pmdp++, addr = next, addr != end); + + return 0; } #else #define hmm_vma_walk_pud NULL diff --git a/mm/pagewalk.c b/mm/pagewalk.c index 0d4c6159a4ea..ec41e7552f37 100644 --- a/mm/pagewalk.c +++ b/mm/pagewalk.c @@ -45,9 +45,6 @@ again: break; continue; } - - walk->action = ACTION_SUBTREE; - /* * This implies that each ->pmd_entry() handler * needs to know about pmd_trans_huge() pmds @@ -57,21 +54,16 @@ again: if (err) break; - if (walk->action == ACTION_AGAIN) - goto again; - /* * Check this here so we only break down trans_huge * pages when we _need_ to */ - if (walk->action == ACTION_CONTINUE || - !(ops->pte_entry)) + if (!ops->pte_entry) continue; split_huge_pmd(walk->vma, pmd, addr); if (pmd_trans_unstable(pmd)) goto again; - err = walk_pte_range(pmd, addr, next, walk); if (err) break; @@ -100,25 +92,24 @@ static int walk_pud_range(p4d_t *p4d, unsigned long addr, unsigned long end, continue; } - walk->action = ACTION_SUBTREE; + if (ops->pud_entry) { + spinlock_t *ptl = pud_trans_huge_lock(pud, walk->vma); - if (ops->pud_entry) - err = ops->pud_entry(pud, addr, next, walk); - if (err) - break; - - if (walk->action == ACTION_AGAIN) - goto again; - - if (walk->action == ACTION_CONTINUE || - !(ops->pmd_entry || ops->pte_entry)) - continue; + if (ptl) { + err = ops->pud_entry(pud, addr, next, walk); + spin_unlock(ptl); + if (err) + break; + continue; + } + } split_huge_pud(walk->vma, pud, addr); if (pud_none(*pud)) goto again; - err = walk_pmd_range(pud, addr, next, walk); + if (ops->pmd_entry || ops->pte_entry) + err = walk_pmd_range(pud, addr, next, walk); if (err) break; } while (pud++, addr = next, addr != end); @@ -144,12 +135,7 @@ static int walk_p4d_range(pgd_t *pgd, unsigned long addr, unsigned long end, break; continue; } - if (ops->p4d_entry) { - err = ops->p4d_entry(p4d, addr, next, walk); - if (err) - break; - } - if (ops->pud_entry || ops->pmd_entry || ops->pte_entry) + if (ops->pmd_entry || ops->pte_entry) err = walk_pud_range(p4d, addr, next, walk); if (err) break; @@ -176,13 +162,7 @@ static int walk_pgd_range(unsigned long addr, unsigned long end, break; continue; } - if (ops->pgd_entry) { - err = ops->pgd_entry(pgd, addr, next, walk); - if (err) - break; - } - if (ops->p4d_entry || ops->pud_entry || ops->pmd_entry || - ops->pte_entry) + if (ops->pmd_entry || ops->pte_entry) err = walk_p4d_range(pgd, addr, next, walk); if (err) break; From b573ae35879f0bce9d721207283635f259184fe5 Mon Sep 17 00:00:00 2001 From: xiewen3 Date: Tue, 16 May 2023 23:05:22 +0800 Subject: [PATCH 603/698] LUR: Revert "UPSTREAM: x86: mm: add p?d_leaf() definitions" The LRU function is not compatible with GKI, causing GKI to fail to start, so revert. This reverts commit 6cf2be0cfe0c9bc4ca6ab1e8835aace0b2ebcfdd. Change-Id: I0a30e2ff207d91387d94ea7593ef69555101ce9d Reviewed-on: https://gerrit.mot.com/2609779 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- arch/x86/include/asm/pgtable.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h index d711bc431a2c..cc64fbb33f66 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h @@ -239,7 +239,6 @@ static inline unsigned long pgd_pfn(pgd_t pgd) return (pgd_val(pgd) & PTE_PFN_MASK) >> PAGE_SHIFT; } -#define p4d_leaf p4d_large static inline int p4d_large(p4d_t p4d) { /* No 512 GiB pages yet */ @@ -248,7 +247,6 @@ static inline int p4d_large(p4d_t p4d) #define pte_page(pte) pfn_to_page(pte_pfn(pte)) -#define pmd_leaf pmd_large static inline int pmd_large(pmd_t pte) { return pmd_flags(pte) & _PAGE_PSE; @@ -880,7 +878,6 @@ static inline pmd_t *pmd_offset(pud_t *pud, unsigned long address) return (pmd_t *)pud_page_vaddr(*pud) + pmd_index(address); } -#define pud_leaf pud_large static inline int pud_large(pud_t pud) { return (pud_val(pud) & (_PAGE_PSE | _PAGE_PRESENT)) == @@ -892,7 +889,6 @@ static inline int pud_bad(pud_t pud) return (pud_flags(pud) & ~(_KERNPG_TABLE | _PAGE_USER)) != 0; } #else -#define pud_leaf pud_large static inline int pud_large(pud_t pud) { return 0; @@ -1241,7 +1237,6 @@ static inline bool pgdp_maps_userspace(void *__ptr) return (((ptr & ~PAGE_MASK) / sizeof(pgd_t)) < PGD_KERNEL_START); } -#define pgd_leaf pgd_large static inline int pgd_large(pgd_t pgd) { return 0; } #ifdef CONFIG_PAGE_TABLE_ISOLATION From 8798d74854016b59957f9de8177426ac9caea4ec Mon Sep 17 00:00:00 2001 From: xiewen3 Date: Tue, 16 May 2023 23:06:19 +0800 Subject: [PATCH 604/698] LUR: Revert "BACKPORT: arm64: mm: fix p?d_leaf()" The LRU function is not compatible with GKI, causing GKI to fail to start, so revert. This reverts commit 745ca1533026d727942efca5464a7334208a9ee7. Change-Id: I7945c064acad381753d3db6c36985b478447dc9f Reviewed-on: https://gerrit.mot.com/2609780 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- arch/arm64/include/asm/pgtable.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h index 4f48704996dc..d3c05457377b 100644 --- a/arch/arm64/include/asm/pgtable.h +++ b/arch/arm64/include/asm/pgtable.h @@ -455,7 +455,7 @@ extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, PMD_TYPE_TABLE) #define pmd_sect(pmd) ((pmd_val(pmd) & PMD_TYPE_MASK) == \ PMD_TYPE_SECT) -#define pmd_leaf(pmd) (pmd_present(pmd) && !pmd_table(pmd)) +#define pmd_leaf(pmd) pmd_sect(pmd) #if defined(CONFIG_ARM64_64K_PAGES) || CONFIG_PGTABLE_LEVELS < 3 static inline bool pud_sect(pud_t pud) { return false; } @@ -547,7 +547,7 @@ static inline unsigned long pmd_page_vaddr(pmd_t pmd) #define pud_none(pud) (!pud_val(pud)) #define pud_bad(pud) (!(pud_val(pud) & PUD_TABLE_BIT)) #define pud_present(pud) pte_present(pud_pte(pud)) -#define pud_leaf(pud) (pud_present(pud) && !pud_table(pud)) +#define pud_leaf(pud) pud_sect(pud) #define pud_valid(pud) pte_valid(pud_pte(pud)) static inline void set_pud(pud_t *pudp, pud_t pud) From 6ec3a670bf43a47037ce87f93809c743885885bf Mon Sep 17 00:00:00 2001 From: xiewen3 Date: Tue, 16 May 2023 23:07:59 +0800 Subject: [PATCH 605/698] LUR: Revert "UPSTREAM: arm64: mm: add p?d_leaf() definitions" The LRU function is not compatible with GKI, causing GKI to fail to start, so revert. This reverts commit 5f9995fba5dfa040728619437610119360f64ccd. Change-Id: I4a0dfd382d738cbd18513d71ed9250b60c7349df Reviewed-on: https://gerrit.mot.com/2609781 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- arch/arm64/include/asm/pgtable.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h index d3c05457377b..30588e12752b 100644 --- a/arch/arm64/include/asm/pgtable.h +++ b/arch/arm64/include/asm/pgtable.h @@ -455,7 +455,6 @@ extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, PMD_TYPE_TABLE) #define pmd_sect(pmd) ((pmd_val(pmd) & PMD_TYPE_MASK) == \ PMD_TYPE_SECT) -#define pmd_leaf(pmd) pmd_sect(pmd) #if defined(CONFIG_ARM64_64K_PAGES) || CONFIG_PGTABLE_LEVELS < 3 static inline bool pud_sect(pud_t pud) { return false; } @@ -547,7 +546,6 @@ static inline unsigned long pmd_page_vaddr(pmd_t pmd) #define pud_none(pud) (!pud_val(pud)) #define pud_bad(pud) (!(pud_val(pud) & PUD_TABLE_BIT)) #define pud_present(pud) pte_present(pud_pte(pud)) -#define pud_leaf(pud) pud_sect(pud) #define pud_valid(pud) pte_valid(pud_pte(pud)) static inline void set_pud(pud_t *pudp, pud_t pud) From e76cbb48fbcdb808242af41772a4d6ed9d708fd0 Mon Sep 17 00:00:00 2001 From: xiewen3 Date: Tue, 16 May 2023 23:09:36 +0800 Subject: [PATCH 606/698] LUR: Revert "UPSTREAM: mm: add generic p?d_leaf() macros" The LRU function is not compatible with GKI, causing GKI to fail to start, so revert. This reverts commit 7159dbb11d03d5ed343be00e604b0323389bedc9. Change-Id: I033fff852c69af310709f76e817801a5e19fbe48 Reviewed-on: https://gerrit.mot.com/2609782 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- include/asm-generic/pgtable.h | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h index f5895a174b3b..15f77361eb13 100644 --- a/include/asm-generic/pgtable.h +++ b/include/asm-generic/pgtable.h @@ -1206,24 +1206,4 @@ static inline bool arch_has_pfn_modify_check(void) #define mm_pmd_folded(mm) __is_defined(__PAGETABLE_PMD_FOLDED) #endif -/* - * p?d_leaf() - true if this entry is a final mapping to a physical address. - * This differs from p?d_huge() by the fact that they are always available (if - * the architecture supports large pages at the appropriate level) even - * if CONFIG_HUGETLB_PAGE is not defined. - * Only meaningful when called on a valid entry. - */ -#ifndef pgd_leaf -#define pgd_leaf(x) 0 -#endif -#ifndef p4d_leaf -#define p4d_leaf(x) 0 -#endif -#ifndef pud_leaf -#define pud_leaf(x) 0 -#endif -#ifndef pmd_leaf -#define pmd_leaf(x) 0 -#endif - #endif /* _ASM_GENERIC_PGTABLE_H */ From 1a384eabfe277c199b6166a9019c221824ab968f Mon Sep 17 00:00:00 2001 From: xiewen3 Date: Tue, 16 May 2023 23:10:21 +0800 Subject: [PATCH 607/698] LUR: Revert "UPSTREAM: x86/mm: implement arch_faults_on_old_pte() stub on x86" The LRU function is not compatible with GKI, causing GKI to fail to start, so revert. This reverts commit 0c5ddd0dfcff97eb4546d087c2757cf8d149bd57. Change-Id: I9bd79de6463879a398a28d5921655e3038ef1320 Reviewed-on: https://gerrit.mot.com/2609783 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- arch/x86/include/asm/pgtable.h | 6 ------ 1 file changed, 6 deletions(-) diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h index cc64fbb33f66..1ae7c20f5469 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h @@ -1467,12 +1467,6 @@ static inline bool arch_has_pfn_modify_check(void) return boot_cpu_has_bug(X86_BUG_L1TF); } -#define arch_faults_on_old_pte arch_faults_on_old_pte -static inline bool arch_faults_on_old_pte(void) -{ - return false; -} - #include #endif /* __ASSEMBLY__ */ From eb19889bf22fd4a8968dcaab3b4ba5db22d2d9ab Mon Sep 17 00:00:00 2001 From: xiewen3 Date: Tue, 16 May 2023 23:10:51 +0800 Subject: [PATCH 608/698] LUR: Revert "UPSTREAM: arm64: mm: implement arch_faults_on_old_pte() on arm64" The LRU function is not compatible with GKI, causing GKI to fail to start, so revert. This reverts commit c929eb69b36f01d4920bf516f1fee4be7b4abeec. Change-Id: I1b29555391999bcdc12195cf5e3d10a21ff1af15 Reviewed-on: https://gerrit.mot.com/2609784 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- arch/arm64/include/asm/pgtable.h | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h index 30588e12752b..9197acde622a 100644 --- a/arch/arm64/include/asm/pgtable.h +++ b/arch/arm64/include/asm/pgtable.h @@ -886,20 +886,6 @@ static inline void update_mmu_cache(struct vm_area_struct *vma, #define phys_to_ttbr(addr) (addr) #endif -/* - * On arm64 without hardware Access Flag, copying from user will fail because - * the pte is old and cannot be marked young. So we always end up with zeroed - * page after fork() + CoW for pfn mappings. We don't always have a - * hardware-managed access flag on arm64. - */ -static inline bool arch_faults_on_old_pte(void) -{ - WARN_ON(preemptible()); - - return !cpu_has_hw_af(); -} -#define arch_faults_on_old_pte arch_faults_on_old_pte - #endif /* !__ASSEMBLY__ */ #endif /* __ASM_PGTABLE_H */ From 7a7ea6d35bfcf0b5a10c1ef280e03fce4479fddb Mon Sep 17 00:00:00 2001 From: xiewen3 Date: Tue, 16 May 2023 23:11:28 +0800 Subject: [PATCH 609/698] LUR: Revert "BACKPORT: arm64: cpufeature: introduce helper cpu_has_hw_af()" The LRU function is not compatible with GKI, causing GKI to fail to start, so revert. This reverts commit 3b34499f4bbabc44f1e46239024ca4fe07a00461. Change-Id: I3f9a610dc3f0dbc9e935224956c1a21efc46d33d Reviewed-on: https://gerrit.mot.com/2609785 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- arch/arm64/include/asm/cpufeature.h | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h index 74bc372ec016..95f661f1933f 100644 --- a/arch/arm64/include/asm/cpufeature.h +++ b/arch/arm64/include/asm/cpufeature.h @@ -707,19 +707,6 @@ static inline u32 id_aa64mmfr0_parange_to_phys_shift(int parange) extern bool cpu_has_amu_feat(int cpu); #endif -/* Check whether hardware update of the Access flag is supported */ -static inline bool cpu_has_hw_af(void) -{ - u64 mmfr1; - - if (!IS_ENABLED(CONFIG_ARM64_HW_AFDBM)) - return false; - - mmfr1 = read_cpuid(ID_AA64MMFR1_EL1); - return cpuid_feature_extract_unsigned_field(mmfr1, - ID_AA64MMFR1_HADBS_SHIFT); -} - #endif /* __ASSEMBLY__ */ #endif From 836e3b0c9a1c14137ea826a6c5bcc5b18b9776a4 Mon Sep 17 00:00:00 2001 From: Tony Truong Date: Wed, 16 Mar 2022 16:11:12 -0700 Subject: [PATCH 610/698] net: qrtr: get svc_id before queueing sk_buff In qrtr_endpoint_post, getting svc_id based on sk_buff->cb after sk_buff has been queued to the endpoint leads to a potential use-after-free scenario. To avoid this race condition, get the service ID via sk_buff->cb before queueing the sk_buff. Mot-CRs-fixed: (CR) CVE-Fixed: CVE-2022-33292 Bug: 250627197 CRs-Fixed: 3152855 Change-Id: I53205fdffc08fd6dc48fd158c7fe5966f38aa978 Signed-off-by: Tony Truong Signed-off-by: Ashutosh Verma Reviewed-on: https://gerrit.mot.com/2601336 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- net/qrtr/qrtr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/qrtr/qrtr.c b/net/qrtr/qrtr.c index 0b4873903143..fa7610531358 100644 --- a/net/qrtr/qrtr.c +++ b/net/qrtr/qrtr.c @@ -929,6 +929,7 @@ int qrtr_endpoint_post(struct qrtr_endpoint *ep, const void *data, size_t len) /* All control packets and non-local destined data packets should be * queued to the worker for forwarding handling. */ + svc_id = qrtr_get_service_id(cb->src_node, cb->src_port); if (cb->type != QRTR_TYPE_DATA || cb->dst_node != qrtr_local_nid) { skb_queue_tail(&node->rx_queue, skb); kthread_queue_work(&node->kworker, &node->read_data); @@ -941,7 +942,6 @@ int qrtr_endpoint_post(struct qrtr_endpoint *ep, const void *data, size_t len) } if (node->nid == 5) { - svc_id = qrtr_get_service_id(cb->src_node, cb->src_port); if (svc_id > 0){ for (i = 0; i < node->no_wake_svc.size; i++) { if (svc_id == node->no_wake_svc.arr[i]) { From c70d0886c829041628e00c942164dc8b799d678f Mon Sep 17 00:00:00 2001 From: huqian4 Date: Mon, 22 May 2023 11:45:16 +0800 Subject: [PATCH 611/698] bangkk: support dw9784 af drift details: Enable dw9784 af drift. Change-Id: I0299a0a7109e88f04315be2640042b130cb16297 Signed-off-by: huqian4 Reviewed-on: https://gerrit.mot.com/2616203 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Wang Liu Reviewed-by: Reviewed-by: Reviewed-by: Reviewed-by: Zhichao Chen Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- arch/arm64/Kconfig | 6 ++++++ .../configs/vendor/ext_config/factory-holi-bangkk.config | 1 + .../arm64/configs/vendor/ext_config/moto-holi-bangkk.config | 1 + 3 files changed, 8 insertions(+) diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 7df8d2b8ef5b..9bcb5cca72e6 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -1927,3 +1927,9 @@ config CAMERA_FLASH_IIC_COMPATIBLE default n help Enable it, this is automatically selected flash supplers. + +config MOT_DONGWOON_OIS_AF_DRIFT + bool "dongwoon ois af drift" + default n + help + Enable it will support dongwoon ois af drift. diff --git a/arch/arm64/configs/vendor/ext_config/factory-holi-bangkk.config b/arch/arm64/configs/vendor/ext_config/factory-holi-bangkk.config index cc7be9152bdd..89cbb53b692c 100644 --- a/arch/arm64/configs/vendor/ext_config/factory-holi-bangkk.config +++ b/arch/arm64/configs/vendor/ext_config/factory-holi-bangkk.config @@ -14,3 +14,4 @@ # being set as expected. # CONFIG_CAMERA_DISABLE_VSYNC_IRQ=y +# CONFIG_MOT_DONGWOON_OIS_AF_DRIFT is not set diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-bangkk.config b/arch/arm64/configs/vendor/ext_config/moto-holi-bangkk.config index 9c9a7fa94347..82a65ea61482 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-bangkk.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-bangkk.config @@ -22,6 +22,7 @@ CONFIG_ZRAM_WRITEBACK=y # CONFIG_UFSTW is not set CONFIG_CRYPTO_CHACHA20POLY1305=y CONFIG_CAM_SENSOR_PROBE_RETRY=y +CONFIG_MOT_DONGWOON_OIS_AF_DRIFT=y CONFIG_SND_SOC_AW87XXX=m #CONFIG_NFC_QTI_I2C=m CONFIG_MSM_TZ_QSEE_LOG=y From 7b3d3158527e1cc57fda830727210203b1f7136d Mon Sep 17 00:00:00 2001 From: Gilberto Gambugge Date: Sat, 20 May 2023 01:12:05 -0300 Subject: [PATCH 612/698] techpack: add camera legacy support Add camera legacy support by checking BOARD_CONFIG_CAMERA_KERNEL_NAME to decide which folder will be used to compile the camera techpack. Change-Id: I674bc4531818273881e068e29cd8449443e9afc6 Reviewed-on: https://gerrit.mot.com/2616053 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Rav(CR) Vembu Submit-Approved: Marcelo Pincinato Reviewed-by: Rafael Ortolan --- techpack/Kbuild | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/techpack/Kbuild b/techpack/Kbuild index 037f394ff675..ecc335151076 100644 --- a/techpack/Kbuild +++ b/techpack/Kbuild @@ -1,5 +1,16 @@ # SPDX-License-Identifier: GPL-2.0-only TECHPACK?=y -techpack-dirs := $(shell find $(srctree)/techpack -maxdepth 1 -mindepth 1 -type d -not -name ".*") +ifeq ($(BOARD_CONFIG_CAMERA_KERNEL_NAME),) +$(info "using default camera path") +techpack-dirs := $(shell find $(srctree)/techpack -maxdepth 1 -mindepth 1 -type d -not -name ".*"\ + | grep -v legacy) +else +$(info "using camera-legacy/$(BOARD_CONFIG_CAMERA_KERNEL_NAME)") +techpack-dirs := $(shell find $(srctree)/techpack -maxdepth 1 -mindepth 1 -type d -not -name ".*"\ + | grep -v camera) +techpack-dirs += $(shell find $(srctree)/techpack -maxdepth 2 -mindepth 2 -name "$(BOARD_CONFIG_CAMERA_KERNEL_NAME)") +endif + +$(info "techpack-dirs:=$(techpack-dirs)") obj-${TECHPACK} += stub/ $(addsuffix /,$(subst $(srctree)/techpack/,,$(techpack-dirs))) From 224f1618700c8a4c460ee49a5fb14937e0078095 Mon Sep 17 00:00:00 2001 From: Gilberto Gambugge Date: Wed, 24 May 2023 13:37:37 -0300 Subject: [PATCH 613/698] camera_legacy: update camera uapi kernel headers installation Due to camera legacy, the camera uapi kernel headers installation routines need to be updated to consider the camera legacy support. This commit fixes the routines to install kernel headers for 'make headers_install' and also 'qti_generate_kernel_headers_arm' and 'qti_generate_kernel_headers_arm64'. Change-Id: Iec98dad164d5efc0acaa8f90c29a9672efbe3142 Reviewed-on: https://gerrit.mot.com/2619497 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Rafael Ortolan Reviewed-by: Rav(CR) Vembu Submit-Approved: Jira Key --- Android.bp | 103 +++++++++++++++++++++++++++++++++++++++++++ Makefile | 6 +++ gen_headers_arm.bp | 18 +------- gen_headers_arm64.bp | 16 +------ kernel_headers.py | 14 ++++-- 5 files changed, 122 insertions(+), 35 deletions(-) diff --git a/Android.bp b/Android.bp index 3d5382bfbd47..a1fde7b44556 100644 --- a/Android.bp +++ b/Android.bp @@ -28,6 +28,109 @@ kernel_headers_verbose = "" build = ["gen_headers_arm.bp", "gen_headers_arm64.bp"] +soong_config_module_type { + name: "mmi_camera_legacy_genrule_defaults", + module_type: "genrule_defaults", + config_namespace: "mmi_camera_legacy", + variables: ["board_config_camera_legacy_kernel"], + properties: ["cmd"], +} + +soong_config_string_variable { + name: "board_config_camera_legacy_kernel", + values: ["enabled", "disabled"], +} + +mmi_camera_legacy_genrule_defaults { + name: "mmi_kernel_headers_cmdrules_arm", + soong_config_variables: { + board_config_camera_legacy_kernel: { + disabled: { + cmd: "python3 $(location kernel_headers.py) " + + kernel_headers_verbose + + "--header_arch arm " + + "--gen_dir $(genDir) " + + "--arch_asm_kbuild $(location arch/arm/include/uapi/asm/Kbuild) " + + "--arch_include_uapi $(locations arch/arm/include/uapi/**/*.h) " + + "--techpack_include_uapi $(locations techpack/*/include/uapi/*/**/*.h) " + + "--asm_generic_kbuild $(location include/uapi/asm-generic/Kbuild) " + + "headers " + + "--old_gen_headers_bp $(location gen_headers_arm.bp) " + + "--new_gen_headers_bp $(location :qti_generate_gen_headers_arm) " + + "--version_makefile $(location Makefile) " + + "--arch_syscall_tool $(location arch/arm/tools/syscallhdr.sh) " + + "--arch_syscall_tbl $(location arch/arm/tools/syscall.tbl) " + + "--headers_install $(location headers_install.sh) " + + "--unifdef $(location unifdef) " + + "--include_uapi $(locations include/uapi/**/*.h)", + }, + enabled: { + cmd: "python3 $(location kernel_headers.py) " + + kernel_headers_verbose + + "--header_arch arm " + + "--gen_dir $(genDir) " + + "--arch_asm_kbuild $(location arch/arm/include/uapi/asm/Kbuild) " + + "--arch_include_uapi $(locations arch/arm/include/uapi/**/*.h) " + + "--techpack_include_uapi $(locations techpack/*/include/uapi/*/**/*.h) " + + "--asm_generic_kbuild $(location include/uapi/asm-generic/Kbuild) " + + "headers " + + "--old_gen_headers_bp $(location gen_headers_arm.bp) " + + "--new_gen_headers_bp $(location :qti_generate_gen_headers_arm) " + + "--version_makefile $(location Makefile) " + + "--arch_syscall_tool $(location arch/arm/tools/syscallhdr.sh) " + + "--arch_syscall_tbl $(location arch/arm/tools/syscall.tbl) " + + "--headers_install $(location headers_install.sh) " + + "--unifdef $(location unifdef) " + + "--include_uapi $(locations include/uapi/**/*.h) " + + "--camera_legacy ", + }, + }, + }, +} + +mmi_camera_legacy_genrule_defaults { + name: "mmi_kernel_headers_cmdrules_arm64", + soong_config_variables: { + board_config_camera_legacy_kernel: { + disabled: { + cmd: "python3 $(location kernel_headers.py) " + + kernel_headers_verbose + + "--header_arch arm64 " + + "--gen_dir $(genDir) " + + "--arch_asm_kbuild $(location arch/arm64/include/uapi/asm/Kbuild) " + + "--arch_include_uapi $(locations arch/arm64/include/uapi/**/*.h) " + + "--techpack_include_uapi $(locations techpack/*/include/uapi/*/**/*.h) " + + "--asm_generic_kbuild $(location include/uapi/asm-generic/Kbuild) " + + "headers " + + "--old_gen_headers_bp $(location gen_headers_arm64.bp) " + + "--new_gen_headers_bp $(location :qti_generate_gen_headers_arm64) " + + "--version_makefile $(location Makefile) " + + "--headers_install $(location headers_install.sh) " + + "--unifdef $(location unifdef) " + + "--include_uapi $(locations include/uapi/**/*.h)", + }, + enabled: { + cmd: "python3 $(location kernel_headers.py) " + + kernel_headers_verbose + + "--header_arch arm64 " + + "--gen_dir $(genDir) " + + "--arch_asm_kbuild $(location arch/arm64/include/uapi/asm/Kbuild) " + + "--arch_include_uapi $(locations arch/arm64/include/uapi/**/*.h) " + + "--techpack_include_uapi $(locations techpack/*/include/uapi/*/**/*.h) " + + "--asm_generic_kbuild $(location include/uapi/asm-generic/Kbuild) " + + "headers " + + "--old_gen_headers_bp $(location gen_headers_arm64.bp) " + + "--new_gen_headers_bp $(location :qti_generate_gen_headers_arm64) " + + "--version_makefile $(location Makefile) " + + "--headers_install $(location headers_install.sh) " + + "--unifdef $(location unifdef) " + + "--include_uapi $(locations include/uapi/**/*.h) " + + "--camera_legacy ", + }, + }, + }, +} + cc_library_headers { name: "qti_kernel_headers", arch: { diff --git a/Makefile b/Makefile index 8e0f6cfd1ee1..ccd36a0ea656 100644 --- a/Makefile +++ b/Makefile @@ -1334,7 +1334,13 @@ PHONY += archheaders archscripts hdr-inst := -f $(srctree)/scripts/Makefile.headersinst obj +ifeq ($(BOARD_CONFIG_CAMERA_KERNEL_NAME),) techpack-dirs := $(shell find $(srctree)/techpack -maxdepth 1 -mindepth 1 -type d -not -name ".*") +else +techpack-dirs := $(shell find $(srctree)/techpack -maxdepth 1 -mindepth 1 -type d -not -name ".*"\ + | grep -v camera) +techpack-dirs += $(shell find $(srctree)/techpack -maxdepth 2 -mindepth 2 -name "$(BOARD_CONFIG_CAMERA_KERNEL_NAME)") +endif techpack-dirs := $(subst $(srctree)/,,$(techpack-dirs)) PHONY += headers diff --git a/gen_headers_arm.bp b/gen_headers_arm.bp index 05661be1f7a8..525d83fa016a 100644 --- a/gen_headers_arm.bp +++ b/gen_headers_arm.bp @@ -1064,22 +1064,6 @@ genrule { ":qti_generate_gen_headers_arm", ], exclude_srcs: gen_headers_exclude_srcs_arm, - cmd: "python3 $(location kernel_headers.py) " + - kernel_headers_verbose + - "--header_arch arm " + - "--gen_dir $(genDir) " + - "--arch_asm_kbuild $(location arch/arm/include/uapi/asm/Kbuild) " + - "--arch_include_uapi $(locations arch/arm/include/uapi/**/*.h) " + - "--techpack_include_uapi $(locations techpack/*/include/uapi/*/**/*.h) " + - "--asm_generic_kbuild $(location include/uapi/asm-generic/Kbuild) " + - "headers " + - "--old_gen_headers_bp $(location gen_headers_arm.bp) " + - "--new_gen_headers_bp $(location :qti_generate_gen_headers_arm) " + - "--version_makefile $(location Makefile) " + - "--arch_syscall_tool $(location arch/arm/tools/syscallhdr.sh) " + - "--arch_syscall_tbl $(location arch/arm/tools/syscall.tbl) " + - "--headers_install $(location headers_install.sh) " + - "--unifdef $(location unifdef) " + - "--include_uapi $(locations include/uapi/**/*.h)", out: ["linux/version.h"] + gen_headers_out_arm, + defaults: ["mmi_kernel_headers_cmdrules_arm"], } diff --git a/gen_headers_arm64.bp b/gen_headers_arm64.bp index bee9c6226a0e..b2130898935f 100644 --- a/gen_headers_arm64.bp +++ b/gen_headers_arm64.bp @@ -1058,20 +1058,6 @@ genrule { ":qti_generate_gen_headers_arm64", ], exclude_srcs: gen_headers_exclude_srcs_arm64, - cmd: "python3 $(location kernel_headers.py) " + - kernel_headers_verbose + - "--header_arch arm64 " + - "--gen_dir $(genDir) " + - "--arch_asm_kbuild $(location arch/arm64/include/uapi/asm/Kbuild) " + - "--arch_include_uapi $(locations arch/arm64/include/uapi/**/*.h) " + - "--techpack_include_uapi $(locations techpack/*/include/uapi/*/**/*.h) " + - "--asm_generic_kbuild $(location include/uapi/asm-generic/Kbuild) " + - "headers " + - "--old_gen_headers_bp $(location gen_headers_arm64.bp) " + - "--new_gen_headers_bp $(location :qti_generate_gen_headers_arm64) " + - "--version_makefile $(location Makefile) " + - "--headers_install $(location headers_install.sh) " + - "--unifdef $(location unifdef) " + - "--include_uapi $(locations include/uapi/**/*.h)", out: ["linux/version.h"] + gen_headers_out_arm64, + defaults: ["mmi_kernel_headers_cmdrules_arm64"], } diff --git a/kernel_headers.py b/kernel_headers.py index 27ef474957fd..1d482338a296 100644 --- a/kernel_headers.py +++ b/kernel_headers.py @@ -754,7 +754,7 @@ def gen_headers( verbose, header_arch, gen_dir, arch_asm_kbuild, asm_generic_kbuild, module_dir, old_gen_headers_bp, new_gen_headers_bp, version_makefile, arch_syscall_tool, arch_syscall_tbl, headers_install, unifdef, include_uapi, - arch_include_uapi, techpack_include_uapi): + arch_include_uapi, techpack_include_uapi, camera_legacy): """Generate the kernel headers. This script generates the version.h file, the arch-specific headers including @@ -781,7 +781,6 @@ def gen_headers( Return: The number of errors encountered. """ - if headers_diff(old_gen_headers_bp, new_gen_headers_bp): print('error: gen_headers blueprints file is out of date, suggested fix:') print('#######Please add or remove the above mentioned headers from %s' % (old_gen_headers_bp)) @@ -813,6 +812,10 @@ def gen_headers( arch_uapi_include_prefix, h): error_count += 1 + if camera_legacy == True: + legacy_product = os.getenv('TARGET_PRODUCT').split("_", 1)[0] + techpack_include_uapi = [i.replace('techpack/camera','techpack/camera-legacy/' + legacy_product) for i in techpack_include_uapi] + for h in techpack_include_uapi: techpack_uapi_include_prefix = os.path.join(h.split('/include/uapi')[0], 'include', 'uapi') + os.sep if not run_headers_install( @@ -952,6 +955,11 @@ def main(): required=True, nargs='*', help='The list of include/uapi header files.') + parser_headers.add_argument( + '--camera_legacy', + default=False, + action='store_true', + help='If set, define the camera legacy folder being used. By default, it\'s disabled.') args = parser.parse_args() @@ -1002,7 +1010,7 @@ def main(): args.asm_generic_kbuild, module_dir, args.old_gen_headers_bp, args.new_gen_headers_bp, args.version_makefile, args.arch_syscall_tool, args.arch_syscall_tbl, args.headers_install, args.unifdef, args.include_uapi, args.arch_include_uapi, - args.techpack_include_uapi) + args.techpack_include_uapi, args.camera_legacy) print('error: unknown mode: %s' % args.mode) return 1 From 246b0b8ca3b8bbf2c9b87b7a63654376e80a3e76 Mon Sep 17 00:00:00 2001 From: liyun zhang Date: Wed, 31 May 2023 15:14:22 +0800 Subject: [PATCH 614/698] arm64/configs: Add Fogo5G defconfig Add initial defconfig for Fogo5G(fogor) bringup, these configs are copied from bangkk. Change-Id: I6266b787f979b4aaa622c897ac960f133f469cff Reviewed-on: https://gerrit.mot.com/2627354 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Reviewed-by: Minghui Wei Tested-by: Jira Key Reviewed-by: Xiaojun Ji Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- .../vendor/ext_config/debug-holi-fogor.config | 28 ++++++++++++ .../ext_config/factory-holi-fogor.config | 17 ++++++++ .../vendor/ext_config/moto-holi-fogor.config | 43 +++++++++++++++++++ drivers/soc/qcom/Kconfig | 8 ++++ 4 files changed, 96 insertions(+) create mode 100644 arch/arm64/configs/vendor/ext_config/debug-holi-fogor.config create mode 100644 arch/arm64/configs/vendor/ext_config/factory-holi-fogor.config create mode 100644 arch/arm64/configs/vendor/ext_config/moto-holi-fogor.config diff --git a/arch/arm64/configs/vendor/ext_config/debug-holi-fogor.config b/arch/arm64/configs/vendor/ext_config/debug-holi-fogor.config new file mode 100644 index 000000000000..95c989c10a1b --- /dev/null +++ b/arch/arm64/configs/vendor/ext_config/debug-holi-fogor.config @@ -0,0 +1,28 @@ +# +# Please avoid changing the Qualcomm defconfig files and use this file to +# add any Motorola-specific configuration changes that are applicable to +# userdebug, eng, and user builds. +# +# After building, a list of all of the config files that are used can be found +# at the top of: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/mapphone_defconfig +# +# The actual output of the kernel configuration system can be found at: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/.config +# +# You can check the .config file to verify that your configuration option is +# being set as expected. +# + +# CONFIG_CGROUP_DEBUG is not set +# CONFIG_CLEANCACHE is not set +# CONFIG_CMA_ALLOW_WRITE_DEBUGFS is not set +# CONFIG_CMA_DEBUG is not set +# CONFIG_PREEMPTIRQ_EVENTS is not set +# CONFIG_PREEMPT_TRACER is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_TEST_USER_COPY is not set +# CONFIG_UFSTW is not set + +# CONFIG_SLUB_DEBUG_ON is not set diff --git a/arch/arm64/configs/vendor/ext_config/factory-holi-fogor.config b/arch/arm64/configs/vendor/ext_config/factory-holi-fogor.config new file mode 100644 index 000000000000..89cbb53b692c --- /dev/null +++ b/arch/arm64/configs/vendor/ext_config/factory-holi-fogor.config @@ -0,0 +1,17 @@ +# +# Please avoid changing the Qualcomm defconfig files and use this file to +# add any Motorola-specific configuration changes that are applicable to +# userdebug, eng, and user builds. +# +# After building, a list of all of the config files that are used can be found +# at the top of: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/mapphone_defconfig +# +# The actual output of the kernel configuration system can be found at: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/.config +# +# You can check the .config file to verify that your configuration option is +# being set as expected. +# +CONFIG_CAMERA_DISABLE_VSYNC_IRQ=y +# CONFIG_MOT_DONGWOON_OIS_AF_DRIFT is not set diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-fogor.config b/arch/arm64/configs/vendor/ext_config/moto-holi-fogor.config new file mode 100644 index 000000000000..4636c5578f03 --- /dev/null +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-fogor.config @@ -0,0 +1,43 @@ +# +# Please avoid changing the Qualcomm defconfig files and use this file to +# add any Motorola-specific configuration changes that are applicable to +# userdebug, eng, and user builds. +# +# After building, a list of all of the config files that are used can be found +# at the top of: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/mapphone_defconfig +# +# The actual output of the kernel configuration system can be found at: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/.config +# +# You can check the .config file to verify that your configuration option is +# being set as expected. +# +CONFIG_FOGOR_DTB=y +# CONFIG_NFC_QTI_I2C is not set +CONFIG_FS_EPOLL_WAKEUP_DEBUG=y +CONFIG_ZRAM_WRITEBACK=y +# CONFIG_THERMAL_STATISTICS is not set +# CONFIG_REGULATOR_QPNP_LCDB is not set +# CONFIG_UFSTW is not set +CONFIG_CRYPTO_CHACHA20POLY1305=y +CONFIG_CAM_SENSOR_PROBE_RETRY=y +CONFIG_MOT_DONGWOON_OIS_AF_DRIFT=y +CONFIG_SND_SOC_AW87XXX=m +#CONFIG_NFC_QTI_I2C=m +CONFIG_MSM_TZ_QSEE_LOG=y +CONFIG_AF_NOISE_ELIMINATION=y +# CONFIG_TOUCHSCREEN_FTS is not set +CONFIG_FELICA_MOUNT_BLOCK=y +# CONFIG_UFSFEATURE is not set +# CONFIG_UFSHPB is not set +# CONFIG_UFSTW is not set +# CONFIG_SCSI_SKHPB is not set +CONFIG_NFC=y +CONFIG_SEC_NFC_PRODUCT_N5=y +CONFIG_SEC_NFC=m +CONFIG_SEC_NFC_IF_I2C=y +CONFIG_QUP0_SE2_AP=y +CONFIG_CAMERA_FLASH_IIC_COMPATIBLE=y +CONFIG_EROFS_FS_PCPU_KTHREAD=y +CONFIG_EROFS_FS_PCPU_KTHREAD_HIPRI=y diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index fea4a4e7006c..1537a2e4a437 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -118,6 +118,14 @@ config BANGKK_DTB Only include PENANG specific DTBs to limit the number that get built during kernel compilation. +config FOGOR_DTB + depends on ARCH_QCOM + default n + bool "FOGOR DTBs" + help + Only include FOGOR specific DTBs to limit the number that + get built during kernel compilation. + config PENANGB_DTB depends on ARCH_QCOM default n From 0c44b6ea8cc7e3efffa46657ec9c4f72febe6f5a Mon Sep 17 00:00:00 2001 From: Liu Yang Date: Mon, 12 Jun 2023 10:46:32 +0800 Subject: [PATCH 615/698] bangkk: Powerup and initialize sensor early [4/4] Powering on and initializing main sensor in camera open instead of streams configuration to optimize the startup KPI. It is a common feature and depends on sensor setting. It can save about 30ms. Porting this func from (CR) and (CR). mot-cam-category: KPI Change-Id: I622db10b469c0e3f26619200bebad95836d8ed9f Signed-off-by: Liu Yang Reviewed-on: https://gerrit.mot.com/2640370 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Zilong Zhang Reviewed-by: Reviewed-by: Bolei Shang Reviewed-by: Reviewed-by: Reviewed-by: Ji Zhao Reviewed-by: Dongju He Reviewed-by: Reviewed-by: Zhuoran Xu Reviewed-by: Guobin Zhang Submit-Approved: Jira Key --- arch/arm64/Kconfig | 6 ++++++ .../arm64/configs/vendor/ext_config/moto-holi-bangkk.config | 1 + 2 files changed, 7 insertions(+) diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 9bcb5cca72e6..0e0e47774e46 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -1933,3 +1933,9 @@ config MOT_DONGWOON_OIS_AF_DRIFT default n help Enable it will support dongwoon ois af drift. + +config MOT_SENSOR_PRE_POWERUP + bool "For sensor power up and initialization early" + default n + help + Enable it to power up and initialise early. diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-bangkk.config b/arch/arm64/configs/vendor/ext_config/moto-holi-bangkk.config index 82a65ea61482..8ecb42d8c0a8 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-bangkk.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-bangkk.config @@ -41,3 +41,4 @@ CONFIG_QUP0_SE2_AP=y CONFIG_CAMERA_FLASH_IIC_COMPATIBLE=y CONFIG_EROFS_FS_PCPU_KTHREAD=y CONFIG_EROFS_FS_PCPU_KTHREAD_HIPRI=y +CONFIG_MOT_SENSOR_PRE_POWERUP=y From e188599cbf115b015ef3215856e2b11f8e6184d2 Mon Sep 17 00:00:00 2001 From: liaohj Date: Fri, 9 Jun 2023 17:24:58 +0800 Subject: [PATCH 616/698] config:FOGO ROW:audio:CONFIG_SND_SOC_FS1815 fogo use wcd9370+fs1815 4375 platform. add CONFIG_SND_SOC_FS1815 to support. Change-Id: I228eae099cb71b0eb76c43d0dbefde4f05c6e3b2 Signed-off-by: liaohj Reviewed-on: https://gerrit.mot.com/2639573 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- arch/arm64/Kconfig | 6 ++++++ arch/arm64/configs/vendor/ext_config/moto-holi-fogor.config | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 0e0e47774e46..7808b086c4e1 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -1898,6 +1898,12 @@ config SND_SOC_AW87XXX help This option enables support for AW87XXX Smart K PA. +config SND_SOC_FS1815 + tristate "SoC Audio for fs1815 Smart K PA" + depends on I2C + help + This option enables support for fs1815 K PA. + config CAMERA_FLASH_PWM bool "control flash" default n diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-fogor.config b/arch/arm64/configs/vendor/ext_config/moto-holi-fogor.config index 4636c5578f03..d3d62cb17422 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-fogor.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-fogor.config @@ -23,7 +23,7 @@ CONFIG_ZRAM_WRITEBACK=y CONFIG_CRYPTO_CHACHA20POLY1305=y CONFIG_CAM_SENSOR_PROBE_RETRY=y CONFIG_MOT_DONGWOON_OIS_AF_DRIFT=y -CONFIG_SND_SOC_AW87XXX=m +CONFIG_SND_SOC_FS1815=m #CONFIG_NFC_QTI_I2C=m CONFIG_MSM_TZ_QSEE_LOG=y CONFIG_AF_NOISE_ELIMINATION=y From c1faff2cb8c5423619880b717f918aa513586e16 Mon Sep 17 00:00:00 2001 From: liuzhen Date: Fri, 16 Jun 2023 15:31:55 +0800 Subject: [PATCH 617/698] Modify the fake battery spec 1.modify the voltage of fake battery to 4.2V 2.modify the level of fake battery to 10% Change-Id: I851ea8d5e80c3fa78eb659992446e0b81dbb43b4 Reviewed-on: https://gerrit.mot.com/2646055 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Lei Chen Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- drivers/power/supply/qcom/qg-util.c | 2 +- drivers/power/supply/qcom/qpnp-qg.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/power/supply/qcom/qg-util.c b/drivers/power/supply/qcom/qg-util.c index 2e2f61225ee4..61f91c1c088a 100644 --- a/drivers/power/supply/qcom/qg-util.c +++ b/drivers/power/supply/qcom/qg-util.c @@ -419,7 +419,7 @@ int qg_get_battery_voltage(struct qpnp_qg *chip, int *vbat_uv) u64 last_vbat = 0; if (chip->battery_missing) { - *vbat_uv = 3700000; + *vbat_uv = 4200000; return 0; } diff --git a/drivers/power/supply/qcom/qpnp-qg.c b/drivers/power/supply/qcom/qpnp-qg.c index 940172326c87..4150966bd5f6 100644 --- a/drivers/power/supply/qcom/qpnp-qg.c +++ b/drivers/power/supply/qcom/qpnp-qg.c @@ -1785,7 +1785,7 @@ static const char *qg_get_battery_type(struct qpnp_qg *chip) } #define DEBUG_BATT_SOC 67 -#define BATT_MISSING_SOC 50 +#define BATT_MISSING_SOC 10 #define EMPTY_SOC 0 #define FULL_SOC 100 static int qg_get_battery_capacity(struct qpnp_qg *chip, int *soc) From db3567cce04a3a1b88f05d98b7b9d73fccd3749e Mon Sep 17 00:00:00 2001 From: Lei Chen Date: Mon, 19 Jun 2023 13:57:06 +0800 Subject: [PATCH 618/698] charge:optimize the cp enable in ESR Sometimes the cell voltage exceed the max limit when pump disable/enable. Only allow the pump enable/disable when soc is lower than 90%. Change-Id: I775d22ee7491cd25e2a3a53fbbb5472c80cc8fc6 Signed-off-by: Lei Chen Reviewed-on: https://gerrit.mot.com/2647497 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Reviewed-by: Wei Xu Submit-Approved: Jira Key --- drivers/power/supply/qcom/qg-core.h | 1 + drivers/power/supply/qcom/qpnp-qg.c | 15 +++++++++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/power/supply/qcom/qg-core.h b/drivers/power/supply/qcom/qg-core.h index 5c099d1d8168..9ee46f79ed4a 100644 --- a/drivers/power/supply/qcom/qg-core.h +++ b/drivers/power/supply/qcom/qg-core.h @@ -66,6 +66,7 @@ struct qg_dt { int fvss_vbat_mv; int tcss_entry_soc; int esr_low_temp_threshold; + int cp_chrg_soc_limit; bool hold_soc_while_full; bool linearize_soc; bool cl_disable; diff --git a/drivers/power/supply/qcom/qpnp-qg.c b/drivers/power/supply/qcom/qpnp-qg.c index 4150966bd5f6..7351d60a3563 100644 --- a/drivers/power/supply/qcom/qpnp-qg.c +++ b/drivers/power/supply/qcom/qpnp-qg.c @@ -1103,12 +1103,12 @@ static int qg_esr_estimate(struct qpnp_qg *chip) goto done; } - if (chip->dt.cp_use_internal_qg) { + if ((chip->dt.cp_use_internal_qg) && (chip->msoc < chip->dt.cp_chrg_soc_limit)) { rc = qg_write_iio_chan(chip, CP_CHARGING_ENABLED, 0); if (rc < 0) pr_err("Failed to force disable cp rc=%d\n", rc); else - qg_dbg(chip, QG_DEBUG_STATUS, "disable cp\n"); + qg_dbg(chip, QG_DEBUG_STATUS, "disable cp, msoc =%d\n",chip->msoc); msleep(1000); } @@ -1200,12 +1200,12 @@ static int qg_esr_estimate(struct qpnp_qg *chip) msleep(200); } - if (chip->dt.cp_use_internal_qg) { + if ((chip->dt.cp_use_internal_qg) && (chip->msoc < chip->dt.cp_chrg_soc_limit)) { rc = qg_write_iio_chan(chip, CP_CHARGING_ENABLED, 1); if (rc < 0) pr_err("Failed to force enable cp rc=%d\n", rc); else - qg_dbg(chip, QG_DEBUG_STATUS, "enable cp\n"); + qg_dbg(chip, QG_DEBUG_STATUS, "enable cp, msoc =%d\n",chip->msoc); } rc = qg_process_esr_data(chip); @@ -4392,6 +4392,13 @@ static int qg_parse_dt(struct qpnp_qg *chip) "qcom,esr-discharge-enable"); chip->dt.cp_use_internal_qg = of_property_read_bool(node, "mmi,cp-use-internal-qg"); + + rc = of_property_read_u32(node, "mmi,cp-chrg-soc-limit", &temp); + if (rc < 0) + chip->dt.cp_chrg_soc_limit = 100; + else + chip->dt.cp_chrg_soc_limit = temp; + rc = of_property_read_u32(node, "qcom,esr-qual-current-ua", &temp); if (rc < 0) chip->dt.esr_qual_i_ua = DEFAULT_ESR_QUAL_CURRENT_UA; From 6a8ae96b3619be5de5468ca6fb538dcd13c22f7e Mon Sep 17 00:00:00 2001 From: wangwang Date: Wed, 21 Jun 2023 12:21:19 +0800 Subject: [PATCH 619/698] bangkok:set mmap readahead upbound limitation vdex/odex file mmap operation actually does random access, the large read ahead size can harm the performance, use this configuration to limit the uplimit of read ahead cache size Change-Id: Ic370e9372803e538b247b69501875018afeba32e Signed-off-by: wangwang Reviewed-on: https://gerrit.mot.com/2650468 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- mm/Kconfig | 7 +++++++ mm/filemap.c | 17 ++++++++++++++--- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/mm/Kconfig b/mm/Kconfig index fe6c22bc562c..5c61895faa01 100644 --- a/mm/Kconfig +++ b/mm/Kconfig @@ -736,6 +736,13 @@ config DEVICE_PRIVATE memory; i.e., memory that is only accessible from the device (or group of devices). You likely also want to select HMM_MIRROR. +config MMAP_READAROUND_LIMIT + int "Limit mmap readaround upperbond" + default 0 + help + Inappropriate mmap readaround size can hurt device performance + during the sluggish situation. Add the hard upper-limit for + mmap readaround config FRAME_VECTOR bool diff --git a/mm/filemap.c b/mm/filemap.c index a40325c67251..7fdae5f71937 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -2560,6 +2560,7 @@ static struct file *do_sync_mmap_readahead(struct vm_fault *vmf) struct address_space *mapping = file->f_mapping; struct file *fpin = NULL; pgoff_t offset = vmf->pgoff; + unsigned int ra_pages; /* If we don't want any read-ahead, don't bother */ if (vmf->vma_flags & VM_RAND_READ) @@ -2588,10 +2589,20 @@ static struct file *do_sync_mmap_readahead(struct vm_fault *vmf) /* * mmap read-around */ + +#if CONFIG_MMAP_READAROUND_LIMIT == 0 + ra_pages = ra->ra_pages; +#else + if (ra->ra_pages > CONFIG_MMAP_READAROUND_LIMIT) + ra_pages = CONFIG_MMAP_READAROUND_LIMIT < 0 ? 0 : CONFIG_MMAP_READAROUND_LIMIT; + else + ra_pages = ra->ra_pages; +#endif + fpin = maybe_unlock_mmap_for_io(vmf, fpin); - ra->start = max_t(long, 0, offset - ra->ra_pages / 2); - ra->size = ra->ra_pages; - ra->async_size = ra->ra_pages / 4; + ra->start = max_t(long, 0, offset - ra_pages / 2); + ra->size = ra_pages; + ra->async_size = ra_pages / 4; ra_submit(ra, mapping, file); return fpin; } From dea5a184f1e8cd5f89ba6942fd8f1a14be9b8559 Mon Sep 17 00:00:00 2001 From: wangwang Date: Wed, 21 Jun 2023 12:22:15 +0800 Subject: [PATCH 620/698] bangkok:set mmap readahead upbound limitation as 16 pages Change-Id: I3fc051ab1b079189018e489c6eb0b90c4a3cd549 Signed-off-by: wangwang Reviewed-on: https://gerrit.mot.com/2650469 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi-bangkk.config | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-bangkk.config b/arch/arm64/configs/vendor/ext_config/moto-holi-bangkk.config index 8ecb42d8c0a8..660007619b0c 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-bangkk.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-bangkk.config @@ -42,3 +42,5 @@ CONFIG_CAMERA_FLASH_IIC_COMPATIBLE=y CONFIG_EROFS_FS_PCPU_KTHREAD=y CONFIG_EROFS_FS_PCPU_KTHREAD_HIPRI=y CONFIG_MOT_SENSOR_PRE_POWERUP=y +CONFIG_MMAP_READAROUND_LIMIT=16 + From 77819a1ccc516721daa6b15474b40dd981cb975b Mon Sep 17 00:00:00 2001 From: Lei Chen Date: Tue, 20 Jun 2023 18:52:45 +0800 Subject: [PATCH 621/698] topolygy:fix kansan panic at topology_parse_cpu_capacity BUG: KASAN: slab-out-of-bounds in topology_parse_cpu_capacity Write of size 4 at addr ffffffa64515031c by task swapper/0/1 Revert the changes I90055f96c320b15960efac10d8d92c69413eeb6b Fix the kasan panic. Change-Id: I7a8701e29a9de82c175e3c4e265a9bf179e32f91 Signed-off-by: Lei Chen Reviewed-on: https://gerrit.mot.com/2649556 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- drivers/base/arch_topology.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/base/arch_topology.c b/drivers/base/arch_topology.c index 6a5ba34ad958..54d08abbd43d 100644 --- a/drivers/base/arch_topology.c +++ b/drivers/base/arch_topology.c @@ -167,7 +167,7 @@ bool __init topology_parse_cpu_capacity(struct device_node *cpu_node, int cpu) &cpu_capacity); if (!ret) { if (!raw_capacity) { - raw_capacity = kcalloc(cpumask_last(cpu_possible_mask), + raw_capacity = kcalloc(num_possible_cpus(), sizeof(*raw_capacity), GFP_KERNEL); if (!raw_capacity) { From d77a95a22579b5c93eb449cf640e0b1a0da3f47b Mon Sep 17 00:00:00 2001 From: liuzhen Date: Sun, 25 Jun 2023 20:42:02 +0800 Subject: [PATCH 622/698] Open USB log in factory version for bangkk[2/3] In order to track the usb abnormal disconnect problem, open some log about usb in factory version recommended by Qualcomm for bangkk. Change-Id: I015803505ac6111780ca29f6684a8e3780ae938b Reviewed-on: https://gerrit.mot.com/2654714 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Zonghua Liu Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- arch/arm64/Kconfig | 4 ++++ .../configs/vendor/ext_config/factory-holi-bangkk.config | 1 + 2 files changed, 5 insertions(+) diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 7808b086c4e1..307473ca4b12 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -1945,3 +1945,7 @@ config MOT_SENSOR_PRE_POWERUP default n help Enable it to power up and initialise early. + +config MOT_USB_DEBUG_LOG + bool "For usb debug log in factiry SW" + default n diff --git a/arch/arm64/configs/vendor/ext_config/factory-holi-bangkk.config b/arch/arm64/configs/vendor/ext_config/factory-holi-bangkk.config index 89cbb53b692c..059b41766762 100644 --- a/arch/arm64/configs/vendor/ext_config/factory-holi-bangkk.config +++ b/arch/arm64/configs/vendor/ext_config/factory-holi-bangkk.config @@ -14,4 +14,5 @@ # being set as expected. # CONFIG_CAMERA_DISABLE_VSYNC_IRQ=y +CONFIG_MOT_USB_DEBUG_LOG=y # CONFIG_MOT_DONGWOON_OIS_AF_DRIFT is not set From 87cc6eac0b7747b623c5e82a41875c29c1eefe8b Mon Sep 17 00:00:00 2001 From: liyun zhang Date: Wed, 28 Jun 2023 14:16:32 +0800 Subject: [PATCH 623/698] arm64/configs: Add Fogo5G NA defconfig Add initial defconfig for Fogo5G NA(fogo) bringup, these configs are copied from Fogo5G ROW(fogor) Change-Id: I35d45642b982aa0daa0a2421b83114431e8e4ad2 Reviewed-on: https://gerrit.mot.com/2658394 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Reviewed-by: Xiaojun Ji Reviewed-by: Huosheng Liao Tested-by: Jira Key Submit-Approved: Jira Key --- .../vendor/ext_config/debug-holi-fogo.config | 28 ++++++++++++ .../ext_config/factory-holi-fogo.config | 17 ++++++++ .../vendor/ext_config/moto-holi-fogo.config | 43 +++++++++++++++++++ drivers/soc/qcom/Kconfig | 8 ++++ 4 files changed, 96 insertions(+) create mode 100644 arch/arm64/configs/vendor/ext_config/debug-holi-fogo.config create mode 100644 arch/arm64/configs/vendor/ext_config/factory-holi-fogo.config create mode 100644 arch/arm64/configs/vendor/ext_config/moto-holi-fogo.config diff --git a/arch/arm64/configs/vendor/ext_config/debug-holi-fogo.config b/arch/arm64/configs/vendor/ext_config/debug-holi-fogo.config new file mode 100644 index 000000000000..95c989c10a1b --- /dev/null +++ b/arch/arm64/configs/vendor/ext_config/debug-holi-fogo.config @@ -0,0 +1,28 @@ +# +# Please avoid changing the Qualcomm defconfig files and use this file to +# add any Motorola-specific configuration changes that are applicable to +# userdebug, eng, and user builds. +# +# After building, a list of all of the config files that are used can be found +# at the top of: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/mapphone_defconfig +# +# The actual output of the kernel configuration system can be found at: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/.config +# +# You can check the .config file to verify that your configuration option is +# being set as expected. +# + +# CONFIG_CGROUP_DEBUG is not set +# CONFIG_CLEANCACHE is not set +# CONFIG_CMA_ALLOW_WRITE_DEBUGFS is not set +# CONFIG_CMA_DEBUG is not set +# CONFIG_PREEMPTIRQ_EVENTS is not set +# CONFIG_PREEMPT_TRACER is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_TEST_USER_COPY is not set +# CONFIG_UFSTW is not set + +# CONFIG_SLUB_DEBUG_ON is not set diff --git a/arch/arm64/configs/vendor/ext_config/factory-holi-fogo.config b/arch/arm64/configs/vendor/ext_config/factory-holi-fogo.config new file mode 100644 index 000000000000..89cbb53b692c --- /dev/null +++ b/arch/arm64/configs/vendor/ext_config/factory-holi-fogo.config @@ -0,0 +1,17 @@ +# +# Please avoid changing the Qualcomm defconfig files and use this file to +# add any Motorola-specific configuration changes that are applicable to +# userdebug, eng, and user builds. +# +# After building, a list of all of the config files that are used can be found +# at the top of: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/mapphone_defconfig +# +# The actual output of the kernel configuration system can be found at: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/.config +# +# You can check the .config file to verify that your configuration option is +# being set as expected. +# +CONFIG_CAMERA_DISABLE_VSYNC_IRQ=y +# CONFIG_MOT_DONGWOON_OIS_AF_DRIFT is not set diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-fogo.config b/arch/arm64/configs/vendor/ext_config/moto-holi-fogo.config new file mode 100644 index 000000000000..60a80b15124c --- /dev/null +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-fogo.config @@ -0,0 +1,43 @@ +# +# Please avoid changing the Qualcomm defconfig files and use this file to +# add any Motorola-specific configuration changes that are applicable to +# userdebug, eng, and user builds. +# +# After building, a list of all of the config files that are used can be found +# at the top of: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/mapphone_defconfig +# +# The actual output of the kernel configuration system can be found at: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/.config +# +# You can check the .config file to verify that your configuration option is +# being set as expected. +# +CONFIG_FOGO_DTB=y +# CONFIG_NFC_QTI_I2C is not set +CONFIG_FS_EPOLL_WAKEUP_DEBUG=y +CONFIG_ZRAM_WRITEBACK=y +# CONFIG_THERMAL_STATISTICS is not set +# CONFIG_REGULATOR_QPNP_LCDB is not set +# CONFIG_UFSTW is not set +CONFIG_CRYPTO_CHACHA20POLY1305=y +CONFIG_CAM_SENSOR_PROBE_RETRY=y +CONFIG_MOT_DONGWOON_OIS_AF_DRIFT=y +CONFIG_SND_SOC_FS1815=m +#CONFIG_NFC_QTI_I2C=m +CONFIG_MSM_TZ_QSEE_LOG=y +CONFIG_AF_NOISE_ELIMINATION=y +# CONFIG_TOUCHSCREEN_FTS is not set +CONFIG_FELICA_MOUNT_BLOCK=y +# CONFIG_UFSFEATURE is not set +# CONFIG_UFSHPB is not set +# CONFIG_UFSTW is not set +# CONFIG_SCSI_SKHPB is not set +CONFIG_NFC=y +CONFIG_SEC_NFC_PRODUCT_N5=y +CONFIG_SEC_NFC=m +CONFIG_SEC_NFC_IF_I2C=y +CONFIG_QUP0_SE2_AP=y +CONFIG_CAMERA_FLASH_IIC_COMPATIBLE=y +CONFIG_EROFS_FS_PCPU_KTHREAD=y +CONFIG_EROFS_FS_PCPU_KTHREAD_HIPRI=y diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index 1537a2e4a437..ca78760e5c37 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -126,6 +126,14 @@ config FOGOR_DTB Only include FOGOR specific DTBs to limit the number that get built during kernel compilation. +config FOGO_DTB + depends on ARCH_QCOM + default n + bool "FOGO DTBs" + help + Only include FOGO specific DTBs to limit the number that + get built during kernel compilation. + config PENANGB_DTB depends on ARCH_QCOM default n From ba9b6641585a71f90b2875ad0583162e7d4e5236 Mon Sep 17 00:00:00 2001 From: liaohj Date: Wed, 28 Jun 2023 17:05:42 +0800 Subject: [PATCH 624/698] qcom: whitelist: Add necessary api for fs1815 dlkm add "snd_soc_add_card_controls" white list for fs1815 driver. it could be found in the latest abi_gki_aarch64*.xml file. Change-Id: I3f31e167317f273322858da8bf2188c161c88a3d Signed-off-by: liaohj Reviewed-on: https://gerrit.mot.com/2658776 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Huosheng Liao Reviewed-by: Wanlong Zhou Submit-Approved: Jira Key --- android/abi_gki_aarch64_qcom | 1 + 1 file changed, 1 insertion(+) diff --git a/android/abi_gki_aarch64_qcom b/android/abi_gki_aarch64_qcom index a0f66bbb8ad9..b867d3928ebd 100644 --- a/android/abi_gki_aarch64_qcom +++ b/android/abi_gki_aarch64_qcom @@ -2364,6 +2364,7 @@ snd_pcm_stop _snd_pcm_stream_lock_irqsave snd_pcm_stream_unlock_irqrestore + snd_soc_add_card_controls snd_soc_add_component_controls snd_soc_bytes_tlv_callback snd_soc_card_get_kcontrol From 9c369fe3594015a3f314f6d0a97f8fd6b6fae550 Mon Sep 17 00:00:00 2001 From: Lei Chen Date: Thu, 6 Jul 2023 15:03:39 +0800 Subject: [PATCH 625/698] smb5:optimize the pmic irq logs Frequent input-current-limiting irq logs was print sometimes. Optimize the pm7250b icl irq logs. Change-Id: Id60d0749338bdb9d23c1ab3f1ecc69921a6845e8 Signed-off-by: Lei Chen Reviewed-on: https://gerrit.mot.com/2667390 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Wei Xu Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- drivers/power/supply/qcom/qpnp-smb5.c | 2 +- drivers/power/supply/qcom/smb5-lib.c | 8 ++++++++ drivers/power/supply/qcom/smb5-lib.h | 1 + 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/power/supply/qcom/qpnp-smb5.c b/drivers/power/supply/qcom/qpnp-smb5.c index 6ef6655e5640..deccb443912c 100644 --- a/drivers/power/supply/qcom/qpnp-smb5.c +++ b/drivers/power/supply/qcom/qpnp-smb5.c @@ -2514,7 +2514,7 @@ static struct smb_irq_info smb5_irqs[] = { }, [INPUT_CURRENT_LIMITING_IRQ] = { .name = "input-current-limiting", - .handler = smb5_default_irq_handler, + .handler = smb5_icl_irq_handler, }, [CONCURRENT_MODE_DISABLE_IRQ] = { .name = "concurrent-mode-disable", diff --git a/drivers/power/supply/qcom/smb5-lib.c b/drivers/power/supply/qcom/smb5-lib.c index f4e0ea2aaca9..e0c9d9f1faa9 100644 --- a/drivers/power/supply/qcom/smb5-lib.c +++ b/drivers/power/supply/qcom/smb5-lib.c @@ -5266,6 +5266,14 @@ irqreturn_t smb5_default_irq_handler(int irq, void *data) return IRQ_HANDLED; } +irqreturn_t smb5_icl_irq_handler(int irq, void *data) +{ + struct smb_irq_data *irq_data = data; + + pr_debug("%s IRQ: %s\n",__func__, irq_data->name); + return IRQ_HANDLED; +} + irqreturn_t smb5_smb_en_irq_handler(int irq, void *data) { struct smb_irq_data *irq_data = data; diff --git a/drivers/power/supply/qcom/smb5-lib.h b/drivers/power/supply/qcom/smb5-lib.h index 8d9f93a717b8..d2375b05853a 100644 --- a/drivers/power/supply/qcom/smb5-lib.h +++ b/drivers/power/supply/qcom/smb5-lib.h @@ -671,6 +671,7 @@ int smblib_vconn_regulator_disable(struct regulator_dev *rdev); int smblib_vconn_regulator_is_enabled(struct regulator_dev *rdev); irqreturn_t smb5_default_irq_handler(int irq, void *data); +irqreturn_t smb5_icl_irq_handler(int irq, void *data); irqreturn_t smb5_smb_en_irq_handler(int irq, void *data); irqreturn_t smb5_chg_state_change_irq_handler(int irq, void *data); irqreturn_t smb5_batt_temp_changed_irq_handler(int irq, void *data); From 6b73bc7b238ab374e1c3530a702b2a5b35ca2b57 Mon Sep 17 00:00:00 2001 From: zhucc2 Date: Tue, 11 Jul 2023 17:45:44 +0800 Subject: [PATCH 626/698] arm64/config: enable UFS HID and disable HPB on fogo row Disable CONFIG_UFSFEATURE will disable SS/Micron HID function. so need enable it. Disable HPB function to decrease memory cost. Change-Id: I405ad02a5d7f22e5604c0148562705670b9f2bea Reviewed-on: https://gerrit.mot.com/2672202 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Dongliang Yue Reviewed-by: Hujun Liao Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi-fogor.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-fogor.config b/arch/arm64/configs/vendor/ext_config/moto-holi-fogor.config index d3d62cb17422..7a3ada6a1833 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-fogor.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-fogor.config @@ -29,10 +29,10 @@ CONFIG_MSM_TZ_QSEE_LOG=y CONFIG_AF_NOISE_ELIMINATION=y # CONFIG_TOUCHSCREEN_FTS is not set CONFIG_FELICA_MOUNT_BLOCK=y -# CONFIG_UFSFEATURE is not set # CONFIG_UFSHPB is not set # CONFIG_UFSTW is not set # CONFIG_SCSI_SKHPB is not set +# CONFIG_MICRON_HPB is not set CONFIG_NFC=y CONFIG_SEC_NFC_PRODUCT_N5=y CONFIG_SEC_NFC=m From c9a0ce3cf351add3e632ec0bbf490285b840e0be Mon Sep 17 00:00:00 2001 From: zhu chuanchun Date: Tue, 11 Jul 2023 17:53:41 +0800 Subject: [PATCH 627/698] arm64/config: enable UFS HID and disable HPB on fogo NA Disable CONFIG_UFSFEATURE will disable SS/Micron HID function. so need enable it. Disable HPB function to decrease memory cost. Change-Id: I5cf1d00fc4922b3c6c5dae903289ba3a64779a55 Reviewed-on: https://gerrit.mot.com/2672207 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Dongliang Yue Reviewed-by: Hujun Liao Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi-fogo.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-fogo.config b/arch/arm64/configs/vendor/ext_config/moto-holi-fogo.config index 60a80b15124c..03db2ed2711c 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-fogo.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-fogo.config @@ -29,10 +29,10 @@ CONFIG_MSM_TZ_QSEE_LOG=y CONFIG_AF_NOISE_ELIMINATION=y # CONFIG_TOUCHSCREEN_FTS is not set CONFIG_FELICA_MOUNT_BLOCK=y -# CONFIG_UFSFEATURE is not set # CONFIG_UFSHPB is not set # CONFIG_UFSTW is not set # CONFIG_SCSI_SKHPB is not set +# CONFIG_MICRON_HPB is not set CONFIG_NFC=y CONFIG_SEC_NFC_PRODUCT_N5=y CONFIG_SEC_NFC=m From 3fd5a6de05e7603e9008631887d9c0f37f256164 Mon Sep 17 00:00:00 2001 From: xuwei9 Date: Thu, 13 Jul 2023 22:13:12 +0800 Subject: [PATCH 628/698] FG:improve charger counter accuracy Improve charger counter report accuracy for server data collection. Change-Id: I212961a3db43771a68fc0c2e4b37009f255f2f59 Signed-off-by: xuwei9 Reviewed-on: https://gerrit.mot.com/2675505 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- drivers/power/supply/qcom/qpnp-qg.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/power/supply/qcom/qpnp-qg.c b/drivers/power/supply/qcom/qpnp-qg.c index 7351d60a3563..165f19ef6a22 100644 --- a/drivers/power/supply/qcom/qpnp-qg.c +++ b/drivers/power/supply/qcom/qpnp-qg.c @@ -1845,8 +1845,10 @@ static int qg_get_charge_counter(struct qpnp_qg *chip, int *charge_counter) return rc; } - cc_soc = CAP(0, 100, DIV_ROUND_CLOSEST(chip->cc_soc, 100)); - *charge_counter = div_s64(temp * cc_soc, 100); + cc_soc = CAP(0, 100*100, chip->cc_soc); + *charge_counter = div_s64(temp * cc_soc, 10000); + + pr_info("charge-counter:%d\n",*charge_counter); return 0; } From c43b6350c3c2090b56d249c1d86d53b330fdf8bc Mon Sep 17 00:00:00 2001 From: gaoyx9 Date: Wed, 12 Jul 2023 16:17:20 +0800 Subject: [PATCH 629/698] initial kernel defconfig for fogos Change-Id: I836e00db2c8b70f0542b5703b38f9ee52b8bf86b Reviewed-on: https://gerrit.mot.com/2674579 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Reviewed-by: gaoyx9 Submit-Approved: gaoyx9 Tested-by: gaoyx9 Tested-by: Jira Key Reviewed-by: Hujun Liao --- .../vendor/ext_config/debug-holi-fogos.config | 28 ++++++++++++ .../ext_config/factory-holi-fogos.config | 17 ++++++++ .../vendor/ext_config/moto-holi-fogos.config | 43 +++++++++++++++++++ drivers/soc/qcom/Kconfig | 8 ++++ 4 files changed, 96 insertions(+) create mode 100644 arch/arm64/configs/vendor/ext_config/debug-holi-fogos.config create mode 100644 arch/arm64/configs/vendor/ext_config/factory-holi-fogos.config create mode 100644 arch/arm64/configs/vendor/ext_config/moto-holi-fogos.config diff --git a/arch/arm64/configs/vendor/ext_config/debug-holi-fogos.config b/arch/arm64/configs/vendor/ext_config/debug-holi-fogos.config new file mode 100644 index 000000000000..95c989c10a1b --- /dev/null +++ b/arch/arm64/configs/vendor/ext_config/debug-holi-fogos.config @@ -0,0 +1,28 @@ +# +# Please avoid changing the Qualcomm defconfig files and use this file to +# add any Motorola-specific configuration changes that are applicable to +# userdebug, eng, and user builds. +# +# After building, a list of all of the config files that are used can be found +# at the top of: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/mapphone_defconfig +# +# The actual output of the kernel configuration system can be found at: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/.config +# +# You can check the .config file to verify that your configuration option is +# being set as expected. +# + +# CONFIG_CGROUP_DEBUG is not set +# CONFIG_CLEANCACHE is not set +# CONFIG_CMA_ALLOW_WRITE_DEBUGFS is not set +# CONFIG_CMA_DEBUG is not set +# CONFIG_PREEMPTIRQ_EVENTS is not set +# CONFIG_PREEMPT_TRACER is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_TEST_USER_COPY is not set +# CONFIG_UFSTW is not set + +# CONFIG_SLUB_DEBUG_ON is not set diff --git a/arch/arm64/configs/vendor/ext_config/factory-holi-fogos.config b/arch/arm64/configs/vendor/ext_config/factory-holi-fogos.config new file mode 100644 index 000000000000..89cbb53b692c --- /dev/null +++ b/arch/arm64/configs/vendor/ext_config/factory-holi-fogos.config @@ -0,0 +1,17 @@ +# +# Please avoid changing the Qualcomm defconfig files and use this file to +# add any Motorola-specific configuration changes that are applicable to +# userdebug, eng, and user builds. +# +# After building, a list of all of the config files that are used can be found +# at the top of: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/mapphone_defconfig +# +# The actual output of the kernel configuration system can be found at: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/.config +# +# You can check the .config file to verify that your configuration option is +# being set as expected. +# +CONFIG_CAMERA_DISABLE_VSYNC_IRQ=y +# CONFIG_MOT_DONGWOON_OIS_AF_DRIFT is not set diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-fogos.config b/arch/arm64/configs/vendor/ext_config/moto-holi-fogos.config new file mode 100644 index 000000000000..d3d62cb17422 --- /dev/null +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-fogos.config @@ -0,0 +1,43 @@ +# +# Please avoid changing the Qualcomm defconfig files and use this file to +# add any Motorola-specific configuration changes that are applicable to +# userdebug, eng, and user builds. +# +# After building, a list of all of the config files that are used can be found +# at the top of: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/mapphone_defconfig +# +# The actual output of the kernel configuration system can be found at: +# out/target/product/$(PRODUCT)/obj/KERNEL_OBJ/.config +# +# You can check the .config file to verify that your configuration option is +# being set as expected. +# +CONFIG_FOGOR_DTB=y +# CONFIG_NFC_QTI_I2C is not set +CONFIG_FS_EPOLL_WAKEUP_DEBUG=y +CONFIG_ZRAM_WRITEBACK=y +# CONFIG_THERMAL_STATISTICS is not set +# CONFIG_REGULATOR_QPNP_LCDB is not set +# CONFIG_UFSTW is not set +CONFIG_CRYPTO_CHACHA20POLY1305=y +CONFIG_CAM_SENSOR_PROBE_RETRY=y +CONFIG_MOT_DONGWOON_OIS_AF_DRIFT=y +CONFIG_SND_SOC_FS1815=m +#CONFIG_NFC_QTI_I2C=m +CONFIG_MSM_TZ_QSEE_LOG=y +CONFIG_AF_NOISE_ELIMINATION=y +# CONFIG_TOUCHSCREEN_FTS is not set +CONFIG_FELICA_MOUNT_BLOCK=y +# CONFIG_UFSFEATURE is not set +# CONFIG_UFSHPB is not set +# CONFIG_UFSTW is not set +# CONFIG_SCSI_SKHPB is not set +CONFIG_NFC=y +CONFIG_SEC_NFC_PRODUCT_N5=y +CONFIG_SEC_NFC=m +CONFIG_SEC_NFC_IF_I2C=y +CONFIG_QUP0_SE2_AP=y +CONFIG_CAMERA_FLASH_IIC_COMPATIBLE=y +CONFIG_EROFS_FS_PCPU_KTHREAD=y +CONFIG_EROFS_FS_PCPU_KTHREAD_HIPRI=y diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index ca78760e5c37..524a5cdf8a94 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -126,6 +126,14 @@ config FOGOR_DTB Only include FOGOR specific DTBs to limit the number that get built during kernel compilation. +config FOGOS_DTB + depends on ARCH_QCOM + default n + bool "FOGOS DTBs" + help + Only include FOGOS specific DTBs to limit the number that + get built during kernel compilation. + config FOGO_DTB depends on ARCH_QCOM default n From 51922949591b0f1b762c71f120dae58230236030 Mon Sep 17 00:00:00 2001 From: Simon C Date: Thu, 13 Jul 2023 15:02:03 +0800 Subject: [PATCH 630/698] fogo: Bring up flash[3/3] Details: There is no second flash supplier So close this macro Change-Id: I7f2fd8ed04d3e16ff15cd1ecfc34d9f2710452c6 Signed-off-by: Simon C Reviewed-on: https://gerrit.mot.com/2674947 Reviewed-by: SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Reviewed-by: Zhichao Chen Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi-fogo.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-fogo.config b/arch/arm64/configs/vendor/ext_config/moto-holi-fogo.config index 03db2ed2711c..09336e3a730b 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-fogo.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-fogo.config @@ -38,6 +38,6 @@ CONFIG_SEC_NFC_PRODUCT_N5=y CONFIG_SEC_NFC=m CONFIG_SEC_NFC_IF_I2C=y CONFIG_QUP0_SE2_AP=y -CONFIG_CAMERA_FLASH_IIC_COMPATIBLE=y +# CONFIG_CAMERA_FLASH_IIC_COMPATIBLE is not set CONFIG_EROFS_FS_PCPU_KTHREAD=y CONFIG_EROFS_FS_PCPU_KTHREAD_HIPRI=y From a5ae1d0a5a64c5616058dcd951aeb9e04e5ec5a6 Mon Sep 17 00:00:00 2001 From: liaohj Date: Mon, 17 Jul 2023 15:32:28 +0800 Subject: [PATCH 631/698] config:fogo:audio bringpu,add related configs fogo use 4350+aw88261(pri i2s) add related configs Change-Id: I0a6873327670b1eb05e882022406aecf00c24aa7 Signed-off-by: liaohj Reviewed-on: https://gerrit.mot.com/2677509 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Wanlong Zhou Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- arch/arm64/Kconfig | 6 ++++++ arch/arm64/configs/vendor/ext_config/moto-holi-fogo.config | 5 ++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 307473ca4b12..441c6ae835e2 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -1892,6 +1892,12 @@ config AW882XX_MAPSIZE_16K help Enable it only for use 16k mapsize. +config AW882XX_STEREO_SMARTPA_PRI + bool "aw dual smart pa pri i2s" + default n + help + Enable it only for dual smart pa. + config SND_SOC_AW87XXX tristate "SoC Audio for awinic AW87XXX Smart K PA" depends on I2C diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-fogo.config b/arch/arm64/configs/vendor/ext_config/moto-holi-fogo.config index 09336e3a730b..8b17b94421f2 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-fogo.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-fogo.config @@ -23,7 +23,10 @@ CONFIG_ZRAM_WRITEBACK=y CONFIG_CRYPTO_CHACHA20POLY1305=y CONFIG_CAM_SENSOR_PROBE_RETRY=y CONFIG_MOT_DONGWOON_OIS_AF_DRIFT=y -CONFIG_SND_SOC_FS1815=m +CONFIG_AW882XX_STEREO_SMARTPA=y +CONFIG_AW882XX_STEREO_SMARTPA_PRI=y +# CONFIG_AW882XX_PARAMS_FROM_BIN is not set +# CONFIG_AW882XX_MAPSIZE_16K is not set #CONFIG_NFC_QTI_I2C=m CONFIG_MSM_TZ_QSEE_LOG=y CONFIG_AF_NOISE_ELIMINATION=y From f210f91a8a109bd8c914eb735d42caf131465d5d Mon Sep 17 00:00:00 2001 From: Yonghua Yan Date: Fri, 12 May 2023 20:04:06 +0800 Subject: [PATCH 632/698] Add HS phy init sequence dtsi for Host Add HS phy init sequence for Host mode to support configure the HS phy parameters for Host and Device mode separately from device tree. Change-Id: Ia532d638c6e32377be9c4062f63f0cf227d55d2c Signed-off-by: Yonghua Yan Reviewed-on: https://gerrit.mot.com/2605855 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Guobin Zhang Submit-Approved: Jira Key Reviewed-on: https://gerrit.mot.com/2677516 Reviewed-by: Zonghua Liu Reviewed-by: Yeqing Wang Reviewed-by: Huosheng Liao --- drivers/usb/phy/phy-msm-snps-hs.c | 38 ++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/drivers/usb/phy/phy-msm-snps-hs.c b/drivers/usb/phy/phy-msm-snps-hs.c index a7c8d043b56a..8dfbdc702770 100644 --- a/drivers/usb/phy/phy-msm-snps-hs.c +++ b/drivers/usb/phy/phy-msm-snps-hs.c @@ -114,6 +114,9 @@ struct msm_hsphy { int *param_override_seq; int param_override_seq_cnt; + int *host_param_override_seq; + int host_param_override_seq_cnt; + void __iomem *phy_rcal_reg; u32 rcal_mask; @@ -397,9 +400,14 @@ static int msm_hsphy_init(struct usb_phy *uphy) VBUSVLDEXT0, VBUSVLDEXT0); /* set parameter ovrride if needed */ - if (phy->param_override_seq) + if ((phy->phy.flags & PHY_HOST_MODE) && + phy->host_param_override_seq) { + hsusb_phy_write_seq(phy->base, phy->host_param_override_seq, + phy->host_param_override_seq_cnt, 0); + } else if (phy->param_override_seq) { hsusb_phy_write_seq(phy->base, phy->param_override_seq, phy->param_override_seq_cnt, 0); + } if (phy->pre_emphasis) { u8 val = TXPREEMPAMPTUNE0(phy->pre_emphasis) & @@ -823,6 +831,34 @@ static int msm_hsphy_probe(struct platform_device *pdev) if (IS_ERR(phy->phy_reset)) return PTR_ERR(phy->phy_reset); + phy->host_param_override_seq_cnt = of_property_count_elems_of_size( + dev->of_node, + "qcom,host-param-override-seq", + sizeof(*phy->host_param_override_seq)); + if (phy->host_param_override_seq_cnt > 0) { + phy->host_param_override_seq = devm_kcalloc(dev, + phy->host_param_override_seq_cnt, + sizeof(*phy->host_param_override_seq), + GFP_KERNEL); + if (!phy->host_param_override_seq) + return -ENOMEM; + + if (phy->host_param_override_seq_cnt % 2) { + dev_err(dev, "invalid host_param_override_seq_len\n"); + return -EINVAL; + } + + ret = of_property_read_u32_array(dev->of_node, + "qcom,host-param-override-seq", + phy->host_param_override_seq, + phy->host_param_override_seq_cnt); + if (ret) { + dev_err(dev, "qcom,host_param-override-seq read failed %d\n", + ret); + return ret; + } + } + phy->param_override_seq_cnt = of_property_count_elems_of_size( dev->of_node, "qcom,param-override-seq", From 5d49be2fa48dd36bc48770cf9bc8e0964f05c539 Mon Sep 17 00:00:00 2001 From: liaohj Date: Thu, 20 Jul 2023 11:07:34 +0800 Subject: [PATCH 633/698] configs:fogo:open aw algo fogo use aw88261 open aw algo. Change-Id: I5594444436febe1d1521fe666109ed6a4916c319 Signed-off-by: liaohj Reviewed-on: https://gerrit.mot.com/2682285 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Wanlong Zhou Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi-fogo.config | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-fogo.config b/arch/arm64/configs/vendor/ext_config/moto-holi-fogo.config index 8b17b94421f2..e2f485e79690 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-fogo.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-fogo.config @@ -25,8 +25,8 @@ CONFIG_CAM_SENSOR_PROBE_RETRY=y CONFIG_MOT_DONGWOON_OIS_AF_DRIFT=y CONFIG_AW882XX_STEREO_SMARTPA=y CONFIG_AW882XX_STEREO_SMARTPA_PRI=y -# CONFIG_AW882XX_PARAMS_FROM_BIN is not set -# CONFIG_AW882XX_MAPSIZE_16K is not set +CONFIG_AW882XX_PARAMS_FROM_BIN=y +CONFIG_AW882XX_MAPSIZE_16K=y #CONFIG_NFC_QTI_I2C=m CONFIG_MSM_TZ_QSEE_LOG=y CONFIG_AF_NOISE_ELIMINATION=y From 33c1286f56a1f0c0053b830cf5baa3781bd88335 Mon Sep 17 00:00:00 2001 From: Franz Wang Date: Fri, 21 Jul 2023 15:17:29 +0800 Subject: [PATCH 634/698] arm64/vendor: ext_config: add board dtb for fogos fix the error dtb project config the error will block start-up, the error uart log is as below: Best Soc Dtb 0x1FB/0x10000/0x0/0x0 Unable to find the Board Dtb Error: Board Dtbo blob not found BootLinux() failed: Not Found Slot _a is not looking good Change-Id: Id147a84a0beafba097b2915303d9944834e9c550 Signed-off-by: Franz Wang Reviewed-on: https://gerrit.mot.com/2684376 Reviewed-by: Xiaojun Ji SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi-fogos.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-fogos.config b/arch/arm64/configs/vendor/ext_config/moto-holi-fogos.config index d3d62cb17422..997d2973c7c2 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-fogos.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-fogos.config @@ -13,7 +13,7 @@ # You can check the .config file to verify that your configuration option is # being set as expected. # -CONFIG_FOGOR_DTB=y +CONFIG_FOGOS_DTB=y # CONFIG_NFC_QTI_I2C is not set CONFIG_FS_EPOLL_WAKEUP_DEBUG=y CONFIG_ZRAM_WRITEBACK=y From 1cefe28d0bef3e3e8ce7228c5099b80f5f142248 Mon Sep 17 00:00:00 2001 From: Liu Yang Date: Fri, 28 Jul 2023 20:08:08 +0800 Subject: [PATCH 635/698] Feature: Check power up and initialize early Check feature -- ENABLE_MOT_PRE_POWERUP_INIT_SENSOR. 1.Solve a issue for this feature. 2. This feature does not merge into factory version. Change-Id: I29b7b4464acf6925a196e57b6a2a8c0dd41fe138 Signed-off-by: Liu Yang Reviewed-on: https://gerrit.mot.com/2693577 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Reviewed-by: Simon C Reviewed-by: Hualong Zhu Reviewed-by: Bolei Shang Reviewed-by: Reviewed-by: Reviewed-by: Zhuoran Xu Reviewed-by: Guobin Zhang Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi-fogo.config | 1 + arch/arm64/configs/vendor/ext_config/moto-holi-fogor.config | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-fogo.config b/arch/arm64/configs/vendor/ext_config/moto-holi-fogo.config index e2f485e79690..79d8f37ae8a0 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-fogo.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-fogo.config @@ -44,3 +44,4 @@ CONFIG_QUP0_SE2_AP=y # CONFIG_CAMERA_FLASH_IIC_COMPATIBLE is not set CONFIG_EROFS_FS_PCPU_KTHREAD=y CONFIG_EROFS_FS_PCPU_KTHREAD_HIPRI=y +CONFIG_MOT_SENSOR_PRE_POWERUP=y diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-fogor.config b/arch/arm64/configs/vendor/ext_config/moto-holi-fogor.config index 7a3ada6a1833..ce000d53b72d 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-fogor.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-fogor.config @@ -41,3 +41,4 @@ CONFIG_QUP0_SE2_AP=y CONFIG_CAMERA_FLASH_IIC_COMPATIBLE=y CONFIG_EROFS_FS_PCPU_KTHREAD=y CONFIG_EROFS_FS_PCPU_KTHREAD_HIPRI=y +CONFIG_MOT_SENSOR_PRE_POWERUP=y From 16c8d2ce9e47b5627d5fd49ef24b83e5b02c967a Mon Sep 17 00:00:00 2001 From: Alison Venancio Date: Tue, 1 Aug 2023 17:32:17 -0400 Subject: [PATCH 636/698] [MIAMI] spi: spi-msm-geni: system suspend support we are not serving system suspend if spi xfers were in progress, doing force suspend if spi xfers were completed. Port of patch spi_geni_fix2.patch provided by qcom in case 06677540 Change-Id: I929031556694abf77e78e573a6f56986dc8667e9 Reviewed-on: https://gerrit.mot.com/2697260 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Bruno Oliveira Reviewed-by: Rafael Ortolan Reviewed-by: Jun Weng Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- .../vendor/ext_config/moto-holi-miami.config | 1 + drivers/spi/Kconfig | 5 ++ drivers/spi/spi-msm-geni.c | 48 ++++++++++++++++--- 3 files changed, 47 insertions(+), 7 deletions(-) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-miami.config b/arch/arm64/configs/vendor/ext_config/moto-holi-miami.config index 8bceb5f1ae07..e3262cd2ae6f 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-miami.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-miami.config @@ -28,3 +28,4 @@ CONFIG_QUP0_SE2_AP=y CONFIG_CRYPTO_CHACHA20POLY1305=y CONFIG_CAM_SENSOR_PROBE_RETRY=y CONFIG_CAMERA_CCI_ADDR_SWITCH=y +CONFIG_IS_XFER_IN_PROGRESS=y diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index d15432fccf8b..005b10b1e0e8 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -960,3 +960,8 @@ config SPI_DYNAMIC def_bool ACPI || OF_DYNAMIC || SPI_SLAVE endif # SPI + +config IS_XFER_IN_PROGRESS + bool "Check if xfer is in progress" + help + Force suspend if spi xfers were completed. diff --git a/drivers/spi/spi-msm-geni.c b/drivers/spi/spi-msm-geni.c index 7cb55b6bdb1b..db735e1c5bae 100644 --- a/drivers/spi/spi-msm-geni.c +++ b/drivers/spi/spi-msm-geni.c @@ -164,6 +164,9 @@ struct spi_geni_master { int num_rx_eot; int num_xfers; atomic_t is_irq_enable; +#ifdef CONFIG_IS_XFER_IN_PROGRESS + bool is_xfer_in_progress; +#endif void *ipc; bool gsi_mode; /* GSI Mode */ bool shared_ee; /* Dual EE use case */ @@ -1006,7 +1009,7 @@ static int spi_geni_prepare_message(struct spi_master *spi, if (mas->shared_ee) { if (mas->setup) { -#if 0 +#ifdef CONFIG_IS_XFER_IN_PROGRESS /* Client to respect system suspend */ if (!pm_runtime_enabled(mas->dev)) { GENI_SE_ERR(mas->ipc, false, NULL, @@ -1021,7 +1024,7 @@ static int spi_geni_prepare_message(struct spi_master *spi, __func__, ret); WARN_ON_ONCE(1); pm_runtime_put_noidle(mas->dev); -#if 0 +#ifdef CONFIG_IS_XFER_IN_PROGRESS /* Set device in suspended since resume failed */ pm_runtime_set_suspended(mas->dev); #endif @@ -1338,6 +1341,10 @@ static int spi_geni_prepare_transfer_hardware(struct spi_master *spi) /* Adjust the IB based on the max speed of the slave in kHz.*/ rsc->ib = (max_speed * DEFAULT_BUS_WIDTH) / 1000; +#ifdef CONFIG_IS_XFER_IN_PROGRESS + mas->is_xfer_in_progress = true; +#endif + /* * Not required for LE as below intializations are specific * to usecases. For LE, client takes care of get_sync. @@ -1345,11 +1352,12 @@ static int spi_geni_prepare_transfer_hardware(struct spi_master *spi) if (mas->is_le_vm) return 0; -#if 0 +#ifdef CONFIG_IS_XFER_IN_PROGRESS /* Client to respect system suspend */ if (!pm_runtime_enabled(mas->dev)) { GENI_SE_ERR(mas->ipc, false, NULL, "%s: System suspended\n", __func__); + mas->is_xfer_in_progress = false; return -EACCES; } #endif @@ -1385,9 +1393,10 @@ static int spi_geni_prepare_transfer_hardware(struct spi_master *spi) __func__, ret); WARN_ON_ONCE(1); pm_runtime_put_noidle(mas->dev); -#if 0 +#ifdef CONFIG_IS_XFER_IN_PROGRESS /* Set device in suspended since resume failed */ pm_runtime_set_suspended(mas->dev); + mas->is_xfer_in_progress = false; #endif return ret; } @@ -1397,6 +1406,9 @@ static int spi_geni_prepare_transfer_hardware(struct spi_master *spi) if (ret) { GENI_SE_ERR(mas->ipc, true, NULL, "%s mas_setup failed: %d\n", __func__, ret); +#ifdef CONFIG_IS_XFER_IN_PROGRESS + mas->is_xfer_in_progress = false; +#endif return ret; } } @@ -1418,8 +1430,12 @@ static int spi_geni_unprepare_transfer_hardware(struct spi_master *spi) struct spi_geni_master *mas = spi_master_get_devdata(spi); int count = 0; - if (mas->shared_ee || mas->is_le_vm) + if (mas->shared_ee || mas->is_le_vm) { +#ifdef CONFIG_IS_XFER_IN_PROGRESS + mas->is_xfer_in_progress = false; +#endif return 0; + } if (mas->gsi_mode) { struct se_geni_rsc *rsc; @@ -1448,6 +1464,9 @@ static int spi_geni_unprepare_transfer_hardware(struct spi_master *spi) pm_runtime_mark_last_busy(mas->dev); pm_runtime_put_autosuspend(mas->dev); } +#ifdef CONFIG_IS_XFER_IN_PROGRESS + mas->is_xfer_in_progress = false; +#endif return 0; } @@ -1674,7 +1693,7 @@ static int spi_geni_transfer_one(struct spi_master *spi, GENI_SE_DBG(mas->ipc, false, mas->dev, "current xfer_timeout:%lu ms.\n", xfer_timeout); -#if 0 +#ifdef CONFIG_IS_XFER_IN_PROGRESS /* Double check PM status, client might have not taken wakelock and * continue to queue more transfers. Post auto-suspend, system suspend * can keep driver to forced suspend, hence it's client's responsibility @@ -2221,6 +2240,9 @@ static int spi_geni_probe(struct platform_device *pdev) "M - DRIVER GENI_SPI_%d Ready", spi->bus_num); place_marker(boot_marker); dev_info(&pdev->dev, "%s: completed\n", __func__); +#ifdef CONFIG_IS_XFER_IN_PROGRESS + geni_mas->is_xfer_in_progress = false; +#endif return ret; spi_geni_probe_unmap: devm_iounmap(&pdev->dev, geni_mas->base); @@ -2329,11 +2351,23 @@ static int spi_geni_suspend(struct device *dev) int ret = 0; struct spi_master *spi = get_spi_master(dev); struct spi_geni_master *geni_mas = spi_master_get_devdata(spi); - +#ifdef CONFIG_IS_XFER_IN_PROGRESS + if (geni_mas->is_xfer_in_progress) { + ret = -EBUSY; + if (!pm_runtime_status_suspended(dev)) { + GENI_SE_ERR(geni_mas->ipc, true, dev, + ":%s: runtime PM is active\n", __func__); + return ret; + } + GENI_SE_ERR(geni_mas->ipc, true, dev, + "%s System suspend not allowed while xfer in progress\n", + __func__); +#else if (!pm_runtime_status_suspended(dev)) { GENI_SE_ERR(geni_mas->ipc, true, dev, ":%s: runtime PM is active\n", __func__); ret = -EBUSY; +#endif return ret; } From 30443996b3a9d96a0a2f77705a7de364a5133dc4 Mon Sep 17 00:00:00 2001 From: liaohj Date: Fri, 4 Aug 2023 18:41:29 +0800 Subject: [PATCH 637/698] configs:add aw8838 macro for gogo 5g na fogo 5g na need to pass HAC test. so hardware add aw8838 for handset hac output. add aw8838 macro for gogo 5g na. Change-Id: I6cf76364f8d702545024403ddf88b928e29dbb36 Signed-off-by: liaohj Reviewed-on: https://gerrit.mot.com/2700962 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Wanlong Zhou Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- arch/arm64/Kconfig | 6 ++++++ arch/arm64/configs/vendor/ext_config/moto-holi-fogo.config | 1 + 2 files changed, 7 insertions(+) diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 441c6ae835e2..fd5991f6ce74 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -1910,6 +1910,12 @@ config SND_SOC_FS1815 help This option enables support for fs1815 K PA. +config SND_SOC_AW8838 + bool "aw8838 for hac" + default n + help + Enable it only for hac on. + config CAMERA_FLASH_PWM bool "control flash" default n diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-fogo.config b/arch/arm64/configs/vendor/ext_config/moto-holi-fogo.config index 79d8f37ae8a0..09bc0529055e 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-fogo.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-fogo.config @@ -27,6 +27,7 @@ CONFIG_AW882XX_STEREO_SMARTPA=y CONFIG_AW882XX_STEREO_SMARTPA_PRI=y CONFIG_AW882XX_PARAMS_FROM_BIN=y CONFIG_AW882XX_MAPSIZE_16K=y +CONFIG_SND_SOC_AW8838=y #CONFIG_NFC_QTI_I2C=m CONFIG_MSM_TZ_QSEE_LOG=y CONFIG_AF_NOISE_ELIMINATION=y From c60b62822de2ac1bd110615ac5b82a4f891294a9 Mon Sep 17 00:00:00 2001 From: zhu chuanchun Date: Tue, 8 Aug 2023 11:14:37 +0800 Subject: [PATCH 638/698] arm64/config: enable UFS HID and disable HPB on fogos Disable CONFIG_UFSFEATURE will disable SS/Micron HID function. so need enable it. Disable HPB function to decrease memory cost. Change-Id: Icb06d88273de52b49f2cd9cc0afc4767a93a4684 Reviewed-on: https://gerrit.mot.com/2703221 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi-fogos.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-fogos.config b/arch/arm64/configs/vendor/ext_config/moto-holi-fogos.config index 997d2973c7c2..f97b86eaa755 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-fogos.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-fogos.config @@ -29,10 +29,10 @@ CONFIG_MSM_TZ_QSEE_LOG=y CONFIG_AF_NOISE_ELIMINATION=y # CONFIG_TOUCHSCREEN_FTS is not set CONFIG_FELICA_MOUNT_BLOCK=y -# CONFIG_UFSFEATURE is not set # CONFIG_UFSHPB is not set # CONFIG_UFSTW is not set # CONFIG_SCSI_SKHPB is not set +# CONFIG_MICRON_HPB is not set CONFIG_NFC=y CONFIG_SEC_NFC_PRODUCT_N5=y CONFIG_SEC_NFC=m From 398970c39011eaa82cec7db3793d2f8882280d06 Mon Sep 17 00:00:00 2001 From: liaohj Date: Thu, 10 Aug 2023 10:41:49 +0800 Subject: [PATCH 639/698] qcom: whitelist: Add necessary api for aw8838 dlkm add "device_remove_bin_file" white list for aw8838 driver. it could be found in the latest abi_gki_aarch64*.xml file. Change-Id: I1d73efccfd0d6f2e5d412a3e327843b04b62ce2b Signed-off-by: liaohj Reviewed-on: https://gerrit.mot.com/2706089 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Zhenxin Xi Submit-Approved: Jira Key --- android/abi_gki_aarch64_qcom | 1 + 1 file changed, 1 insertion(+) diff --git a/android/abi_gki_aarch64_qcom b/android/abi_gki_aarch64_qcom index b867d3928ebd..bf40649817b8 100644 --- a/android/abi_gki_aarch64_qcom +++ b/android/abi_gki_aarch64_qcom @@ -390,6 +390,7 @@ device_property_read_u32_array device_property_read_u8_array device_register + device_remove_bin_file device_remove_file device_set_of_node_from_dev device_set_wakeup_capable From 8d2ad2e01eb5e10a6b85c986509bf377daaeff4a Mon Sep 17 00:00:00 2001 From: ontim52 Date: Wed, 16 Aug 2023 10:34:32 +0800 Subject: [PATCH 640/698] kernel: show kernel suspend info 1. show kernel suspend info 2. sunch as: PM: suspend entry (deep) state=3(mem) Change-Id: I031e40f0b88b2a8544bb56c24a55102560a520cf Signed-off-by: ontim52 Reviewed-on: https://gerrit.mot.com/2710376 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- kernel/power/suspend.c | 54 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 49 insertions(+), 5 deletions(-) diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c index b584c67f57ab..68c6e560c53e 100644 --- a/kernel/power/suspend.c +++ b/kernel/power/suspend.c @@ -32,6 +32,7 @@ #include #include #include +#include #include "power.h" @@ -63,6 +64,46 @@ static DECLARE_SWAIT_QUEUE_HEAD(s2idle_wait_head); enum s2idle_states __read_mostly s2idle_state; static DEFINE_RAW_SPINLOCK(s2idle_lock); +const char *suspend_state_name[] = { +"ON", +"TO IDLE", +"STANDBY", +"MEM", +"MIN", +"MAX", +}; + +void print_time(bool running) +{ + static ktime_t kt_boot0 = 0; + ktime_t kt_boot; + u32 rem; + unsigned long delta; + struct timespec ts; + struct rtc_time tm; + char sign = '-'; + int tz_min = sys_tz.tz_minuteswest; + if (tz_min < 0) { + sign = '+'; + tz_min = -tz_min; + } + + kt_boot = ktime_get_boottime(); + delta = div_u64(kt_boot - kt_boot0, NSEC_PER_SEC); + + kt_boot0 = kt_boot; + kt_boot = div_u64_rem(kt_boot, NSEC_PER_SEC, &rem); + + getnstimeofday(&ts); + ts.tv_sec -= sys_tz.tz_minuteswest * 60; + rtc_time_to_tm(ts.tv_sec, &tm); + pr_err("realtime: %u-%02u-%02u %02u:%02u:%02u.%06u UTC%c%02d:%02d boottime: %5lu.%06u %s: %lu\n", + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, + tm.tm_hour, tm.tm_min, tm.tm_sec, (int)(ts.tv_nsec / 1000), + sign, tz_min / 60, tz_min % 60, + (long)kt_boot, (int)rem / 1000, running ? "running" : "sleep", delta); +} + /** * pm_suspend_default_s2idle - Check if suspend-to-idle is the default suspend. * @@ -121,7 +162,7 @@ static void s2idle_enter(void) static void s2idle_loop(void) { - pm_pr_dbg("suspend-to-idle\n"); + pr_err("suspend-to-idle\n"); /* * Suspend-to-idle equals: @@ -144,7 +185,7 @@ static void s2idle_loop(void) s2idle_enter(); } - pm_pr_dbg("resume from suspend-to-idle\n"); + pr_err("resume from suspend-to-idle\n"); } void s2idle_wake(void) @@ -325,7 +366,7 @@ static int suspend_test(int level) { #ifdef CONFIG_PM_DEBUG if (pm_test_level == level) { - pr_info("suspend debug: Waiting for %d second(s).\n", + pr_err("suspend debug: Waiting for %d second(s).\n", pm_test_delay); mdelay(pm_test_delay * 1000); return 1; @@ -636,7 +677,9 @@ int pm_suspend(suspend_state_t state) return -EINVAL; pm_suspend_marker("entry"); - pr_info("suspend entry (%s)\n", mem_sleep_labels[state]); + pr_err("suspend entry (%s) state=%d (%s)\n", mem_sleep_labels[state], state, + state < ARRAY_SIZE(suspend_state_name) ? suspend_state_name[state] : "unknow"); + print_time(true); error = enter_state(state); if (error) { suspend_stats.fail++; @@ -645,7 +688,8 @@ int pm_suspend(suspend_state_t state) suspend_stats.success++; } pm_suspend_marker("exit"); - pr_info("suspend exit\n"); + pr_err("suspend exit err=%d success=%d fail=%d\n", error, suspend_stats.success, suspend_stats.fail); + print_time(false); return error; } EXPORT_SYMBOL(pm_suspend); From ef1ce4231a6e2ba6f70ab311b0886598b1dc37b0 Mon Sep 17 00:00:00 2001 From: ontim52 Date: Wed, 16 Aug 2023 10:40:29 +0800 Subject: [PATCH 641/698] kernel: add debug-config for debug use 1. gpio status printed before cpu sleep, for debug use. 2. enable dump clk/regulator on suspend for userdebug SW. Change-Id: Icb45c5bd9300650bba4ab6c8795b492bedaa25de Signed-off-by: ontim52 Reviewed-on: https://gerrit.mot.com/2710381 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- arch/arm64/configs/vendor/holi_debug.config | 3 + drivers/clk/clk.c | 2 +- drivers/cpuidle/lpm-levels.c | 3 + drivers/gpio/gpiolib.c | 99 +++++++++++++++++++++ drivers/regulator/core.c | 2 +- init/Kconfig | 9 ++ 6 files changed, 116 insertions(+), 2 deletions(-) diff --git a/arch/arm64/configs/vendor/holi_debug.config b/arch/arm64/configs/vendor/holi_debug.config index 8cf2926d45f4..fe2e00c5079e 100644 --- a/arch/arm64/configs/vendor/holi_debug.config +++ b/arch/arm64/configs/vendor/holi_debug.config @@ -140,3 +140,6 @@ CONFIG_MMC_IPC_LOGGING=y CONFIG_CRYPTO_SHA1_ARM64_CE=y CONFIG_DEBUG_PAGEALLOC=y CONFIG_DEBUG_PAGEALLOC_ENABLE_DEFAULT=y +CONFIG_DUMP_GPIO_ON_SUSPEND=y +CONFIG_DUMP_CLK_ON_SUSPEND=y +CONFIG_DUMP_REGULATOR_ON_SUSPEND=y diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index f385e141577c..c076e6a7460f 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -3481,7 +3481,7 @@ static const struct file_operations clk_enabled_list_fops = { .release = seq_release, }; -static u32 debug_suspend; +static u32 debug_suspend = IS_ENABLED(CONFIG_DUMP_CLK_ON_SUSPEND); /* * Print the names of all enabled clocks and their parents if diff --git a/drivers/cpuidle/lpm-levels.c b/drivers/cpuidle/lpm-levels.c index 50564ec5ef3f..6ac5669c0403 100644 --- a/drivers/cpuidle/lpm-levels.c +++ b/drivers/cpuidle/lpm-levels.c @@ -123,6 +123,8 @@ static void cluster_prepare(struct lpm_cluster *cluster, static bool sleep_disabled; module_param_named(sleep_disabled, sleep_disabled, bool, 0664); +extern void gpio_debug_print_enabled(void); + #ifdef CONFIG_SMP static int lpm_cpu_qos_notify(struct notifier_block *nb, unsigned long val, void *ptr); @@ -1119,6 +1121,7 @@ static int cluster_configure(struct lpm_cluster *cluster, int idx, if (!from_idle) { clock_debug_print_enabled(); regulator_debug_print_enabled(); + gpio_debug_print_enabled(); } cpu = get_next_online_cpu(from_idle); diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index abdf448b11a3..bbdcce68a206 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -5063,6 +5063,104 @@ static int gpiolib_seq_show(struct seq_file *s, void *v) return 0; } +static u32 debug_gpio = IS_ENABLED(CONFIG_DUMP_GPIO_ON_SUSPEND); +void gpio_debug_print_enabled(void) +{ + unsigned long flags; + struct gpio_device *gdev = NULL; + struct seq_file *s; + int back; + + if (likely(!debug_gpio)) + { + return; + } + + printk("======================= Dump GPIO status begin ======================="); + spin_lock_irqsave(&gpio_lock, flags); + s = kzalloc(sizeof(struct seq_file), GFP_KERNEL); + if(s == NULL) + { + printk("hxy struct seq file failed to alloc memory"); + return; + } + s->index = 0; + s->version = 0; + s->count = s->from = 0; + s->read_pos= 0; + s->private = NULL; + s->file = NULL; + s->op = NULL; + s->private = ""; + + s->buf = kzalloc(s->size = PAGE_SIZE,GFP_KERNEL_ACCOUNT); + if (!s->buf) + { + printk("hxy seq file buffer failed to alloc memory %d bytes",s->size); + kfree(s ); + return ; + } + + list_for_each_entry(gdev, &gpio_devices, list) + { + try_again: + s->count = 0; + back=s->count; + + gpiolib_seq_show(s,gdev); + + if(s->count >= s->size) + { + kfree(s->buf ); + s->buf = kzalloc(s->size = (s->size*2),GFP_KERNEL_ACCOUNT); + if (!s->buf) + { + printk("hxy seq file buffer failed to alloc memory %d bytes",s->size); + kfree(s ); + return ; + } + goto try_again; + } + s->buf[s->count] = '\0'; + { + char tt[256]; + char *ptr; + char *ptr1; + int n; + int loop; + + ptr1=s->buf+back; + ptr=strstr(ptr1,"\x0a"); + loop=0; + while(ptr != NULL && (loop++ < 500) && (ptr < (s->buf+ s->size))) + { + n=ptr-ptr1; + strncpy(tt,ptr1,n); + tt[n]='\0'; + printk(" %s",tt); + ptr1 = ptr+strlen("\x0a"); + ptr=strstr(ptr1,"\x0a"); + } + } + } + + if(s->buf != NULL) + { + kfree(s->buf ); + s->buf = NULL; + } + if(s != NULL) + { + kfree(s ); + s = NULL; + } + spin_unlock_irqrestore(&gpio_lock, flags); + printk("======================= Dump GPIO status end ======================="); + +} + +EXPORT_SYMBOL(gpio_debug_print_enabled); + static const struct seq_operations gpiolib_seq_ops = { .start = gpiolib_seq_start, .next = gpiolib_seq_next, @@ -5088,6 +5186,7 @@ static int __init gpiolib_debugfs_init(void) /* /sys/kernel/debug/gpio */ debugfs_create_file("gpio", S_IFREG | S_IRUGO, NULL, NULL, &gpiolib_operations); + debugfs_create_u32("debug_gpio", 0644, NULL, &debug_gpio); return 0; } subsys_initcall(gpiolib_debugfs_init); diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 018534248353..40ef341f879b 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -55,7 +55,7 @@ static LIST_HEAD(regulator_supply_alias_list); static LIST_HEAD(regulator_coupler_list); static bool has_full_constraints; #ifdef CONFIG_DEBUG_FS -static bool debug_suspend; +static bool debug_suspend = IS_ENABLED(CONFIG_DUMP_REGULATOR_ON_SUSPEND); #endif static struct dentry *debugfs_root; diff --git a/init/Kconfig b/init/Kconfig index 10e37d91b9de..0c7ec0ac0951 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -639,6 +639,15 @@ config IKHEADERS or similar programs. If you build the headers as a module, a module called kheaders.ko is built which can be loaded on-demand to get access to headers. +config DUMP_GPIO_ON_SUSPEND + bool "dump gpio on suspend" + +config DUMP_CLK_ON_SUSPEND + bool "dump clk on suspend" + +config DUMP_REGULATOR_ON_SUSPEND + bool "dump regulator on suspend" + config LOG_BUF_SHIFT int "Kernel log buffer size (16 => 64KB, 17 => 128KB)" range 12 25 if !H8300 From a9cb8e9ca24978d8225e61dab51ab2839ab45313 Mon Sep 17 00:00:00 2001 From: weiweij Date: Fri, 18 Aug 2023 12:36:16 +0800 Subject: [PATCH 642/698] gpio: fix compile error for gpio_debug_print_enabled The error is from https://gerrit.mot.com/#/c/2710381/ Function gpio_debug_print_enabled is implemented under the control of DEBUG_FS. But user version do not have this macro definition. Error message is as following: ld.lld: error: undefined symbol: gpio_debug_print_enabled >>> referenced by lpm-levels.c:1124 (/home/weiweij/work/u/fogoNA/main/kernel/msm-5.4/drivers/cpuidle/lpm-levels.c:1124) >>> vmlinux.o:(cluster_configure) make[1]: *** [/home/weiweij/work/u/fogoNA/main/kernel/msm-5.4/Makefile:1197: vmlinux] Error 1 Change-Id: I57ae5a19f43dd4bf59196c8d18919f15acf03d4b Reviewed-on: https://gerrit.mot.com/2712951 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Wei Wei Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- drivers/cpuidle/lpm-levels.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/cpuidle/lpm-levels.c b/drivers/cpuidle/lpm-levels.c index 6ac5669c0403..5a9c715868bb 100644 --- a/drivers/cpuidle/lpm-levels.c +++ b/drivers/cpuidle/lpm-levels.c @@ -123,7 +123,9 @@ static void cluster_prepare(struct lpm_cluster *cluster, static bool sleep_disabled; module_param_named(sleep_disabled, sleep_disabled, bool, 0664); +#ifdef CONFIG_DEBUG_FS extern void gpio_debug_print_enabled(void); +#endif #ifdef CONFIG_SMP static int lpm_cpu_qos_notify(struct notifier_block *nb, @@ -1121,7 +1123,9 @@ static int cluster_configure(struct lpm_cluster *cluster, int idx, if (!from_idle) { clock_debug_print_enabled(); regulator_debug_print_enabled(); +#ifdef CONFIG_DEBUG_FS gpio_debug_print_enabled(); +#endif } cpu = get_next_online_cpu(from_idle); From 8b112bfe484b635b874f6561b927002495a602de Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Thu, 24 Aug 2023 09:29:45 -0300 Subject: [PATCH 643/698] Disable dump registers when suspend for penang WHAT: Disable the kernel configs related to debug gpio, clock and regulator dumping its values for penang WHY: This is halting penang driver sgm4154x_chg_mmi, because this config will eventually make sgm4154x_chg_mmi call msleep inside an atomic operation (read the registers that CONFIG_DUMP_* is requiring) and since penang has CONFIG_PANIC_ON_SCHED_BUG it will call BUG(), which will panic Change-Id: I26eb620e832dbf9e94acd4cb22cd87eee444f350 Reviewed-on: https://gerrit.mot.com/2719824 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Gilberto Gambugge Neto Submit-Approved: Jira Key Reviewed-by: Rafael Ortolan --- arch/arm64/configs/vendor/ext_config/debug-holi-penang.config | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm64/configs/vendor/ext_config/debug-holi-penang.config b/arch/arm64/configs/vendor/ext_config/debug-holi-penang.config index 95c989c10a1b..41a60c8502ac 100644 --- a/arch/arm64/configs/vendor/ext_config/debug-holi-penang.config +++ b/arch/arm64/configs/vendor/ext_config/debug-holi-penang.config @@ -26,3 +26,6 @@ # CONFIG_UFSTW is not set # CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_DUMP_GPIO_ON_SUSPEND is not set +# CONFIG_DUMP_CLK_ON_SUSPEND is not set +# CONFIG_DUMP_REGULATOR_ON_SUSPEND is not set From ea0a7de1a627f8d630ab406ae93f58fa9e0cdb4c Mon Sep 17 00:00:00 2001 From: guoyz3 Date: Mon, 28 Aug 2023 18:47:59 +0800 Subject: [PATCH 644/698] Fogor: common: mdlog: Enable coresight for modemlog on factory build Enable minimal coresight configuration for modem qdss log CONFIG_CORESIGHT_LINK_AND_SINK_TMC=y Change-Id: Iebe3b5650300dac56c72fe311f743962f29c0d12 Reviewed-on: https://gerrit.mot.com/2722656 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Chuanchun Zhu Reviewed-by: Yifu Lin Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- .../arm64/configs/vendor/ext_config/factory-holi-fogo.config | 5 +++++ .../configs/vendor/ext_config/factory-holi-fogor.config | 5 +++++ .../configs/vendor/ext_config/factory-holi-fogos.config | 5 +++++ 3 files changed, 15 insertions(+) diff --git a/arch/arm64/configs/vendor/ext_config/factory-holi-fogo.config b/arch/arm64/configs/vendor/ext_config/factory-holi-fogo.config index 89cbb53b692c..0de1c6cc1d60 100644 --- a/arch/arm64/configs/vendor/ext_config/factory-holi-fogo.config +++ b/arch/arm64/configs/vendor/ext_config/factory-holi-fogo.config @@ -15,3 +15,8 @@ # CONFIG_CAMERA_DISABLE_VSYNC_IRQ=y # CONFIG_MOT_DONGWOON_OIS_AF_DRIFT is not set +# Enable minimal coresight configuration for modem qdss log +CONFIG_CORESIGHT=y +CONFIG_CORESIGHT_LINK_AND_SINK_TMC=y +CONFIG_CORESIGHT_STM=y +CONFIG_CORESIGHT_DUMMY=y diff --git a/arch/arm64/configs/vendor/ext_config/factory-holi-fogor.config b/arch/arm64/configs/vendor/ext_config/factory-holi-fogor.config index 89cbb53b692c..0de1c6cc1d60 100644 --- a/arch/arm64/configs/vendor/ext_config/factory-holi-fogor.config +++ b/arch/arm64/configs/vendor/ext_config/factory-holi-fogor.config @@ -15,3 +15,8 @@ # CONFIG_CAMERA_DISABLE_VSYNC_IRQ=y # CONFIG_MOT_DONGWOON_OIS_AF_DRIFT is not set +# Enable minimal coresight configuration for modem qdss log +CONFIG_CORESIGHT=y +CONFIG_CORESIGHT_LINK_AND_SINK_TMC=y +CONFIG_CORESIGHT_STM=y +CONFIG_CORESIGHT_DUMMY=y diff --git a/arch/arm64/configs/vendor/ext_config/factory-holi-fogos.config b/arch/arm64/configs/vendor/ext_config/factory-holi-fogos.config index 89cbb53b692c..0de1c6cc1d60 100644 --- a/arch/arm64/configs/vendor/ext_config/factory-holi-fogos.config +++ b/arch/arm64/configs/vendor/ext_config/factory-holi-fogos.config @@ -15,3 +15,8 @@ # CONFIG_CAMERA_DISABLE_VSYNC_IRQ=y # CONFIG_MOT_DONGWOON_OIS_AF_DRIFT is not set +# Enable minimal coresight configuration for modem qdss log +CONFIG_CORESIGHT=y +CONFIG_CORESIGHT_LINK_AND_SINK_TMC=y +CONFIG_CORESIGHT_STM=y +CONFIG_CORESIGHT_DUMMY=y From de7fe8c180c0ba06115727464954f25015f84894 Mon Sep 17 00:00:00 2001 From: Xiaojun Ji Date: Thu, 24 Aug 2023 10:41:39 +0800 Subject: [PATCH 645/698] mm: set ra_pages according to ram size If enable CONFIG_MMAP_READAROUND_LIMIT, set ra_pages according to ram size 8: < 8G RAM 16: >=8G RAM Change-Id: I379a451e3ecc8d0552dbc2ead00edd24a934468f Reviewed-on: https://gerrit.mot.com/2719221 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Zonghua Liu Reviewed-by: Zhangqing Huang Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- .../vendor/ext_config/moto-holi-bangkk.config | 2 +- mm/Kconfig | 5 +++-- mm/filemap.c | 16 +++++++++------- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-bangkk.config b/arch/arm64/configs/vendor/ext_config/moto-holi-bangkk.config index 660007619b0c..e3350de19055 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-bangkk.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-bangkk.config @@ -42,5 +42,5 @@ CONFIG_CAMERA_FLASH_IIC_COMPATIBLE=y CONFIG_EROFS_FS_PCPU_KTHREAD=y CONFIG_EROFS_FS_PCPU_KTHREAD_HIPRI=y CONFIG_MOT_SENSOR_PRE_POWERUP=y -CONFIG_MMAP_READAROUND_LIMIT=16 +CONFIG_MMAP_READAROUND_LIMIT=y diff --git a/mm/Kconfig b/mm/Kconfig index 5c61895faa01..cf70c44a4288 100644 --- a/mm/Kconfig +++ b/mm/Kconfig @@ -737,12 +737,13 @@ config DEVICE_PRIVATE group of devices). You likely also want to select HMM_MIRROR. config MMAP_READAROUND_LIMIT - int "Limit mmap readaround upperbond" - default 0 + bool "Limit mmap readaround upperbond" + default n help Inappropriate mmap readaround size can hurt device performance during the sluggish situation. Add the hard upper-limit for mmap readaround + config FRAME_VECTOR bool diff --git a/mm/filemap.c b/mm/filemap.c index 7fdae5f71937..bae88d512dd9 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -2560,7 +2560,11 @@ static struct file *do_sync_mmap_readahead(struct vm_fault *vmf) struct address_space *mapping = file->f_mapping; struct file *fpin = NULL; pgoff_t offset = vmf->pgoff; +#ifdef CONFIG_MMAP_READAROUND_LIMIT + static unsigned int ra_pages = 0; +#else unsigned int ra_pages; +#endif /* If we don't want any read-ahead, don't bother */ if (vmf->vma_flags & VM_RAND_READ) @@ -2589,14 +2593,12 @@ static struct file *do_sync_mmap_readahead(struct vm_fault *vmf) /* * mmap read-around */ - -#if CONFIG_MMAP_READAROUND_LIMIT == 0 - ra_pages = ra->ra_pages; +#ifdef CONFIG_MMAP_READAROUND_LIMIT + /* Set 8 pages for < 8G RAM and set 16 pages for >= 8G RAM */ + if (ra_pages == 0) + ra_pages = ((totalram_pages() >> (30 - PAGE_SHIFT)) + 1) < 8 ? 8 : 16; #else - if (ra->ra_pages > CONFIG_MMAP_READAROUND_LIMIT) - ra_pages = CONFIG_MMAP_READAROUND_LIMIT < 0 ? 0 : CONFIG_MMAP_READAROUND_LIMIT; - else - ra_pages = ra->ra_pages; + ra_pages = ra->ra_pages; #endif fpin = maybe_unlock_mmap_for_io(vmf, fpin); From 7765267e701ad9a07c847631449e2346ca90c891 Mon Sep 17 00:00:00 2001 From: Xiaojun Ji Date: Fri, 25 Aug 2023 10:24:17 +0800 Subject: [PATCH 646/698] arch/arm64: enable CONFIG_MMAP_READAROUND_LIMIT 8pages for < 8G RAM 16pages for >= 8G RAM Change-Id: I9ab5c9ca3331aa9769db455ec674dad15f620efa Reviewed-on: https://gerrit.mot.com/2720560 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi-fogo.config | 1 + arch/arm64/configs/vendor/ext_config/moto-holi-fogor.config | 1 + arch/arm64/configs/vendor/ext_config/moto-holi-fogos.config | 1 + 3 files changed, 3 insertions(+) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-fogo.config b/arch/arm64/configs/vendor/ext_config/moto-holi-fogo.config index 09bc0529055e..3ffe6b43c919 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-fogo.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-fogo.config @@ -46,3 +46,4 @@ CONFIG_QUP0_SE2_AP=y CONFIG_EROFS_FS_PCPU_KTHREAD=y CONFIG_EROFS_FS_PCPU_KTHREAD_HIPRI=y CONFIG_MOT_SENSOR_PRE_POWERUP=y +CONFIG_MMAP_READAROUND_LIMIT=y diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-fogor.config b/arch/arm64/configs/vendor/ext_config/moto-holi-fogor.config index ce000d53b72d..a5f9aec4290f 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-fogor.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-fogor.config @@ -42,3 +42,4 @@ CONFIG_CAMERA_FLASH_IIC_COMPATIBLE=y CONFIG_EROFS_FS_PCPU_KTHREAD=y CONFIG_EROFS_FS_PCPU_KTHREAD_HIPRI=y CONFIG_MOT_SENSOR_PRE_POWERUP=y +CONFIG_MMAP_READAROUND_LIMIT=y diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-fogos.config b/arch/arm64/configs/vendor/ext_config/moto-holi-fogos.config index f97b86eaa755..9729fb619a51 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-fogos.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-fogos.config @@ -41,3 +41,4 @@ CONFIG_QUP0_SE2_AP=y CONFIG_CAMERA_FLASH_IIC_COMPATIBLE=y CONFIG_EROFS_FS_PCPU_KTHREAD=y CONFIG_EROFS_FS_PCPU_KTHREAD_HIPRI=y +CONFIG_MMAP_READAROUND_LIMIT=y From 3c30b503284cd3944e01ae4ba57b9dfa2b1dc29e Mon Sep 17 00:00:00 2001 From: Liu Yang Date: Fri, 1 Sep 2023 16:20:01 +0800 Subject: [PATCH 647/698] fogos: Power up and init sensor in advance Open this func for fogos in kernel. Change-Id: If8458d06fa7358453e43ce48da4f90762ce10a22 Signed-off-by: Liu Yang Reviewed-on: https://gerrit.mot.com/2727777 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Bolei Shang Reviewed-by: Ji Zhao Reviewed-by: Reviewed-by: Reviewed-by: Simon C Reviewed-by: Zhang Lei Reviewed-by: Reviewed-by: Guobin Zhang Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi-fogos.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-fogos.config b/arch/arm64/configs/vendor/ext_config/moto-holi-fogos.config index 9729fb619a51..13a09239a9c1 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-fogos.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-fogos.config @@ -42,3 +42,4 @@ CONFIG_CAMERA_FLASH_IIC_COMPATIBLE=y CONFIG_EROFS_FS_PCPU_KTHREAD=y CONFIG_EROFS_FS_PCPU_KTHREAD_HIPRI=y CONFIG_MMAP_READAROUND_LIMIT=y +CONFIG_MOT_SENSOR_PRE_POWERUP=y From c6ae3579617519daf287974875ed1e3ae37c4ac7 Mon Sep 17 00:00:00 2001 From: weiweij Date: Fri, 8 Sep 2023 13:49:03 +0800 Subject: [PATCH 648/698] gpio: fix gpio dump msg missing problem GPIOLIB_IS_REQUEST() checking only return true when the gpio using request_gpio functions. So if using pinctrl and subsystem gpio configuration, this checking logic will block. And we will get lots of following errors: [ 453.757397] gpio25: is not allocated in gpiolib After removing this logic, we could get the gpio status: 09-07 21:27:55.968 0 0 W gpio25 : in low func0 2mA pull down Change-Id: I2d03e86e3a236bd81a72dfa20cb9e0be41354348 Reviewed-on: https://gerrit.mot.com/2733812 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Wei Wei Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- drivers/pinctrl/qcom/pinctrl-msm.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c index de43c64c1dab..4bd5187f90cf 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm.c +++ b/drivers/pinctrl/qcom/pinctrl-msm.c @@ -594,11 +594,6 @@ static void msm_gpio_dbg_show_one(struct seq_file *s, if (!gpiochip_line_is_valid(chip, offset)) return; - if (!gpiochip_is_requested(chip, offset)) { - seq_printf(s, " gpio%d: is not allocated in gpiolib\n", offset); - return; - } - g = &pctrl->soc->groups[offset]; ctl_reg = msm_readl_ctl(pctrl, g); io_reg = msm_readl_io(pctrl, g); From 231e74b2550fcbab7697bb5a60cc9728df9daf6a Mon Sep 17 00:00:00 2001 From: liuyc20 Date: Fri, 8 Sep 2023 17:31:44 +0800 Subject: [PATCH 649/698] PD: PowerRole set to SINK when detected the analog_audio plug-in TYPEC_SINK_AUDIO_ADAPTER ->set current_pr=PR_SINK ->enter_state_snk_startup->typec_set_pwr_role(will sent uevent) ->register and set /sys/class/typec/port0-partner/accessory_mode(analog_audio) Change-Id: I5aa26c83361739feec6e74a46c1ea23e48b0c0bf Signed-off-by: liuyc20 Reviewed-on: https://gerrit.mot.com/2734256 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Haijian Ma Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- drivers/usb/pd/policy_engine.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/usb/pd/policy_engine.c b/drivers/usb/pd/policy_engine.c index 0265fda58b76..eb84b4e2a1ae 100644 --- a/drivers/usb/pd/policy_engine.c +++ b/drivers/usb/pd/policy_engine.c @@ -2650,6 +2650,8 @@ static void enter_state_snk_startup(struct usbpd *pd) memset(&pd->partner_identity, 0, sizeof(pd->partner_identity)); pd->partner_desc.usb_pd = false; pd->partner_desc.accessory = TYPEC_ACCESSORY_NONE; + if (pd->typec_mode == QTI_POWER_SUPPLY_TYPEC_SINK_AUDIO_ADAPTER) + pd->partner_desc.accessory = TYPEC_ACCESSORY_AUDIO; pd->partner = typec_register_partner(pd->typec_port, &pd->partner_desc); } @@ -3735,6 +3737,7 @@ static int usbpd_process_typec_mode(struct usbpd *pd, break; case QTI_POWER_SUPPLY_TYPEC_SINK_AUDIO_ADAPTER: usbpd_info(&pd->dev, "Type-C Analog Audio Adapter connected\n"); + pd->current_pr = PR_SINK; break; default: usbpd_warn(&pd->dev, "Unsupported typec mode:%d\n", From 9244f7f6c6382ee604fa27e8ff2a41956b13b7d2 Mon Sep 17 00:00:00 2001 From: Liujie Xie Date: Sat, 3 Jul 2021 10:05:21 +0800 Subject: [PATCH 650/698] ANDROID: vendor_hooks: add a field in mem_cgroup Add a field in mem_cgroup to record additional per-cgroup information for memory policy tuning. Bug: 192052083 Mot-CRs-fixed: (CR) Signed-off-by: Liujie Xie Change-Id: I28c8bc1c2455d53e68a05555b57b76ded27af98a Reviewed-on: https://gerrit.mot.com/2747019 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- include/linux/memcontrol.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h index a1b04d916526..a56b16cc56f6 100644 --- a/include/linux/memcontrol.h +++ b/include/linux/memcontrol.h @@ -334,6 +334,7 @@ struct mem_cgroup { struct deferred_split deferred_split_queue; #endif + ANDROID_OEM_DATA(1); struct mem_cgroup_per_node *nodeinfo[0]; /* WARNING: nodeinfo must be the last member here */ }; From bd004af78852898dde98262b69bdfb6c3670d274 Mon Sep 17 00:00:00 2001 From: Liujie Xie Date: Sat, 3 Jul 2021 09:58:59 +0800 Subject: [PATCH 651/698] ANDROID: vendor_hooks: add a field in pglist_data Add a pglist_data field to record additional node parameters. Bug: 192052083 Mot-CRs-fixed: (CR) Signed-off-by: Liujie Xie Change-Id: I3d764ab298c71ab9aba245867ee529045551aef4 Reviewed-on: https://gerrit.mot.com/2747020 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- include/linux/mmzone.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index 6f2a15015435..ce7f28658127 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -759,6 +759,7 @@ typedef struct pglist_data { int kswapd_failures; /* Number of 'reclaimed == 0' runs */ + ANDROID_OEM_DATA(1); #ifdef CONFIG_COMPACTION int kcompactd_max_order; enum zone_type kcompactd_classzone_idx; From f62f91132a334f91ac29bc0db363bbc0f01b758b Mon Sep 17 00:00:00 2001 From: huangzq2 Date: Thu, 21 Sep 2023 10:22:16 +0800 Subject: [PATCH 652/698] Porting hooks from 5.10 and move zram to ko Change-Id: I576f9dc68a31900b6fbbe629edbb01cf8a723d8d Signed-off-by: huangzq2 Reviewed-on: https://gerrit.mot.com/2747021 Reviewed-by: Xiangpo Zhao SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Submit-Approved: Jira Key --- arch/arm64/configs/vendor/holi_QGKI.config | 1 + drivers/android/vendor_hooks.c | 11 +++ include/trace/hooks/mm.h | 78 ++++++++++++++++++++++ include/trace/hooks/vmscan.h | 24 +++++++ mm/memcontrol.c | 6 ++ mm/page_alloc.c | 3 + mm/vmscan.c | 7 ++ 7 files changed, 130 insertions(+) create mode 100644 include/trace/hooks/mm.h create mode 100644 include/trace/hooks/vmscan.h diff --git a/arch/arm64/configs/vendor/holi_QGKI.config b/arch/arm64/configs/vendor/holi_QGKI.config index 45369dfd5143..4a9f1f13ab95 100644 --- a/arch/arm64/configs/vendor/holi_QGKI.config +++ b/arch/arm64/configs/vendor/holi_QGKI.config @@ -20,6 +20,7 @@ CONFIG_IOMMU_IO_PGTABLE_FAST=y CONFIG_QCOM_LLCC_PERFMON=m CONFIG_SCHED_WALT=y CONFIG_QGKI=y +CONFIG_ZRAM=m CONFIG_REGULATOR_QTI_DEBUG=y CONFIG_REGMAP_QTI_DEBUG=y CONFIG_REGMAP_ALLOW_WRITE_DEBUGFS=y diff --git a/drivers/android/vendor_hooks.c b/drivers/android/vendor_hooks.c index 0830f821d49b..0b4a3ae830f3 100644 --- a/drivers/android/vendor_hooks.c +++ b/drivers/android/vendor_hooks.c @@ -17,11 +17,13 @@ #include #include #include +#include #include #include #include #include #include +#include /* * Export tracepoints that act as a bare tracehook (ie: have no trace event @@ -71,5 +73,14 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_sysrq_crash); EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_find_busiest_group); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_map_util_freq); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_em_pd_energy); +EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_rmqueue); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_cgroup_set_task); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_syscall_prctl_finished); +EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_tune_scan_type); +EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_tune_swappiness); +EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_tune_inactive_ratio); +EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_mem_cgroup_id_remove); +EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_mem_cgroup_css_offline); +EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_mem_cgroup_css_online); +EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_mem_cgroup_free); +EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_mem_cgroup_alloc); diff --git a/include/trace/hooks/mm.h b/include/trace/hooks/mm.h new file mode 100644 index 000000000000..24834016718f --- /dev/null +++ b/include/trace/hooks/mm.h @@ -0,0 +1,78 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifdef PROTECT_TRACE_INCLUDE_PATH +#undef PROTECT_TRACE_INCLUDE_PATH + +#include +#include +#include + +#else /* PROTECT_TRACE_INCLUDE_PATH */ + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM mm + +#define TRACE_INCLUDE_PATH trace/hooks + +#if !defined(_TRACE_HOOK_MM_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_HOOK_MM_H + +#include + +#include +#include +#include +#include +#include + +#ifdef __GENKSYMS__ +struct slabinfo; +struct cgroup_subsys_state; +struct device; +struct mem_cgroup; +struct readahead_control; +#else +/* struct slabinfo */ +#include <../mm/slab.h> +/* struct cgroup_subsys_state */ +#include +/* struct device */ +#include +/* struct mem_cgroup */ +#include +/* struct readahead_control */ +#include +#endif /* __GENKSYMS__ */ +struct cma; +struct swap_slots_cache; +struct page_vma_mapped_walk; + +DECLARE_HOOK(android_vh_rmqueue, + TP_PROTO(struct zone *preferred_zone, struct zone *zone, + unsigned int order, gfp_t gfp_flags, + unsigned int alloc_flags, int migratetype), + TP_ARGS(preferred_zone, zone, order, + gfp_flags, alloc_flags, migratetype)); + +DECLARE_HOOK(android_vh_mem_cgroup_alloc, + TP_PROTO(struct mem_cgroup *memcg), + TP_ARGS(memcg)); +DECLARE_HOOK(android_vh_mem_cgroup_free, + TP_PROTO(struct mem_cgroup *memcg), + TP_ARGS(memcg)); +DECLARE_HOOK(android_vh_mem_cgroup_id_remove, + TP_PROTO(struct mem_cgroup *memcg), + TP_ARGS(memcg)); +DECLARE_HOOK(android_vh_mem_cgroup_css_online, + TP_PROTO(struct cgroup_subsys_state *css, struct mem_cgroup *memcg), + TP_ARGS(css, memcg)); +DECLARE_HOOK(android_vh_mem_cgroup_css_offline, + TP_PROTO(struct cgroup_subsys_state *css, struct mem_cgroup *memcg), + TP_ARGS(css, memcg)); +/* macro versions of hooks are no longer required */ + +#endif /* _TRACE_HOOK_MM_H */ + +/* This part must be outside protection */ +#include + +#endif /* PROTECT_TRACE_INCLUDE_PATH */ diff --git a/include/trace/hooks/vmscan.h b/include/trace/hooks/vmscan.h new file mode 100644 index 000000000000..0f156f3aad7d --- /dev/null +++ b/include/trace/hooks/vmscan.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#undef TRACE_SYSTEM +#define TRACE_SYSTEM vmscan + +#define TRACE_INCLUDE_PATH trace/hooks + +#if !defined(_TRACE_HOOK_VMSCAN_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_HOOK_VMSCAN_H + +#include +#include + +DECLARE_HOOK(android_vh_tune_scan_type, + TP_PROTO(char *scan_type), + TP_ARGS(scan_type)); +DECLARE_HOOK(android_vh_tune_swappiness, + TP_PROTO(int *swappiness), + TP_ARGS(swappiness)); +DECLARE_HOOK(android_vh_tune_inactive_ratio, + TP_PROTO(unsigned long *inactive_ratio, int file), + TP_ARGS(inactive_ratio, file)) +#endif /* _TRACE_HOOK_VMSCAN_H */ +/* This part must be outside protection */ +#include diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 0140629b7cb2..6fea1bfbea07 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -67,6 +67,7 @@ #include #include +#include struct cgroup_subsys memory_cgrp_subsys __read_mostly; EXPORT_SYMBOL(memory_cgrp_subsys); @@ -5005,6 +5006,7 @@ static DEFINE_IDR(mem_cgroup_idr); static void mem_cgroup_id_remove(struct mem_cgroup *memcg) { if (memcg->id.id > 0) { + trace_android_vh_mem_cgroup_id_remove(memcg); idr_remove(&mem_cgroup_idr, memcg->id.id); memcg->id.id = 0; } @@ -5098,6 +5100,7 @@ static void __mem_cgroup_free(struct mem_cgroup *memcg) { int node; + trace_android_vh_mem_cgroup_free(memcg); for_each_node(node) free_mem_cgroup_per_node_info(memcg, node); free_percpu(memcg->vmstats_percpu); @@ -5179,6 +5182,7 @@ static struct mem_cgroup *mem_cgroup_alloc(void) memcg->deferred_split_queue.split_queue_len = 0; #endif idr_replace(&mem_cgroup_idr, memcg, memcg->id.id); + trace_android_vh_mem_cgroup_alloc(memcg); return memcg; fail: mem_cgroup_id_remove(memcg); @@ -5265,6 +5269,7 @@ static int mem_cgroup_css_online(struct cgroup_subsys_state *css) /* Online state pins memcg ID, memcg ID pins CSS */ refcount_set(&memcg->id.ref, 1); css_get(css); + trace_android_vh_mem_cgroup_css_online(css, memcg); return 0; } @@ -5273,6 +5278,7 @@ static void mem_cgroup_css_offline(struct cgroup_subsys_state *css) struct mem_cgroup *memcg = mem_cgroup_from_css(css); struct mem_cgroup_event *event, *tmp; + trace_android_vh_mem_cgroup_css_offline(css, memcg); /* * Unregister events and notify userspace. * Notify userspace about cgroup removing only after rmdir of cgroup diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 7d51ecf3504a..d65ae4be77c1 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -70,6 +70,7 @@ #include #include #include +#include #include #include @@ -3414,6 +3415,8 @@ struct page *rmqueue(struct zone *preferred_zone, __count_zid_vm_events(PGALLOC, page_zonenum(page), 1 << order); zone_statistics(preferred_zone, zone); + trace_android_vh_rmqueue(preferred_zone, zone, order, + gfp_flags, alloc_flags, migratetype); local_irq_restore(flags); out: diff --git a/mm/vmscan.c b/mm/vmscan.c index 90ef9c46e2f3..9811188f7570 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -63,6 +63,9 @@ #define CREATE_TRACE_POINTS #include +#undef CREATE_TRACE_POINTS +#include + struct scan_control { /* How many pages shrink_list() should reclaim */ unsigned long nr_to_reclaim; @@ -2341,6 +2344,8 @@ static bool inactive_list_is_low(struct lruvec *lruvec, bool file, lruvec_lru_size(lruvec, active_lru, MAX_NR_ZONES), active, inactive_ratio, file); + trace_android_vh_tune_inactive_ratio(&inactive_ratio, is_file_lru(inactive_lru)); + return inactive * inactive_ratio < active; } @@ -2393,6 +2398,7 @@ static void get_scan_count(struct lruvec *lruvec, struct mem_cgroup *memcg, goto out; } + trace_android_vh_tune_swappiness(&swappiness); /* * Global reclaim will swap to prevent OOM even with no * swappiness, but memcg users want to use this knob to @@ -2526,6 +2532,7 @@ static void get_scan_count(struct lruvec *lruvec, struct mem_cgroup *memcg, fraction[1] = fp; denominator = ap + fp + 1; out: + trace_android_vh_tune_scan_type((char *)(&scan_balance)); *lru_pages = 0; for_each_evictable_lru(lru) { int file = is_file_lru(lru); From 8686f439ac3f9c5efaef9d03729e44c4eae09725 Mon Sep 17 00:00:00 2001 From: Xiaojun Ji Date: Thu, 21 Sep 2023 14:56:48 +0800 Subject: [PATCH 653/698] Export some APIs moto_swap.ko need use this APIs Change-Id: I98e91d6bfadcd931f493a7dbb4447d8d7e9f0a34 Reviewed-on: https://gerrit.mot.com/2749373 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- kernel/cgroup/cgroup.c | 1 + mm/memcontrol.c | 1 + mm/swapfile.c | 1 + mm/vmscan.c | 2 ++ 4 files changed, 5 insertions(+) diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c index 2822b46db8f1..180e8fe77459 100644 --- a/kernel/cgroup/cgroup.c +++ b/kernel/cgroup/cgroup.c @@ -4315,6 +4315,7 @@ int cgroup_add_legacy_cftypes(struct cgroup_subsys *ss, struct cftype *cfts) return cgroup_add_cftypes(ss, cfts); } +EXPORT_SYMBOL_GPL(cgroup_add_legacy_cftypes); /** * cgroup_file_notify - generate a file modified event for a cgroup_file * @cfile: target cgroup_file diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 6fea1bfbea07..78b18ce5a4fd 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -5044,6 +5044,7 @@ struct mem_cgroup *mem_cgroup_from_id(unsigned short id) return idr_find(&mem_cgroup_idr, id); } +EXPORT_SYMBOL_GPL(mem_cgroup_from_id); static int alloc_mem_cgroup_per_node_info(struct mem_cgroup *memcg, int node) { struct mem_cgroup_per_node *pn; diff --git a/mm/swapfile.c b/mm/swapfile.c index f0f77c750c56..5fdb4122cac2 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -3384,6 +3384,7 @@ void si_swapinfo(struct sysinfo *val) val->totalswap = total_swap_pages + nr_to_be_unused; spin_unlock(&swap_lock); } +EXPORT_SYMBOL_GPL(si_swapinfo); /* * Verify that a swap entry is valid and increment its swap map count. diff --git a/mm/vmscan.c b/mm/vmscan.c index 9811188f7570..2f34fc523b20 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -3490,6 +3490,8 @@ unsigned long try_to_free_mem_cgroup_pages(struct mem_cgroup *memcg, return nr_reclaimed; } + +EXPORT_SYMBOL_GPL(try_to_free_mem_cgroup_pages); #endif static void age_active_anon(struct pglist_data *pgdat, From 06f890cf6f59ed10cf287b3d391d7c8c591ba1eb Mon Sep 17 00:00:00 2001 From: Xiaojun Ji Date: Fri, 22 Sep 2023 14:27:54 +0800 Subject: [PATCH 654/698] Fix KMI break on GKI build Only add OEM DATA on QGKI and keep the origin struct on GKI to avoid break KMI. Change-Id: I6678db4ce211a21c91c5305024cb18b9f5e1265e Reviewed-on: https://gerrit.mot.com/2749363 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- include/linux/memcontrol.h | 3 ++- include/linux/mmzone.h | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h index a56b16cc56f6..528380117ab8 100644 --- a/include/linux/memcontrol.h +++ b/include/linux/memcontrol.h @@ -333,8 +333,9 @@ struct mem_cgroup { #if defined(CONFIG_TRANSPARENT_HUGEPAGE) || defined(CONFIG_GKI_OPT_FEATURES) struct deferred_split deferred_split_queue; #endif - +#ifdef CONFIG_QGKI ANDROID_OEM_DATA(1); +#endif struct mem_cgroup_per_node *nodeinfo[0]; /* WARNING: nodeinfo must be the last member here */ }; diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index ce7f28658127..3bae2136989a 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -758,8 +758,9 @@ typedef struct pglist_data { enum zone_type kswapd_classzone_idx; int kswapd_failures; /* Number of 'reclaimed == 0' runs */ - +#ifdef CONFIG_QGKI ANDROID_OEM_DATA(1); +#endif #ifdef CONFIG_COMPACTION int kcompactd_max_order; enum zone_type kcompactd_classzone_idx; From a4f0de2f15657ed6fcf13eadc8cb6299aff362c4 Mon Sep 17 00:00:00 2001 From: Guocheng Wang Date: Wed, 27 Sep 2023 17:42:32 +0800 Subject: [PATCH 655/698] typec: Fix COM charging failed when using audio 2-1 adapter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using Type-C to 3.5mm Headphone 2-in-1 Adapter,COM charging Failed. Because the devices are in off-mode when usb plug-in,bootup process might cause some detection delay. So when DUT power on with typec and the typec vbus is exist,we need to wait some times for check type-c is connected before call smb5_typec_attach_detach_irq_handler. Change-Id: I8ea0e904bc493c13d666a09f81c34d33fdb2663f Signed-off-by: Guocheng Wang Reviewed-on: https://gerrit.mot.com/2752957 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Haijian Ma Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- drivers/power/supply/qcom/qpnp-smb5.c | 45 +++++++++++++++++++++++++++ drivers/power/supply/qcom/smb5-reg.h | 1 + 2 files changed, 46 insertions(+) diff --git a/drivers/power/supply/qcom/qpnp-smb5.c b/drivers/power/supply/qcom/qpnp-smb5.c index deccb443912c..824952c76a1c 100644 --- a/drivers/power/supply/qcom/qpnp-smb5.c +++ b/drivers/power/supply/qcom/qpnp-smb5.c @@ -2975,6 +2975,49 @@ static int smb5_init_typec_class(struct smb5 *chip) return rc; } +static int smb5_typec_cable_check(struct smb5 *chip) +{ + struct smb_charger *chg = &chip->chg; + int rc = 0; + int i = 0; + u8 stat = 0; + bool usb_input_present = false; + + if (chg->pd_not_supported) + return rc; + + rc = smblib_read(chg, USBIN_BASE + INT_RT_STS_OFFSET, &stat); + if (rc < 0) { + pr_err("%s Couldn't read USBIN_RT_STS rc=%d\n", __func__, rc); + return rc; + } + usb_input_present = stat & USBIN_PLUGIN_RT_STS_BIT; + + rc = smblib_read(chg, TYPE_C_MISC_STATUS_REG, &stat); + if (rc < 0) { + pr_err("%s Couldn't read TYPE_C_STATUS_4 rc=%d\n", __func__, rc); + return rc; + } + pr_info("%s usb_input_present=%d TYPE_C_STATUS_4=0x%02X\n", __func__, usb_input_present, stat); + + if (usb_input_present || (stat & TYPEC_VBUS_STATUS)) { + for (i = 0; i < 10; i++) { + rc = smblib_read(chg, TYPE_C_STATE_MACHINE_STATUS_REG, &stat); + if (rc < 0) { + pr_err("%s Couldn't read TYPE_C_STATE_MACHINE_STATUS rc=%d\n", __func__, rc); + return rc; + } + pr_info("%s index=%d stat=0x%02X\n", __func__, i, stat); + if (stat & TYPEC_ATTACH_DETACH_STATE_BIT) { + break; + } + msleep(50); + } + } + + return rc; +} + static int smb5_of_xlate(struct iio_dev *indio_dev, const struct of_phandle_args *iiospec) { @@ -3256,6 +3299,8 @@ static int smb5_probe(struct platform_device *pdev) goto cleanup; } + smb5_typec_cable_check(chip); + rc = smb5_determine_initial_status(chip); if (rc < 0) { pr_err("Couldn't determine initial status rc=%d\n", diff --git a/drivers/power/supply/qcom/smb5-reg.h b/drivers/power/supply/qcom/smb5-reg.h index 2f9976a659e4..6b58cfd65e76 100644 --- a/drivers/power/supply/qcom/smb5-reg.h +++ b/drivers/power/supply/qcom/smb5-reg.h @@ -359,6 +359,7 @@ enum { #define TYPE_C_MISC_STATUS_REG (TYPEC_BASE + 0x0B) #define TYPEC_WATER_DETECTION_STATUS_BIT BIT(7) #define SNK_SRC_MODE_BIT BIT(6) +#define TYPEC_VBUS_STATUS BIT(5) #define TYPEC_VBUS_ERROR_STATUS_BIT BIT(4) #define TYPEC_TCCDEBOUNCE_DONE_STATUS_BIT BIT(3) #define CC_ORIENTATION_BIT BIT(1) From b593dc6aeedfdde0240e0927c7f8c3bfd300f97b Mon Sep 17 00:00:00 2001 From: Guocheng Wang Date: Sat, 7 Oct 2023 17:07:24 +0800 Subject: [PATCH 656/698] charge: Skip AICL when usb /charger cable is not connected The prerequisite for AICL is that VBUS is required, so when usb or charger cable is not connected (neither usbin nor dcin exists), we need to skip re-run AICL. Change-Id: I2d039fbfaa090ac3e7682e4ddb9889a278503484 Signed-off-by: Guocheng Wang Reviewed-on: https://gerrit.mot.com/2760500 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Wei Wei Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- drivers/power/supply/qcom/smb5-lib.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/power/supply/qcom/smb5-lib.c b/drivers/power/supply/qcom/smb5-lib.c index e0c9d9f1faa9..3c6c2e2bfd07 100644 --- a/drivers/power/supply/qcom/smb5-lib.c +++ b/drivers/power/supply/qcom/smb5-lib.c @@ -2654,6 +2654,10 @@ int smblib_run_aicl(struct smb_charger *chg, int type) if (stat & USBIN_SUSPEND_STS_BIT) return rc; + /* Neither usbin nor dcin exists so skip re-running AICL */ + if (!(stat & (USE_USBIN_BIT | USE_DCIN_BIT))) + return rc; + smblib_dbg(chg, PR_MISC, "re-running AICL\n"); stat = (type == RERUN_AICL) ? RERUN_AICL_BIT : RESTART_AICL_BIT; From 1a68f6d94e46e8b2d50b7ebf78278afc2115ca56 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Thu, 5 Oct 2023 18:40:27 -0300 Subject: [PATCH 657/698] Disable dump registers when suspend for miami WHAT: Disable the kernel configs related to debug gpio, clock and regulator dumping its values for miami WHY: This is halting penang driver sgm4154x_chg_mmi, because this config will eventually make sgm4154x_chg_mmi call msleep inside an atomic operation (read the registers that CONFIG_DUMP_* is requiring) and since penang has CONFIG_PANIC_ON_SCHED_BUG it will call BUG(), which will panic Change-Id: I8768dd99eafc854c0cd55cd57b51b241798ea64f Reviewed-on: https://gerrit.mot.com/2759524 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Reviewed-by: Rafael Ortolan Tested-by: Jira Key Reviewed-by: Gilberto Gambugge Neto Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/debug-holi-miami.config | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm64/configs/vendor/ext_config/debug-holi-miami.config b/arch/arm64/configs/vendor/ext_config/debug-holi-miami.config index f7dfd271a2c2..2d6354f8a3a9 100644 --- a/arch/arm64/configs/vendor/ext_config/debug-holi-miami.config +++ b/arch/arm64/configs/vendor/ext_config/debug-holi-miami.config @@ -25,3 +25,7 @@ # CONFIG_TEST_USER_COPY is not set # CONFIG_CAMERA_FLASH_PWM is not set # CONFIG_UFSTW is not set +# CONFIG_DUMP_GPIO_ON_SUSPEND is not set +# CONFIG_DUMP_CLK_ON_SUSPEND is not set +# CONFIG_DUMP_REGULATOR_ON_SUSPEND is not set + From 477019ca8ad7bc0ad473c618093908cf38002564 Mon Sep 17 00:00:00 2001 From: Xiaojun Ji Date: Thu, 12 Oct 2023 16:21:32 +0800 Subject: [PATCH 658/698] Revert "mm/madvise: support both pid and pidfd for process_madvise" Mot-CRs-fixed: (CR) it only has 5 parameters in libc, currently has 6 parameters in kernel to cause it return -EINVAL in "flags" check libc defined: ssize_t process_madvise(int __pid_fd, const struct iovec* __iov, size_t __count, int __advice, unsigned __flags) __INTRODUCED_IN(31); This reverts commit 306d0c3e29cad7c8e41e1bdfc53a3ceac5d2ad66. Change-Id: If69151ae97498f4db210fbe4d16bf53ad4abf42b Reviewed-on: https://gerrit.mot.com/2765786 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Zhangqing Huang Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- include/linux/syscalls.h | 2 +- mm/madvise.c | 26 ++++++-------------------- 2 files changed, 7 insertions(+), 21 deletions(-) diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index a8e20cb00e5d..0fb592752e13 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h @@ -874,7 +874,7 @@ asmlinkage long sys_munlockall(void); asmlinkage long sys_mincore(unsigned long start, size_t len, unsigned char __user * vec); asmlinkage long sys_madvise(unsigned long start, size_t len, int behavior); -asmlinkage long sys_process_madvise(int which, pid_t upid, +asmlinkage long sys_process_madvise(int pidfd, const struct iovec __user *vec, unsigned long vlen, int behavior, unsigned long flags); asmlinkage long sys_remap_file_pages(unsigned long start, unsigned long size, diff --git a/mm/madvise.c b/mm/madvise.c index c87d4c43b885..72ef91c3a188 100644 --- a/mm/madvise.c +++ b/mm/madvise.c @@ -1235,7 +1235,7 @@ static int do_process_madvise(struct task_struct *target_task, return ret; } -SYSCALL_DEFINE6(process_madvise, int, which, pid_t, upid, +SYSCALL_DEFINE5(process_madvise, int, pidfd, const struct iovec __user *, vec, unsigned long, vlen, int, behavior, unsigned long, flags) { @@ -1250,25 +1250,10 @@ SYSCALL_DEFINE6(process_madvise, int, which, pid_t, upid, if (flags != 0) return -EINVAL; - switch (which) { - case P_PID: - if (upid <= 0) - return -EINVAL; - - pid = find_get_pid(upid); - if (!pid) - return -ESRCH; - break; - case P_PIDFD: - if (upid < 0) - return -EINVAL; - - pid = pidfd_get_pid(upid); - if (IS_ERR(pid)) - return PTR_ERR(pid); - break; - default: - return -EINVAL; + pid = pidfd_get_pid(pidfd); + if (IS_ERR(pid)) { + ret = PTR_ERR(pid); + goto out; } task = get_pid_task(pid, PIDTYPE_PID); @@ -1302,5 +1287,6 @@ release_task: put_task_struct(task); put_pid: put_pid(pid); +out: return ret; } From a90824b3cb95a1407dc4ea595e739ccf3541d6db Mon Sep 17 00:00:00 2001 From: Edgar Arriaga Date: Mon, 11 Jan 2021 15:19:48 -0800 Subject: [PATCH 659/698] FROMLIST: mm/madvise: replace ptrace attach requirement for process_madvise Mot-CRs-fixed: (CR) process_madvise currently requires ptrace attach capability. PTRACE_MODE_ATTACH gives one process complete control over another process. It effectively removes the security boundary between the two processes (in one direction). Granting ptrace attach capability even to a system process is considered dangerous since it creates an attack surface. This severely limits the usage of this API. The operations process_madvise can perform do not affect the correctness of the operation of the target process; they only affect where the data is physically located (and therefore, how fast it can be accessed). What we want is the ability for one process to influence another process in order to optimize performance across the entire system while leaving the security boundary intact. Replace PTRACE_MODE_ATTACH with a combination of PTRACE_MODE_READ and CAP_SYS_NICE. PTRACE_MODE_READ to prevent leaking ASLR metadata and CAP_SYS_NICE for influencing process performance. Signed-off-by: Suren Baghdasaryan Acked-by: Minchan Kim Acked-by: David Rientjes Link: https://lore.kernel.org/lkml/202101111033.2D03EA97@keescook/T/#u Test: built and flashed kernel Bug: 153444106 Signed-off-by: Edgar Arriaga Change-Id: I3624a8b0697d70f23587c1dcb746ba753c301f45 Reviewed-on: https://gerrit.mot.com/2765787 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Zhangqing Huang Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- mm/madvise.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/mm/madvise.c b/mm/madvise.c index 72ef91c3a188..739ad2486ebf 100644 --- a/mm/madvise.c +++ b/mm/madvise.c @@ -1267,12 +1267,22 @@ SYSCALL_DEFINE5(process_madvise, int, pidfd, goto release_task; } - mm = mm_access(task, PTRACE_MODE_ATTACH_FSCREDS); + /* Require PTRACE_MODE_READ to avoid leaking ASLR metadata. */ + mm = mm_access(task, PTRACE_MODE_READ_FSCREDS); if (IS_ERR_OR_NULL(mm)) { ret = IS_ERR(mm) ? PTR_ERR(mm) : -ESRCH; goto release_task; } + /* + * Require CAP_SYS_NICE for influencing process performance. Note that + * only non-destructive hints are currently supported. + */ + if (!capable(CAP_SYS_NICE)) { + ret = -EPERM; + goto release_mm; + } + ret = import_iovec(READ, vec, vlen, ARRAY_SIZE(iovstack), &iov, &iter); if (ret >= 0) { size_t total_len = iov_iter_count(&iter); @@ -1282,6 +1292,8 @@ SYSCALL_DEFINE5(process_madvise, int, pidfd, ret = total_len - iov_iter_count(&iter); kfree(iov); } + +release_mm: mmput(mm); release_task: put_task_struct(task); From f6795b4ad6bb42a4ae20ac3428ec5c10dab6b09c Mon Sep 17 00:00:00 2001 From: Jilai Wang Date: Thu, 22 Jun 2023 11:41:21 -0400 Subject: [PATCH 660/698] msm: npu: Fix use after free issue There is possibility that network will be used after free. This change is to fix this issue. Mot-CRs-fixed: (CR) CVE-Fixed: CVE-2023-33114 CRs-Fixed: 3520999 Change-Id: I25eaf33f2a641127f13ec20df5da29d2b2923828 Signed-off-by: Jilai Wang Sigend-off-by: Ashutosh Verma Reviewed-on: https://gerrit.mot.com/2760383 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- drivers/media/platform/msm/npu/npu_mgr.c | 15 +++++++++++++++ drivers/media/platform/msm/npu/npu_mgr.h | 1 + 2 files changed, 16 insertions(+) diff --git a/drivers/media/platform/msm/npu/npu_mgr.c b/drivers/media/platform/msm/npu/npu_mgr.c index f36aff27ccc5..e000242354dc 100644 --- a/drivers/media/platform/msm/npu/npu_mgr.c +++ b/drivers/media/platform/msm/npu/npu_mgr.c @@ -1641,6 +1641,13 @@ int32_t npu_host_unload_network(struct npu_client *client, return -EINVAL; } + if (network->is_unloading) { + NPU_ERR("network is unloading\n"); + network_put(network); + mutex_unlock(&host_ctx->lock); + return -EINVAL; + } + if (!network->is_active) { pr_err("network is not active\n"); network_put(network); @@ -1653,6 +1660,8 @@ int32_t npu_host_unload_network(struct npu_client *client, goto free_network; } + network->is_unloading = true; + pr_debug("Unload network %lld\n", network->id); /* prepare IPC packet for UNLOAD */ unload_packet.header.cmd_type = NPU_IPC_CMD_UNLOAD; @@ -1755,6 +1764,12 @@ int32_t npu_host_exec_network(struct npu_client *client, if (atomic_inc_return(&host_ctx->network_execute_cnt) == 1) npu_notify_cdsprm_cxlimit_activity(npu_dev, true); + if (network->is_unloading) { + NPU_ERR("network is unloading\n"); + ret = -EINVAL; + goto exec_v2_done; + } + if (!network->is_active) { pr_err("network is not active\n"); ret = -EINVAL; diff --git a/drivers/media/platform/msm/npu/npu_mgr.h b/drivers/media/platform/msm/npu/npu_mgr.h index f0ab23267787..8845ed2696df 100644 --- a/drivers/media/platform/msm/npu/npu_mgr.h +++ b/drivers/media/platform/msm/npu/npu_mgr.h @@ -52,6 +52,7 @@ struct npu_network { atomic_t ref_cnt; bool is_valid; bool is_active; + bool is_unloading; bool fw_error; bool cmd_pending; bool cmd_async; From 32ac22edb42b8770b9af16ff4862881e7bc6f47b Mon Sep 17 00:00:00 2001 From: Praveen koya Date: Tue, 20 Jul 2021 15:39:21 +0530 Subject: [PATCH 661/698] slatecom: add rpmsg glink support for slatecom_interface Add rpmsg support for slatecom interface driver to send msm state transition commands to slate. Add Opcodes to be received on slate-ctrl channel from hal. Send TWM_ENTER, DEEP SLEEP ENTER & EXIT to slate. Mot-CRs-fixed: (CR) CVE-Fixed: CVE-2023-33085 CRs-Fixed: 3512209 Change-Id: Ic29b116da7b90e1a1d71a14b970a2a53b1b3c20f Signed-off-by: Praveen koya Signed-off-by: Ashutosh Verma Reviewed-on: https://gerrit.mot.com/2762749 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- drivers/soc/qcom/Kconfig | 9 ++ drivers/soc/qcom/Makefile | 1 + drivers/soc/qcom/slatecom_interface.c | 117 +++++++++++++++++++++++- drivers/soc/qcom/slatecom_interface.h | 74 +++++++++++++++ drivers/soc/qcom/slatecom_rpmsg.c | 101 ++++++++++++++++++++ drivers/soc/qcom/slatecom_rpmsg.h | 31 +++++++ include/uapi/linux/slatecom_interface.h | 13 +++ 7 files changed, 345 insertions(+), 1 deletion(-) create mode 100644 drivers/soc/qcom/slatecom_rpmsg.c create mode 100644 drivers/soc/qcom/slatecom_rpmsg.h diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index 524a5cdf8a94..7f2f34b3c008 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -1483,6 +1483,15 @@ config MSM_SLATECOM_INTERFACE from hardware. Hardware will provide access to read registers and read/write AHB memory in the device. +config MSM_SLATECOM_RPMSG + tristate "Provide support for slate GLINK channel" + depends on MSM_SLATECOM_INTERFACE + help + MSM_SLATECOM_RPMSG informs SLATECOM_INTERFACE driver if GLINK channel + has been opened by remote processor. It doesn't maintain state machine + and is probed when Slate opens channel and removed when the channel is + closed by remote processor. + config QCOM_AOP_SET_DDR tristate "Sysfs to communicate with AOP using QMP protocol" help diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile index 6bd8d4a71359..7faed000a678 100644 --- a/drivers/soc/qcom/Makefile +++ b/drivers/soc/qcom/Makefile @@ -119,6 +119,7 @@ obj-$(CONFIG_RENAME_BLOCK_DEVICE) += rename_block_device.o obj-$(CONFIG_QCOM_ADSP_MANUAL_VOTE) += adsp_vote_qmi.o adsp_lpm_voting_v01.o obj-$(CONFIG_MSM_SLATECOM) += slatecom_spi.o obj-$(CONFIG_MSM_SLATECOM_INTERFACE) += slatecom_interface.o +obj-$(CONFIG_MSM_SLATECOM_RPMSG) += slatecom_rpmsg.o obj-$(CONFIG_QCOM_AOP_SET_DDR) += aop-set-ddr.o obj-$(CONFIG_CPU_V7) += idle-v7.o obj-$(CONFIG_DUMP_XBL_LOG) += dump_boot_log.o diff --git a/drivers/soc/qcom/slatecom_interface.c b/drivers/soc/qcom/slatecom_interface.c index 36bf60355d8a..9517cd8c877a 100644 --- a/drivers/soc/qcom/slatecom_interface.c +++ b/drivers/soc/qcom/slatecom_interface.c @@ -31,7 +31,7 @@ #include "peripheral-loader.h" #include "../../misc/qseecom_kernel.h" -//#include "pil_slate_intf.h" +#include "slatecom_rpmsg.h" #define SLATECOM "slate_com_dev" @@ -95,7 +95,14 @@ struct slatedaemon_priv { unsigned long attrs; u32 cmd_status; struct device *platform_dev; + bool slatecom_rpmsg; + bool slate_resp_cmplt; + void *lhndl; + wait_queue_head_t link_state_wait; + char rx_buf[20]; + struct mutex glink_mutex; }; +static void *slatecom_intf_drv; struct slate_event { enum slate_event_type e_type; @@ -182,6 +189,104 @@ static int send_uevent(struct slate_event *pce) return kobject_uevent_env(&dev_ret->kobj, KOBJ_CHANGE, envp); } +void slatecom_intf_notify_glink_channel_state(bool state) +{ + struct slatedaemon_priv *dev = + container_of(slatecom_intf_drv, struct slatedaemon_priv, lhndl); + + pr_debug("%s: slate_ctrl channel state: %d\n", __func__, state); + dev->slatecom_rpmsg = state; +} +EXPORT_SYMBOL(slatecom_intf_notify_glink_channel_state); + +void slatecom_rx_msg(void *data, int len) +{ + struct slatedaemon_priv *dev = + container_of(slatecom_intf_drv, struct slatedaemon_priv, lhndl); + + dev->slate_resp_cmplt = true; + wake_up(&dev->link_state_wait); + memcpy(dev->rx_buf, data, len); +} +EXPORT_SYMBOL(slatecom_rx_msg); + +static int slatecom_tx_msg(struct slatedaemon_priv *dev, void *msg, size_t len) +{ + int rc = 0; + uint8_t resp = 0; + + mutex_lock(&dev->glink_mutex); + if (!dev->slatecom_rpmsg) { + pr_err("slatecom-rpmsg is not probed yet, waiting for it to be probed\n"); + goto err_ret; + } + rc = slatecom_rpmsg_tx_msg(msg, len); + + /* wait for sending command to SLATE */ + rc = wait_event_timeout(dev->link_state_wait, + (rc == 0), msecs_to_jiffies(TIMEOUT_MS)); + if (rc == 0) { + pr_err("failed to send command to SLATE %d\n", rc); + goto err_ret; + } + + /* wait for getting response from SLATE */ + rc = wait_event_timeout(dev->link_state_wait, + dev->slate_resp_cmplt, + msecs_to_jiffies(TIMEOUT_MS)); + if (rc == 0) { + pr_err("failed to get SLATE response %d\n", rc); + goto err_ret; + } + dev->slate_resp_cmplt = false; + /* check SLATE response */ + resp = *(uint8_t *)dev->rx_buf; + if (!(resp == 0x01)) { + pr_err("Bad SLATE response\n"); + rc = -EINVAL; + goto err_ret; + } + rc = 0; + +err_ret: + mutex_unlock(&dev->glink_mutex); + return rc; +} + +/** + * send_state_change_cmd send state transition event to Slate + * and wait for the response. + * The response is returned to the caller. + */ +static int send_state_change_cmd(struct slate_ui_data *ui_obj_msg) +{ + int ret = 0; + struct wear_header wear_header_t = {0, 0}; + struct slatedaemon_priv *dev = container_of(slatecom_intf_drv, + struct slatedaemon_priv, + lhndl); + uint32_t state = ui_obj_msg->cmd; + + switch (state) { + case STATE_TWM_ENTER: + wear_header_t.opcode = GMI_WEAR_MGR_ENTER_TWM; + break; + case STATE_DS_ENTER: + wear_header_t.opcode = GMI_WEAR_MGR_ENTER_TRACKER_DS; + break; + case STATE_DS_EXIT: + wear_header_t.opcode = GMI_WEAR_MGR_EXIT_TRACKER_DS; + break; + default: + pr_err("Invalid MSM State transtion cmd\n"); + break; + } + ret = slatecom_tx_msg(dev, &wear_header_t.opcode, sizeof(wear_header_t.opcode)); + if (ret < 0) + pr_err("MSM State transtion event cmd failed\n"); + return ret; +} + static int slatecom_char_open(struct inode *inode, struct file *file) { int ret; @@ -382,6 +487,16 @@ static long slate_com_ioctl(struct file *filp, } ret = 0; break; + case DEVICE_STATE_TRANSITION: + if (copy_from_user(&ui_obj_msg, (void __user *)arg, + sizeof(ui_obj_msg))) { + pr_err("The copy from user failed for state transition cmd\n"); + ret = -EFAULT; + } + ret = send_state_change_cmd(&ui_obj_msg); + if (ret < 0) + pr_err("device state transition cmd failed\n"); + break; default: ret = -ENOIOCTLCMD; break; diff --git a/drivers/soc/qcom/slatecom_interface.h b/drivers/soc/qcom/slatecom_interface.h index a64777a3b12f..9fa010771415 100644 --- a/drivers/soc/qcom/slatecom_interface.h +++ b/drivers/soc/qcom/slatecom_interface.h @@ -36,6 +36,80 @@ void set_slate_dsp_state(bool status); * Set slate bt state */ void set_slate_bt_state(bool status); +void slatecom_intf_notify_glink_channel_state(bool state); +void slatecom_rx_msg(void *data, int len); +/* + * WM header type - generic header structure + */ +struct wear_header { + uint32_t opcode; + uint32_t payload_size; +}; + +/** + * Opcodes to be received on slate-control channel. + */ +enum WMSlateCtrlChnlOpcode { + /* + * Command to slate to enter TWM mode + */ + GMI_WEAR_MGR_ENTER_TWM = 1, + + /* + * Notification to slate about Modem Processor Sub System + * is down due to a subsystem reset. + */ + GMI_WEAR_MGR_SSR_MPSS_DOWN_NOTIFICATION = 2, + + /* + * Notification to slate about Modem Processor Sub System + * being brought up after a subsystem reset. + */ + GMI_WEAR_MGR_SSR_MPSS_UP_NOTIFICATION = 3, + + /* + * Notification to slate about ADSP Sub System + * is down due to a subsystem reset. + */ + GMI_WEAR_MGR_SSR_ADSP_DOWN_INDICATION = 8, + + /* + * Notification to slate about Modem Processor + * Sub System being brought up after a subsystem reset. + */ + GMI_WEAR_MGR_SSR_ADSP_UP_INDICATION = 9, + + /* + * Notification to MSM for generic wakeup in tracker mode + */ + GMI_WEAR_MGR_WAKE_UP_NO_REASON = 10, + + /* + * Notification to Slate About Entry to Tracker-DS + */ + GMI_WEAR_MGR_ENTER_TRACKER_DS = 11, + + /* + * Notification to Slate About Entry to Tracker-DS + */ + GMI_WEAR_MGR_EXIT_TRACKER_DS = 12, + + /* + * Notification to Slate About Time-sync update + */ + GMI_WEAR_MGR_TIME_SYNC_UPDATE = 13, /* payload struct: wear_time_sync_t*/ + + /* + * Notification to Slate About Timeval UTC + */ + GMI_WEAR_MGR_TIMEVAL_UTC = 14, /* payload struct: wear_timeval_utc_t*/ + + /* + * Notification to Slate About Daylight saving time + */ + GMI_WEAR_MGR_DST = 15, /* payload struct: wear_dst_t*/ + +}; #endif /* SLATECOM_INTERFACE_H */ diff --git a/drivers/soc/qcom/slatecom_rpmsg.c b/drivers/soc/qcom/slatecom_rpmsg.c new file mode 100644 index 000000000000..919be0338bde --- /dev/null +++ b/drivers/soc/qcom/slatecom_rpmsg.c @@ -0,0 +1,101 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2021, The Linux Foundation. All rights reserved. + */ +#include +#include +#include +#include +#include "slatecom_rpmsg.h" + +static struct slatecom_rpmsg_dev *pdev; + +int slatecom_rpmsg_tx_msg(void *msg, size_t len) +{ + int ret = 0; + + if (pdev == NULL || !pdev->chnl_state) + pr_err("pmsg_device is null, channel is closed\n"); + + pdev->message = msg; + pdev->message_length = len; + if (pdev->message) { + ret = rpmsg_send(pdev->channel, pdev->message, pdev->message_length); + if (ret) + pr_err("rpmsg_send failed: %d\n", ret); + + } + return ret; +} +EXPORT_SYMBOL(slatecom_rpmsg_tx_msg); + +static int slatecom_rpmsg_probe(struct rpmsg_device *rpdev) +{ + int ret = 0; + void *msg = NULL; + + pdev = devm_kzalloc(&rpdev->dev, sizeof(*pdev), GFP_KERNEL); + if (!pdev) + return -ENOMEM; + + pdev->channel = rpdev->ept; + pdev->dev = &rpdev->dev; + if (pdev->channel == NULL) + return -ENOMEM; + + pdev->chnl_state = true; + dev_set_drvdata(&rpdev->dev, pdev); + + /* send a callback to slatecom-interface driver*/ + slatecom_intf_notify_glink_channel_state(true); + if (pdev->message == NULL) + ret = slatecom_rpmsg_tx_msg(msg, 0); + return 0; +} + +static void slatecom_rpmsg_remove(struct rpmsg_device *rpdev) +{ + pdev->chnl_state = false; + pdev->message = NULL; + dev_dbg(&rpdev->dev, "rpmsg client driver is removed\n"); + slatecom_intf_notify_glink_channel_state(false); + dev_set_drvdata(&rpdev->dev, NULL); +} + +static int slatecom_rpmsg_cb(struct rpmsg_device *rpdev, + void *data, int len, void *priv, u32 src) +{ + struct slatecom_rpmsg_dev *dev = + dev_get_drvdata(&rpdev->dev); + + if (!dev) + return -ENODEV; + slatecom_rx_msg(data, len); + return 0; +} + +static const struct rpmsg_device_id rpmsg_driver_slatecom_id_table[] = { + { "SLATECOM_CTRL" }, + {}, +}; +MODULE_DEVICE_TABLE(rpmsg, rpmsg_driver_slatecom_id_table); + +static const struct of_device_id rpmsg_driver_slatecom_of_match[] = { + { .compatible = "qcom,slatecom-rpmsg" }, + {}, +}; + +static struct rpmsg_driver rpmsg_slatecom_client = { + .id_table = rpmsg_driver_slatecom_id_table, + .probe = slatecom_rpmsg_probe, + .callback = slatecom_rpmsg_cb, + .remove = slatecom_rpmsg_remove, + .drv = { + .name = "qcom,slatecom_rpmsg", + .of_match_table = rpmsg_driver_slatecom_of_match, + }, +}; +module_rpmsg_driver(rpmsg_slatecom_client); + +MODULE_DESCRIPTION("Interface Driver for SLATECOM and RPMSG"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/soc/qcom/slatecom_rpmsg.h b/drivers/soc/qcom/slatecom_rpmsg.h new file mode 100644 index 000000000000..1d80bb0511dc --- /dev/null +++ b/drivers/soc/qcom/slatecom_rpmsg.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2021, The Linux Foundation. All rights reserved. + */ +#ifndef SLATECOMRPMSG_H +#define SLATECOMRPMSG_H + +#include +#include "slatecom_interface.h" + +#define TIMEOUT_MS 2000 + +struct slatecom_rpmsg_dev { + struct rpmsg_endpoint *channel; + struct device *dev; + bool chnl_state; + void *message; + size_t message_length; +}; + + +#if IS_ENABLED(CONFIG_MSM_SLATECOM_RPMSG) +int slatecom_rpmsg_tx_msg(void *msg, size_t len); +#else +static inline int slatecom_rpmsg_tx_msg(void *msg, size_t len) +{ + return -EIO; +} +#endif + +#endif diff --git a/include/uapi/linux/slatecom_interface.h b/include/uapi/linux/slatecom_interface.h index 6f58ef8057e6..d41af0e47178 100644 --- a/include/uapi/linux/slatecom_interface.h +++ b/include/uapi/linux/slatecom_interface.h @@ -20,6 +20,7 @@ #define SLATECOM_ADSP_DOWN2_SLATE 10 #define SLATECOM_SLATE_WEAR_LOAD 11 #define SLATECOM_SLATE_WEAR_UNLOAD 12 +#define SLATECOM_DEVICE_STATE_TRANSITION 13 #define EXCHANGE_CODE 'V' struct slate_ui_data { @@ -47,6 +48,15 @@ enum slate_event_type { SLATE_BT_READY, }; +enum device_state_transition { + STATE_TWM_ENTER = 1, + STATE_TWM_EXIT, + STATE_DS_ENTER, + STATE_DS_EXIT, + STATE_S2D_ENTER, + STATE_S2D_EXIT, +}; + #define REG_READ \ _IOWR(EXCHANGE_CODE, SLATECOM_REG_READ, \ struct slate_ui_data) @@ -86,6 +96,9 @@ enum slate_event_type { #define SLATE_ADSP_DOWN2_SLATE_DONE \ _IOWR(EXCHANGE_CODE, SLATECOM_ADSP_DOWN2_SLATE, \ struct slate_ui_data) +#define DEVICE_STATE_TRANSITION \ + _IOWR(EXCHANGE_CODE, SLATECOM_DEVICE_STATE_TRANSITION, \ + struct slate_ui_data) #endif /* LINUX_SLATECOM_INTERFACE_H */ From dd3f8fe03f7861ca9ac97bcd36761cbb33a57038 Mon Sep 17 00:00:00 2001 From: Praveen koya Date: Tue, 30 May 2023 14:47:21 +0530 Subject: [PATCH 662/698] soc: qcom: add buffer overflow check on AON rx_buffer Add buffer overflow check while accessing data buffer received from AON Mot-CRs-fixed: (CR) CVE-Fixed: CVE-2023-33085 CRs-Fixed: 3512209 Change-Id: I0472a0ad1e6edc3fe8102850fddacd89ceea4959 Signed-off-by: Praveen koya Signed-off-by: Ashutosh Verma Reviewed-on: https://gerrit.mot.com/2762750 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- drivers/soc/qcom/slatecom_interface.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/soc/qcom/slatecom_interface.c b/drivers/soc/qcom/slatecom_interface.c index 9517cd8c877a..0001b31dbe21 100644 --- a/drivers/soc/qcom/slatecom_interface.c +++ b/drivers/soc/qcom/slatecom_interface.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved. */ #define pr_fmt(msg) "slatecom_dev:" msg @@ -44,6 +45,7 @@ #define MPPS_DOWN_EVENT_TO_SLATE_TIMEOUT 3000 #define ADSP_DOWN_EVENT_TO_SLATE_TIMEOUT 3000 #define MAX_APP_NAME_SIZE 100 +#define SCOM_GLINK_INTENT_SIZE 308 /*pil_slate_intf.h*/ #define RESULT_SUCCESS 0 @@ -99,7 +101,7 @@ struct slatedaemon_priv { bool slate_resp_cmplt; void *lhndl; wait_queue_head_t link_state_wait; - char rx_buf[20]; + char rx_buf[SCOM_GLINK_INTENT_SIZE]; struct mutex glink_mutex; }; static void *slatecom_intf_drv; @@ -204,6 +206,10 @@ void slatecom_rx_msg(void *data, int len) struct slatedaemon_priv *dev = container_of(slatecom_intf_drv, struct slatedaemon_priv, lhndl); + if (len > SCOM_GLINK_INTENT_SIZE) { + pr_err("Invalid slatecom_intf glink intent size\n"); + return; + } dev->slate_resp_cmplt = true; wake_up(&dev->link_state_wait); memcpy(dev->rx_buf, data, len); From 27abaa391d327014e0a6163d09ebb1e1d9b7735a Mon Sep 17 00:00:00 2001 From: Johannes Weiner Date: Thu, 6 Aug 2020 23:22:15 -0700 Subject: [PATCH 663/698] mm: memcontrol: don't count limit-setting reclaim as memory pressure Mot-CRs-fixed: (CR) When an outside process lowers one of the memory limits of a cgroup (or uses the force_empty knob in cgroup1), direct reclaim is performed in the context of the write(), in order to directly enforce the new limit and have it being met by the time the write() returns. Currently, this reclaim activity is accounted as memory pressure in the cgroup that the writer(!) belongs to. This is unexpected. It specifically causes problems for senpai (https://github.com/facebookincubator/senpai), which is an agent that routinely adjusts the memory limits and performs associated reclaim work in tens or even hundreds of cgroups running on the host. The cgroup that senpai is running in itself will report elevated levels of memory pressure, even though it itself is under no memory shortage or any sort of distress. Move the psi annotation from the central cgroup reclaim function to callsites in the allocation context, and thereby no longer count any limit-setting reclaim as memory pressure. If the newly set limit causes the workload inside the cgroup into direct reclaim, that of course will continue to count as memory pressure. Signed-off-by: Johannes Weiner Signed-off-by: Andrew Morton Reviewed-by: Shakeel Butt Reviewed-by: Roman Gushchin Acked-by: Chris Down Acked-by: Michal Hocko Link: http://lkml.kernel.org/r/20200728135210.379885-2-hannes@cmpxchg.org Signed-off-by: Linus Torvalds Change-Id: I49bbfc4c462e1e42264558566ab495e695d9e00d Reviewed-on: https://gerrit.mot.com/2771207 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Yonghui Jia Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- mm/memcontrol.c | 10 +++++++++- mm/vmscan.c | 3 --- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 78b18ce5a4fd..1a2fa8c95410 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -2362,10 +2362,15 @@ static void reclaim_high(struct mem_cgroup *memcg, gfp_t gfp_mask) { do { + unsigned long pflags; if (page_counter_read(&memcg->memory) <= memcg->high) continue; + memcg_memory_event(memcg, MEMCG_HIGH); + + psi_memstall_enter(&pflags); try_to_free_mem_cgroup_pages(memcg, nr_pages, gfp_mask, true); + psi_memstall_leave(&pflags); } while ((memcg = parent_mem_cgroup(memcg))); } @@ -2552,9 +2557,10 @@ static int try_charge(struct mem_cgroup *memcg, gfp_t gfp_mask, struct mem_cgroup *mem_over_limit; struct page_counter *counter; unsigned long nr_reclaimed; + enum oom_status oom_status; bool may_swap = true; bool drained = false; - enum oom_status oom_status; + unsigned long pflags; if (mem_cgroup_is_root(memcg)) return 0; @@ -2614,8 +2620,10 @@ retry: memcg_memory_event(mem_over_limit, MEMCG_MAX); + psi_memstall_enter(&pflags); nr_reclaimed = try_to_free_mem_cgroup_pages(mem_over_limit, nr_pages, gfp_mask, may_swap); + psi_memstall_leave(&pflags); if (mem_cgroup_margin(mem_over_limit) >= nr_pages) goto retry; diff --git a/mm/vmscan.c b/mm/vmscan.c index 2f34fc523b20..37775dacd9dc 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -3450,7 +3450,6 @@ unsigned long try_to_free_mem_cgroup_pages(struct mem_cgroup *memcg, { struct zonelist *zonelist; unsigned long nr_reclaimed; - unsigned long pflags; int nid; unsigned int noreclaim_flag; struct scan_control sc = { @@ -3477,13 +3476,11 @@ unsigned long try_to_free_mem_cgroup_pages(struct mem_cgroup *memcg, trace_mm_vmscan_memcg_reclaim_begin(0, sc.gfp_mask); - psi_memstall_enter(&pflags); noreclaim_flag = memalloc_noreclaim_save(); nr_reclaimed = do_try_to_free_pages(zonelist, &sc); memalloc_noreclaim_restore(noreclaim_flag); - psi_memstall_leave(&pflags); trace_mm_vmscan_memcg_reclaim_end(nr_reclaimed); set_task_reclaim_state(current, NULL); From 2d00f1c06ffe13424846b359a60ba29f8e0d967b Mon Sep 17 00:00:00 2001 From: zhanggc10 Date: Fri, 20 Oct 2023 11:08:40 +0800 Subject: [PATCH 664/698] fogo: Fix secure mode switch error (1/2) Detail: For secure camera case, sometime switch secure mode fail,so add retry logic to fix it Change-Id: Ie3185979ef6bc5c86ac45067ffd83c23a9e507c7 Signed-off-by: zhanggc10 Reviewed-on: https://gerrit.mot.com/2772999 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Reviewed-by: Reviewed-by: Bolei Shang Reviewed-by: Reviewed-by: Long Cheng Reviewed-by: Reviewed-by: Zhichao Chen Reviewed-by: Guobin Zhang Submit-Approved: Jira Key --- arch/arm64/Kconfig | 6 ++++++ arch/arm64/configs/vendor/ext_config/moto-holi-fogo.config | 1 + 2 files changed, 7 insertions(+) diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index fd5991f6ce74..6796c2f08a44 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -1958,6 +1958,12 @@ config MOT_SENSOR_PRE_POWERUP help Enable it to power up and initialise early. +config MOT_SECURE_CAMERA + bool "For switch secure mode successfully" + default n + help + Enable it to fix switch secure mode error. + config MOT_USB_DEBUG_LOG bool "For usb debug log in factiry SW" default n diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-fogo.config b/arch/arm64/configs/vendor/ext_config/moto-holi-fogo.config index 3ffe6b43c919..0710193ab5c6 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-fogo.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-fogo.config @@ -47,3 +47,4 @@ CONFIG_EROFS_FS_PCPU_KTHREAD=y CONFIG_EROFS_FS_PCPU_KTHREAD_HIPRI=y CONFIG_MOT_SENSOR_PRE_POWERUP=y CONFIG_MMAP_READAROUND_LIMIT=y +CONFIG_MOT_SECURE_CAMERA=y \ No newline at end of file From b14cb56415ca514eb7c0c081eed6540b4fe80948 Mon Sep 17 00:00:00 2001 From: zhanggc10 Date: Fri, 20 Oct 2023 17:44:34 +0800 Subject: [PATCH 665/698] fogos: Fix secure mode switch error Detail: For secure camera case, sometime switch secure mode fail,so add retry logic to fix it Follow (CR) Change-Id: I86ba4c8b8812801bde2b64a9778c40e613849c96 Signed-off-by: zhanggc10 Reviewed-on: https://gerrit.mot.com/2773381 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Reviewed-by: Reviewed-by: Bolei Shang Reviewed-by: Reviewed-by: Long Cheng Reviewed-by: Reviewed-by: Zhichao Chen Reviewed-by: Guobin Zhang Submit-Approved: Jira Key --- arch/arm64/configs/vendor/ext_config/moto-holi-fogos.config | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/vendor/ext_config/moto-holi-fogos.config b/arch/arm64/configs/vendor/ext_config/moto-holi-fogos.config index 13a09239a9c1..9eaafd22de67 100644 --- a/arch/arm64/configs/vendor/ext_config/moto-holi-fogos.config +++ b/arch/arm64/configs/vendor/ext_config/moto-holi-fogos.config @@ -43,3 +43,4 @@ CONFIG_EROFS_FS_PCPU_KTHREAD=y CONFIG_EROFS_FS_PCPU_KTHREAD_HIPRI=y CONFIG_MMAP_READAROUND_LIMIT=y CONFIG_MOT_SENSOR_PRE_POWERUP=y +CONFIG_MOT_SECURE_CAMERA=y \ No newline at end of file From 117cca314f04c3ff35853e86baa6f9e0adebe465 Mon Sep 17 00:00:00 2001 From: zhu chuanchun Date: Mon, 23 Oct 2023 15:22:18 +0800 Subject: [PATCH 666/698] ufs: enable Micron HID feature. On previous projects, Micron use Samsung driver to fulfill the TW, HPB and HID features, so could use CONFIG_MICRON_HPB to check if the Micron chip of one project support TW, HPB and HID. However, we have use original WB to instead of Samsung TW, and disable HPB also. Now, Micron use Samsung HID driver only, we need add Micron HID config to enable Samsung feature init, or Micron HID funcion will not active. Change-Id: Ie75bd535e4b56e7d359f3b8687fa30405ade6358 Reviewed-on: https://gerrit.mot.com/2774267 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Zonghua Liu Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- drivers/scsi/ufs/ufshcd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 7b1ed7744336..39a687a8a063 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -243,7 +243,7 @@ static inline int is_support_hpb_100_device(unsigned int mfrid){ #endif #if defined(CONFIG_UFSFEATURE) static inline int is_support_hpb_200_device(unsigned int mfrid){ -#if defined(CONFIG_MICRON_HPB) +#if defined(CONFIG_MICRON_HPB) || defined(CONFIG_MICRON_UFSHID) return (IS_SAMSUNG_DEVICE(mfrid) || IS_MICRON_DEVICE(mfrid)); #else return IS_SAMSUNG_DEVICE(mfrid); From 2a0f6e2bf42a9989ade2f74fddd52af53069a4f8 Mon Sep 17 00:00:00 2001 From: Guocheng Wang Date: Tue, 24 Oct 2023 15:14:52 +0800 Subject: [PATCH 667/698] charge: Fix OCP charger icl more then 1A in COM When using OCP charger in charge only mode,the input current limit is 2A. But the expected icl is 1A. In smblib_apsd_results: [OCP] = { .name = "OCP", .bit = OCP_CHARGER_BIT, .val = POWER_SUPPLY_TYPE_USB_DCP } So the OCP charger power supply type is USB_DCP. And in func update_sw_icl_max,it will using "vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, true, rp_ua);" to set the usb_icl to be 2A. So we need to recheck the OCP_CHARGER_BIT and reset usb_icl to OCP_CURRENT_UA (1A). Change-Id: Ifd4ccceb91c227c12e5f4b628606f2de166155af Signed-off-by: Guocheng Wang Reviewed-on: https://gerrit.mot.com/2775176 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Haijian Ma Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- drivers/power/supply/qcom/smb5-lib.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/power/supply/qcom/smb5-lib.c b/drivers/power/supply/qcom/smb5-lib.c index 3c6c2e2bfd07..bc5c4f28e8da 100644 --- a/drivers/power/supply/qcom/smb5-lib.c +++ b/drivers/power/supply/qcom/smb5-lib.c @@ -6156,6 +6156,7 @@ static void update_sw_icl_max(struct smb_charger *chg, int val) { int typec_mode; int rp_ua; + const struct apsd_result *apsd = NULL; /* while PD is active it should have complete ICL control */ if (chg->pd_active) @@ -6198,8 +6199,14 @@ static void update_sw_icl_max(struct smb_charger *chg, int val) vote(chg->usb_icl_votable, USB_PSY_VOTER, false, 0); break; case POWER_SUPPLY_TYPE_USB_DCP: - rp_ua = get_rp_based_dcp_current(chg, typec_mode); - vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, true, rp_ua); + apsd = smblib_get_apsd_result(chg); + if (apsd->bit == OCP_CHARGER_BIT) { + vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, true, + OCP_CURRENT_UA); + } else { + rp_ua = get_rp_based_dcp_current(chg, typec_mode); + vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, true, rp_ua); + } vote(chg->usb_icl_votable, USB_PSY_VOTER, false, 0); break; case QTI_POWER_SUPPLY_TYPE_USB_FLOAT: From 106bde7f454e358ab70631d9a3d7d974b7d3fb06 Mon Sep 17 00:00:00 2001 From: wuwl10 Date: Thu, 26 Oct 2023 14:32:28 +0800 Subject: [PATCH 668/698] fogo: vibrator: increase the Vreg_Ready timeout Increase the timeout from 1ms to 2ms to fix the issue to vibrator LDO enable fail issue. Change-Id: I7a71d1bc46c103149fdce7ccf42f658ef445720f Signed-off-by: wuwl10 Reviewed-on: https://gerrit.mot.com/2777439 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Wanlong Zhou Reviewed-by: Hujun Liao Submit-Approved: Jira Key --- drivers/leds/leds-qpnp-vibrator-ldo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/leds/leds-qpnp-vibrator-ldo.c b/drivers/leds/leds-qpnp-vibrator-ldo.c index 59d391aeb551..373c150e2f48 100644 --- a/drivers/leds/leds-qpnp-vibrator-ldo.c +++ b/drivers/leds/leds-qpnp-vibrator-ldo.c @@ -67,7 +67,7 @@ static inline int qpnp_vib_ldo_poll_status(struct vib_ldo_chip *chip) ret = regmap_read_poll_timeout(chip->regmap, chip->base + QPNP_VIB_LDO_REG_STATUS1, val, - val & QPNP_VIB_LDO_VREG_READY, 100, 1000); + val & QPNP_VIB_LDO_VREG_READY, 100, 2000); if (ret < 0) { pr_err("Vibrator LDO vreg_ready timeout, status=0x%02x, ret=%d\n", val, ret); From ae805cb0adbb7fe08ae9e1e0865a464693d95ce3 Mon Sep 17 00:00:00 2001 From: yangcj Date: Fri, 10 Mar 2023 15:47:49 +0800 Subject: [PATCH 669/698] mmc: fix sdcard nullpoint exception port from: (CR) Symptom: host->card is null when call mmc_sd_suspend. Root Cause: the another process call mmc_remove_card,then host->card = NULL Solution: add host->card check when it used. Test result: The SD card functions normally Change-Id: Id3312d5be7403457a864e5ddc628fd4e6da0b459 Reviewed-on: https://gerrit.mot.com/2535590 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Ying Shen Reviewed-by: Zonghua Liu Reviewed-by: Qiong Xie Submit-Approved: Jira Key Reviewed-on: https://gerrit.mot.com/2808715 Reviewed-by: Zhenghai Pan Reviewed-by: Huosheng Liao --- drivers/mmc/core/sd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index 9607ff927ea4..5c5bc269916a 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -1289,7 +1289,7 @@ static int mmc_sd_suspend(struct mmc_host *host) int err; err = _mmc_sd_suspend(host); - if (!err) { + if (!err && host->card) { pm_runtime_disable(&host->card->dev); pm_runtime_set_suspended(&host->card->dev); } From 8d0e729e1c96ed584cc6387f05df7fb90d8de59b Mon Sep 17 00:00:00 2001 From: Johannes Weiner Date: Mon, 3 May 2021 13:49:17 -0400 Subject: [PATCH 670/698] psi: Fix psi state corruption when schedule() races with cgroup move 4117cebf1a9f ("psi: Optimize task switch inside shared cgroups") introduced a race condition that corrupts internal psi state. This manifests as kernel warnings, sometimes followed by bogusly high IO pressure: psi: task underflow! cpu=1 t=2 tasks=[0 0 0 0] clear=c set=0 (schedule() decreasing RUNNING and ONCPU, both of which are 0) psi: incosistent task state! task=2412744:systemd cpu=17 psi_flags=e clear=3 set=0 (cgroup_move_task() clearing MEMSTALL and IOWAIT, but task is MEMSTALL | RUNNING | ONCPU) What the offending commit does is batch the two psi callbacks in schedule() to reduce the number of cgroup tree updates. When prev is deactivated and removed from the runqueue, nothing is done in psi at first; when the task switch completes, TSK_RUNNING and TSK_IOWAIT are updated along with TSK_ONCPU. However, the deactivation and the task switch inside schedule() aren't atomic: pick_next_task() may drop the rq lock for load balancing. When this happens, cgroup_move_task() can run after the task has been physically dequeued, but the psi updates are still pending. Since it looks at the task's scheduler state, it doesn't move everything to the new cgroup that the task switch that follows is about to clear from it. cgroup_move_task() will leak the TSK_RUNNING count in the old cgroup, and psi_sched_switch() will underflow it in the new cgroup. A similar thing can happen for iowait. TSK_IOWAIT is usually set when a p->in_iowait task is dequeued, but again this update is deferred to the switch. cgroup_move_task() can see an unqueued p->in_iowait task and move a non-existent TSK_IOWAIT. This results in the inconsistent task state warning, as well as a counter underflow that will result in permanent IO ghost pressure being reported. Fix this bug by making cgroup_move_task() use task->psi_flags instead of looking at the potentially mismatching scheduler state. [ We used the scheduler state historically in order to not rely on task->psi_flags for anything but debugging. But that ship has sailed anyway, and this is simpler and more robust. We previously already batched TSK_ONCPU clearing with the TSK_RUNNING update inside the deactivation call from schedule(). But that ordering was safe and didn't result in TSK_ONCPU corruption: unl(CR) most places in the scheduler, cgroup_move_task() only checked task_current() and handled TSK_ONCPU if the task was still queued. ] Fixes: 4117cebf1a9f ("psi: Optimize task switch inside shared cgroups") Signed-off-by: Johannes Weiner Signed-off-by: Peter Zijlstra (Intel) Link: https://lkml.kernel.org/r/20210503174917.38579-1-hannes@cmpxchg.org Change-Id: I83fc22d7ecb515896a526892f40066353a6dadd0 Mot-CRs-fixed: (CR) Reviewed-on: https://gerrit.mot.com/2408024 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key Reviewed-on: https://gerrit.mot.com/2817400 Reviewed-by: Hongshu Lou Reviewed-by: Huosheng Liao --- kernel/sched/psi.c | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/kernel/sched/psi.c b/kernel/sched/psi.c index bf8bc1b2bb19..4c060fb2b4cb 100644 --- a/kernel/sched/psi.c +++ b/kernel/sched/psi.c @@ -946,7 +946,7 @@ void psi_cgroup_free(struct cgroup *cgroup) */ void cgroup_move_task(struct task_struct *task, struct css_set *to) { - unsigned int task_flags = 0; + unsigned int task_flags; struct rq_flags rf; struct rq *rq; @@ -961,13 +961,31 @@ void cgroup_move_task(struct task_struct *task, struct css_set *to) rq = task_rq_lock(task, &rf); - if (task_on_rq_queued(task)) - task_flags = TSK_RUNNING; - else if (task->in_iowait) - task_flags = TSK_IOWAIT; - - if (task->flags & PF_MEMSTALL) - task_flags |= TSK_MEMSTALL; + /* + * We may race with schedule() dropping the rq lock between + * deactivating prev and switching to next. Because the psi + * updates from the deactivation are deferred to the switch + * callback to save cgroup tree updates, the task's scheduling + * state here is not coherent with its psi state: + * + * schedule() cgroup_move_task() + * rq_lock() + * deactivate_task() + * p->on_rq = 0 + * psi_dequeue() // defers TSK_RUNNING & TSK_IOWAIT updates + * pick_next_task() + * rq_unlock() + * rq_lock() + * psi_task_change() // old cgroup + * task->cgroups = to + * psi_task_change() // new cgroup + * rq_unlock() + * rq_lock() + * psi_sched_switch() // does deferred updates in new cgroup + * + * Don't rely on the scheduling state. Use psi_flags instead. + */ + task_flags = task->psi_flags; if (task_flags) psi_task_change(task, task_flags, 0); From 8608c07035059640eb52038de1c1c910b0dbf95d Mon Sep 17 00:00:00 2001 From: Haijian Ma Date: Fri, 15 Dec 2023 17:48:05 +0800 Subject: [PATCH 671/698] add CDP max current config interface add CDP max current config interface for product config Change-Id: I31dc81b67c46dc747163ceaa71bf61e8250b6385 Signed-off-by: Haijian Ma Reviewed-on: https://gerrit.mot.com/2826519 Reviewed-by: Huosheng Liao SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Submit-Approved: Jira Key --- drivers/power/supply/qcom/qpnp-smb5.c | 6 ++++++ drivers/power/supply/qcom/smb5-lib.c | 2 +- drivers/power/supply/qcom/smb5-lib.h | 1 + 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/power/supply/qcom/qpnp-smb5.c b/drivers/power/supply/qcom/qpnp-smb5.c index 824952c76a1c..d50f82d5b8fc 100644 --- a/drivers/power/supply/qcom/qpnp-smb5.c +++ b/drivers/power/supply/qcom/qpnp-smb5.c @@ -805,6 +805,12 @@ static int smb5_parse_dt_mmi(struct smb5 *chip, struct device_node *node) chg->usb_dcp_curr_max = 0; np = of_find_node_by_path("/chosen"); + retval = of_property_read_u32(npoint, "qcom,cdp-curr-max", + &chg->usb_cdp_curr_max); + if (retval) { + chg->usb_cdp_curr_max = 1500000; + } + retval = of_property_read_u32(npoint, "qcom,dcp-curr-max", &chg->usb_dcp_curr_max); if (retval) { diff --git a/drivers/power/supply/qcom/smb5-lib.c b/drivers/power/supply/qcom/smb5-lib.c index bc5c4f28e8da..e236b761be31 100644 --- a/drivers/power/supply/qcom/smb5-lib.c +++ b/drivers/power/supply/qcom/smb5-lib.c @@ -6195,7 +6195,7 @@ static void update_sw_icl_max(struct smb_charger *chg, int val) break; case POWER_SUPPLY_TYPE_USB_CDP: vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, true, - CDP_CURRENT_UA); + (chg->usb_cdp_curr_max > 0) ? chg->usb_cdp_curr_max : CDP_CURRENT_UA); vote(chg->usb_icl_votable, USB_PSY_VOTER, false, 0); break; case POWER_SUPPLY_TYPE_USB_DCP: diff --git a/drivers/power/supply/qcom/smb5-lib.h b/drivers/power/supply/qcom/smb5-lib.h index d2375b05853a..6618d8b6fb73 100644 --- a/drivers/power/supply/qcom/smb5-lib.h +++ b/drivers/power/supply/qcom/smb5-lib.h @@ -633,6 +633,7 @@ struct smb_charger { ktime_t dcin_uv_last_time; int last_wls_vout; int usb_dcp_curr_max; + int usb_cdp_curr_max; /* mmi qc3p */ struct iio_channel **iio_chan_list_mmi_cp; From 87a7aa0e83bf7d49c3fa260bc825e310d04ba192 Mon Sep 17 00:00:00 2001 From: DEEPAK SANNAPAREDDY Date: Wed, 4 Oct 2023 14:53:03 +0530 Subject: [PATCH 672/698] msm: adsprpc : Fix use after free in fastrpc_internal_mem_unmap Thread 1 can make a to call fastrpc_mmap_create under internal mem map and release fl->map_mutex. Thread 2 can make call to internal mem unmap, acquire fl->map_mutex and get same map though fastrpc_mmap_remove. Thread 1 fail in fastrpc_mem_map_to_dsp jumps to bail and do map free. Thread 2 still holds same map which can lead use after free. Serialize fastrpc internal mem map and unmap. Mot-CRs-fixed: (CR) CVE-Fixed: CVE-2023-43514 CRs-Fixed: 3613254 Bug: 303101664 Change-Id: I54a3602914b43fc67635c0de193bd21aa13daaa3 Signed-off-by: DEEPAK SANNAPAREDDY Signed-off-by: Ashutosh Verma Reviewed-on: https://gerrit.mot.com/2832044 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Chakradhar Gajjala Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- drivers/char/adsprpc.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c index 8e7b4eff7325..9268f39cb328 100644 --- a/drivers/char/adsprpc.c +++ b/drivers/char/adsprpc.c @@ -4959,6 +4959,7 @@ static int fastrpc_internal_mem_map(struct fastrpc_file *fl, int err = 0; struct fastrpc_mmap *map = NULL; + mutex_lock(&fl->internal_map_mutex); VERIFY(err, fl->dsp_proc_init == 1); if (err) { pr_err("adsprpc: ERROR: %s: user application %s trying to map without initialization\n", @@ -4997,6 +4998,7 @@ bail: mutex_unlock(&fl->map_mutex); } } + mutex_unlock(&fl->internal_map_mutex); return err; } @@ -5006,6 +5008,7 @@ static int fastrpc_internal_mem_unmap(struct fastrpc_file *fl, int err = 0; struct fastrpc_mmap *map = NULL; + mutex_lock(&fl->internal_map_mutex); VERIFY(err, fl->dsp_proc_init == 1); if (err) { pr_err("adsprpc: ERROR: %s: user application %s trying to map without initialization\n", @@ -5051,6 +5054,7 @@ bail: mutex_unlock(&fl->map_mutex); } } + mutex_unlock(&fl->internal_map_mutex); return err; } From c17f8768101315c5c88e7092386d39fb2915295b Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 28 May 2024 11:43:53 +0000 Subject: [PATCH 673/698] BACKPORT: net: fix __dst_negative_advice() race __dst_negative_advice() does not enforce proper RCU rules when sk->dst_cache must be cleared, leading to possible UAF. RCU rules are that we must first clear sk->sk_dst_cache, then call dst_release(old_dst). Note that sk_dst_reset(sk) is implementing this protocol correctly, while __dst_negative_advice() uses the wrong order. Given that ip6_negative_advice() has special logic against RTF_CACHE, this means each of the three ->negative_advice() existing methods must perform the sk_dst_reset() themselves. Note the check against NULL dst is centralized in __dst_negative_advice(), there is no need to duplicate it in various callbacks. Many thanks to Clement Lecigne for tracking this issue. This old bug became visible after the blamed commit, using UDP sockets. Mot-CRs-fixed: (CR) Bug: 343727534 Fixes: a87cb3e48ee8 ("net: Facility to report route quality of connected sockets") Reported-by: Clement Lecigne Diagnosed-by: Clement Lecigne Signed-off-by: Eric Dumazet Cc: Tom Herbert Reviewed-by: David Ahern Link: https://lore.kernel.org/r/20240528114353.1794151-1-edumazet@google.com Signed-off-by: Jakub Kicinski (cherry picked from commit 92f1655aa2b2294d0b49925f3b875a634bd3b59e) [Lee: Trivial/unrelated conflict - no change to the patch] Signed-off-by: Lee Jones Change-Id: I293734dca1b81fcb712e1de294f51e96a405f7e4 Signed-off-by: Greg Kroah-Hartman Reviewed-on: https://gerrit.mot.com/2996680 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Zhihong Kang Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- include/net/dst_ops.h | 2 +- include/net/sock.h | 13 +++---------- net/ipv4/route.c | 22 ++++++++-------------- net/ipv6/route.c | 29 +++++++++++++++-------------- net/xfrm/xfrm_policy.c | 11 +++-------- 5 files changed, 30 insertions(+), 47 deletions(-) diff --git a/include/net/dst_ops.h b/include/net/dst_ops.h index 443863c7b8da..b93799fe46e8 100644 --- a/include/net/dst_ops.h +++ b/include/net/dst_ops.h @@ -24,7 +24,7 @@ struct dst_ops { void (*destroy)(struct dst_entry *); void (*ifdown)(struct dst_entry *, struct net_device *dev, int how); - struct dst_entry * (*negative_advice)(struct dst_entry *); + void (*negative_advice)(struct sock *sk, struct dst_entry *); void (*link_failure)(struct sk_buff *); void (*update_pmtu)(struct dst_entry *dst, struct sock *sk, struct sk_buff *skb, u32 mtu, diff --git a/include/net/sock.h b/include/net/sock.h index 125b16200ca4..f37ddce89483 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -1936,19 +1936,12 @@ sk_dst_get(struct sock *sk) static inline void dst_negative_advice(struct sock *sk) { - struct dst_entry *ndst, *dst = __sk_dst_get(sk); + struct dst_entry *dst = __sk_dst_get(sk); sk_rethink_txhash(sk); - if (dst && dst->ops->negative_advice) { - ndst = dst->ops->negative_advice(dst); - - if (ndst != dst) { - rcu_assign_pointer(sk->sk_dst_cache, ndst); - sk_tx_queue_clear(sk); - sk->sk_dst_pending_confirm = 0; - } - } + if (dst && dst->ops->negative_advice) + dst->ops->negative_advice(sk, dst); } static inline void diff --git a/net/ipv4/route.c b/net/ipv4/route.c index f82d456afd0e..3a876eacb07d 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -137,7 +137,8 @@ static int ip_rt_gc_timeout __read_mostly = RT_GC_TIMEOUT; static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie); static unsigned int ipv4_default_advmss(const struct dst_entry *dst); static unsigned int ipv4_mtu(const struct dst_entry *dst); -static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst); +static void ipv4_negative_advice(struct sock *sk, + struct dst_entry *dst); static void ipv4_link_failure(struct sk_buff *skb); static void ip_rt_update_pmtu(struct dst_entry *dst, struct sock *sk, struct sk_buff *skb, u32 mtu, @@ -856,22 +857,15 @@ static void ip_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_buf __ip_do_redirect(rt, skb, &fl4, true); } -static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst) +static void ipv4_negative_advice(struct sock *sk, + struct dst_entry *dst) { struct rtable *rt = (struct rtable *)dst; - struct dst_entry *ret = dst; - if (rt) { - if (dst->obsolete > 0) { - ip_rt_put(rt); - ret = NULL; - } else if ((rt->rt_flags & RTCF_REDIRECTED) || - rt->dst.expires) { - ip_rt_put(rt); - ret = NULL; - } - } - return ret; + if ((dst->obsolete > 0) || + (rt->rt_flags & RTCF_REDIRECTED) || + rt->dst.expires) + sk_dst_reset(sk); } /* diff --git a/net/ipv6/route.c b/net/ipv6/route.c index defd581ae9d6..3731d74e2b28 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -84,7 +84,8 @@ enum rt6_nud_state { static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie); static unsigned int ip6_default_advmss(const struct dst_entry *dst); static unsigned int ip6_mtu(const struct dst_entry *dst); -static struct dst_entry *ip6_negative_advice(struct dst_entry *); +static void ip6_negative_advice(struct sock *sk, + struct dst_entry *dst); static void ip6_dst_destroy(struct dst_entry *); static void ip6_dst_ifdown(struct dst_entry *, struct net_device *dev, int how); @@ -2658,24 +2659,24 @@ static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie) return dst_ret; } -static struct dst_entry *ip6_negative_advice(struct dst_entry *dst) +static void ip6_negative_advice(struct sock *sk, + struct dst_entry *dst) { struct rt6_info *rt = (struct rt6_info *) dst; - if (rt) { - if (rt->rt6i_flags & RTF_CACHE) { - rcu_read_lock(); - if (rt6_check_expired(rt)) { - rt6_remove_exception_rt(rt); - dst = NULL; - } - rcu_read_unlock(); - } else { - dst_release(dst); - dst = NULL; + if (rt->rt6i_flags & RTF_CACHE) { + rcu_read_lock(); + if (rt6_check_expired(rt)) { + /* counteract the dst_release() in sk_dst_reset() */ + dst_hold(dst); + sk_dst_reset(sk); + + rt6_remove_exception_rt(rt); } + rcu_read_unlock(); + return; } - return dst; + sk_dst_reset(sk); } static void ip6_link_failure(struct sk_buff *skb) diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 8632776ae4da..cbf9387b1650 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -3778,15 +3778,10 @@ static void xfrm_link_failure(struct sk_buff *skb) /* Impossible. Such dst must be popped before reaches point of failure. */ } -static struct dst_entry *xfrm_negative_advice(struct dst_entry *dst) +static void xfrm_negative_advice(struct sock *sk, struct dst_entry *dst) { - if (dst) { - if (dst->obsolete) { - dst_release(dst); - dst = NULL; - } - } - return dst; + if (dst->obsolete) + sk_dst_reset(sk); } static void xfrm_init_pmtu(struct xfrm_dst **bundle, int nr) From ec1b288e67aa590ff69f547172f3110e430d20d2 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 1 Jun 2024 09:33:51 +0000 Subject: [PATCH 674/698] ANDROID: ABI fixup for abi break in struct dst_ops In commit 92f1655aa2b2 ("net: fix __dst_negative_advice() race") the struct dst_ops callback negative_advice is callback changes function parameters. But as this pointer is part of a structure that is tracked in the ABI checker, the tool triggers when this is changed. However, the callback pointer is internal to the networking stack, so changing the function type is safe, so needing to preserve this is not required. To do so, switch the function pointer type back to the old one so that the checking tools pass, AND then do a hard cast of the function pointer to the new type when assigning and calling the function. Mot-CRs-fixed: (CR) Bug: 343727534 Fixes: 92f1655aa2b2 ("net: fix __dst_negative_advice() race") Change-Id: I48d4ab4bbd29f8edc8fbd7923828b7f78a23e12e Signed-off-by: Greg Kroah-Hartman Reviewed-on: https://gerrit.mot.com/2996719 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Zhihong Kang Reviewed-by: Huosheng Liao Submit-Approved: Jira Key --- include/net/dst_ops.h | 12 +++++++++++- include/net/sock.h | 12 ++++++++++-- net/ipv4/route.c | 2 +- net/ipv6/route.c | 2 +- net/xfrm/xfrm_policy.c | 2 +- 5 files changed, 24 insertions(+), 6 deletions(-) diff --git a/include/net/dst_ops.h b/include/net/dst_ops.h index b93799fe46e8..337479ab1356 100644 --- a/include/net/dst_ops.h +++ b/include/net/dst_ops.h @@ -12,6 +12,16 @@ struct sk_buff; struct sock; struct net; +/* *** ANDROID FIXUP *** + * These typedefs are used to help fixup the ABI break caused by commit + * 92f1655aa2b2 ("net: fix __dst_negative_advice() race") where the + * negative_advice callback changed function signatures. + * See b/343727534 for more details. + * *** ANDROID FIXUP *** + */ +typedef void (*android_dst_ops_negative_advice_new_t)(struct sock *sk, struct dst_entry *); +typedef struct dst_entry * (*android_dst_ops_negative_advice_old_t)(struct dst_entry *); + struct dst_ops { unsigned short family; unsigned int gc_thresh; @@ -24,7 +34,7 @@ struct dst_ops { void (*destroy)(struct dst_entry *); void (*ifdown)(struct dst_entry *, struct net_device *dev, int how); - void (*negative_advice)(struct sock *sk, struct dst_entry *); + struct dst_entry * (*negative_advice)(struct dst_entry *); void (*link_failure)(struct sk_buff *); void (*update_pmtu)(struct dst_entry *dst, struct sock *sk, struct sk_buff *skb, u32 mtu, diff --git a/include/net/sock.h b/include/net/sock.h index f37ddce89483..b84ebc1ad206 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -1936,12 +1936,20 @@ sk_dst_get(struct sock *sk) static inline void dst_negative_advice(struct sock *sk) { + /* *** ANDROID FIXUP *** + * See b/343727534 for more details why this typedef is needed here. + * *** ANDROID FIXUP *** + */ + android_dst_ops_negative_advice_new_t negative_advice; + struct dst_entry *dst = __sk_dst_get(sk); sk_rethink_txhash(sk); - if (dst && dst->ops->negative_advice) - dst->ops->negative_advice(sk, dst); + if (dst && dst->ops->negative_advice) { + negative_advice = (android_dst_ops_negative_advice_new_t)dst->ops->negative_advice; + negative_advice(sk, dst); + } } static inline void diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 3a876eacb07d..55448b6329c8 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -165,7 +165,7 @@ static struct dst_ops ipv4_dst_ops = { .mtu = ipv4_mtu, .cow_metrics = ipv4_cow_metrics, .destroy = ipv4_dst_destroy, - .negative_advice = ipv4_negative_advice, + .negative_advice = (android_dst_ops_negative_advice_old_t)ipv4_negative_advice, .link_failure = ipv4_link_failure, .update_pmtu = ip_rt_update_pmtu, .redirect = ip_do_redirect, diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 3731d74e2b28..c2c2fd7def03 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -250,7 +250,7 @@ static struct dst_ops ip6_dst_ops_template = { .cow_metrics = dst_cow_metrics_generic, .destroy = ip6_dst_destroy, .ifdown = ip6_dst_ifdown, - .negative_advice = ip6_negative_advice, + .negative_advice = (android_dst_ops_negative_advice_old_t)ip6_negative_advice, .link_failure = ip6_link_failure, .update_pmtu = ip6_rt_update_pmtu, .redirect = rt6_do_redirect, diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index cbf9387b1650..0fe167dca7c2 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -3949,7 +3949,7 @@ int xfrm_policy_register_afinfo(const struct xfrm_policy_afinfo *afinfo, int fam if (likely(dst_ops->mtu == NULL)) dst_ops->mtu = xfrm_mtu; if (likely(dst_ops->negative_advice == NULL)) - dst_ops->negative_advice = xfrm_negative_advice; + dst_ops->negative_advice = (android_dst_ops_negative_advice_old_t)xfrm_negative_advice; if (likely(dst_ops->link_failure == NULL)) dst_ops->link_failure = xfrm_link_failure; if (likely(dst_ops->neigh_lookup == NULL)) From 782c247b2377d6e8371741d21af04f980a16230a Mon Sep 17 00:00:00 2001 From: Carlos Llamas Date: Sat, 30 Mar 2024 19:01:14 +0000 Subject: [PATCH 675/698] FROMLIST: binder: check offset alignment in binder_get_object() Commit 6d98eb95b450 ("binder: avoid potential data leakage when copying txn") introduced changes to how binder objects are copied. In doing so, it unintentionally removed an offset alignment check done through calls to binder_alloc_copy_from_buffer() -> check_buffer(). These calls were replaced in binder_get_object() with copy_from_user(), so now an explicit offset alignment check is needed here. This avoids later complications when unwinding the objects gets harder. It is worth noting this check existed prior to commit 7a67a39320df ("binder: add function to copy binder object from buffer"), l(CR) removed due to redundancy at the time. Fixes: 6d98eb95b450 ("binder: avoid potential data leakage when copying txn") Cc: Acked-by: Todd Kjos Signed-off-by: Carlos Llamas Mot-CRs-fixed: (CR) CVE-Fixed: CVE-2024-26926 Bug: 320661088 Link: https://lore.kernel.org/all/20240330190115.1877819-1-cmllamas@google.com/ Change-Id: Iaddabaa28de7ba7b7d35dbb639d38ca79dbc5077 Signed-off-by: Carlos Llamas Signed-off-by: Ashutosh Verma Reviewed-on: https://gerrit.mot.com/2960965 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Chakradhar Gajjala Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- drivers/android/binder.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/android/binder.c b/drivers/android/binder.c index 77b06f304754..00f6de623ffe 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -1825,8 +1825,10 @@ static size_t binder_get_object(struct binder_proc *proc, size_t object_size = 0; read_size = min_t(size_t, sizeof(*object), buffer->data_size - offset); - if (offset > buffer->data_size || read_size < sizeof(*hdr)) + if (offset > buffer->data_size || read_size < sizeof(*hdr) || + !IS_ALIGNED(offset, sizeof(u32))) return 0; + if (u) { if (copy_from_user(object, u + offset, read_size)) return 0; From 9ef7c24511b39a841fae4fa064349dddb9214c83 Mon Sep 17 00:00:00 2001 From: Kuniyuki Iwashima Date: Tue, 23 Jan 2024 09:08:53 -0800 Subject: [PATCH 676/698] af_unix: Do not use atomic ops for unix_sk(sk)->inflight. [ Upstream commit 97af84a6bba2ab2b9c704c08e67de3b5ea551bb2 ] When touching unix_sk(sk)->inflight, we are always under spin_lock(&unix_gc_lock). Let's convert unix_sk(sk)->inflight to the normal unsigned long. Mot-CRs-fixed: (CR) CVE-Fixed: CVE-2024-26923 Bug: 336268889 Signed-off-by: Kuniyuki Iwashima Reviewed-by: Simon Horman Link: https://lore.kernel.org/r/20240123170856.41348-3-kuniyu@amazon.com Signed-off-by: Jakub Kicinski Stable-dep-of: 47d8ac011fe1 ("af_unix: Fix garbage collector racing against connect()") Signed-off-by: Sasha Levin Change-Id: I0cce0315d435a8f54400c30e4e59dca9271c147e Signed-off-by: Gajjala Chakradhar Reviewed-on: https://gerrit.mot.com/2992980 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key (cherry picked from commit d851483056e4ab05f5290b91f85272bdf50413c5) --- include/net/af_unix.h | 2 +- net/unix/af_unix.c | 4 ++-- net/unix/garbage.c | 17 ++++++++--------- net/unix/scm.c | 8 +++++--- 4 files changed, 16 insertions(+), 15 deletions(-) diff --git a/include/net/af_unix.h b/include/net/af_unix.h index 3426d6dacc45..1b3c59323002 100644 --- a/include/net/af_unix.h +++ b/include/net/af_unix.h @@ -58,7 +58,7 @@ struct unix_sock { struct mutex iolock, bindlock; struct sock *peer; struct list_head link; - atomic_long_t inflight; + unsigned long inflight; spinlock_t lock; unsigned long gc_flags; #define UNIX_GC_CANDIDATE 0 diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 304eb26b34dc..966856dbea88 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -809,11 +809,11 @@ static struct sock *unix_create1(struct net *net, struct socket *sock, int kern) sk->sk_write_space = unix_write_space; sk->sk_max_ack_backlog = net->unx.sysctl_max_dgram_qlen; sk->sk_destruct = unix_sock_destructor; - u = unix_sk(sk); + u = unix_sk(sk); + u->inflight = 0; u->path.dentry = NULL; u->path.mnt = NULL; spin_lock_init(&u->lock); - atomic_long_set(&u->inflight, 0); INIT_LIST_HEAD(&u->link); mutex_init(&u->iolock); /* single task reading lock */ mutex_init(&u->bindlock); /* single task binding lock */ diff --git a/net/unix/garbage.c b/net/unix/garbage.c index dc2763540393..312474c23e9a 100644 --- a/net/unix/garbage.c +++ b/net/unix/garbage.c @@ -166,17 +166,18 @@ static void scan_children(struct sock *x, void (*func)(struct unix_sock *), static void dec_inflight(struct unix_sock *usk) { - atomic_long_dec(&usk->inflight); + usk->inflight--; } static void inc_inflight(struct unix_sock *usk) { - atomic_long_inc(&usk->inflight); + usk->inflight++; } static void inc_inflight_move_tail(struct unix_sock *u) { - atomic_long_inc(&u->inflight); + u->inflight++; + /* If this still might be part of a cycle, move it to the end * of the list, so that it's checked even if it was already * passed over @@ -237,14 +238,12 @@ void unix_gc(void) */ list_for_each_entry_safe(u, next, &gc_inflight_list, link) { long total_refs; - long inflight_refs; total_refs = file_count(u->sk.sk_socket->file); - inflight_refs = atomic_long_read(&u->inflight); - BUG_ON(inflight_refs < 1); - BUG_ON(total_refs < inflight_refs); - if (total_refs == inflight_refs) { + BUG_ON(!u->inflight); + BUG_ON(total_refs < u->inflight); + if (total_refs == u->inflight) { list_move_tail(&u->link, &gc_candidates); __set_bit(UNIX_GC_CANDIDATE, &u->gc_flags); __set_bit(UNIX_GC_MAYBE_CYCLE, &u->gc_flags); @@ -271,7 +270,7 @@ void unix_gc(void) /* Move cursor to after the current position. */ list_move(&cursor, &u->link); - if (atomic_long_read(&u->inflight) > 0) { + if (u->inflight) { list_move_tail(&u->link, ¬_cycle_list); __clear_bit(UNIX_GC_MAYBE_CYCLE, &u->gc_flags); scan_children(&u->sk, inc_inflight_move_tail, NULL); diff --git a/net/unix/scm.c b/net/unix/scm.c index e881a6e78af5..ab2d664b7528 100644 --- a/net/unix/scm.c +++ b/net/unix/scm.c @@ -53,12 +53,13 @@ void unix_inflight(struct user_struct *user, struct file *fp) if (s) { struct unix_sock *u = unix_sk(s); - if (atomic_long_inc_return(&u->inflight) == 1) { + if (!u->inflight) { BUG_ON(!list_empty(&u->link)); list_add_tail(&u->link, &gc_inflight_list); } else { BUG_ON(list_empty(&u->link)); } + u->inflight++; /* Paired with READ_ONCE() in wait_for_unix_gc() */ WRITE_ONCE(unix_tot_inflight, unix_tot_inflight + 1); } @@ -75,10 +76,11 @@ void unix_notinflight(struct user_struct *user, struct file *fp) if (s) { struct unix_sock *u = unix_sk(s); - BUG_ON(!atomic_long_read(&u->inflight)); + BUG_ON(!u->inflight); BUG_ON(list_empty(&u->link)); - if (atomic_long_dec_and_test(&u->inflight)) + u->inflight--; + if (!u->inflight) list_del_init(&u->link); /* Paired with READ_ONCE() in wait_for_unix_gc() */ WRITE_ONCE(unix_tot_inflight, unix_tot_inflight - 1); From 6487f3d3468b5df030838ad7dc02d63ab99d81eb Mon Sep 17 00:00:00 2001 From: Michal Luczaj Date: Tue, 9 Apr 2024 22:09:39 +0200 Subject: [PATCH 677/698] af_unix: Fix garbage collector racing against connect() [ Upstream commit 47d8ac011fe1c9251070e1bd64cb10b48193ec51 ] Garbage collector does not take into account the risk of embryo getting enqueued during the garbage collection. If such embryo has a peer that carries SCM_RIGHTS, two consecutive passes of scan_children() may see a different set of children. Leading to an incorrectly elevated inflight count, and then a dangling pointer within the gc_inflight_list. sockets are AF_UNIX/SOCK_STREAM S is an unconnected socket L is a listening in-flight socket bound to addr, not in fdtable V's fd will be passed via sendmsg(), gets inflight count bumped connect(S, addr) sendmsg(S, [V]); close(V) __unix_gc() ---------------- ------------------------- ----------- NS = unix_create1() skb1 = sock_wmalloc(NS) L = unix_find_other(addr) unix_state_lock(L) unix_peer(S) = NS // V count=1 inflight=0 NS = unix_peer(S) skb2 = sock_alloc() skb_queue_tail(NS, skb2[V]) // V became in-flight // V count=2 inflight=1 close(V) // V count=1 inflight=1 // GC candidate condition met for u in gc_inflight_list: if (total_refs == inflight_refs) add u to gc_candidates // gc_candidates={L, V} for u in gc_candidates: scan_children(u, dec_inflight) // embryo (skb1) was not // reachable from L yet, so V's // inflight remains unchanged __skb_queue_tail(L, skb1) unix_state_unlock(L) for u in gc_candidates: if (u.inflight) scan_children(u, inc_inflight_move_tail) // V count=1 inflight=2 (!) If there is a GC-candidate listening socket, lock/unlock its state. This makes GC wait until the end of any ongoing connect() to that socket. After flipping the lock, a possibly SCM-laden embryo is already enqueued. And if there is another embryo coming, it can not possibly carry SCM_RIGHTS. At this point, unix_inflight() can not happen because unix_gc_lock is already taken. Inflight graph remains unaffected. Mot-CRs-fixed: (CR) CVE-Fixed: CVE-2024-26923 Bug: 336268889 Fixes: 1fd05ba5a2f2 ("[AF_UNIX]: Rewrite garbage collector, fixes race.") Signed-off-by: Michal Luczaj Reviewed-by: Kuniyuki Iwashima Link: https://lore.kernel.org/r/20240409201047.1032217-1-mhal@rbox.co Signed-off-by: Paolo Abeni Signed-off-by: Sasha Levin Change-Id: I26e0e5ef98139d739bccd6a33aa518376590a5d1 Signed-off-by: Gajjala Chakradhar Reviewed-on: https://gerrit.mot.com/2992981 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key (cherry picked from commit 8be8171b515b73fa028df2188d5f0a0ff1ff71ff) --- net/unix/garbage.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/net/unix/garbage.c b/net/unix/garbage.c index 312474c23e9a..67b2c3bfa113 100644 --- a/net/unix/garbage.c +++ b/net/unix/garbage.c @@ -235,11 +235,22 @@ void unix_gc(void) * receive queues. Other, non candidate sockets _can_ be * added to queue, so we must make sure only to touch * candidates. + * + * Embryos, though never candidates themselves, affect which + * candidates are reachable by the garbage collector. Before + * being added to a listener's queue, an embryo may already + * receive data carrying SCM_RIGHTS, potentially making the + * passed socket a candidate that is not yet reachable by the + * collector. It becomes reachable once the embryo is + * enqueued. Therefore, we must ensure that no SCM-laden + * embryo appears in a (candidate) listener's queue between + * consecutive scan_children() calls. */ list_for_each_entry_safe(u, next, &gc_inflight_list, link) { + struct sock *sk = &u->sk; long total_refs; - total_refs = file_count(u->sk.sk_socket->file); + total_refs = file_count(sk->sk_socket->file); BUG_ON(!u->inflight); BUG_ON(total_refs < u->inflight); @@ -247,6 +258,11 @@ void unix_gc(void) list_move_tail(&u->link, &gc_candidates); __set_bit(UNIX_GC_CANDIDATE, &u->gc_flags); __set_bit(UNIX_GC_MAYBE_CYCLE, &u->gc_flags); + + if (sk->sk_state == TCP_LISTEN) { + unix_state_lock(sk); + unix_state_unlock(sk); + } } } From bc3b7c1be57bbc33d9a87091b9f1a175bd47995b Mon Sep 17 00:00:00 2001 From: Mehul Raninga Date: Fri, 15 Mar 2024 10:24:28 +0530 Subject: [PATCH 678/698] slimbus: qcom-ngd-ctrl: Avoid accessing deallocated stack The functions qcom_slim_ngd_xfer_msg and qcom_slim_ngd_xfer_msg_sync declare a local completion variable called done. However, this variable is accessed beyond the scope of these functions. To address this issue: 1. Instead of keeping done as a local variable, move it to qcom_slim_ngd_ctrl. 2. Initialize done during the probe phase. 3. Use this variable for handling transfer and synchronization messages. Mot-CRs-fixed: (CR) CVE-Fixed: CVE-2024-33045 CRs-Fixed: 3745620 Change-Id: If97b71e2db730ab21bfd07479d2737b0546e1f8e Signed-off-by: Mehul Raninga Signed-off-by: Ashutosh Verma Reviewed-on: https://gerrit.mot.com/2991299 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Chakradhar Gajjala Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- drivers/slimbus/qcom-ngd-ctrl.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/drivers/slimbus/qcom-ngd-ctrl.c b/drivers/slimbus/qcom-ngd-ctrl.c index 09ecd1fb24ae..2244923532f2 100644 --- a/drivers/slimbus/qcom-ngd-ctrl.c +++ b/drivers/slimbus/qcom-ngd-ctrl.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 // Copyright (c) 2011-2017, The Linux Foundation. All rights reserved. // Copyright (c) 2018, Linaro Limited +// Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved. #include #include @@ -156,6 +157,8 @@ struct qcom_slim_ngd_ctrl { struct completion reconf; struct work_struct m_work; struct workqueue_struct *mwq; + struct completion xfer_done; + struct completion sync_done; spinlock_t tx_buf_lock; enum qcom_slim_ngd_state state; dma_addr_t rx_phys_base; @@ -768,7 +771,6 @@ static int qcom_slim_ngd_xfer_msg(struct slim_controller *sctrl, { struct qcom_slim_ngd_ctrl *ctrl = dev_get_drvdata(sctrl->dev); DECLARE_COMPLETION_ONSTACK(tx_sent); - DECLARE_COMPLETION_ONSTACK(done); int ret, timeout, i; u8 wbuf[SLIM_MSGQ_BUF_LEN]; u8 rbuf[SLIM_MSGQ_BUF_LEN]; @@ -777,6 +779,8 @@ static int qcom_slim_ngd_xfer_msg(struct slim_controller *sctrl, u8 la = txn->la; bool usr_msg = false; + reinit_completion(&ctrl->xfer_done); + if (txn->mt == SLIM_MSG_MT_CORE && (txn->mc >= SLIM_MSG_MC_BEGIN_RECONFIGURATION && txn->mc <= SLIM_MSG_MC_RECONFIGURE_NOW)) @@ -824,7 +828,7 @@ static int qcom_slim_ngd_xfer_msg(struct slim_controller *sctrl, if (txn->mc != SLIM_USR_MC_DISCONNECT_PORT) wbuf[i++] = txn->msg->wbuf[1]; - txn->comp = &done; + txn->comp = &ctrl->xfer_done; ret = slim_alloc_txn_tid(sctrl, txn); if (ret) { dev_err(ctrl->dev, "Unable to allocate TID\n"); @@ -876,7 +880,7 @@ static int qcom_slim_ngd_xfer_msg(struct slim_controller *sctrl, } if (usr_msg) { - timeout = wait_for_completion_timeout(&done, HZ); + timeout = wait_for_completion_timeout(&ctrl->xfer_done, HZ); if (!timeout) { dev_err(sctrl->dev, "TX timed out:MC:0x%x,mt:0x%x", txn->mc, txn->mt); @@ -890,18 +894,21 @@ static int qcom_slim_ngd_xfer_msg(struct slim_controller *sctrl, static int qcom_slim_ngd_xfer_msg_sync(struct slim_controller *ctrl, struct slim_msg_txn *txn) { - DECLARE_COMPLETION_ONSTACK(done); + struct qcom_slim_ngd_ctrl *dev = + container_of(ctrl, struct qcom_slim_ngd_ctrl, ctrl); int ret, timeout; + reinit_completion(&dev->sync_done); + pm_runtime_get_sync(ctrl->dev); - txn->comp = &done; + txn->comp = &dev->sync_done; ret = qcom_slim_ngd_xfer_msg(ctrl, txn); if (ret) return ret; - timeout = wait_for_completion_timeout(&done, HZ); + timeout = wait_for_completion_timeout(&dev->sync_done, HZ); if (!timeout) { dev_err(ctrl->dev, "TX timed out:MC:0x%x,mt:0x%x", txn->mc, txn->mt); @@ -1460,6 +1467,9 @@ static int qcom_slim_ngd_ctrl_probe(struct platform_device *pdev) init_completion(&ctrl->reconf); init_completion(&ctrl->qmi.qmi_comp); + init_completion(&ctrl->xfer_done); + init_completion(&ctrl->sync_done); + platform_driver_register(&qcom_slim_ngd_driver); return of_qcom_slim_ngd_register(dev, ctrl); } From 9556c1f5891990c38f219d64cbffca5099a9a615 Mon Sep 17 00:00:00 2001 From: Santosh Sakore Date: Mon, 27 May 2024 14:29:54 +0530 Subject: [PATCH 679/698] msm: adsprpc: use-after-free (UAF) in global maps Currently, remote heap maps get added to the global list before the fastrpc_internal_mmap function completes the mapping. Meanwhile, the fastrpc_internal_munmap function accesses the map, starts unmapping, and frees the map before the fastrpc_internal_mmap function completes, resulting in a use-after-free (UAF) issue. Add the map to the list after the fastrpc_internal_mmap function completes the mapping. Mot-CRs-fixed: (CR) CVE-Fixed: CVE-2024-33060 CRs-Fixed: 3735984 Bug: 350500584 Change-Id: Ia524f142edba57a1f389dd0e5c83a1967c7f5a59 Acked-by: Abhishek Singh Signed-off-by: Santosh Sakore (cherry picked from commit 6f9f631c909b217b1510e1b385ce341a08061d6e) Signed-off-by: Ashutosh Verma Reviewed-on: https://gerrit.mot.com/3032196 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Varun Shrivastava Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- drivers/char/adsprpc.c | 92 ++++++++++++++++++++---------------------- 1 file changed, 44 insertions(+), 48 deletions(-) diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c index 9268f39cb328..5debb2b4bc9c 100644 --- a/drivers/char/adsprpc.c +++ b/drivers/char/adsprpc.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2012-2021, The Linux Foundation. All rights reserved. - * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. */ /* Uncomment this block to log an error on every VERIFY failure */ @@ -1108,64 +1108,43 @@ static void fastrpc_remote_buf_list_free(struct fastrpc_file *fl) } while (free); } +static void fastrpc_mmap_add_global(struct fastrpc_mmap *map) +{ + struct fastrpc_apps *me = &gfa; + unsigned long irq_flags = 0; + + spin_lock_irqsave(&me->hlock, irq_flags); + hlist_add_head(&map->hn, &me->maps); + spin_unlock_irqrestore(&me->hlock, irq_flags); +} + static void fastrpc_mmap_add(struct fastrpc_mmap *map) { - if (map->flags == ADSP_MMAP_HEAP_ADDR || - map->flags == ADSP_MMAP_REMOTE_HEAP_ADDR) { - struct fastrpc_apps *me = &gfa; + struct fastrpc_file *fl = map->fl; - spin_lock(&me->hlock); - hlist_add_head(&map->hn, &me->maps); - spin_unlock(&me->hlock); - } else { - struct fastrpc_file *fl = map->fl; - - hlist_add_head(&map->hn, &fl->maps); - } + hlist_add_head(&map->hn, &fl->maps); } static int fastrpc_mmap_find(struct fastrpc_file *fl, int fd, uintptr_t va, size_t len, int mflags, int refs, struct fastrpc_mmap **ppmap) { - struct fastrpc_apps *me = &gfa; struct fastrpc_mmap *match = NULL, *map = NULL; struct hlist_node *n; if ((va + len) < va) return -EFAULT; - if (mflags == ADSP_MMAP_HEAP_ADDR || - mflags == ADSP_MMAP_REMOTE_HEAP_ADDR) { - spin_lock(&me->hlock); - hlist_for_each_entry_safe(map, n, &me->maps, hn) { - if (va >= map->va && - va + len <= map->va + map->len && - map->fd == fd) { - if (refs) { - if (map->refs + 1 == INT_MAX) { - spin_unlock(&me->hlock); - return -ETOOMANYREFS; - } - map->refs++; - } - match = map; - break; - } - } - spin_unlock(&me->hlock); - } else { - hlist_for_each_entry_safe(map, n, &fl->maps, hn) { - if (va >= map->va && - va + len <= map->va + map->len && - map->fd == fd) { - if (refs) { - if (map->refs + 1 == INT_MAX) - return -ETOOMANYREFS; - map->refs++; - } - match = map; - break; + hlist_for_each_entry_safe(map, n, &fl->maps, hn) { + if (va >= map->va && + va + len <= map->va + map->len && + map->fd == fd) { + if (refs) { + if (map->refs + 1 == INT_MAX) + return -ETOOMANYREFS; + map->refs++; } + match = map; + break; } } if (match) { @@ -1641,7 +1620,9 @@ static int fastrpc_mmap_create(struct fastrpc_file *fl, int fd, } map->len = len; - fastrpc_mmap_add(map); + if ((mflags != ADSP_MMAP_HEAP_ADDR) && + (mflags != ADSP_MMAP_REMOTE_HEAP_ADDR)) + fastrpc_mmap_add(map); *ppmap = map; bail: @@ -4039,6 +4020,7 @@ static int fastrpc_init_create_static_process(struct fastrpc_file *fl, spin_lock(&me->hlock); mem->in_use = true; spin_unlock(&me->hlock); + fastrpc_mmap_add_global(mem); } phys = mem->phys; size = mem->size; @@ -4772,7 +4754,7 @@ static int fastrpc_mmap_remove_ssr(struct fastrpc_file *fl) me->enable_ramdump = false; bail: if (err && match) - fastrpc_mmap_add(match); + fastrpc_mmap_add_global(match); return err; } @@ -4901,7 +4883,11 @@ static int fastrpc_internal_munmap(struct fastrpc_file *fl, bail: if (err && map) { mutex_lock(&fl->map_mutex); - fastrpc_mmap_add(map); + if ((map->flags == ADSP_MMAP_HEAP_ADDR) || + (map->flags == ADSP_MMAP_REMOTE_HEAP_ADDR)) + fastrpc_mmap_add_global(map); + else + fastrpc_mmap_add(map); mutex_unlock(&fl->map_mutex); } mutex_unlock(&fl->internal_map_mutex); @@ -4988,6 +4974,9 @@ static int fastrpc_internal_mem_map(struct fastrpc_file *fl, if (err) goto bail; ud->m.vaddrout = map->raddr; + if (ud->m.flags == ADSP_MMAP_HEAP_ADDR || + ud->m.flags == ADSP_MMAP_REMOTE_HEAP_ADDR) + fastrpc_mmap_add_global(map); bail: if (err) { pr_err("adsprpc: %s failed to map fd %d flags %d err %d\n", @@ -5050,7 +5039,11 @@ bail: /* Add back to map list in case of error to unmap on DSP */ if (map) { mutex_lock(&fl->map_mutex); - fastrpc_mmap_add(map); + if ((map->flags == ADSP_MMAP_HEAP_ADDR) || + (map->flags == ADSP_MMAP_REMOTE_HEAP_ADDR)) + fastrpc_mmap_add_global(map); + else + fastrpc_mmap_add(map); mutex_unlock(&fl->map_mutex); } } @@ -5119,6 +5112,9 @@ static int fastrpc_internal_mmap(struct fastrpc_file *fl, if (err) goto bail; map->raddr = raddr; + if (ud->flags == ADSP_MMAP_HEAP_ADDR || + ud->flags == ADSP_MMAP_REMOTE_HEAP_ADDR) + fastrpc_mmap_add_global(map); } ud->vaddrout = raddr; bail: From a63ba862ae29aee603fc93b30f32320c3e8f61a0 Mon Sep 17 00:00:00 2001 From: Sipra Patel Date: Thu, 19 Sep 2024 11:10:57 +0530 Subject: [PATCH 680/698] adsprpc: Handle UAF scenario in put_args Currently, the DSP updates header buffers with unused DMA handle fds. In the put_args section, if any DMA handle FDs are present in the header buffer, the corresponding map is freed. However, since the header buffer is exposed to users in unsigned PD, users can update invalid FDs. If this invalid FD matches with any FD that is already in use, it could lead to a use-after-free (UAF) vulnerability. As a solution,add DMA handle references for DMA FDs, and the map for the FD will be freed only when a reference is found. Acked-by: quic_anane Change-Id: I83ae12329003db14dae8d430ab74925f2a30947b Signed-off-by: Ansa Ahmed --- Mot-CRs-fixed: (CR) CVE- fixed: CVE-2024-21455 CRs Fixed: QC-CR#3875202 Signed-off-by: Sipra Patel Reviewed-on: https://gerrit.mot.com/3075244 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Varun Shrivastava Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- drivers/char/adsprpc.c | 71 +++++++++++++++++++++++++++++++----------- 1 file changed, 53 insertions(+), 18 deletions(-) diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c index 5debb2b4bc9c..4d97d3811f8a 100644 --- a/drivers/char/adsprpc.c +++ b/drivers/char/adsprpc.c @@ -584,6 +584,8 @@ struct fastrpc_mmap { struct timespec64 map_end_time; bool is_filemap; /* flag to indicate map used in process init */ unsigned int ctx_refs; /* Indicates reference count for context map */ + /* Map in use for dma handle */ + unsigned int dma_handle_refs; }; enum fastrpc_perfkeys { @@ -1213,9 +1215,14 @@ static int fastrpc_mmap_remove(struct fastrpc_file *fl, int fd, uintptr_t va, return 0; } hlist_for_each_entry_safe(map, n, &fl->maps, hn) { - /* Remove if only one reference map and no context map */ - if (map->refs == 1 && !map->ctx_refs && - map->raddr == va && map->raddr + map->len == va + len && + if ((fd < 0 || map->fd == fd) && + map->raddr == va && + map->raddr + map->len == va + len && + /* Remove if only one reference map and no context map */ + map->refs == 1 && + !map->ctx_refs && + /* Remove map only if it isn't being used by DSP */ + !map->dma_handle_refs && /* Remove map if not used in process initialization */ !map->is_filemap) { match = map; @@ -1254,8 +1261,9 @@ static void fastrpc_mmap_free(struct fastrpc_mmap *map, uint32_t flags) if (map->flags == ADSP_MMAP_HEAP_ADDR || map->flags == ADSP_MMAP_REMOTE_HEAP_ADDR) { spin_lock(&me->hlock); - map->refs--; - if (!map->refs && !map->is_persistent && !map->ctx_refs) + if (map->refs) + map->refs--; + if (!map->refs && !map->is_persistent) hlist_del_init(&map->hn); spin_unlock(&me->hlock); if (map->refs > 0) { @@ -1270,8 +1278,13 @@ static void fastrpc_mmap_free(struct fastrpc_mmap *map, uint32_t flags) spin_unlock(&me->hlock); } } else { - map->refs--; - if (!map->refs && !map->ctx_refs) + if (map->refs) + map->refs--; + /* flags is passed as 1 during fastrpc_file_free + * (ie process exit), so that maps will be cleared + * even though references are present. + */ + if (!map->refs && !map->ctx_refs && !map->dma_handle_refs) hlist_del_init(&map->hn); if (map->refs > 0 && !flags) return; @@ -2492,12 +2505,13 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx) FASTRPC_ATTR_NOVA, 0, 0, dmaflags, &ctx->maps[i]); if (!err && ctx->maps[i]) - ctx->maps[i]->ctx_refs++; + ctx->maps[i]->dma_handle_refs++; if (err) { for (j = bufs; j < i; j++) { - if (ctx->maps[j] && ctx->maps[j]->ctx_refs) - ctx->maps[j]->ctx_refs--; - fastrpc_mmap_free(ctx->maps[j], 0); + if (ctx->maps[j] && ctx->maps[j]->dma_handle_refs) { + ctx->maps[j]->dma_handle_refs--; + fastrpc_mmap_free(ctx->maps[j], 0); + } } mutex_unlock(&ctx->fl->map_mutex); goto bail; @@ -2635,13 +2649,33 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx) rpra[i].buf.pv = buf; } PERF_END); + /* Since we are not holidng map_mutex during get args whole time + * it is possible that dma handle map may be removed by some invalid + * fd passed by DSP. Inside the lock check if the map present or not + */ + mutex_lock(&ctx->fl->map_mutex); for (i = bufs; i < bufs + handles; ++i) { - struct fastrpc_mmap *map = ctx->maps[i]; - if (map) { - pages[i].addr = map->phys; - pages[i].size = map->size; + struct fastrpc_mmap *mmap = NULL; + /* check if map was created */ + if (ctx->maps[i]) { + /* check if map still exist */ + if (!fastrpc_mmap_find(ctx->fl, ctx->fds[i], 0, 0, + 0, 0, &mmap)) { + if (mmap) { + pages[i].addr = mmap->phys; + pages[i].size = mmap->size; + } + + } else { + /* map already freed by some other call */ + mutex_unlock(&ctx->fl->map_mutex); + ADSPRPC_ERR("could not find map associated with dma handle fd %d\n", + ctx->fds[i]); + goto bail; + } } } + mutex_unlock(&ctx->fl->map_mutex); fdlist = (uint64_t *)&pages[bufs + handles]; crclist = (uint32_t *)&fdlist[M_FDLIST]; /* reset fds, crc and early wakeup hint memory */ @@ -2842,9 +2876,10 @@ static int put_args(uint32_t kernel, struct smq_invoke_ctx *ctx, break; if (!fastrpc_mmap_find(ctx->fl, (int)fdlist[i], 0, 0, 0, 0, &mmap)) { - if (mmap && mmap->ctx_refs) - mmap->ctx_refs--; - fastrpc_mmap_free(mmap, 0); + if (mmap && mmap->dma_handle_refs) { + mmap->dma_handle_refs = 0; + fastrpc_mmap_free(mmap, 0); + } } } mutex_unlock(&ctx->fl->map_mutex); From 43c500e215a18f4d9741424e0c1502465df8bda4 Mon Sep 17 00:00:00 2001 From: ANANDU KRISHNAN E Date: Tue, 20 Aug 2024 17:21:05 +0530 Subject: [PATCH 681/698] msm: adsprpc: Avoid taking reference for group_info Currently, the get_current_groups API accesses group info, which increases the usage refcount. If the IOCTL using the get_current_groups API is called many times, the usage counter overflows. To avoid this, access group info without taking a reference. A reference is not required as group info is not released during the IOCTL call. Signed-off-by: ANANDU KRISHNAN E Mot-CRs-fixed: (CR) CVE- fixed: CVE-2024-38402 CRs Fixed: QC-CR#3890158 Signed-off-by: Sipra Patel Change-Id: I266f4dde0ff732f944589ecadc4b72d82a8024e2 Reviewed-on: https://gerrit.mot.com/3091032 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Varun Shrivastava Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- drivers/char/adsprpc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c index 4d97d3811f8a..c5c3d59c7709 100644 --- a/drivers/char/adsprpc.c +++ b/drivers/char/adsprpc.c @@ -5845,7 +5845,7 @@ static int fastrpc_device_open(struct inode *inode, struct file *filp) static int fastrpc_get_process_gids(struct gid_list *gidlist) { - struct group_info *group_info = get_current_groups(); + struct group_info *group_info = current_cred()->group_info; int i = 0, err = 0, num_gids = group_info->ngroups + 1; unsigned int *gids = NULL; From 848895a54d8cbbc1a0b94a9b551bd450d6e1ced3 Mon Sep 17 00:00:00 2001 From: Michael Bestas Date: Wed, 19 Mar 2025 07:22:36 +0200 Subject: [PATCH 682/698] Revert "UPSTREAM: erofs: fix an error code in z_erofs_init_zip_subsystem()" This reverts commit 45482ab6d38d38a3167e9b8bd48824cee7890263. Reason for revert: Conflicts with upstream commits. Change-Id: I9f82deafc00f195ed1064146511b0642eb4a08a4 --- fs/erofs/zdata.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/fs/erofs/zdata.c b/fs/erofs/zdata.c index f54710a05b4d..1bfda6b57a0d 100644 --- a/fs/erofs/zdata.c +++ b/fs/erofs/zdata.c @@ -260,10 +260,8 @@ int __init z_erofs_init_zip_subsystem(void) z_erofs_workqueue = alloc_workqueue("erofs_worker", WQ_UNBOUND | WQ_HIGHPRI, num_possible_cpus()); - if (!z_erofs_workqueue) { - err = -ENOMEM; + if (!z_erofs_workqueue) goto out_error_workqueue_init; - } err = erofs_init_percpu_workers(); if (err) From 944e8a32b997d7ce8d3cefbeacadf13a2c4cc3b3 Mon Sep 17 00:00:00 2001 From: Michael Bestas Date: Wed, 19 Mar 2025 07:22:43 +0200 Subject: [PATCH 683/698] Revert "BACKPORT:erofs: add per-cpu threads for decompression as an option" This reverts commit 8199049168939354150faeeed0bb2d788bebddb7. Reason for revert: Conflicts with upstream commits. Change-Id: Ifb8fc9271cea27ac8a9c282cd9a75329be06725d --- fs/erofs/Kconfig | 18 ----- fs/erofs/zdata.c | 190 +++++------------------------------------------ fs/erofs/zdata.h | 2 - 3 files changed, 19 insertions(+), 191 deletions(-) diff --git a/fs/erofs/Kconfig b/fs/erofs/Kconfig index 3adc06ad950a..858b3339f381 100644 --- a/fs/erofs/Kconfig +++ b/fs/erofs/Kconfig @@ -76,21 +76,3 @@ config EROFS_FS_ZIP If you don't want to enable compression feature, say N. - -config EROFS_FS_PCPU_KTHREAD - bool "EROFS per-cpu decompression kthread workers" - depends on EROFS_FS_ZIP - help - Saying Y here enables per-CPU kthread workers pool to carry out - async decompression for low latencies on some architectures. - - If unsure, say N. - -config EROFS_FS_PCPU_KTHREAD_HIPRI - bool "EROFS high priority per-CPU kthread workers" - depends on EROFS_FS_ZIP && EROFS_FS_PCPU_KTHREAD - help - This permits EROFS to configure per-CPU kthread workers to run - at higher priority. - - If unsure, say N. \ No newline at end of file diff --git a/fs/erofs/zdata.c b/fs/erofs/zdata.c index 1bfda6b57a0d..15e03d0f60a0 100644 --- a/fs/erofs/zdata.c +++ b/fs/erofs/zdata.c @@ -7,7 +7,7 @@ #include "zdata.h" #include "compress.h" #include -#include + #include /* @@ -125,161 +125,35 @@ typedef tagptr1_t compressed_page_t; static struct workqueue_struct *z_erofs_workqueue __read_mostly; -#ifdef CONFIG_EROFS_FS_PCPU_KTHREAD -static struct kthread_worker __rcu **z_erofs_pcpu_workers; - -static void erofs_destroy_percpu_workers(void) -{ - struct kthread_worker *worker; - unsigned int cpu; - - for_each_possible_cpu(cpu) { - worker = rcu_dereference_protected( - z_erofs_pcpu_workers[cpu], 1); - rcu_assign_pointer(z_erofs_pcpu_workers[cpu], NULL); - if (worker) - kthread_destroy_worker(worker); - } - kfree(z_erofs_pcpu_workers); -} - -static struct kthread_worker *erofs_init_percpu_worker(int cpu) -{ - - struct kthread_worker *worker = - kthread_create_worker_on_cpu(cpu, 0, "erofs_worker/%u", cpu); - - if (IS_ERR(worker)) - return worker; - if (IS_ENABLED(CONFIG_EROFS_FS_PCPU_KTHREAD_HIPRI)) - sched_set_fifo_low(worker->task); - else - sched_set_normal(worker->task, 0); - - return worker; -} - -static int erofs_init_percpu_workers(void) -{ - struct kthread_worker *worker; - unsigned int cpu; - - z_erofs_pcpu_workers = kcalloc(num_possible_cpus(), - sizeof(struct kthread_worker *), GFP_ATOMIC); - if (!z_erofs_pcpu_workers) - return -ENOMEM; - - for_each_online_cpu(cpu) { /* could miss cpu{off,on}line? */ - worker = erofs_init_percpu_worker(cpu); - if (!IS_ERR(worker)) - rcu_assign_pointer(z_erofs_pcpu_workers[cpu], worker); - } - return 0; -} -#else -static inline void erofs_destroy_percpu_workers(void) {} -static inline int erofs_init_percpu_workers(void) { return 0; } -#endif - -#if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_EROFS_FS_PCPU_KTHREAD) -static DEFINE_SPINLOCK(z_erofs_pcpu_worker_lock); -static enum cpuhp_state erofs_cpuhp_state; - -static int erofs_cpu_online(unsigned int cpu) -{ - struct kthread_worker *worker, *old; - - worker = erofs_init_percpu_worker(cpu); - if (IS_ERR(worker)) - return PTR_ERR(worker); - - spin_lock(&z_erofs_pcpu_worker_lock); - old = rcu_dereference_protected(z_erofs_pcpu_workers[cpu], - lockdep_is_held(&z_erofs_pcpu_worker_lock)); - if (!old) - rcu_assign_pointer(z_erofs_pcpu_workers[cpu], worker); - spin_unlock(&z_erofs_pcpu_worker_lock); - if (old) - kthread_destroy_worker(worker); - return 0; -} - -static int erofs_cpu_offline(unsigned int cpu) -{ - struct kthread_worker *worker; - - spin_lock(&z_erofs_pcpu_worker_lock); - worker = rcu_dereference_protected(z_erofs_pcpu_workers[cpu], - lockdep_is_held(&z_erofs_pcpu_worker_lock)); - rcu_assign_pointer(z_erofs_pcpu_workers[cpu], NULL); - spin_unlock(&z_erofs_pcpu_worker_lock); - - synchronize_rcu(); - if (worker) - kthread_destroy_worker(worker); - return 0; -} - -static int erofs_cpu_hotplug_init(void) -{ - int state; - - state = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN, - "fs/erofs:online", erofs_cpu_online, erofs_cpu_offline); - if (state < 0) - return state; - - erofs_cpuhp_state = state; - return 0; -} - -static void erofs_cpu_hotplug_destroy(void) -{ - if (erofs_cpuhp_state) - cpuhp_remove_state_nocalls(erofs_cpuhp_state); -} -#else /* !CONFIG_HOTPLUG_CPU || !CONFIG_EROFS_FS_PCPU_KTHREAD */ -static inline int erofs_cpu_hotplug_init(void) { return 0; } -static inline void erofs_cpu_hotplug_destroy(void) {} -#endif - void z_erofs_exit_zip_subsystem(void) { - erofs_cpu_hotplug_destroy(); - erofs_destroy_percpu_workers(); destroy_workqueue(z_erofs_workqueue); z_erofs_destroy_pcluster_pool(); } +static inline int z_erofs_init_workqueue(void) +{ + const unsigned int onlinecpus = num_possible_cpus(); + + /* + * no need to spawn too many threads, limiting threads could minimum + * scheduling overhead, perhaps per-CPU threads should be better? + */ + z_erofs_workqueue = alloc_workqueue("erofs_unzipd", + WQ_UNBOUND | WQ_HIGHPRI, + onlinecpus + onlinecpus / 4); + return z_erofs_workqueue ? 0 : -ENOMEM; +} + int __init z_erofs_init_zip_subsystem(void) { int err = z_erofs_create_pcluster_pool(); if (err) - goto out_error_pcluster_pool; - - z_erofs_workqueue = alloc_workqueue("erofs_worker", - WQ_UNBOUND | WQ_HIGHPRI, num_possible_cpus()); - if (!z_erofs_workqueue) - goto out_error_workqueue_init; - - err = erofs_init_percpu_workers(); + return err; + err = z_erofs_init_workqueue(); if (err) - goto out_error_pcpu_worker; - - err = erofs_cpu_hotplug_init(); - if (err < 0) - goto out_error_cpuhp_init; - return err; - -out_error_cpuhp_init: - erofs_destroy_percpu_workers(); -out_error_pcpu_worker: - destroy_workqueue(z_erofs_workqueue); -out_error_workqueue_init: - z_erofs_destroy_pcluster_pool(); -out_error_pcluster_pool: - + z_erofs_destroy_pcluster_pool(); return err; } @@ -910,12 +784,6 @@ err_out: } static void z_erofs_decompressqueue_work(struct work_struct *work); -#ifdef CONFIG_EROFS_FS_PCPU_KTHREAD -static void z_erofs_decompressqueue_kthread_work(struct kthread_work *work) -{ - z_erofs_decompressqueue_work((struct work_struct *)work); -} -#endif static void z_erofs_decompress_kickoff(struct z_erofs_decompressqueue *io, bool sync, int bios) { @@ -936,22 +804,7 @@ static void z_erofs_decompress_kickoff(struct z_erofs_decompressqueue *io, return; /* Use workqueue and sync decompression for atomic contexts only */ if (in_atomic() || irqs_disabled()) { -#ifdef CONFIG_EROFS_FS_PCPU_KTHREAD - struct kthread_worker *worker; - - rcu_read_lock(); - worker = rcu_dereference( - z_erofs_pcpu_workers[raw_smp_processor_id()]); - if (!worker) { - INIT_WORK(&io->u.work, z_erofs_decompressqueue_work); - queue_work(z_erofs_workqueue, &io->u.work); - } else { - kthread_queue_work(worker, &io->u.kthread_work); - } - rcu_read_unlock(); -#else queue_work(z_erofs_workqueue, &io->u.work); -#endif sbi->ctx.readahead_sync_decompress = true; return; } @@ -1359,12 +1212,7 @@ jobqueue_init(struct super_block *sb, *fg = true; goto fg_out; } -#ifdef CONFIG_EROFS_FS_PCPU_KTHREAD - kthread_init_work(&q->u.kthread_work, - z_erofs_decompressqueue_kthread_work); -#else INIT_WORK(&q->u.work, z_erofs_decompressqueue_work); -#endif } else { fg_out: q = fgq; @@ -1505,7 +1353,7 @@ submit_bio_retry: /* * although background is preferred, no one is pending for submission. - * don't issue decompression but drop it directly instead. + * don't issue workqueue for decompression but drop it directly instead. */ if (!*force_fg && !nr_bios) { kvfree(q[JQ_SUBMIT]); diff --git a/fs/erofs/zdata.h b/fs/erofs/zdata.h index fd0fa55b00f4..942ee69dff6a 100644 --- a/fs/erofs/zdata.h +++ b/fs/erofs/zdata.h @@ -7,7 +7,6 @@ #ifndef __EROFS_FS_ZDATA_H #define __EROFS_FS_ZDATA_H -#include #include "internal.h" #include "zpvec.h" @@ -93,7 +92,6 @@ struct z_erofs_decompressqueue { union { wait_queue_head_t wait; struct work_struct work; - struct kthread_work kthread_work; } u; }; From 7d4510686981b4a9fee6832758b409411d72b228 Mon Sep 17 00:00:00 2001 From: Michael Bestas Date: Wed, 19 Mar 2025 07:22:49 +0200 Subject: [PATCH 684/698] Revert "fs:EROFS:Porting 5.10 erofs to 5.4" This reverts commit fa3b0b74bbcf5a0ec20be524615ba02c6ee022d8. Reason for revert: Conflicts with upstream commits. Change-Id: I10bbd4c822e516266dd4be504f42ff9e1dcf9032 --- fs/erofs/Kconfig | 15 +- fs/erofs/Makefile | 7 +- fs/erofs/compress.h | 56 +-- fs/erofs/data.c | 23 +- fs/erofs/decompressor.c | 291 ++++++---------- fs/erofs/dir.c | 2 +- fs/erofs/erofs_fs.h | 56 +-- fs/erofs/inode.c | 8 +- fs/erofs/internal.h | 130 +++---- fs/erofs/namei.c | 4 +- fs/erofs/pcpubuf.c | 148 -------- fs/erofs/super.c | 457 +++++++++--------------- fs/erofs/utils.c | 148 +++++--- fs/erofs/xattr.c | 6 +- fs/erofs/xattr.h | 26 +- fs/erofs/zdata.c | 750 +++++++++++++++++++--------------------- fs/erofs/zdata.h | 25 +- fs/erofs/zmap.c | 213 +++--------- fs/erofs/zpvec.h | 2 +- 19 files changed, 909 insertions(+), 1458 deletions(-) delete mode 100644 fs/erofs/pcpubuf.c diff --git a/fs/erofs/Kconfig b/fs/erofs/Kconfig index 858b3339f381..9d634d3a1845 100644 --- a/fs/erofs/Kconfig +++ b/fs/erofs/Kconfig @@ -3,7 +3,6 @@ config EROFS_FS tristate "EROFS filesystem support" depends on BLOCK - select LIBCRC32C help EROFS (Enhanced Read-Only File System) is a lightweight read-only file system with modern designs (eg. page-sized @@ -76,3 +75,17 @@ config EROFS_FS_ZIP If you don't want to enable compression feature, say N. +config EROFS_FS_CLUSTER_PAGE_LIMIT + int "EROFS Cluster Pages Hard Limit" + depends on EROFS_FS_ZIP + range 1 256 + default "1" + help + Indicates maximum # of pages of a compressed + physical cluster. + + For example, if files in a image were compressed + into 8k-unit, hard limit should not be configured + less than 2. Otherwise, the image will be refused + to mount on this kernel. + diff --git a/fs/erofs/Makefile b/fs/erofs/Makefile index 1f9aced49070..46f2aa4ba46c 100644 --- a/fs/erofs/Makefile +++ b/fs/erofs/Makefile @@ -1,6 +1,11 @@ # SPDX-License-Identifier: GPL-2.0-only +EROFS_VERSION = "1.0" + +ccflags-y += -DEROFS_VERSION=\"$(EROFS_VERSION)\" + obj-$(CONFIG_EROFS_FS) += erofs.o -erofs-objs := super.o inode.o data.o namei.o dir.o utils.o pcpubuf.o +erofs-objs := super.o inode.o data.o namei.o dir.o utils.o erofs-$(CONFIG_EROFS_FS_XATTR) += xattr.o erofs-$(CONFIG_EROFS_FS_ZIP) += decompressor.o zmap.o zdata.o + diff --git a/fs/erofs/compress.h b/fs/erofs/compress.h index aea129ddda74..07d279fd5d67 100644 --- a/fs/erofs/compress.h +++ b/fs/erofs/compress.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (C) 2019 HUAWEI, Inc. - * https://www.huawei.com/ + * http://www.huawei.com/ * Created by Gao Xiang */ #ifndef __EROFS_FS_COMPRESS_H @@ -26,58 +26,30 @@ struct z_erofs_decompress_req { bool inplace_io, partial_decoding; }; -/* some special page->private (unsigned long, see below) */ -#define Z_EROFS_SHORTLIVED_PAGE (-1UL << 2) -#define Z_EROFS_PREALLOCATED_PAGE (-2UL << 2) - /* - * For all pages in a pcluster, page->private should be one of - * Type Last 2bits page->private - * short-lived page 00 Z_EROFS_SHORTLIVED_PAGE - * preallocated page (tryalloc) 00 Z_EROFS_PREALLOCATED_PAGE - * cached/managed page 00 pointer to z_erofs_pcluster - * online page (file-backed, 01/10/11 sub-index << 2 | count - * some pages can be used for inplace I/O) - * - * page->mapping should be one of - * Type page->mapping - * short-lived page NULL - * preallocated page NULL - * cached/managed page non-NULL or NULL (invalidated/truncated page) - * online page non-NULL - * - * For all managed pages, PG_private should be set with 1 extra refcount, - * which is used for page reclaim / migration. + * - 0x5A110C8D ('sallocated', Z_EROFS_MAPPING_STAGING) - + * used to mark temporary allocated pages from other + * file/cached pages and NULL mapping pages. */ +#define Z_EROFS_MAPPING_STAGING ((void *)0x5A110C8D) -/* - * short-lived pages are pages directly from buddy system with specific - * page->private (no need to set PagePrivate since these are non-LRU / - * non-movable pages and bypass reclaim / migration code). - */ -static inline bool z_erofs_is_shortlived_page(struct page *page) +/* check if a page is marked as staging */ +static inline bool z_erofs_page_is_staging(struct page *page) { - if (page->private != Z_EROFS_SHORTLIVED_PAGE) - return false; - - DBG_BUGON(page->mapping); - return true; + return page->mapping == Z_EROFS_MAPPING_STAGING; } -static inline bool z_erofs_put_shortlivedpage(struct list_head *pagepool, - struct page *page) +static inline bool z_erofs_put_stagingpage(struct list_head *pagepool, + struct page *page) { - if (!z_erofs_is_shortlived_page(page)) + if (!z_erofs_page_is_staging(page)) return false; - /* short-lived pages should not be used by others at the same time */ - if (page_ref_count(page) > 1) { + /* staging pages should not be used by others at the same time */ + if (page_ref_count(page) > 1) put_page(page); - } else { - /* follow the pcluster rule above. */ - set_page_private(page, 0); + else list_add(&page->lru, pagepool); - } return true; } diff --git a/fs/erofs/data.c b/fs/erofs/data.c index b336a6201bca..b22a08ac53a2 100644 --- a/fs/erofs/data.c +++ b/fs/erofs/data.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2017-2018 HUAWEI, Inc. - * https://www.huawei.com/ + * http://www.huawei.com/ * Created by Gao Xiang */ #include "internal.h" @@ -109,6 +109,21 @@ err_out: return err; } +int erofs_map_blocks(struct inode *inode, + struct erofs_map_blocks *map, int flags) +{ + if (erofs_inode_is_data_compressed(EROFS_I(inode)->datalayout)) { + int err = z_erofs_map_blocks_iter(inode, map, flags); + + if (map->mpage) { + put_page(map->mpage); + map->mpage = NULL; + } + return err; + } + return erofs_map_blocks_flatmode(inode, map, flags); +} + static inline struct bio *erofs_read_raw_page(struct bio *bio, struct address_space *mapping, struct page *page, @@ -144,7 +159,7 @@ submit_bio_retry: erofs_blk_t blknr; unsigned int blkoff; - err = erofs_map_blocks_flatmode(inode, &map, EROFS_GET_BLOCKS_RAW); + err = erofs_map_blocks(inode, &map, EROFS_GET_BLOCKS_RAW); if (err) goto err_out; @@ -209,7 +224,7 @@ submit_bio_retry: bio_set_dev(bio, sb->s_bdev); bio->bi_iter.bi_sector = (sector_t)blknr << LOG_SECTORS_PER_BLOCK; - bio->bi_opf = REQ_OP_READ | (ra ? REQ_RAHEAD : 0); + bio->bi_opf = REQ_OP_READ; } err = bio_add_page(bio, page, PAGE_SIZE, 0); @@ -322,7 +337,7 @@ static sector_t erofs_bmap(struct address_space *mapping, sector_t block) return 0; } - if (!erofs_map_blocks_flatmode(inode, &map, EROFS_GET_BLOCKS_RAW)) + if (!erofs_map_blocks(inode, &map, EROFS_GET_BLOCKS_RAW)) return erofs_blknr(map.m_pa); return 0; diff --git a/fs/erofs/decompressor.c b/fs/erofs/decompressor.c index 6f6e3d0af2fd..38eeec5e3032 100644 --- a/fs/erofs/decompressor.c +++ b/fs/erofs/decompressor.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2019 HUAWEI, Inc. - * https://www.huawei.com/ + * http://www.huawei.com/ * Created by Gao Xiang */ #include "compress.h" @@ -28,42 +28,6 @@ struct z_erofs_decompressor { char *name; }; -int z_erofs_load_lz4_config(struct super_block *sb, - struct erofs_super_block *dsb, - struct z_erofs_lz4_cfgs *lz4, int size) -{ - struct erofs_sb_info *sbi = EROFS_SB(sb); - u16 distance; - - if (lz4) { - if (size < sizeof(struct z_erofs_lz4_cfgs)) { - erofs_err(sb, "invalid lz4 cfgs, size=%u", size); - return -EINVAL; - } - distance = le16_to_cpu(lz4->max_distance); - - sbi->lz4.max_pclusterblks = le16_to_cpu(lz4->max_pclusterblks); - if (!sbi->lz4.max_pclusterblks) { - sbi->lz4.max_pclusterblks = 1; /* reserved case */ - } else if (sbi->lz4.max_pclusterblks > - Z_EROFS_PCLUSTER_MAX_SIZE / EROFS_BLKSIZ) { - erofs_err(sb, "too large lz4 pclusterblks %u", - sbi->lz4.max_pclusterblks); - return -EINVAL; - } else if (sbi->lz4.max_pclusterblks >= 2) { - erofs_info(sb, "EXPERIMENTAL big pcluster feature in use. Use at your own risk!"); - } - } else { - distance = le16_to_cpu(dsb->u1.lz4_max_distance); - sbi->lz4.max_pclusterblks = 1; - } - - sbi->lz4.max_distance_pages = distance ? - DIV_ROUND_UP(distance, PAGE_SIZE) + 1 : - LZ4_MAX_DISTANCE_PAGES; - return erofs_pcpubuf_growsize(sbi->lz4.max_pclusterblks); -} - static int z_erofs_lz4_prepare_destpages(struct z_erofs_decompress_req *rq, struct list_head *pagepool) { @@ -72,8 +36,6 @@ static int z_erofs_lz4_prepare_destpages(struct z_erofs_decompress_req *rq, struct page *availables[LZ4_MAX_DISTANCE_PAGES] = { NULL }; unsigned long bounced[DIV_ROUND_UP(LZ4_MAX_DISTANCE_PAGES, BITS_PER_LONG)] = { 0 }; - unsigned int lz4_max_distance_pages = - EROFS_SB(rq->sb)->lz4.max_distance_pages; void *kaddr = NULL; unsigned int i, j, top; @@ -82,14 +44,14 @@ static int z_erofs_lz4_prepare_destpages(struct z_erofs_decompress_req *rq, struct page *const page = rq->out[i]; struct page *victim; - if (j >= lz4_max_distance_pages) + if (j >= LZ4_MAX_DISTANCE_PAGES) j = 0; /* 'valid' bounced can only be tested after a complete round */ if (test_bit(j, bounced)) { - DBG_BUGON(i < lz4_max_distance_pages); - DBG_BUGON(top >= lz4_max_distance_pages); - availables[top++] = rq->out[i - lz4_max_distance_pages]; + DBG_BUGON(i < LZ4_MAX_DISTANCE_PAGES); + DBG_BUGON(top >= LZ4_MAX_DISTANCE_PAGES); + availables[top++] = rq->out[i - LZ4_MAX_DISTANCE_PAGES]; } if (page) { @@ -115,149 +77,108 @@ static int z_erofs_lz4_prepare_destpages(struct z_erofs_decompress_req *rq, victim = availables[--top]; get_page(victim); } else { - victim = erofs_allocpage(pagepool, - GFP_KERNEL | __GFP_NOFAIL); - set_page_private(victim, Z_EROFS_SHORTLIVED_PAGE); + victim = erofs_allocpage(pagepool, GFP_KERNEL, false); + if (!victim) + return -ENOMEM; + victim->mapping = Z_EROFS_MAPPING_STAGING; } rq->out[i] = victim; } return kaddr ? 1 : 0; } -static void *z_erofs_handle_inplace_io(struct z_erofs_decompress_req *rq, - void *inpage, unsigned int *inputmargin, int *maptype, - bool support_0padding) +static void *generic_copy_inplace_data(struct z_erofs_decompress_req *rq, + u8 *src, unsigned int pageofs_in) { - unsigned int nrpages_in, nrpages_out; - unsigned int ofull, oend, inputsize, total, i, j; - struct page **in; - void *src, *tmp; + /* + * if in-place decompression is ongoing, those decompressed + * pages should be copied in order to avoid being overlapped. + */ + struct page **in = rq->in; + u8 *const tmp = erofs_get_pcpubuf(0); + u8 *tmpp = tmp; + unsigned int inlen = rq->inputsize - pageofs_in; + unsigned int count = min_t(uint, inlen, PAGE_SIZE - pageofs_in); - inputsize = rq->inputsize; - nrpages_in = PAGE_ALIGN(inputsize) >> PAGE_SHIFT; - oend = rq->pageofs_out + rq->outputsize; - ofull = PAGE_ALIGN(oend); - nrpages_out = ofull >> PAGE_SHIFT; - - if (rq->inplace_io) { - if (rq->partial_decoding || !support_0padding || - ofull - oend < LZ4_DECOMPRESS_INPLACE_MARGIN(inputsize)) - goto docopy; - - for (i = 0; i < nrpages_in; ++i) { - DBG_BUGON(rq->in[i] == NULL); - for (j = 0; j < nrpages_out - nrpages_in + i; ++j) - if (rq->out[j] == rq->in[i]) - goto docopy; - } - } - - if (nrpages_in <= 1) { - *maptype = 0; - return inpage; - } - kunmap_atomic(inpage); - might_sleep(); - src = erofs_vm_map_ram(rq->in, nrpages_in); - if (!src) - return ERR_PTR(-ENOMEM); - *maptype = 1; - return src; - -docopy: - /* Or copy compressed data which can be overlapped to per-CPU buffer */ - in = rq->in; - src = erofs_get_pcpubuf(nrpages_in); - if (!src) { - DBG_BUGON(1); - kunmap_atomic(inpage); - return ERR_PTR(-EFAULT); - } - - tmp = src; - total = rq->inputsize; - while (total) { - unsigned int page_copycnt = - min_t(unsigned int, total, PAGE_SIZE - *inputmargin); - - if (!inpage) - inpage = kmap_atomic(*in); - memcpy(tmp, inpage + *inputmargin, page_copycnt); - kunmap_atomic(inpage); - inpage = NULL; - tmp += page_copycnt; - total -= page_copycnt; + while (tmpp < tmp + inlen) { + if (!src) + src = kmap_atomic(*in); + memcpy(tmpp, src + pageofs_in, count); + kunmap_atomic(src); + src = NULL; + tmpp += count; + pageofs_in = 0; + count = PAGE_SIZE; ++in; - *inputmargin = 0; } - *maptype = 2; - return src; + return tmp; } static int z_erofs_lz4_decompress(struct z_erofs_decompress_req *rq, u8 *out) { - unsigned int inputmargin; - u8 *headpage, *src; - bool support_0padding; - int ret, maptype; + unsigned int inputmargin, inlen; + u8 *src; + bool copied, support_0padding; + int ret; - DBG_BUGON(*rq->in == NULL); - headpage = kmap_atomic(*rq->in); + if (rq->inputsize > PAGE_SIZE) + return -EOPNOTSUPP; + + src = kmap_atomic(*rq->in); inputmargin = 0; support_0padding = false; /* decompression inplace is only safe when 0padding is enabled */ - if (erofs_sb_has_lz4_0padding(EROFS_SB(rq->sb))) { + if (EROFS_SB(rq->sb)->feature_incompat & + EROFS_FEATURE_INCOMPAT_LZ4_0PADDING) { support_0padding = true; - while (!headpage[inputmargin & ~PAGE_MASK]) + while (!src[inputmargin & ~PAGE_MASK]) if (!(++inputmargin & ~PAGE_MASK)) break; if (inputmargin >= rq->inputsize) { - kunmap_atomic(headpage); + kunmap_atomic(src); return -EIO; } } - rq->inputsize -= inputmargin; - src = z_erofs_handle_inplace_io(rq, headpage, &inputmargin, &maptype, - support_0padding); - if (IS_ERR(src)) - return PTR_ERR(src); + copied = false; + inlen = rq->inputsize - inputmargin; + if (rq->inplace_io) { + const uint oend = (rq->pageofs_out + + rq->outputsize) & ~PAGE_MASK; + const uint nr = PAGE_ALIGN(rq->pageofs_out + + rq->outputsize) >> PAGE_SHIFT; - /* legacy format could compress extra data in a pcluster. */ - if (rq->partial_decoding || !support_0padding) - ret = LZ4_decompress_safe_partial(src + inputmargin, out, - rq->inputsize, rq->outputsize, rq->outputsize); - else - ret = LZ4_decompress_safe(src + inputmargin, out, - rq->inputsize, rq->outputsize); - - if (ret != rq->outputsize) { - erofs_err(rq->sb, "failed to decompress %d in[%u, %u] out[%u]", - ret, rq->inputsize, inputmargin, rq->outputsize); + if (rq->partial_decoding || !support_0padding || + rq->out[nr - 1] != rq->in[0] || + rq->inputsize - oend < + LZ4_DECOMPRESS_INPLACE_MARGIN(inlen)) { + src = generic_copy_inplace_data(rq, src, inputmargin); + inputmargin = 0; + copied = true; + } + } + ret = LZ4_decompress_safe_partial(src + inputmargin, out, + inlen, rq->outputsize, + rq->outputsize); + if (ret < 0) { + erofs_err(rq->sb, "failed to decompress, in[%u, %u] out[%u]", + inlen, inputmargin, rq->outputsize); + WARN_ON(1); print_hex_dump(KERN_DEBUG, "[ in]: ", DUMP_PREFIX_OFFSET, - 16, 1, src + inputmargin, rq->inputsize, true); + 16, 1, src + inputmargin, inlen, true); print_hex_dump(KERN_DEBUG, "[out]: ", DUMP_PREFIX_OFFSET, 16, 1, out, rq->outputsize, true); - - if (ret >= 0) - memset(out + ret, 0, rq->outputsize - ret); ret = -EIO; } - if (maptype == 0) { - kunmap_atomic(src); - } else if (maptype == 1) { - vm_unmap_ram(src, PAGE_ALIGN(rq->inputsize) >> PAGE_SHIFT); - } else if (maptype == 2) { + if (copied) erofs_put_pcpubuf(src); - } else { - DBG_BUGON(1); - return -EFAULT; - } + else + kunmap_atomic(src); return ret; } @@ -307,51 +228,57 @@ static int z_erofs_decompress_generic(struct z_erofs_decompress_req *rq, const struct z_erofs_decompressor *alg = decompressors + rq->alg; unsigned int dst_maptype; void *dst; - int ret; + int ret, i; - /* two optimized fast paths only for non bigpcluster cases yet */ - if (rq->inputsize <= PAGE_SIZE) { - if (nrpages_out == 1 && !rq->inplace_io) { - DBG_BUGON(!*rq->out); - dst = kmap_atomic(*rq->out); - dst_maptype = 0; - goto dstmap_out; - } - - /* - * For the case of small output size (especially much less - * than PAGE_SIZE), memcpy the decompressed data rather than - * compressed data is preferred. - */ - if (rq->outputsize <= PAGE_SIZE * 7 / 8) { - dst = erofs_get_pcpubuf(1); - if (IS_ERR(dst)) - return PTR_ERR(dst); - - rq->inplace_io = false; - ret = alg->decompress(rq, dst); - if (!ret) - copy_from_pcpubuf(rq->out, dst, rq->pageofs_out, - rq->outputsize); - - erofs_put_pcpubuf(dst); - return ret; - } + if (nrpages_out == 1 && !rq->inplace_io) { + DBG_BUGON(!*rq->out); + dst = kmap_atomic(*rq->out); + dst_maptype = 0; + goto dstmap_out; } - /* general decoding path which can be used for all cases */ - ret = alg->prepare_destpages(rq, pagepool); - if (ret < 0) + /* + * For the case of small output size (especially much less + * than PAGE_SIZE), memcpy the decompressed data rather than + * compressed data is preferred. + */ + if (rq->outputsize <= PAGE_SIZE * 7 / 8) { + dst = erofs_get_pcpubuf(0); + if (IS_ERR(dst)) + return PTR_ERR(dst); + + rq->inplace_io = false; + ret = alg->decompress(rq, dst); + if (!ret) + copy_from_pcpubuf(rq->out, dst, rq->pageofs_out, + rq->outputsize); + + erofs_put_pcpubuf(dst); return ret; - if (ret) { + } + + ret = alg->prepare_destpages(rq, pagepool); + if (ret < 0) { + return ret; + } else if (ret) { dst = page_address(*rq->out); dst_maptype = 1; goto dstmap_out; } - dst = erofs_vm_map_ram(rq->out, nrpages_out); + i = 0; + while (1) { + dst = vm_map_ram(rq->out, nrpages_out, -1, PAGE_KERNEL); + + /* retry two more times (totally 3 times) */ + if (dst || ++i >= 3) + break; + vm_unmap_aliases(); + } + if (!dst) return -ENOMEM; + dst_maptype = 2; dstmap_out: diff --git a/fs/erofs/dir.c b/fs/erofs/dir.c index 2776bb832127..d28c623dfef9 100644 --- a/fs/erofs/dir.c +++ b/fs/erofs/dir.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2017-2018 HUAWEI, Inc. - * https://www.huawei.com/ + * http://www.huawei.com/ * Created by Gao Xiang */ #include "internal.h" diff --git a/fs/erofs/erofs_fs.h b/fs/erofs/erofs_fs.h index 8739d3adf51f..52ab96154467 100644 --- a/fs/erofs/erofs_fs.h +++ b/fs/erofs/erofs_fs.h @@ -3,7 +3,7 @@ * EROFS (Enhanced ROM File System) on-disk format definition * * Copyright (C) 2017-2018 HUAWEI, Inc. - * https://www.huawei.com/ + * http://www.huawei.com/ * Created by Gao Xiang */ #ifndef __EROFS_FS_H @@ -11,29 +11,20 @@ #define EROFS_SUPER_OFFSET 1024 -#define EROFS_FEATURE_COMPAT_SB_CHKSUM 0x00000001 - /* * Any bits that aren't in EROFS_ALL_FEATURE_INCOMPAT should * be incompatible with this kernel version. */ #define EROFS_FEATURE_INCOMPAT_LZ4_0PADDING 0x00000001 -#define EROFS_FEATURE_INCOMPAT_COMPR_CFGS 0x00000002 -#define EROFS_FEATURE_INCOMPAT_BIG_PCLUSTER 0x00000002 -#define EROFS_ALL_FEATURE_INCOMPAT \ - (EROFS_FEATURE_INCOMPAT_LZ4_0PADDING | \ - EROFS_FEATURE_INCOMPAT_COMPR_CFGS | \ - EROFS_FEATURE_INCOMPAT_BIG_PCLUSTER) +#define EROFS_ALL_FEATURE_INCOMPAT EROFS_FEATURE_INCOMPAT_LZ4_0PADDING -#define EROFS_SB_EXTSLOT_SIZE 16 - -/* erofs on-disk super block (currently 128 bytes) */ +/* 128-byte erofs on-disk super block */ struct erofs_super_block { __le32 magic; /* file system magic number */ __le32 checksum; /* crc32c(super_block) */ __le32 feature_compat; __u8 blkszbits; /* support block_size == PAGE_SIZE only */ - __u8 sb_extslots; /* superblock size = 128 + sb_extslots * 16 */ + __u8 reserved; __le16 root_nid; /* nid of root directory */ __le64 inos; /* total valid ino # (== f_files - f_favail) */ @@ -46,13 +37,8 @@ struct erofs_super_block { __u8 uuid[16]; /* 128-bit uuid for volume */ __u8 volume_name[16]; /* volume name */ __le32 feature_incompat; - union { - /* bitmap for available compression algorithms */ - __le16 available_compr_algs; - /* customized sliding window size instead of 64k by default */ - __le16 lz4_max_distance; - } __packed u1; - __u8 reserved2[42]; + + __u8 reserved2[44]; }; /* @@ -205,33 +191,20 @@ static inline unsigned int erofs_xattr_entry_size(struct erofs_xattr_entry *e) e->e_name_len + le16_to_cpu(e->e_value_size)); } -/* maximum supported size of a physical compression cluster */ -#define Z_EROFS_PCLUSTER_MAX_SIZE (1024 * 1024) - /* available compression algorithm types (for h_algorithmtype) */ enum { Z_EROFS_COMPRESSION_LZ4 = 0, Z_EROFS_COMPRESSION_MAX }; -#define Z_EROFS_ALL_COMPR_ALGS (1 << (Z_EROFS_COMPRESSION_MAX - 1)) - -/* 14 bytes (+ length field = 16 bytes) */ -struct z_erofs_lz4_cfgs { - __le16 max_distance; - __le16 max_pclusterblks; - u8 reserved[10]; -} __packed; /* * bit 0 : COMPACTED_2B indexes (0 - off; 1 - on) * e.g. for 4k logical cluster size, 4B if compacted 2B is off; * (4B) + 2B + (4B) if compacted 2B is on. - * bit 1 : HEAD1 big pcluster (0 - off; 1 - on) - * bit 2 : HEAD2 big pcluster (0 - off; 1 - on) */ -#define Z_EROFS_ADVISE_COMPACTED_2B 0x0001 -#define Z_EROFS_ADVISE_BIG_PCLUSTER_1 0x0002 -#define Z_EROFS_ADVISE_BIG_PCLUSTER_2 0x0004 +#define Z_EROFS_ADVISE_COMPACTED_2B_BIT 0 + +#define Z_EROFS_ADVISE_COMPACTED_2B (1 << Z_EROFS_ADVISE_COMPACTED_2B_BIT) struct z_erofs_map_header { __le32 h_reserved1; @@ -243,7 +216,9 @@ struct z_erofs_map_header { __u8 h_algorithmtype; /* * bit 0-2 : logical cluster bits - 12, e.g. 0 for 4096; - * bit 3-7 : reserved. + * bit 3-4 : (physical - logical) cluster bits of head 1: + * For example, if logical clustersize = 4096, 1 for 8192. + * bit 5-7 : (physical - logical) cluster bits of head 2. */ __u8 h_clusterbits; }; @@ -286,13 +261,6 @@ enum { #define Z_EROFS_VLE_DI_CLUSTER_TYPE_BITS 2 #define Z_EROFS_VLE_DI_CLUSTER_TYPE_BIT 0 -/* - * D0_CBLKCNT will be marked _only_ at the 1st non-head lcluster to store the - * compressed block count of a compressed extent (in logical clusters, aka. - * block count of a pcluster). - */ -#define Z_EROFS_VLE_DI_D0_CBLKCNT (1 << 11) - struct z_erofs_vle_decompressed_index { __le16 di_advise; /* where to decompress in the head cluster */ diff --git a/fs/erofs/inode.c b/fs/erofs/inode.c index 0a94a52a119f..0dbeaf68e1d6 100644 --- a/fs/erofs/inode.c +++ b/fs/erofs/inode.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2017-2018 HUAWEI, Inc. - * https://www.huawei.com/ + * http://www.huawei.com/ * Created by Gao Xiang */ #include "xattr.h" @@ -356,21 +356,27 @@ int erofs_getattr(const struct path *path, struct kstat *stat, const struct inode_operations erofs_generic_iops = { .getattr = erofs_getattr, +#ifdef CONFIG_EROFS_FS_XATTR .listxattr = erofs_listxattr, +#endif .get_acl = erofs_get_acl, }; const struct inode_operations erofs_symlink_iops = { .get_link = page_get_link, .getattr = erofs_getattr, +#ifdef CONFIG_EROFS_FS_XATTR .listxattr = erofs_listxattr, +#endif .get_acl = erofs_get_acl, }; const struct inode_operations erofs_fast_symlink_iops = { .get_link = simple_get_link, .getattr = erofs_getattr, +#ifdef CONFIG_EROFS_FS_XATTR .listxattr = erofs_listxattr, +#endif .get_acl = erofs_get_acl, }; diff --git a/fs/erofs/internal.h b/fs/erofs/internal.h index c18b0553cb98..cc7a42682814 100644 --- a/fs/erofs/internal.h +++ b/fs/erofs/internal.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (C) 2017-2018 HUAWEI, Inc. - * https://www.huawei.com/ + * http://www.huawei.com/ * Created by Gao Xiang */ #ifndef __EROFS_INTERNAL_H @@ -46,43 +46,25 @@ typedef u64 erofs_off_t; /* data type for filesystem-wide blocks number */ typedef u32 erofs_blk_t; -struct erofs_fs_context { -#ifdef CONFIG_EROFS_FS_ZIP - /* current strategy of how to use managed cache */ - unsigned char cache_strategy; - /* strategy of sync decompression (false - auto, true - force on) */ - bool readahead_sync_decompress; - - /* threshold for decompression synchronously */ - unsigned int max_sync_decompress_pages; -#endif - unsigned int mount_opt; -}; - -/* all filesystem-wide lz4 configurations */ -struct erofs_sb_lz4_info { - /* # of pages needed for EROFS lz4 rolling decompression */ - u16 max_distance_pages; - /* maximum possible blocks for pclusters in the filesystem */ - u16 max_pclusterblks; -}; - struct erofs_sb_info { #ifdef CONFIG_EROFS_FS_ZIP /* list for all registered superblocks, mainly for shrinker */ struct list_head list; struct mutex umount_mutex; - /* managed XArray arranged in physical block number */ - struct xarray managed_pslots; + /* the dedicated workstation for compression */ + struct radix_tree_root workstn_tree; + + /* threshold for decompression synchronously */ + unsigned int max_sync_decompress_pages; unsigned int shrinker_run_no; - u16 available_compr_algs; + + /* current strategy of how to use managed cache */ + unsigned char cache_strategy; /* pseudo inode to manage cached pages */ struct inode *managed_cache; - - struct erofs_sb_lz4_info lz4; #endif /* CONFIG_EROFS_FS_ZIP */ u32 blocks; u32 meta_blkaddr; @@ -93,7 +75,6 @@ struct erofs_sb_info { /* inode slot unit size in bit shift */ unsigned char islotbits; - u32 sb_size; /* total superblock size */ u32 build_time_nsec; u64 build_time; @@ -104,10 +85,9 @@ struct erofs_sb_info { u8 uuid[16]; /* 128-bit uuid for volume */ u8 volume_name[16]; /* volume name */ - u32 feature_compat; u32 feature_incompat; - struct erofs_fs_context ctx; /* options */ + unsigned int mount_opt; }; #define EROFS_SB(sb) ((struct erofs_sb_info *)(sb)->s_fs_info) @@ -117,17 +97,17 @@ struct erofs_sb_info { #define EROFS_MOUNT_XATTR_USER 0x00000010 #define EROFS_MOUNT_POSIX_ACL 0x00000020 -#define clear_opt(ctx, option) ((ctx)->mount_opt &= ~EROFS_MOUNT_##option) -#define set_opt(ctx, option) ((ctx)->mount_opt |= EROFS_MOUNT_##option) -#define test_opt(ctx, option) ((ctx)->mount_opt & EROFS_MOUNT_##option) +#define clear_opt(sbi, option) ((sbi)->mount_opt &= ~EROFS_MOUNT_##option) +#define set_opt(sbi, option) ((sbi)->mount_opt |= EROFS_MOUNT_##option) +#define test_opt(sbi, option) ((sbi)->mount_opt & EROFS_MOUNT_##option) +#ifdef CONFIG_EROFS_FS_ZIP enum { EROFS_ZIP_CACHE_DISABLED, EROFS_ZIP_CACHE_READAHEAD, EROFS_ZIP_CACHE_READAROUND }; -#ifdef CONFIG_EROFS_FS_ZIP #define EROFS_LOCKED_MAGIC (INT_MIN | 0xE0F510CCL) /* basic unit of the workstation of a super_block */ @@ -196,6 +176,12 @@ static inline int erofs_wait_on_workgroup_freezed(struct erofs_workgroup *grp) return v; } #endif /* !CONFIG_SMP */ + +/* hard limit of pages per compressed cluster */ +#define Z_EROFS_CLUSTER_MAX_PAGES (CONFIG_EROFS_FS_CLUSTER_PAGE_LIMIT) +#define EROFS_PCPUBUF_NR_PAGES Z_EROFS_CLUSTER_MAX_PAGES +#else +#define EROFS_PCPUBUF_NR_PAGES 0 #endif /* !CONFIG_EROFS_FS_ZIP */ /* we strictly follow PAGE_SIZE and no buffer head yet */ @@ -224,17 +210,6 @@ static inline erofs_off_t iloc(struct erofs_sb_info *sbi, erofs_nid_t nid) return blknr_to_addr(sbi->meta_blkaddr) + (nid << sbi->islotbits); } -#define EROFS_FEATURE_FUNCS(name, compat, feature) \ -static inline bool erofs_sb_has_##name(struct erofs_sb_info *sbi) \ -{ \ - return sbi->feature_##compat & EROFS_FEATURE_##feature; \ -} - -EROFS_FEATURE_FUNCS(lz4_0padding, incompat, INCOMPAT_LZ4_0PADDING) -EROFS_FEATURE_FUNCS(compr_cfgs, incompat, INCOMPAT_COMPR_CFGS) -EROFS_FEATURE_FUNCS(big_pcluster, incompat, INCOMPAT_BIG_PCLUSTER) -EROFS_FEATURE_FUNCS(sb_chksum, compat, COMPAT_SB_CHKSUM) - /* atomic flag definitions */ #define EROFS_I_EA_INITED_BIT 0 #define EROFS_I_Z_INITED_BIT 1 @@ -263,6 +238,7 @@ struct erofs_inode { unsigned short z_advise; unsigned char z_algorithmtype[2]; unsigned char z_logical_clusterbits; + unsigned char z_physical_clusterbits[2]; }; #endif /* CONFIG_EROFS_FS_ZIP */ }; @@ -302,10 +278,12 @@ static inline unsigned int erofs_inode_datalayout(unsigned int value) extern const struct super_operations erofs_sops; extern const struct address_space_operations erofs_raw_access_aops; -extern const struct address_space_operations z_erofs_aops; +#ifdef CONFIG_EROFS_FS_ZIP +extern const struct address_space_operations z_erofs_vle_normalaccess_aops; +#endif /* - * Logical to physical block mapping + * Logical to physical block mapping, used by erofs_map_blocks() * * Different with other file systems, it is used for 2 access modes: * @@ -352,7 +330,7 @@ struct erofs_map_blocks { struct page *mpage; }; -/* Flags used by erofs_map_blocks_flatmode() */ +/* Flags used by erofs_map_blocks() */ #define EROFS_GET_BLOCKS_RAW 0x0001 /* zmap.c */ @@ -374,6 +352,8 @@ static inline int z_erofs_map_blocks_iter(struct inode *inode, /* data.c */ struct page *erofs_get_meta_page(struct super_block *sb, erofs_blk_t blkaddr); +int erofs_map_blocks(struct inode *, struct erofs_map_blocks *, int); + /* inode.c */ static inline unsigned long erofs_inode_hash(erofs_nid_t nid) { @@ -401,37 +381,30 @@ int erofs_namei(struct inode *dir, struct qstr *name, /* dir.c */ extern const struct file_operations erofs_dir_fops; -static inline void *erofs_vm_map_ram(struct page **pages, unsigned int count) +/* utils.c / zdata.c */ +struct page *erofs_allocpage(struct list_head *pool, gfp_t gfp, bool nofail); + +#if (EROFS_PCPUBUF_NR_PAGES > 0) +void *erofs_get_pcpubuf(unsigned int pagenr); +#define erofs_put_pcpubuf(buf) do { \ + (void)&(buf); \ + preempt_enable(); \ +} while (0) +#else +static inline void *erofs_get_pcpubuf(unsigned int pagenr) { - int retried = 0; - - while (1) { - void *p = vm_map_ram(pages, count, -1, PAGE_KERNEL); - - /* retry two more times (totally 3 times) */ - if (p || ++retried >= 3) - return p; - vm_unmap_aliases(); - } - return NULL; + return ERR_PTR(-EOPNOTSUPP); } -/* pcpubuf.c */ -void *erofs_get_pcpubuf(unsigned int requiredpages); -void erofs_put_pcpubuf(void *ptr); -int erofs_pcpubuf_growsize(unsigned int nrpages); -void erofs_pcpubuf_init(void); -void erofs_pcpubuf_exit(void); - -/* utils.c / zdata.c */ -struct page *erofs_allocpage(struct list_head *pool, gfp_t gfp); +#define erofs_put_pcpubuf(buf) do {} while (0) +#endif #ifdef CONFIG_EROFS_FS_ZIP int erofs_workgroup_put(struct erofs_workgroup *grp); struct erofs_workgroup *erofs_find_workgroup(struct super_block *sb, - pgoff_t index); -struct erofs_workgroup *erofs_insert_workgroup(struct super_block *sb, - struct erofs_workgroup *grp); + pgoff_t index, bool *tag); +int erofs_register_workgroup(struct super_block *sb, + struct erofs_workgroup *grp, bool tag); void erofs_workgroup_free_rcu(struct erofs_workgroup *grp); void erofs_shrinker_register(struct super_block *sb); void erofs_shrinker_unregister(struct super_block *sb); @@ -443,9 +416,6 @@ int erofs_try_to_free_all_cached_pages(struct erofs_sb_info *sbi, struct erofs_workgroup *egrp); int erofs_try_to_free_cached_page(struct address_space *mapping, struct page *page); -int z_erofs_load_lz4_config(struct super_block *sb, - struct erofs_super_block *dsb, - struct z_erofs_lz4_cfgs *lz4, int len); #else static inline void erofs_shrinker_register(struct super_block *sb) {} static inline void erofs_shrinker_unregister(struct super_block *sb) {} @@ -453,16 +423,6 @@ static inline int erofs_init_shrinker(void) { return 0; } static inline void erofs_exit_shrinker(void) {} static inline int z_erofs_init_zip_subsystem(void) { return 0; } static inline void z_erofs_exit_zip_subsystem(void) {} -static inline int z_erofs_load_lz4_config(struct super_block *sb, - struct erofs_super_block *dsb, - struct z_erofs_lz4_cfgs *lz4, int len) -{ - if (lz4 || dsb->u1.lz4_max_distance) { - erofs_err(sb, "lz4 algorithm isn't enabled"); - return -EINVAL; - } - return 0; -} #endif /* !CONFIG_EROFS_FS_ZIP */ #define EFSCORRUPTED EUCLEAN /* Filesystem is corrupted */ diff --git a/fs/erofs/namei.c b/fs/erofs/namei.c index 5f8cc7346c69..3abbecbf73de 100644 --- a/fs/erofs/namei.c +++ b/fs/erofs/namei.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2017-2018 HUAWEI, Inc. - * https://www.huawei.com/ + * http://www.huawei.com/ * Created by Gao Xiang */ #include "xattr.h" @@ -244,7 +244,9 @@ static struct dentry *erofs_lookup(struct inode *dir, const struct inode_operations erofs_dir_iops = { .lookup = erofs_lookup, .getattr = erofs_getattr, +#ifdef CONFIG_EROFS_FS_XATTR .listxattr = erofs_listxattr, +#endif .get_acl = erofs_get_acl, }; diff --git a/fs/erofs/pcpubuf.c b/fs/erofs/pcpubuf.c deleted file mode 100644 index 6c885575128a..000000000000 --- a/fs/erofs/pcpubuf.c +++ /dev/null @@ -1,148 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (C) Gao Xiang - * - * For low-latency decompression algorithms (e.g. lz4), reserve consecutive - * per-CPU virtual memory (in pages) in advance to store such inplace I/O - * data if inplace decompression is failed (due to unmet inplace margin for - * example). - */ -#include "internal.h" - -struct erofs_pcpubuf { - raw_spinlock_t lock; - void *ptr; - struct page **pages; - unsigned int nrpages; -}; - -static DEFINE_PER_CPU(struct erofs_pcpubuf, erofs_pcb); - -void *erofs_get_pcpubuf(unsigned int requiredpages) - __acquires(pcb->lock) -{ - struct erofs_pcpubuf *pcb = &get_cpu_var(erofs_pcb); - - raw_spin_lock(&pcb->lock); - /* check if the per-CPU buffer is too small */ - if (requiredpages > pcb->nrpages) { - raw_spin_unlock(&pcb->lock); - put_cpu_var(erofs_pcb); - /* (for sparse checker) pretend pcb->lock is still taken */ - __acquire(pcb->lock); - return NULL; - } - return pcb->ptr; -} - -void erofs_put_pcpubuf(void *ptr) __releases(pcb->lock) -{ - struct erofs_pcpubuf *pcb = &per_cpu(erofs_pcb, smp_processor_id()); - - DBG_BUGON(pcb->ptr != ptr); - raw_spin_unlock(&pcb->lock); - put_cpu_var(erofs_pcb); -} - -/* the next step: support per-CPU page buffers hotplug */ -int erofs_pcpubuf_growsize(unsigned int nrpages) -{ - static DEFINE_MUTEX(pcb_resize_mutex); - static unsigned int pcb_nrpages; - LIST_HEAD(pagepool); - int delta, cpu, ret, i; - - mutex_lock(&pcb_resize_mutex); - delta = nrpages - pcb_nrpages; - ret = 0; - /* avoid shrinking pcpubuf, since no idea how many fses rely on */ - if (delta <= 0) - goto out; - - for_each_possible_cpu(cpu) { - struct erofs_pcpubuf *pcb = &per_cpu(erofs_pcb, cpu); - struct page **pages, **oldpages; - void *ptr, *old_ptr; - - pages = kmalloc_array(nrpages, sizeof(*pages), GFP_KERNEL); - if (!pages) { - ret = -ENOMEM; - break; - } - - for (i = 0; i < nrpages; ++i) { - pages[i] = erofs_allocpage(&pagepool, GFP_KERNEL); - if (!pages[i]) { - ret = -ENOMEM; - oldpages = pages; - goto free_pagearray; - } - } - ptr = vmap(pages, nrpages, VM_MAP, PAGE_KERNEL); - if (!ptr) { - ret = -ENOMEM; - oldpages = pages; - goto free_pagearray; - } - raw_spin_lock(&pcb->lock); - old_ptr = pcb->ptr; - pcb->ptr = ptr; - oldpages = pcb->pages; - pcb->pages = pages; - i = pcb->nrpages; - pcb->nrpages = nrpages; - raw_spin_unlock(&pcb->lock); - - if (!oldpages) { - DBG_BUGON(old_ptr); - continue; - } - - if (old_ptr) - vunmap(old_ptr); -free_pagearray: - while (i) - list_add(&oldpages[--i]->lru, &pagepool); - kfree(oldpages); - if (ret) - break; - } - pcb_nrpages = nrpages; - put_pages_list(&pagepool); -out: - mutex_unlock(&pcb_resize_mutex); - return ret; -} - -void erofs_pcpubuf_init(void) -{ - int cpu; - - for_each_possible_cpu(cpu) { - struct erofs_pcpubuf *pcb = &per_cpu(erofs_pcb, cpu); - - raw_spin_lock_init(&pcb->lock); - } -} - -void erofs_pcpubuf_exit(void) -{ - int cpu, i; - - for_each_possible_cpu(cpu) { - struct erofs_pcpubuf *pcb = &per_cpu(erofs_pcb, cpu); - - if (pcb->ptr) { - vunmap(pcb->ptr); - pcb->ptr = NULL; - } - if (!pcb->pages) - continue; - - for (i = 0; i < pcb->nrpages; ++i) - if (pcb->pages[i]) - put_page(pcb->pages[i]); - kfree(pcb->pages); - pcb->pages = NULL; - } -} diff --git a/fs/erofs/super.c b/fs/erofs/super.c index 975c8a18f0ed..22e059b4f745 100644 --- a/fs/erofs/super.c +++ b/fs/erofs/super.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2017-2018 HUAWEI, Inc. - * https://www.huawei.com/ + * http://www.huawei.com/ * Created by Gao Xiang */ #include @@ -9,9 +9,6 @@ #include #include #include -#include -#include -#include #include "xattr.h" #define CREATE_TRACE_POINTS @@ -49,30 +46,6 @@ void _erofs_info(struct super_block *sb, const char *function, va_end(args); } -static int erofs_superblock_csum_verify(struct super_block *sb, void *sbdata) -{ - struct erofs_super_block *dsb; - u32 expected_crc, crc; - - dsb = kmemdup(sbdata + EROFS_SUPER_OFFSET, - EROFS_BLKSIZ - EROFS_SUPER_OFFSET, GFP_KERNEL); - if (!dsb) - return -ENOMEM; - - expected_crc = le32_to_cpu(dsb->checksum); - dsb->checksum = 0; - /* to allow for x86 boot sectors and other oddities. */ - crc = crc32c(~0, dsb, EROFS_BLKSIZ - EROFS_SUPER_OFFSET); - kfree(dsb); - - if (crc != expected_crc) { - erofs_err(sb, "invalid checksum 0x%08x, 0x%08x expected", - crc, expected_crc); - return -EBADMSG; - } - return 0; -} - static void erofs_inode_init_once(void *ptr) { struct erofs_inode *vi = ptr; @@ -122,136 +95,6 @@ static bool check_layout_compatibility(struct super_block *sb, return true; } -#ifdef CONFIG_EROFS_FS_ZIP -/* read variable-sized metadata, offset will be aligned by 4-byte */ -static void *erofs_read_metadata(struct super_block *sb, struct page **pagep, - erofs_off_t *offset, int *lengthp) -{ - struct page *page = *pagep; - u8 *buffer, *ptr; - int len, i, cnt; - erofs_blk_t blk; - - *offset = round_up(*offset, 4); - blk = erofs_blknr(*offset); - - if (!page || page->index != blk) { - if (page) { - unlock_page(page); - put_page(page); - } - page = erofs_get_meta_page(sb, blk); - if (IS_ERR(page)) - goto err_nullpage; - } - - ptr = kmap(page); - len = le16_to_cpu(*(__le16 *)&ptr[erofs_blkoff(*offset)]); - if (!len) - len = U16_MAX + 1; - buffer = kmalloc(len, GFP_KERNEL); - if (!buffer) { - buffer = ERR_PTR(-ENOMEM); - goto out; - } - *offset += sizeof(__le16); - *lengthp = len; - - for (i = 0; i < len; i += cnt) { - cnt = min(EROFS_BLKSIZ - (int)erofs_blkoff(*offset), len - i); - blk = erofs_blknr(*offset); - - if (!page || page->index != blk) { - if (page) { - kunmap(page); - unlock_page(page); - put_page(page); - } - page = erofs_get_meta_page(sb, blk); - if (IS_ERR(page)) { - kfree(buffer); - goto err_nullpage; - } - ptr = kmap(page); - } - memcpy(buffer + i, ptr + erofs_blkoff(*offset), cnt); - *offset += cnt; - } -out: - kunmap(page); - *pagep = page; - return buffer; -err_nullpage: - *pagep = NULL; - return page; -} - -static int erofs_load_compr_cfgs(struct super_block *sb, - struct erofs_super_block *dsb) -{ - struct erofs_sb_info *sbi; - struct page *page; - unsigned int algs, alg; - erofs_off_t offset; - int size, ret; - - sbi = EROFS_SB(sb); - sbi->available_compr_algs = le16_to_cpu(dsb->u1.available_compr_algs); - - if (sbi->available_compr_algs & ~Z_EROFS_ALL_COMPR_ALGS) { - erofs_err(sb, "try to load compressed fs with unsupported algorithms %x", - sbi->available_compr_algs & ~Z_EROFS_ALL_COMPR_ALGS); - return -EINVAL; - } - - offset = EROFS_SUPER_OFFSET + sbi->sb_size; - page = NULL; - alg = 0; - ret = 0; - - for (algs = sbi->available_compr_algs; algs; algs >>= 1, ++alg) { - void *data; - - if (!(algs & 1)) - continue; - - data = erofs_read_metadata(sb, &page, &offset, &size); - if (IS_ERR(data)) { - ret = PTR_ERR(data); - goto err; - } - - switch (alg) { - case Z_EROFS_COMPRESSION_LZ4: - ret = z_erofs_load_lz4_config(sb, dsb, data, size); - break; - default: - DBG_BUGON(1); - ret = -EFAULT; - } - kfree(data); - if (ret) - goto err; - } -err: - if (page) { - unlock_page(page); - put_page(page); - } - return ret; -} -#else -static int erofs_load_compr_cfgs(struct super_block *sb, - struct erofs_super_block *dsb) -{ - if (dsb->u1.available_compr_algs) { - erofs_err(sb, "try to load compressed fs when compression is disabled"); - return -EINVAL; - } - return 0; -} -#endif - static int erofs_read_superblock(struct super_block *sb) { struct erofs_sb_info *sbi; @@ -269,7 +112,7 @@ static int erofs_read_superblock(struct super_block *sb) sbi = EROFS_SB(sb); - data = kmap(page); + data = kmap_atomic(page); dsb = (struct erofs_super_block *)(data + EROFS_SUPER_OFFSET); ret = -EINVAL; @@ -278,14 +121,6 @@ static int erofs_read_superblock(struct super_block *sb) goto out; } - sbi->feature_compat = le32_to_cpu(dsb->feature_compat); - if (erofs_sb_has_sb_chksum(sbi)) { - ret = erofs_superblock_csum_verify(sb, data); - if (ret) - goto out; - } - - ret = -EINVAL; blkszbits = dsb->blkszbits; /* 9(512 bytes) + LOG_SECTORS_PER_BLOCK == LOG_BLOCK_SIZE */ if (blkszbits != LOG_BLOCK_SIZE) { @@ -297,12 +132,6 @@ static int erofs_read_superblock(struct super_block *sb) if (!check_layout_compatibility(sb, dsb)) goto out; - sbi->sb_size = 128 + dsb->sb_extslots * EROFS_SB_EXTSLOT_SIZE; - if (sbi->sb_size > EROFS_BLKSIZ) { - erofs_err(sb, "invalid sb_extslots %u (more than a fs block)", - sbi->sb_size); - goto out; - } sbi->blocks = le32_to_cpu(dsb->blocks); sbi->meta_blkaddr = le32_to_cpu(dsb->meta_blkaddr); #ifdef CONFIG_EROFS_FS_XATTR @@ -324,101 +153,139 @@ static int erofs_read_superblock(struct super_block *sb) ret = -EFSCORRUPTED; goto out; } - - /* parse on-disk compression configurations */ - if (erofs_sb_has_compr_cfgs(sbi)) - ret = erofs_load_compr_cfgs(sb, dsb); - else - ret = z_erofs_load_lz4_config(sb, dsb, NULL, 0); + ret = 0; out: - kunmap(page); + kunmap_atomic(data); put_page(page); return ret; } +#ifdef CONFIG_EROFS_FS_ZIP +static int erofs_build_cache_strategy(struct super_block *sb, + substring_t *args) +{ + struct erofs_sb_info *sbi = EROFS_SB(sb); + const char *cs = match_strdup(args); + int err = 0; + + if (!cs) { + erofs_err(sb, "Not enough memory to store cache strategy"); + return -ENOMEM; + } + + if (!strcmp(cs, "disabled")) { + sbi->cache_strategy = EROFS_ZIP_CACHE_DISABLED; + } else if (!strcmp(cs, "readahead")) { + sbi->cache_strategy = EROFS_ZIP_CACHE_READAHEAD; + } else if (!strcmp(cs, "readaround")) { + sbi->cache_strategy = EROFS_ZIP_CACHE_READAROUND; + } else { + erofs_err(sb, "Unrecognized cache strategy \"%s\"", cs); + err = -EINVAL; + } + kfree(cs); + return err; +} +#else +static int erofs_build_cache_strategy(struct super_block *sb, + substring_t *args) +{ + erofs_info(sb, "EROFS compression is disabled, so cache strategy is ignored"); + return 0; +} +#endif + /* set up default EROFS parameters */ -static void erofs_default_options(struct erofs_fs_context *ctx) +static void erofs_default_options(struct erofs_sb_info *sbi) { #ifdef CONFIG_EROFS_FS_ZIP - ctx->cache_strategy = EROFS_ZIP_CACHE_READAROUND; - ctx->max_sync_decompress_pages = 3; - ctx->readahead_sync_decompress = false; + sbi->cache_strategy = EROFS_ZIP_CACHE_READAROUND; + sbi->max_sync_decompress_pages = 3; #endif #ifdef CONFIG_EROFS_FS_XATTR - set_opt(ctx, XATTR_USER); + set_opt(sbi, XATTR_USER); #endif #ifdef CONFIG_EROFS_FS_POSIX_ACL - set_opt(ctx, POSIX_ACL); + set_opt(sbi, POSIX_ACL); #endif } enum { Opt_user_xattr, + Opt_nouser_xattr, Opt_acl, + Opt_noacl, Opt_cache_strategy, Opt_err }; -static const struct fs_parameter_enum erofs_param_cache_strategy[] ={ - {Opt_cache_strategy, "disabled", EROFS_ZIP_CACHE_DISABLED}, - {Opt_cache_strategy, "readahead", EROFS_ZIP_CACHE_READAHEAD}, - {Opt_cache_strategy, "readaround", EROFS_ZIP_CACHE_READAROUND}, - {} +static match_table_t erofs_tokens = { + {Opt_user_xattr, "user_xattr"}, + {Opt_nouser_xattr, "nouser_xattr"}, + {Opt_acl, "acl"}, + {Opt_noacl, "noacl"}, + {Opt_cache_strategy, "cache_strategy=%s"}, + {Opt_err, NULL} }; -static const struct fs_parameter_spec erofs_fs_param_specs[] = { - fsparam_flag_no("user_xattr", Opt_user_xattr), - fsparam_flag_no("acl", Opt_acl), - fsparam_enum("cache_strategy", Opt_cache_strategy), - {} -}; -const struct fs_parameter_description erofs_fs_parameters = { - .name = "erofs", - .specs = erofs_fs_param_specs, - .enums = erofs_param_cache_strategy, -}; - -static int erofs_fc_parse_param(struct fs_context *fc, - struct fs_parameter *param) +static int erofs_parse_options(struct super_block *sb, char *options) { - struct erofs_fs_context *ctx __maybe_unused = fc->fs_private; - struct fs_parse_result result; - int opt; + substring_t args[MAX_OPT_ARGS]; + char *p; + int err; - opt = fs_parse(fc, &erofs_fs_parameters, param, &result); - if (opt < 0) - return opt; + if (!options) + return 0; - switch (opt) { - case Opt_user_xattr: + while ((p = strsep(&options, ","))) { + int token; + + if (!*p) + continue; + + args[0].to = args[0].from = NULL; + token = match_token(p, erofs_tokens, args); + + switch (token) { #ifdef CONFIG_EROFS_FS_XATTR - if (result.boolean) - set_opt(ctx, XATTR_USER); - else - clear_opt(ctx, XATTR_USER); + case Opt_user_xattr: + set_opt(EROFS_SB(sb), XATTR_USER); + break; + case Opt_nouser_xattr: + clear_opt(EROFS_SB(sb), XATTR_USER); + break; #else - errorfc(fc, "{,no}user_xattr options not supported"); + case Opt_user_xattr: + erofs_info(sb, "user_xattr options not supported"); + break; + case Opt_nouser_xattr: + erofs_info(sb, "nouser_xattr options not supported"); + break; #endif - break; - case Opt_acl: #ifdef CONFIG_EROFS_FS_POSIX_ACL - if (result.boolean) - set_opt(ctx, POSIX_ACL); - else - clear_opt(ctx, POSIX_ACL); + case Opt_acl: + set_opt(EROFS_SB(sb), POSIX_ACL); + break; + case Opt_noacl: + clear_opt(EROFS_SB(sb), POSIX_ACL); + break; #else - errorfc(fc, "{,no}acl options not supported"); + case Opt_acl: + erofs_info(sb, "acl options not supported"); + break; + case Opt_noacl: + erofs_info(sb, "noacl options not supported"); + break; #endif - break; - case Opt_cache_strategy: -#ifdef CONFIG_EROFS_FS_ZIP - ctx->cache_strategy = result.uint_32; -#else - errorfc(fc, "compression not supported, cache_strategy ignored"); -#endif - break; - default: - return -ENOPARAM; + case Opt_cache_strategy: + err = erofs_build_cache_strategy(sb, args); + if (err) + return err; + break; + default: + erofs_err(sb, "Unrecognized mount option \"%s\" or missing value", p); + return -EINVAL; + } } return 0; } @@ -482,11 +349,10 @@ static int erofs_init_managed_cache(struct super_block *sb) static int erofs_init_managed_cache(struct super_block *sb) { return 0; } #endif -static int erofs_fc_fill_super(struct super_block *sb, struct fs_context *fc) +static int erofs_fill_super(struct super_block *sb, void *data, int silent) { struct inode *inode; struct erofs_sb_info *sbi; - struct erofs_fs_context *ctx = fc->fs_private; int err; sb->s_magic = EROFS_SUPER_MAGIC; @@ -510,17 +376,24 @@ static int erofs_fc_fill_super(struct super_block *sb, struct fs_context *fc) sb->s_time_gran = 1; sb->s_op = &erofs_sops; - sb->s_xattr = erofs_xattr_handlers; - if (test_opt(ctx, POSIX_ACL)) +#ifdef CONFIG_EROFS_FS_XATTR + sb->s_xattr = erofs_xattr_handlers; +#endif + /* set erofs default mount options */ + erofs_default_options(sbi); + + err = erofs_parse_options(sb, data); + if (err) + return err; + + if (test_opt(sbi, POSIX_ACL)) sb->s_flags |= SB_POSIXACL; else sb->s_flags &= ~SB_POSIXACL; - sbi->ctx = *ctx; - #ifdef CONFIG_EROFS_FS_ZIP - xa_init(&sbi->managed_pslots); + INIT_RADIX_TREE(&sbi->workstn_tree, GFP_ATOMIC); #endif /* get the root inode */ @@ -545,58 +418,15 @@ static int erofs_fc_fill_super(struct super_block *sb, struct fs_context *fc) if (err) return err; - erofs_info(sb, "mounted with root inode @ nid %llu.", ROOT_NID(sbi)); + erofs_info(sb, "mounted with opts: %s, root inode @ nid %llu.", + (char *)data, ROOT_NID(sbi)); return 0; } -static int erofs_fc_get_tree(struct fs_context *fc) +static struct dentry *erofs_mount(struct file_system_type *fs_type, int flags, + const char *dev_name, void *data) { - return get_tree_bdev(fc, erofs_fc_fill_super); -} - -static int erofs_fc_reconfigure(struct fs_context *fc) -{ - struct super_block *sb = fc->root->d_sb; - struct erofs_sb_info *sbi = EROFS_SB(sb); - struct erofs_fs_context *ctx = fc->fs_private; - - DBG_BUGON(!sb_rdonly(sb)); - - if (test_opt(ctx, POSIX_ACL)) - fc->sb_flags |= SB_POSIXACL; - else - fc->sb_flags &= ~SB_POSIXACL; - - sbi->ctx = *ctx; - - fc->sb_flags |= SB_RDONLY; - return 0; -} - -static void erofs_fc_free(struct fs_context *fc) -{ - kfree(fc->fs_private); -} - -static const struct fs_context_operations erofs_context_ops = { - .parse_param = erofs_fc_parse_param, - .get_tree = erofs_fc_get_tree, - .reconfigure = erofs_fc_reconfigure, - .free = erofs_fc_free, -}; - -static int erofs_init_fs_context(struct fs_context *fc) -{ - fc->fs_private = kzalloc(sizeof(struct erofs_fs_context), GFP_KERNEL); - if (!fc->fs_private) - return -ENOMEM; - - /* set default mount options */ - erofs_default_options(fc->fs_private); - - fc->ops = &erofs_context_ops; - - return 0; + return mount_bdev(fs_type, flags, dev_name, data, erofs_fill_super); } /* @@ -635,7 +465,7 @@ static void erofs_put_super(struct super_block *sb) static struct file_system_type erofs_fs_type = { .owner = THIS_MODULE, .name = "erofs", - .init_fs_context = erofs_init_fs_context, + .mount = erofs_mount, .kill_sb = erofs_kill_sb, .fs_flags = FS_REQUIRES_DEV, }; @@ -660,7 +490,6 @@ static int __init erofs_module_init(void) if (err) goto shrinker_err; - erofs_pcpubuf_init(); err = z_erofs_init_zip_subsystem(); if (err) goto zip_err; @@ -690,7 +519,6 @@ static void __exit erofs_module_exit(void) /* Ensure all RCU free inodes are safe before cache is destroyed. */ rcu_barrier(); kmem_cache_destroy(erofs_inode_cachep); - erofs_pcpubuf_exit(); } /* get filesystem statistics */ @@ -710,44 +538,72 @@ static int erofs_statfs(struct dentry *dentry, struct kstatfs *buf) buf->f_namelen = EROFS_NAME_LEN; - buf->f_fsid = u64_to_fsid(id); + buf->f_fsid.val[0] = (u32)id; + buf->f_fsid.val[1] = (u32)(id >> 32); return 0; } static int erofs_show_options(struct seq_file *seq, struct dentry *root) { struct erofs_sb_info *sbi __maybe_unused = EROFS_SB(root->d_sb); - struct erofs_fs_context *ctx __maybe_unused = &sbi->ctx; #ifdef CONFIG_EROFS_FS_XATTR - if (test_opt(ctx, XATTR_USER)) + if (test_opt(sbi, XATTR_USER)) seq_puts(seq, ",user_xattr"); else seq_puts(seq, ",nouser_xattr"); #endif #ifdef CONFIG_EROFS_FS_POSIX_ACL - if (test_opt(ctx, POSIX_ACL)) + if (test_opt(sbi, POSIX_ACL)) seq_puts(seq, ",acl"); else seq_puts(seq, ",noacl"); #endif #ifdef CONFIG_EROFS_FS_ZIP - if (ctx->cache_strategy == EROFS_ZIP_CACHE_DISABLED) + if (sbi->cache_strategy == EROFS_ZIP_CACHE_DISABLED) { seq_puts(seq, ",cache_strategy=disabled"); - else if (ctx->cache_strategy == EROFS_ZIP_CACHE_READAHEAD) + } else if (sbi->cache_strategy == EROFS_ZIP_CACHE_READAHEAD) { seq_puts(seq, ",cache_strategy=readahead"); - else if (ctx->cache_strategy == EROFS_ZIP_CACHE_READAROUND) + } else if (sbi->cache_strategy == EROFS_ZIP_CACHE_READAROUND) { seq_puts(seq, ",cache_strategy=readaround"); + } else { + seq_puts(seq, ",cache_strategy=(unknown)"); + DBG_BUGON(1); + } #endif return 0; } +static int erofs_remount(struct super_block *sb, int *flags, char *data) +{ + struct erofs_sb_info *sbi = EROFS_SB(sb); + unsigned int org_mnt_opt = sbi->mount_opt; + int err; + + DBG_BUGON(!sb_rdonly(sb)); + err = erofs_parse_options(sb, data); + if (err) + goto out; + + if (test_opt(sbi, POSIX_ACL)) + sb->s_flags |= SB_POSIXACL; + else + sb->s_flags &= ~SB_POSIXACL; + + *flags |= SB_RDONLY; + return 0; +out: + sbi->mount_opt = org_mnt_opt; + return err; +} + const struct super_operations erofs_sops = { .put_super = erofs_put_super, .alloc_inode = erofs_alloc_inode, .free_inode = erofs_free_inode, .statfs = erofs_statfs, .show_options = erofs_show_options, + .remount_fs = erofs_remount, }; module_init(erofs_module_init); @@ -756,5 +612,4 @@ module_exit(erofs_module_exit); MODULE_DESCRIPTION("Enhanced ROM File System"); MODULE_AUTHOR("Gao Xiang, Chao Yu, Miao Xie, CONSUMER BG, HUAWEI Inc."); MODULE_LICENSE("GPL"); -MODULE_IMPORT_NS(ANDROID_GKI_VFS_EXPORT_ONLY); diff --git a/fs/erofs/utils.c b/fs/erofs/utils.c index 9d9c2c73bebd..3e28fd082df0 100644 --- a/fs/erofs/utils.c +++ b/fs/erofs/utils.c @@ -1,13 +1,13 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2018 HUAWEI, Inc. - * https://www.huawei.com/ + * http://www.huawei.com/ * Created by Gao Xiang */ #include "internal.h" #include -struct page *erofs_allocpage(struct list_head *pool, gfp_t gfp) +struct page *erofs_allocpage(struct list_head *pool, gfp_t gfp, bool nofail) { struct page *page; @@ -16,15 +16,30 @@ struct page *erofs_allocpage(struct list_head *pool, gfp_t gfp) DBG_BUGON(page_ref_count(page) != 1); list_del(&page->lru); } else { - page = alloc_page(gfp); + page = alloc_pages(gfp | (nofail ? __GFP_NOFAIL : 0), 0); } return page; } +#if (EROFS_PCPUBUF_NR_PAGES > 0) +static struct { + u8 data[PAGE_SIZE * EROFS_PCPUBUF_NR_PAGES]; +} ____cacheline_aligned_in_smp erofs_pcpubuf[NR_CPUS]; + +void *erofs_get_pcpubuf(unsigned int pagenr) +{ + preempt_disable(); + return &erofs_pcpubuf[smp_processor_id()].data[pagenr * PAGE_SIZE]; +} +#endif + #ifdef CONFIG_EROFS_FS_ZIP /* global shrink count (for all mounted EROFS instances) */ static atomic_long_t erofs_global_shrink_cnt; +#define __erofs_workgroup_get(grp) atomic_inc(&(grp)->refcount) +#define __erofs_workgroup_put(grp) atomic_dec(&(grp)->refcount) + static int erofs_workgroup_get(struct erofs_workgroup *grp) { int o; @@ -44,15 +59,18 @@ repeat: } struct erofs_workgroup *erofs_find_workgroup(struct super_block *sb, - pgoff_t index) + pgoff_t index, bool *tag) { struct erofs_sb_info *sbi = EROFS_SB(sb); struct erofs_workgroup *grp; repeat: rcu_read_lock(); - grp = xa_load(&sbi->managed_pslots, index); + grp = radix_tree_lookup(&sbi->workstn_tree, index); if (grp) { + *tag = xa_pointer_tag(grp); + grp = xa_untag_pointer(grp); + if (erofs_workgroup_get(grp)) { /* prefer to relax rcu read side */ rcu_read_unlock(); @@ -65,37 +83,46 @@ repeat: return grp; } -struct erofs_workgroup *erofs_insert_workgroup(struct super_block *sb, - struct erofs_workgroup *grp) +int erofs_register_workgroup(struct super_block *sb, + struct erofs_workgroup *grp, + bool tag) { - struct erofs_sb_info *const sbi = EROFS_SB(sb); - struct erofs_workgroup *pre; + struct erofs_sb_info *sbi; + int err; + + /* grp shouldn't be broken or used before */ + if (atomic_read(&grp->refcount) != 1) { + DBG_BUGON(1); + return -EINVAL; + } + + err = radix_tree_preload(GFP_NOFS); + if (err) + return err; + + sbi = EROFS_SB(sb); + xa_lock(&sbi->workstn_tree); + + grp = xa_tag_pointer(grp, tag); /* - * Bump up a reference count before making this visible - * to others for the XArray in order to avoid potential - * UAF without serialized by xa_lock. + * Bump up reference count before making this workgroup + * visible to other users in order to avoid potential UAF + * without serialized by workstn_lock. */ - atomic_inc(&grp->refcount); + __erofs_workgroup_get(grp); -repeat: - xa_lock(&sbi->managed_pslots); - pre = __xa_cmpxchg(&sbi->managed_pslots, grp->index, - NULL, grp, GFP_NOFS); - if (pre) { - if (xa_is_err(pre)) { - pre = ERR_PTR(xa_err(pre)); - } else if (erofs_workgroup_get(pre)) { - /* try to legitimize the current in-tree one */ - xa_unlock(&sbi->managed_pslots); - cond_resched(); - goto repeat; - } - atomic_dec(&grp->refcount); - grp = pre; - } - xa_unlock(&sbi->managed_pslots); - return grp; + err = radix_tree_insert(&sbi->workstn_tree, grp->index, grp); + if (err) + /* + * it's safe to decrease since the workgroup isn't visible + * and refcount >= 2 (cannot be freezed). + */ + __erofs_workgroup_put(grp); + + xa_unlock(&sbi->workstn_tree); + radix_tree_preload_end(); + return err; } static void __erofs_workgroup_free(struct erofs_workgroup *grp) @@ -115,8 +142,15 @@ int erofs_workgroup_put(struct erofs_workgroup *grp) return count; } +static void erofs_workgroup_unfreeze_final(struct erofs_workgroup *grp) +{ + erofs_workgroup_unfreeze(grp, 0); + __erofs_workgroup_free(grp); +} + static bool erofs_try_to_release_workgroup(struct erofs_sb_info *sbi, - struct erofs_workgroup *grp) + struct erofs_workgroup *grp, + bool cleanup) { /* * If managed cache is on, refcount of workgroups @@ -128,7 +162,7 @@ static bool erofs_try_to_release_workgroup(struct erofs_sb_info *sbi, /* * Note that all cached pages should be unattached - * before deleted from the XArray. Otherwise some + * before deleted from the radix tree. Otherwise some * cached pages could be still attached to the orphan * old workgroup when the new one is available in the tree. */ @@ -142,34 +176,49 @@ static bool erofs_try_to_release_workgroup(struct erofs_sb_info *sbi, * however in order to avoid some race conditions, add a * DBG_BUGON to observe this in advance. */ - DBG_BUGON(__xa_erase(&sbi->managed_pslots, grp->index) != grp); + DBG_BUGON(xa_untag_pointer(radix_tree_delete(&sbi->workstn_tree, + grp->index)) != grp); - /* last refcount should be connected with its managed pslot. */ - erofs_workgroup_unfreeze(grp, 0); - __erofs_workgroup_free(grp); + /* + * If managed cache is on, last refcount should indicate + * the related workstation. + */ + erofs_workgroup_unfreeze_final(grp); return true; } static unsigned long erofs_shrink_workstation(struct erofs_sb_info *sbi, - unsigned long nr_shrink) + unsigned long nr_shrink, + bool cleanup) { - struct erofs_workgroup *grp; + pgoff_t first_index = 0; + void *batch[PAGEVEC_SIZE]; unsigned int freed = 0; - unsigned long index; - xa_lock(&sbi->managed_pslots); - xa_for_each(&sbi->managed_pslots, index, grp) { + int i, found; +repeat: + xa_lock(&sbi->workstn_tree); + + found = radix_tree_gang_lookup(&sbi->workstn_tree, + batch, first_index, PAGEVEC_SIZE); + + for (i = 0; i < found; ++i) { + struct erofs_workgroup *grp = xa_untag_pointer(batch[i]); + + first_index = grp->index + 1; + /* try to shrink each valid workgroup */ - if (!erofs_try_to_release_workgroup(sbi, grp)) + if (!erofs_try_to_release_workgroup(sbi, grp, cleanup)) continue; - xa_unlock(&sbi->managed_pslots); ++freed; if (!--nr_shrink) - return freed; - xa_lock(&sbi->managed_pslots); + break; } - xa_unlock(&sbi->managed_pslots); + xa_unlock(&sbi->workstn_tree); + + if (i && nr_shrink) + goto repeat; return freed; } @@ -196,8 +245,7 @@ void erofs_shrinker_unregister(struct super_block *sb) struct erofs_sb_info *const sbi = EROFS_SB(sb); mutex_lock(&sbi->umount_mutex); - /* clean up all remaining workgroups in memory */ - erofs_shrink_workstation(sbi, ~0UL); + erofs_shrink_workstation(sbi, ~0UL, true); spin_lock(&erofs_sb_list_lock); list_del(&sbi->list); @@ -246,7 +294,7 @@ static unsigned long erofs_shrink_scan(struct shrinker *shrink, spin_unlock(&erofs_sb_list_lock); sbi->shrinker_run_no = run_no; - freed += erofs_shrink_workstation(sbi, nr - freed); + freed += erofs_shrink_workstation(sbi, nr - freed, false); spin_lock(&erofs_sb_list_lock); /* Get the next list element before we move this one */ diff --git a/fs/erofs/xattr.c b/fs/erofs/xattr.c index 6330bca9d91d..7d6e38116254 100644 --- a/fs/erofs/xattr.c +++ b/fs/erofs/xattr.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2017-2018 HUAWEI, Inc. - * https://www.huawei.com/ + * http://www.huawei.com/ * Created by Gao Xiang */ #include @@ -430,7 +430,7 @@ static int shared_getxattr(struct inode *inode, struct getxattr_iter *it) static bool erofs_xattr_user_list(struct dentry *dentry) { - return test_opt(&EROFS_SB(dentry->d_sb)->ctx, XATTR_USER); + return test_opt(EROFS_SB(dentry->d_sb), XATTR_USER); } static bool erofs_xattr_trusted_list(struct dentry *dentry) @@ -478,7 +478,7 @@ static int erofs_xattr_generic_get(const struct xattr_handler *handler, switch (handler->flags) { case EROFS_XATTR_INDEX_USER: - if (!test_opt(&sbi->ctx, XATTR_USER)) + if (!test_opt(sbi, XATTR_USER)) return -EOPNOTSUPP; break; case EROFS_XATTR_INDEX_TRUSTED: diff --git a/fs/erofs/xattr.h b/fs/erofs/xattr.h index 815304bd335f..3585b84d2f20 100644 --- a/fs/erofs/xattr.h +++ b/fs/erofs/xattr.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (C) 2017-2018 HUAWEI, Inc. - * https://www.huawei.com/ + * http://www.huawei.com/ * Created by Gao Xiang */ #ifndef __EROFS_XATTR_H @@ -46,19 +46,18 @@ extern const struct xattr_handler erofs_xattr_security_handler; static inline const struct xattr_handler *erofs_xattr_handler(unsigned int idx) { - static const struct xattr_handler *xattr_handler_map[] = { - [EROFS_XATTR_INDEX_USER] = &erofs_xattr_user_handler, +static const struct xattr_handler *xattr_handler_map[] = { + [EROFS_XATTR_INDEX_USER] = &erofs_xattr_user_handler, #ifdef CONFIG_EROFS_FS_POSIX_ACL - [EROFS_XATTR_INDEX_POSIX_ACL_ACCESS] = - &posix_acl_access_xattr_handler, - [EROFS_XATTR_INDEX_POSIX_ACL_DEFAULT] = - &posix_acl_default_xattr_handler, + [EROFS_XATTR_INDEX_POSIX_ACL_ACCESS] = &posix_acl_access_xattr_handler, + [EROFS_XATTR_INDEX_POSIX_ACL_DEFAULT] = + &posix_acl_default_xattr_handler, #endif - [EROFS_XATTR_INDEX_TRUSTED] = &erofs_xattr_trusted_handler, + [EROFS_XATTR_INDEX_TRUSTED] = &erofs_xattr_trusted_handler, #ifdef CONFIG_EROFS_FS_SECURITY - [EROFS_XATTR_INDEX_SECURITY] = &erofs_xattr_security_handler, + [EROFS_XATTR_INDEX_SECURITY] = &erofs_xattr_security_handler, #endif - }; +}; return idx && idx < ARRAY_SIZE(xattr_handler_map) ? xattr_handler_map[idx] : NULL; @@ -76,8 +75,11 @@ static inline int erofs_getxattr(struct inode *inode, int index, return -EOPNOTSUPP; } -#define erofs_listxattr (NULL) -#define erofs_xattr_handlers (NULL) +static inline ssize_t erofs_listxattr(struct dentry *dentry, + char *buffer, size_t buffer_size) +{ + return -EOPNOTSUPP; +} #endif /* !CONFIG_EROFS_FS_XATTR */ #ifdef CONFIG_EROFS_FS_POSIX_ACL diff --git a/fs/erofs/zdata.c b/fs/erofs/zdata.c index 15e03d0f60a0..fb718c3e3ebd 100644 --- a/fs/erofs/zdata.c +++ b/fs/erofs/zdata.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2018 HUAWEI, Inc. - * https://www.huawei.com/ + * http://www.huawei.com/ * Created by Gao Xiang */ #include "zdata.h" @@ -10,93 +10,6 @@ #include -/* - * since pclustersize is variable for big pcluster feature, introduce slab - * pools implementation for different pcluster sizes. - */ -struct z_erofs_pcluster_slab { - struct kmem_cache *slab; - unsigned int maxpages; - char name[48]; -}; - -#define _PCLP(n) { .maxpages = n } - -static struct z_erofs_pcluster_slab pcluster_pool[] __read_mostly = { - _PCLP(1), _PCLP(4), _PCLP(16), _PCLP(64), _PCLP(128), - _PCLP(Z_EROFS_PCLUSTER_MAX_PAGES) -}; - -static void z_erofs_destroy_pcluster_pool(void) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(pcluster_pool); ++i) { - if (!pcluster_pool[i].slab) - continue; - kmem_cache_destroy(pcluster_pool[i].slab); - pcluster_pool[i].slab = NULL; - } -} - -static int z_erofs_create_pcluster_pool(void) -{ - struct z_erofs_pcluster_slab *pcs; - struct z_erofs_pcluster *a; - unsigned int size; - - for (pcs = pcluster_pool; - pcs < pcluster_pool + ARRAY_SIZE(pcluster_pool); ++pcs) { - size = struct_size(a, compressed_pages, pcs->maxpages); - - sprintf(pcs->name, "erofs_pcluster-%u", pcs->maxpages); - pcs->slab = kmem_cache_create(pcs->name, size, 0, - SLAB_RECLAIM_ACCOUNT, NULL); - if (pcs->slab) - continue; - - z_erofs_destroy_pcluster_pool(); - return -ENOMEM; - } - return 0; -} - -static struct z_erofs_pcluster *z_erofs_alloc_pcluster(unsigned int nrpages) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(pcluster_pool); ++i) { - struct z_erofs_pcluster_slab *pcs = pcluster_pool + i; - struct z_erofs_pcluster *pcl; - - if (nrpages > pcs->maxpages) - continue; - - pcl = kmem_cache_zalloc(pcs->slab, GFP_NOFS); - if (!pcl) - return ERR_PTR(-ENOMEM); - pcl->pclusterpages = nrpages; - return pcl; - } - return ERR_PTR(-EINVAL); -} - -static void z_erofs_free_pcluster(struct z_erofs_pcluster *pcl) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(pcluster_pool); ++i) { - struct z_erofs_pcluster_slab *pcs = pcluster_pool + i; - - if (pcl->pclusterpages > pcs->maxpages) - continue; - - kmem_cache_free(pcs->slab, pcl); - return; - } - DBG_BUGON(1); -} - /* * a compressed_pages[] placeholder in order to avoid * being filled with file pages for in-place decompression. @@ -107,11 +20,6 @@ static void z_erofs_free_pcluster(struct z_erofs_pcluster *pcl) enum z_erofs_cache_alloctype { DONTALLOC, /* don't allocate any cached pages */ DELAYEDALLOC, /* delayed allocation (at the time of submitting io) */ - /* - * try to use cached I/O if page allocation succeeds or fallback - * to in-place I/O instead to avoid any direct reclaim. - */ - TRYALLOC, }; /* @@ -124,37 +32,64 @@ typedef tagptr1_t compressed_page_t; tagptr_fold(compressed_page_t, page, 1) static struct workqueue_struct *z_erofs_workqueue __read_mostly; +static struct kmem_cache *pcluster_cachep __read_mostly; void z_erofs_exit_zip_subsystem(void) { destroy_workqueue(z_erofs_workqueue); - z_erofs_destroy_pcluster_pool(); + kmem_cache_destroy(pcluster_cachep); } static inline int z_erofs_init_workqueue(void) { const unsigned int onlinecpus = num_possible_cpus(); + const unsigned int flags = WQ_UNBOUND | WQ_HIGHPRI | WQ_CPU_INTENSIVE; /* * no need to spawn too many threads, limiting threads could minimum * scheduling overhead, perhaps per-CPU threads should be better? */ - z_erofs_workqueue = alloc_workqueue("erofs_unzipd", - WQ_UNBOUND | WQ_HIGHPRI, + z_erofs_workqueue = alloc_workqueue("erofs_unzipd", flags, onlinecpus + onlinecpus / 4); return z_erofs_workqueue ? 0 : -ENOMEM; } +static void z_erofs_pcluster_init_once(void *ptr) +{ + struct z_erofs_pcluster *pcl = ptr; + struct z_erofs_collection *cl = z_erofs_primarycollection(pcl); + unsigned int i; + + mutex_init(&cl->lock); + cl->nr_pages = 0; + cl->vcnt = 0; + for (i = 0; i < Z_EROFS_CLUSTER_MAX_PAGES; ++i) + pcl->compressed_pages[i] = NULL; +} + +static void z_erofs_pcluster_init_always(struct z_erofs_pcluster *pcl) +{ + struct z_erofs_collection *cl = z_erofs_primarycollection(pcl); + + atomic_set(&pcl->obj.refcount, 1); + + DBG_BUGON(cl->nr_pages); + DBG_BUGON(cl->vcnt); +} + int __init z_erofs_init_zip_subsystem(void) { - int err = z_erofs_create_pcluster_pool(); + pcluster_cachep = kmem_cache_create("erofs_compress", + Z_EROFS_WORKGROUP_SIZE, 0, + SLAB_RECLAIM_ACCOUNT, + z_erofs_pcluster_init_once); + if (pcluster_cachep) { + if (!z_erofs_init_workqueue()) + return 0; - if (err) - return err; - err = z_erofs_init_workqueue(); - if (err) - z_erofs_destroy_pcluster_pool(); - return err; + kmem_cache_destroy(pcluster_cachep); + } + return -ENOMEM; } enum z_erofs_collectmode { @@ -174,12 +109,6 @@ enum z_erofs_collectmode { * |_______PRIMARY_FOLLOWED_______|________PRIMARY_HOOKED___________| */ COLLECT_PRIMARY_HOOKED, - /* - * a weak form of COLLECT_PRIMARY_FOLLOWED, the difference is that it - * could be dispatched into bypass queue later due to uptodated managed - * pages. All related online pages cannot be reused for inplace I/O (or - * pagevec) since it can be directly decoded without I/O submission. - */ COLLECT_PRIMARY_FOLLOWED_NOINPLACE, /* * The current collection has been linked with the owned chain, and @@ -204,8 +133,7 @@ struct z_erofs_collector { struct z_erofs_pcluster *pcl, *tailpcl; struct z_erofs_collection *cl; - /* a pointer used to pick up inplace I/O pages */ - struct page **icpage_ptr; + struct page **compressedpages; z_erofs_next_pcluster_t owned_head; enum z_erofs_collectmode mode; @@ -217,7 +145,6 @@ struct z_erofs_decompress_frontend { struct z_erofs_collector clt; struct erofs_map_blocks map; - bool readahead; /* used for applying cache strategy on the fly */ bool backmost; erofs_off_t headoffset; @@ -239,22 +166,18 @@ static void preload_compressed_pages(struct z_erofs_collector *clt, enum z_erofs_cache_alloctype type, struct list_head *pagepool) { - struct z_erofs_pcluster *pcl = clt->pcl; + const struct z_erofs_pcluster *pcl = clt->pcl; + const unsigned int clusterpages = BIT(pcl->clusterbits); + struct page **pages = clt->compressedpages; + pgoff_t index = pcl->obj.index + (pages - pcl->compressed_pages); bool standalone = true; - gfp_t gfp = (mapping_gfp_mask(mc) & ~__GFP_DIRECT_RECLAIM) | - __GFP_NOMEMALLOC | __GFP_NORETRY | __GFP_NOWARN; - struct page **pages; - pgoff_t index; if (clt->mode < COLLECT_PRIMARY_FOLLOWED) return; - pages = pcl->compressed_pages; - index = pcl->obj.index; - for (; index < pcl->obj.index + pcl->pclusterpages; ++index, ++pages) { + for (; pages < pcl->compressed_pages + clusterpages; ++pages) { struct page *page; compressed_page_t t; - struct page *newpage = NULL; /* the compressed page was loaded before */ if (READ_ONCE(*pages)) @@ -264,43 +187,23 @@ static void preload_compressed_pages(struct z_erofs_collector *clt, if (page) { t = tag_compressed_page_justfound(page); - } else { - /* I/O is needed, no possible to decompress directly */ + } else if (type == DELAYEDALLOC) { + t = tagptr_init(compressed_page_t, PAGE_UNALLOCATED); + } else { /* DONTALLOC */ + if (standalone) + clt->compressedpages = pages; standalone = false; - switch (type) { - case DELAYEDALLOC: - t = tagptr_init(compressed_page_t, - PAGE_UNALLOCATED); - break; - case TRYALLOC: - newpage = erofs_allocpage(pagepool, gfp); - if (!newpage) - continue; - set_page_private(newpage, - Z_EROFS_PREALLOCATED_PAGE); - t = tag_compressed_page_justfound(newpage); - break; - default: /* DONTALLOC */ - continue; - } + continue; } if (!cmpxchg_relaxed(pages, NULL, tagptr_cast_ptr(t))) continue; - if (page) { + if (page) put_page(page); - } else if (newpage) { - set_page_private(newpage, 0); - list_add(&newpage->lru, pagepool); - } } - /* - * don't do inplace I/O if all compressed pages are available in - * managed cache since it can be moved to the bypass queue instead. - */ - if (standalone) + if (standalone) /* downgrade to PRIMARY_FOLLOWED_NOINPLACE */ clt->mode = COLLECT_PRIMARY_FOLLOWED_NOINPLACE; } @@ -311,13 +214,14 @@ int erofs_try_to_free_all_cached_pages(struct erofs_sb_info *sbi, struct z_erofs_pcluster *const pcl = container_of(grp, struct z_erofs_pcluster, obj); struct address_space *const mapping = MNGD_MAPPING(sbi); + const unsigned int clusterpages = BIT(pcl->clusterbits); int i; /* * refcount of workgroup is now freezed as 1, * therefore no need to worry about available decompression users. */ - for (i = 0; i < pcl->pclusterpages; ++i) { + for (i = 0; i < clusterpages; ++i) { struct page *page = pcl->compressed_pages[i]; if (!page) @@ -332,8 +236,11 @@ int erofs_try_to_free_all_cached_pages(struct erofs_sb_info *sbi, /* barrier is implied in the following 'unlock_page' */ WRITE_ONCE(pcl->compressed_pages[i], NULL); - detach_page_private(page); + set_page_private(page, 0); + ClearPagePrivate(page); + unlock_page(page); + put_page(page); } return 0; } @@ -342,12 +249,13 @@ int erofs_try_to_free_cached_page(struct address_space *mapping, struct page *page) { struct z_erofs_pcluster *const pcl = (void *)page_private(page); + const unsigned int clusterpages = BIT(pcl->clusterbits); int ret = 0; /* 0 - busy */ if (erofs_workgroup_try_to_freeze(&pcl->obj, 1)) { unsigned int i; - for (i = 0; i < pcl->pclusterpages; ++i) { + for (i = 0; i < clusterpages; ++i) { if (pcl->compressed_pages[i] == page) { WRITE_ONCE(pcl->compressed_pages[i], NULL); ret = 1; @@ -356,21 +264,25 @@ int erofs_try_to_free_cached_page(struct address_space *mapping, } erofs_workgroup_unfreeze(&pcl->obj, 1); - if (ret) - detach_page_private(page); + if (ret) { + ClearPagePrivate(page); + put_page(page); + } } return ret; } /* page_type must be Z_EROFS_PAGE_TYPE_EXCLUSIVE */ -static bool z_erofs_try_inplace_io(struct z_erofs_collector *clt, - struct page *page) +static inline bool z_erofs_try_inplace_io(struct z_erofs_collector *clt, + struct page *page) { struct z_erofs_pcluster *const pcl = clt->pcl; + const unsigned int clusterpages = BIT(pcl->clusterbits); - while (clt->icpage_ptr > pcl->compressed_pages) - if (!cmpxchg(--clt->icpage_ptr, NULL, page)) + while (clt->compressedpages < pcl->compressed_pages + clusterpages) { + if (!cmpxchg(clt->compressedpages++, NULL, page)) return true; + } return false; } @@ -423,31 +335,40 @@ retry: return COLLECT_PRIMARY; /* :( better luck next time */ } -static int z_erofs_lookup_collection(struct z_erofs_collector *clt, - struct inode *inode, - struct erofs_map_blocks *map) +static struct z_erofs_collection *cllookup(struct z_erofs_collector *clt, + struct inode *inode, + struct erofs_map_blocks *map) { - struct z_erofs_pcluster *pcl = clt->pcl; + struct erofs_workgroup *grp; + struct z_erofs_pcluster *pcl; struct z_erofs_collection *cl; unsigned int length; + bool tag; - /* to avoid unexpected loop formed by corrupted images */ + grp = erofs_find_workgroup(inode->i_sb, map->m_pa >> PAGE_SHIFT, &tag); + if (!grp) + return NULL; + + pcl = container_of(grp, struct z_erofs_pcluster, obj); if (clt->owned_head == &pcl->next || pcl == clt->tailpcl) { DBG_BUGON(1); - return -EFSCORRUPTED; + erofs_workgroup_put(grp); + return ERR_PTR(-EFSCORRUPTED); } cl = z_erofs_primarycollection(pcl); if (cl->pageofs != (map->m_la & ~PAGE_MASK)) { DBG_BUGON(1); - return -EFSCORRUPTED; + erofs_workgroup_put(grp); + return ERR_PTR(-EFSCORRUPTED); } length = READ_ONCE(pcl->length); if (length & Z_EROFS_PCLUSTER_FULL_LENGTH) { if ((map->m_llen << Z_EROFS_PCLUSTER_LENGTH_BIT) > length) { DBG_BUGON(1); - return -EFSCORRUPTED; + erofs_workgroup_put(grp); + return ERR_PTR(-EFSCORRUPTED); } } else { unsigned int llen = map->m_llen << Z_EROFS_PCLUSTER_LENGTH_BIT; @@ -469,25 +390,25 @@ static int z_erofs_lookup_collection(struct z_erofs_collector *clt, /* clean tailpcl if the current owned_head is Z_EROFS_PCLUSTER_TAIL */ if (clt->owned_head == Z_EROFS_PCLUSTER_TAIL) clt->tailpcl = NULL; + clt->pcl = pcl; clt->cl = cl; - return 0; + return cl; } -static int z_erofs_register_collection(struct z_erofs_collector *clt, - struct inode *inode, - struct erofs_map_blocks *map) +static struct z_erofs_collection *clregister(struct z_erofs_collector *clt, + struct inode *inode, + struct erofs_map_blocks *map) { struct z_erofs_pcluster *pcl; struct z_erofs_collection *cl; - struct erofs_workgroup *grp; int err; - /* no available pcluster, let's allocate one */ - pcl = z_erofs_alloc_pcluster(map->m_plen >> PAGE_SHIFT); - if (IS_ERR(pcl)) - return PTR_ERR(pcl); + /* no available workgroup, let's allocate one */ + pcl = kmem_cache_alloc(pcluster_cachep, GFP_NOFS); + if (!pcl) + return ERR_PTR(-ENOMEM); - atomic_set(&pcl->obj.refcount, 1); + z_erofs_pcluster_init_always(pcl); pcl->obj.index = map->m_pa >> PAGE_SHIFT; pcl->length = (map->m_llen << Z_EROFS_PCLUSTER_LENGTH_BIT) | @@ -499,6 +420,9 @@ static int z_erofs_register_collection(struct z_erofs_collector *clt, else pcl->algorithmformat = Z_EROFS_COMPRESSION_SHIFTED; + pcl->clusterbits = EROFS_I(inode)->z_physical_clusterbits[0]; + pcl->clusterbits -= PAGE_SHIFT; + /* new pclusters should be claimed as type 1, primary and followed */ pcl->next = clt->owned_head; clt->mode = COLLECT_PRIMARY_FOLLOWED; @@ -510,19 +434,13 @@ static int z_erofs_register_collection(struct z_erofs_collector *clt, * lock all primary followed works before visible to others * and mutex_trylock *never* fails for a new pcluster. */ - mutex_init(&cl->lock); - DBG_BUGON(!mutex_trylock(&cl->lock)); + mutex_trylock(&cl->lock); - grp = erofs_insert_workgroup(inode->i_sb, &pcl->obj); - if (IS_ERR(grp)) { - err = PTR_ERR(grp); - goto err_out; - } - - if (grp != &pcl->obj) { - clt->pcl = container_of(grp, struct z_erofs_pcluster, obj); - err = -EEXIST; - goto err_out; + err = erofs_register_workgroup(inode->i_sb, &pcl->obj, 0); + if (err) { + mutex_unlock(&cl->lock); + kmem_cache_free(pcluster_cachep, pcl); + return ERR_PTR(-EAGAIN); } /* used to check tail merging loop due to corrupted images */ if (clt->owned_head == Z_EROFS_PCLUSTER_TAIL) @@ -530,20 +448,14 @@ static int z_erofs_register_collection(struct z_erofs_collector *clt, clt->owned_head = &pcl->next; clt->pcl = pcl; clt->cl = cl; - return 0; - -err_out: - mutex_unlock(&cl->lock); - z_erofs_free_pcluster(pcl); - return err; + return cl; } static int z_erofs_collector_begin(struct z_erofs_collector *clt, struct inode *inode, struct erofs_map_blocks *map) { - struct erofs_workgroup *grp; - int ret; + struct z_erofs_collection *cl; DBG_BUGON(clt->cl); @@ -556,30 +468,24 @@ static int z_erofs_collector_begin(struct z_erofs_collector *clt, return -EINVAL; } - grp = erofs_find_workgroup(inode->i_sb, map->m_pa >> PAGE_SHIFT); - if (grp) { - clt->pcl = container_of(grp, struct z_erofs_pcluster, obj); - } else { - ret = z_erofs_register_collection(clt, inode, map); +repeat: + cl = cllookup(clt, inode, map); + if (!cl) { + cl = clregister(clt, inode, map); - if (!ret) - goto out; - if (ret != -EEXIST) - return ret; + if (cl == ERR_PTR(-EAGAIN)) + goto repeat; } - ret = z_erofs_lookup_collection(clt, inode, map); - if (ret) { - erofs_workgroup_put(&clt->pcl->obj); - return ret; - } + if (IS_ERR(cl)) + return PTR_ERR(cl); -out: z_erofs_pagevec_ctor_init(&clt->vector, Z_EROFS_NR_INLINE_PAGEVECS, - clt->cl->pagevec, clt->cl->vcnt); + cl->pagevec, cl->vcnt); - /* since file-backed online pages are traversed in reverse order */ - clt->icpage_ptr = clt->pcl->compressed_pages + clt->pcl->pclusterpages; + clt->compressedpages = clt->pcl->compressed_pages; + if (clt->mode <= COLLECT_PRIMARY) /* cannot do in-place I/O */ + clt->compressedpages += Z_EROFS_CLUSTER_MAX_PAGES; return 0; } @@ -592,8 +498,9 @@ static void z_erofs_rcu_callback(struct rcu_head *head) struct z_erofs_collection *const cl = container_of(head, struct z_erofs_collection, rcu); - z_erofs_free_pcluster(container_of(cl, struct z_erofs_pcluster, - primary_collection)); + kmem_cache_free(pcluster_cachep, + container_of(cl, struct z_erofs_pcluster, + primary_collection)); } void erofs_workgroup_free_rcu(struct erofs_workgroup *grp) @@ -634,6 +541,15 @@ static bool z_erofs_collector_end(struct z_erofs_collector *clt) return true; } +static inline struct page *__stagingpage_alloc(struct list_head *pagepool, + gfp_t gfp) +{ + struct page *page = erofs_allocpage(pagepool, gfp, true); + + page->mapping = Z_EROFS_MAPPING_STAGING; + return page; +} + static bool should_alloc_managed_pages(struct z_erofs_decompress_frontend *fe, unsigned int cachestrategy, erofs_off_t la) @@ -649,10 +565,11 @@ static bool should_alloc_managed_pages(struct z_erofs_decompress_frontend *fe, } static int z_erofs_do_read_page(struct z_erofs_decompress_frontend *fe, - struct page *page, struct list_head *pagepool) + struct page *page, + struct list_head *pagepool) { struct inode *const inode = fe->inode; - struct erofs_sb_info *const sbi = EROFS_I_SB(inode); + struct erofs_sb_info *const sbi __maybe_unused = EROFS_I_SB(inode); struct erofs_map_blocks *const map = &fe->map; struct z_erofs_collector *const clt = &fe->clt; const loff_t offset = page_offset(page); @@ -701,8 +618,8 @@ restart_now: goto err_out; /* preload all compressed pages (maybe downgrade role if necessary) */ - if (should_alloc_managed_pages(fe, sbi->ctx.cache_strategy, map->m_la)) - cache_strategy = TRYALLOC; + if (should_alloc_managed_pages(fe, sbi->cache_strategy, map->m_la)) + cache_strategy = DELAYEDALLOC; else cache_strategy = DONTALLOC; @@ -742,9 +659,8 @@ retry: /* should allocate an additional staging page for pagevec */ if (err == -EAGAIN) { struct page *const newpage = - alloc_page(GFP_NOFS | __GFP_NOFAIL); + __stagingpage_alloc(pagepool, GFP_NOFS); - set_page_private(newpage, Z_EROFS_SHORTLIVED_PAGE); err = z_erofs_attach_page(clt, newpage, Z_EROFS_PAGE_TYPE_EXCLUSIVE, true); if (!err) @@ -783,14 +699,13 @@ err_out: goto out; } -static void z_erofs_decompressqueue_work(struct work_struct *work); -static void z_erofs_decompress_kickoff(struct z_erofs_decompressqueue *io, - bool sync, int bios) +static void z_erofs_vle_unzip_kickoff(void *ptr, int bios) { - struct erofs_sb_info *const sbi = EROFS_SB(io->sb); + tagptr1_t t = tagptr_init(tagptr1_t, ptr); + struct z_erofs_unzip_io *io = tagptr_unfold_ptr(t); + bool background = tagptr_unfold_tags(t); - /* wake up the caller thread for sync decompression */ - if (sync) { + if (!background) { unsigned long flags; spin_lock_irqsave(&io->u.wait.lock, flags); @@ -800,46 +715,41 @@ static void z_erofs_decompress_kickoff(struct z_erofs_decompressqueue *io, return; } - if (atomic_add_return(bios, &io->pending_bios)) - return; - /* Use workqueue and sync decompression for atomic contexts only */ - if (in_atomic() || irqs_disabled()) { + if (!atomic_add_return(bios, &io->pending_bios)) queue_work(z_erofs_workqueue, &io->u.work); - sbi->ctx.readahead_sync_decompress = true; - return; - } - z_erofs_decompressqueue_work(&io->u.work); } -static bool z_erofs_page_is_invalidated(struct page *page) +static inline void z_erofs_vle_read_endio(struct bio *bio) { - return !page->mapping && !z_erofs_is_shortlived_page(page); -} - -static void z_erofs_decompressqueue_endio(struct bio *bio) -{ - tagptr1_t t = tagptr_init(tagptr1_t, bio->bi_private); - struct z_erofs_decompressqueue *q = tagptr_unfold_ptr(t); + struct erofs_sb_info *sbi = NULL; blk_status_t err = bio->bi_status; struct bio_vec *bvec; struct bvec_iter_all iter_all; bio_for_each_segment_all(bvec, bio, iter_all) { struct page *page = bvec->bv_page; + bool cachemngd = false; DBG_BUGON(PageUptodate(page)); - DBG_BUGON(z_erofs_page_is_invalidated(page)); + DBG_BUGON(!page->mapping); + + if (!sbi && !z_erofs_page_is_staging(page)) + sbi = EROFS_SB(page->mapping->host->i_sb); + + /* sbi should already be gotten if the page is managed */ + if (sbi) + cachemngd = erofs_page_is_managed(sbi, page); if (err) SetPageError(page); + else if (cachemngd) + SetPageUptodate(page); - if (erofs_page_is_managed(EROFS_SB(q->sb), page)) { - if (!err) - SetPageUptodate(page); + if (cachemngd) unlock_page(page); - } } - z_erofs_decompress_kickoff(q, tagptr_unfold_tags(t), -1); + + z_erofs_vle_unzip_kickoff(bio->bi_private, -1); bio_put(bio); } @@ -848,8 +758,9 @@ static int z_erofs_decompress_pcluster(struct super_block *sb, struct list_head *pagepool) { struct erofs_sb_info *const sbi = EROFS_SB(sb); + const unsigned int clusterpages = BIT(pcl->clusterbits); struct z_erofs_pagevec_ctor ctor; - unsigned int i, inputsize, outputsize, llen, nr_pages; + unsigned int i, outputsize, llen, nr_pages; struct page *pages_onstack[Z_EROFS_VMAP_ONSTACK_PAGES]; struct page **pages, **compressed_pages, *page; @@ -900,9 +811,9 @@ static int z_erofs_decompress_pcluster(struct super_block *sb, /* all pages in pagevec ought to be valid */ DBG_BUGON(!page); - DBG_BUGON(z_erofs_page_is_invalidated(page)); + DBG_BUGON(!page->mapping); - if (z_erofs_put_shortlivedpage(pagepool, page)) + if (z_erofs_put_stagingpage(pagepool, page)) continue; if (page_type == Z_EROFS_VLE_PAGE_TYPE_HEAD) @@ -929,16 +840,16 @@ static int z_erofs_decompress_pcluster(struct super_block *sb, overlapped = false; compressed_pages = pcl->compressed_pages; - for (i = 0; i < pcl->pclusterpages; ++i) { + for (i = 0; i < clusterpages; ++i) { unsigned int pagenr; page = compressed_pages[i]; /* all compressed pages ought to be valid */ DBG_BUGON(!page); - DBG_BUGON(z_erofs_page_is_invalidated(page)); + DBG_BUGON(!page->mapping); - if (!z_erofs_is_shortlived_page(page)) { + if (!z_erofs_page_is_staging(page)) { if (erofs_page_is_managed(sbi, page)) { if (!PageUptodate(page)) err = -EIO; @@ -963,7 +874,7 @@ static int z_erofs_decompress_pcluster(struct super_block *sb, overlapped = true; } - /* PG_error needs checking for all non-managed pages */ + /* PG_error needs checking for inplaced and staging pages */ if (PageError(page)) { DBG_BUGON(PageUptodate(page)); err = -EIO; @@ -982,13 +893,12 @@ static int z_erofs_decompress_pcluster(struct super_block *sb, partial = true; } - inputsize = pcl->pclusterpages * PAGE_SIZE; err = z_erofs_decompress(&(struct z_erofs_decompress_req) { .sb = sb, .in = compressed_pages, .out = pages, .pageofs_out = cl->pageofs, - .inputsize = inputsize, + .inputsize = PAGE_SIZE, .outputsize = outputsize, .alg = pcl->algorithmformat, .inplace_io = overlapped, @@ -996,15 +906,15 @@ static int z_erofs_decompress_pcluster(struct super_block *sb, }, pagepool); out: - /* must handle all compressed pages before ending pages */ - for (i = 0; i < pcl->pclusterpages; ++i) { + /* must handle all compressed pages before endding pages */ + for (i = 0; i < clusterpages; ++i) { page = compressed_pages[i]; if (erofs_page_is_managed(sbi, page)) continue; - /* recycle all individual short-lived pages */ - (void)z_erofs_put_shortlivedpage(pagepool, page); + /* recycle all individual staging pages */ + (void)z_erofs_put_stagingpage(pagepool, page); WRITE_ONCE(compressed_pages[i], NULL); } @@ -1014,10 +924,10 @@ out: if (!page) continue; - DBG_BUGON(z_erofs_page_is_invalidated(page)); + DBG_BUGON(!page->mapping); - /* recycle all individual short-lived pages */ - if (z_erofs_put_shortlivedpage(pagepool, page)) + /* recycle all individual staging pages */ + if (z_erofs_put_stagingpage(pagepool, page)) continue; if (err < 0) @@ -1044,8 +954,9 @@ out: return err; } -static void z_erofs_decompress_queue(const struct z_erofs_decompressqueue *io, - struct list_head *pagepool) +static void z_erofs_vle_unzip_all(struct super_block *sb, + struct z_erofs_unzip_io *io, + struct list_head *pagepool) { z_erofs_next_pcluster_t owned = io->head; @@ -1061,21 +972,21 @@ static void z_erofs_decompress_queue(const struct z_erofs_decompressqueue *io, pcl = container_of(owned, struct z_erofs_pcluster, next); owned = READ_ONCE(pcl->next); - z_erofs_decompress_pcluster(io->sb, pcl, pagepool); + z_erofs_decompress_pcluster(sb, pcl, pagepool); } } -static void z_erofs_decompressqueue_work(struct work_struct *work) +static void z_erofs_vle_unzip_wq(struct work_struct *work) { - struct z_erofs_decompressqueue *bgq = - container_of(work, struct z_erofs_decompressqueue, u.work); + struct z_erofs_unzip_io_sb *iosb = + container_of(work, struct z_erofs_unzip_io_sb, io.u.work); LIST_HEAD(pagepool); - DBG_BUGON(bgq->head == Z_EROFS_PCLUSTER_TAIL_CLOSED); - z_erofs_decompress_queue(bgq, &pagepool); + DBG_BUGON(iosb->io.head == Z_EROFS_PCLUSTER_TAIL_CLOSED); + z_erofs_vle_unzip_all(iosb->sb, &iosb->io, &pagepool); put_pages_list(&pagepool); - kvfree(bgq); + kvfree(iosb); } static struct page *pickup_page_for_submission(struct z_erofs_pcluster *pcl, @@ -1084,6 +995,8 @@ static struct page *pickup_page_for_submission(struct z_erofs_pcluster *pcl, struct address_space *mc, gfp_t gfp) { + /* determined at compile time to avoid too many #ifdefs */ + const bool nocache = __builtin_constant_p(mc) ? !mc : false; const pgoff_t index = pcl->obj.index; bool tocache = false; @@ -1104,7 +1017,7 @@ repeat: * the cached page has not been allocated and * an placeholder is out there, prepare it now. */ - if (page == PAGE_UNALLOCATED) { + if (!nocache && page == PAGE_UNALLOCATED) { tocache = true; goto out_allocpage; } @@ -1114,30 +1027,31 @@ repeat: justfound = tagptr_unfold_tags(t); page = tagptr_unfold_ptr(t); - /* - * preallocated cached pages, which is used to avoid direct reclaim - * otherwise, it will go inplace I/O path instead. - */ - if (page->private == Z_EROFS_PREALLOCATED_PAGE) { - WRITE_ONCE(pcl->compressed_pages[nr], page); - set_page_private(page, 0); - tocache = true; - goto out_tocache; - } mapping = READ_ONCE(page->mapping); /* - * file-backed online pages in plcuster are all locked steady, + * if managed cache is disabled, it's no way to + * get such a cached-like page. + */ + if (nocache) { + /* if managed cache is disabled, it is impossible `justfound' */ + DBG_BUGON(justfound); + + /* and it should be locked, not uptodate, and not truncated */ + DBG_BUGON(!PageLocked(page)); + DBG_BUGON(PageUptodate(page)); + DBG_BUGON(!mapping); + goto out; + } + + /* + * unmanaged (file) pages are all locked solidly, * therefore it is impossible for `mapping' to be NULL. */ if (mapping && mapping != mc) /* ought to be unmanaged pages */ goto out; - /* directly return for shortlived page as well */ - if (z_erofs_is_shortlived_page(page)) - goto out; - lock_page(page); /* only true if page reclaim goes wrong, should never happen */ @@ -1180,48 +1094,50 @@ repeat: unlock_page(page); put_page(page); out_allocpage: - page = erofs_allocpage(pagepool, gfp | __GFP_NOFAIL); + page = __stagingpage_alloc(pagepool, gfp); if (oldpage != cmpxchg(&pcl->compressed_pages[nr], oldpage, page)) { list_add(&page->lru, pagepool); - cond_resched(); + cpu_relax(); goto repeat; } -out_tocache: - if (!tocache || add_to_page_cache_lru(page, mc, index + nr, gfp)) { - /* turn into temporary page if fails (1 ref) */ - set_page_private(page, Z_EROFS_SHORTLIVED_PAGE); + if (nocache || !tocache) + goto out; + if (add_to_page_cache_lru(page, mc, index + nr, gfp)) { + page->mapping = Z_EROFS_MAPPING_STAGING; goto out; } - attach_page_private(page, pcl); - /* drop a refcount added by allocpage (then we have 2 refs here) */ - put_page(page); + set_page_private(page, (unsigned long)pcl); + SetPagePrivate(page); out: /* the only exit (for tracing and debugging) */ return page; } -static struct z_erofs_decompressqueue * -jobqueue_init(struct super_block *sb, - struct z_erofs_decompressqueue *fgq, bool *fg) +static struct z_erofs_unzip_io *jobqueue_init(struct super_block *sb, + struct z_erofs_unzip_io *io, + bool foreground) { - struct z_erofs_decompressqueue *q; + struct z_erofs_unzip_io_sb *iosb; - if (fg && !*fg) { - q = kvzalloc(sizeof(*q), GFP_KERNEL | __GFP_NOWARN); - if (!q) { - *fg = true; - goto fg_out; - } - INIT_WORK(&q->u.work, z_erofs_decompressqueue_work); - } else { -fg_out: - q = fgq; - init_waitqueue_head(&fgq->u.wait); - atomic_set(&fgq->pending_bios, 0); + if (foreground) { + /* waitqueue available for foreground io */ + DBG_BUGON(!io); + + init_waitqueue_head(&io->u.wait); + atomic_set(&io->pending_bios, 0); + goto out; } - q->sb = sb; - q->head = Z_EROFS_PCLUSTER_TAIL_CLOSED; - return q; + + iosb = kvzalloc(sizeof(*iosb), GFP_KERNEL | __GFP_NOFAIL); + DBG_BUGON(!iosb); + + /* initialize fields in the allocated descriptor */ + io = &iosb->io; + iosb->sb = sb; + INIT_WORK(&io->u.work, z_erofs_vle_unzip_wq); +out: + io->head = Z_EROFS_PCLUSTER_TAIL_CLOSED; + return io; } /* define decompression jobqueue types */ @@ -1232,17 +1148,22 @@ enum { }; static void *jobqueueset_init(struct super_block *sb, - struct z_erofs_decompressqueue *q[], - struct z_erofs_decompressqueue *fgq, bool *fg) + z_erofs_next_pcluster_t qtail[], + struct z_erofs_unzip_io *q[], + struct z_erofs_unzip_io *fgq, + bool forcefg) { /* * if managed cache is enabled, bypass jobqueue is needed, * no need to read from device for all pclusters in this queue. */ - q[JQ_BYPASS] = jobqueue_init(sb, fgq + JQ_BYPASS, NULL); - q[JQ_SUBMIT] = jobqueue_init(sb, fgq + JQ_SUBMIT, fg); + q[JQ_BYPASS] = jobqueue_init(sb, fgq + JQ_BYPASS, true); + qtail[JQ_BYPASS] = &q[JQ_BYPASS]->head; - return tagptr_cast_ptr(tagptr_fold(tagptr1_t, q[JQ_SUBMIT], *fg)); + q[JQ_SUBMIT] = jobqueue_init(sb, fgq + JQ_SUBMIT, forcefg); + qtail[JQ_SUBMIT] = &q[JQ_SUBMIT]->head; + + return tagptr_cast_ptr(tagptr_fold(tagptr1_t, q[JQ_SUBMIT], !forcefg)); } static void move_to_bypass_jobqueue(struct z_erofs_pcluster *pcl, @@ -1264,34 +1185,55 @@ static void move_to_bypass_jobqueue(struct z_erofs_pcluster *pcl, qtail[JQ_BYPASS] = &pcl->next; } -static void z_erofs_submit_queue(struct super_block *sb, - struct z_erofs_decompress_frontend *f, - struct list_head *pagepool, - struct z_erofs_decompressqueue *fgq, - bool *force_fg) +static bool postsubmit_is_all_bypassed(struct z_erofs_unzip_io *q[], + unsigned int nr_bios, + bool force_fg) { - struct erofs_sb_info *const sbi = EROFS_SB(sb); - z_erofs_next_pcluster_t qtail[NR_JOBQUEUES]; - struct z_erofs_decompressqueue *q[NR_JOBQUEUES]; - void *bi_private; - z_erofs_next_pcluster_t owned_head = f->clt.owned_head; - /* since bio will be NULL, no need to initialize last_index */ - pgoff_t last_index; - unsigned int nr_bios = 0; - struct bio *bio = NULL; + /* + * although background is preferred, no one is pending for submission. + * don't issue workqueue for decompression but drop it directly instead. + */ + if (force_fg || nr_bios) + return false; - bi_private = jobqueueset_init(sb, q, fgq, force_fg); - qtail[JQ_BYPASS] = &q[JQ_BYPASS]->head; - qtail[JQ_SUBMIT] = &q[JQ_SUBMIT]->head; + kvfree(container_of(q[JQ_SUBMIT], struct z_erofs_unzip_io_sb, io)); + return true; +} + +static bool z_erofs_vle_submit_all(struct super_block *sb, + z_erofs_next_pcluster_t owned_head, + struct list_head *pagepool, + struct z_erofs_unzip_io *fgq, + bool force_fg) +{ + struct erofs_sb_info *const sbi __maybe_unused = EROFS_SB(sb); + z_erofs_next_pcluster_t qtail[NR_JOBQUEUES]; + struct z_erofs_unzip_io *q[NR_JOBQUEUES]; + struct bio *bio; + void *bi_private; + /* since bio will be NULL, no need to initialize last_index */ + pgoff_t uninitialized_var(last_index); + bool force_submit = false; + unsigned int nr_bios; + + if (owned_head == Z_EROFS_PCLUSTER_TAIL) + return false; + + force_submit = false; + bio = NULL; + nr_bios = 0; + bi_private = jobqueueset_init(sb, qtail, q, fgq, force_fg); /* by default, all need io submission */ q[JQ_SUBMIT]->head = owned_head; do { struct z_erofs_pcluster *pcl; - pgoff_t cur, end; - unsigned int i = 0; - bool bypass = true; + unsigned int clusterpages; + pgoff_t first_index; + struct page *page; + unsigned int i = 0, bypass = 0; + int err; /* no possible 'owned_head' equals the following */ DBG_BUGON(owned_head == Z_EROFS_PCLUSTER_TAIL_CLOSED); @@ -1299,50 +1241,55 @@ static void z_erofs_submit_queue(struct super_block *sb, pcl = container_of(owned_head, struct z_erofs_pcluster, next); - cur = pcl->obj.index; - end = cur + pcl->pclusterpages; + clusterpages = BIT(pcl->clusterbits); /* close the main owned chain at first */ owned_head = cmpxchg(&pcl->next, Z_EROFS_PCLUSTER_TAIL, Z_EROFS_PCLUSTER_TAIL_CLOSED); - do { - struct page *page; + first_index = pcl->obj.index; + force_submit |= (first_index != last_index + 1); - page = pickup_page_for_submission(pcl, i++, pagepool, - MNGD_MAPPING(sbi), - GFP_NOFS); - if (!page) - continue; +repeat: + page = pickup_page_for_submission(pcl, i, pagepool, + MNGD_MAPPING(sbi), + GFP_NOFS); + if (!page) { + force_submit = true; + ++bypass; + goto skippage; + } - if (bio && cur != last_index + 1) { + if (bio && force_submit) { submit_bio_retry: - submit_bio(bio); - bio = NULL; - } + submit_bio(bio); + bio = NULL; + } - if (!bio) { - bio = bio_alloc(GFP_NOIO, BIO_MAX_PAGES); + if (!bio) { + bio = bio_alloc(GFP_NOIO, BIO_MAX_PAGES); - bio->bi_end_io = z_erofs_decompressqueue_endio; - bio_set_dev(bio, sb->s_bdev); - bio->bi_iter.bi_sector = (sector_t)cur << - LOG_SECTORS_PER_BLOCK; - bio->bi_private = bi_private; - bio->bi_opf = REQ_OP_READ; - if (f->readahead) - bio->bi_opf |= REQ_RAHEAD; - ++nr_bios; - } + bio->bi_end_io = z_erofs_vle_read_endio; + bio_set_dev(bio, sb->s_bdev); + bio->bi_iter.bi_sector = (sector_t)(first_index + i) << + LOG_SECTORS_PER_BLOCK; + bio->bi_private = bi_private; + bio->bi_opf = REQ_OP_READ; - if (bio_add_page(bio, page, PAGE_SIZE, 0) < PAGE_SIZE) - goto submit_bio_retry; + ++nr_bios; + } - last_index = cur; - bypass = false; - } while (++cur < end); + err = bio_add_page(bio, page, PAGE_SIZE, 0); + if (err < PAGE_SIZE) + goto submit_bio_retry; - if (!bypass) + force_submit = false; + last_index = first_index + i; +skippage: + if (++i < clusterpages) + goto repeat; + + if (bypass < clusterpages) qtail[JQ_SUBMIT] = &pcl->next; else move_to_bypass_jobqueue(pcl, qtail, owned_head); @@ -1351,42 +1298,40 @@ submit_bio_retry: if (bio) submit_bio(bio); - /* - * although background is preferred, no one is pending for submission. - * don't issue workqueue for decompression but drop it directly instead. - */ - if (!*force_fg && !nr_bios) { - kvfree(q[JQ_SUBMIT]); - return; - } - z_erofs_decompress_kickoff(q[JQ_SUBMIT], *force_fg, nr_bios); + if (postsubmit_is_all_bypassed(q, nr_bios, force_fg)) + return true; + + z_erofs_vle_unzip_kickoff(bi_private, nr_bios); + return true; } -static void z_erofs_runqueue(struct super_block *sb, - struct z_erofs_decompress_frontend *f, - struct list_head *pagepool, bool force_fg) +static void z_erofs_submit_and_unzip(struct super_block *sb, + struct z_erofs_collector *clt, + struct list_head *pagepool, + bool force_fg) { - struct z_erofs_decompressqueue io[NR_JOBQUEUES]; + struct z_erofs_unzip_io io[NR_JOBQUEUES]; - if (f->clt.owned_head == Z_EROFS_PCLUSTER_TAIL) + if (!z_erofs_vle_submit_all(sb, clt->owned_head, + pagepool, io, force_fg)) return; - z_erofs_submit_queue(sb, f, pagepool, io, &force_fg); - /* handle bypass queue (no i/o pclusters) immediately */ - z_erofs_decompress_queue(&io[JQ_BYPASS], pagepool); + /* decompress no I/O pclusters immediately */ + z_erofs_vle_unzip_all(sb, &io[JQ_BYPASS], pagepool); if (!force_fg) return; /* wait until all bios are completed */ - io_wait_event(io[JQ_SUBMIT].u.wait, - !atomic_read(&io[JQ_SUBMIT].pending_bios)); + wait_event(io[JQ_SUBMIT].u.wait, + !atomic_read(&io[JQ_SUBMIT].pending_bios)); - /* handle synchronous decompress queue in the caller context */ - z_erofs_decompress_queue(&io[JQ_SUBMIT], pagepool); + /* let's synchronous decompression */ + z_erofs_vle_unzip_all(sb, &io[JQ_SUBMIT], pagepool); } -static int z_erofs_readpage(struct file *file, struct page *page) +static int z_erofs_vle_normalaccess_readpage(struct file *file, + struct page *page) { struct inode *const inode = page->mapping->host; struct z_erofs_decompress_frontend f = DECOMPRESS_FRONTEND_INIT(inode); @@ -1401,7 +1346,7 @@ static int z_erofs_readpage(struct file *file, struct page *page) (void)z_erofs_collector_end(&f.clt); /* if some compressed cluster ready, need submit them anyway */ - z_erofs_runqueue(inode->i_sb, &f, &pagepool, true); + z_erofs_submit_and_unzip(inode->i_sb, &f.clt, &pagepool, true); if (err) erofs_err(inode->i_sb, "failed to read, err [%d]", err); @@ -1417,7 +1362,7 @@ static int z_erofs_readpage(struct file *file, struct page *page) static bool should_decompress_synchronously(struct erofs_sb_info *sbi, unsigned int nr) { - return nr <= 3; + return nr <= sbi->max_sync_decompress_pages; } static int z_erofs_vle_normalaccess_readpages(struct file *filp, @@ -1478,7 +1423,7 @@ static int z_erofs_vle_normalaccess_readpages(struct file *filp, (void)z_erofs_collector_end(&f.clt); - z_erofs_runqueue(inode->i_sb, &f, &pagepool, sync); + z_erofs_submit_and_unzip(inode->i_sb, &f.clt, &pagepool, sync); if (f.map.mpage) put_page(f.map.mpage); @@ -1488,9 +1433,8 @@ static int z_erofs_vle_normalaccess_readpages(struct file *filp, return 0; } - -const struct address_space_operations z_erofs_aops = { - .readpage = z_erofs_readpage, +const struct address_space_operations z_erofs_vle_normalaccess_aops = { + .readpage = z_erofs_vle_normalaccess_readpage, .readpages = z_erofs_vle_normalaccess_readpages, }; diff --git a/fs/erofs/zdata.h b/fs/erofs/zdata.h index 942ee69dff6a..568d5a493876 100644 --- a/fs/erofs/zdata.h +++ b/fs/erofs/zdata.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (C) 2018 HUAWEI, Inc. - * https://www.huawei.com/ + * http://www.huawei.com/ * Created by Gao Xiang */ #ifndef __EROFS_FS_ZDATA_H @@ -10,7 +10,6 @@ #include "internal.h" #include "zpvec.h" -#define Z_EROFS_PCLUSTER_MAX_PAGES (Z_EROFS_PCLUSTER_MAX_SIZE / PAGE_SIZE) #define Z_EROFS_NR_INLINE_PAGEVECS 3 /* @@ -60,17 +59,16 @@ struct z_erofs_pcluster { /* A: point to next chained pcluster or TAILs */ z_erofs_next_pcluster_t next; + /* A: compressed pages (including multi-usage pages) */ + struct page *compressed_pages[Z_EROFS_CLUSTER_MAX_PAGES]; + /* A: lower limit of decompressed length and if full length or not */ unsigned int length; - /* I: physical cluster size in pages */ - unsigned short pclusterpages; - /* I: compression algorithm format */ unsigned char algorithmformat; - - /* A: compressed pages (can be cached or inplaced pages) */ - struct page *compressed_pages[]; + /* I: bit shift of physical cluster size */ + unsigned char clusterbits; }; #define z_erofs_primarycollection(pcluster) (&(pcluster)->primary_collection) @@ -84,8 +82,9 @@ struct z_erofs_pcluster { #define Z_EROFS_PCLUSTER_NIL (NULL) -struct z_erofs_decompressqueue { - struct super_block *sb; +#define Z_EROFS_WORKGROUP_SIZE sizeof(struct z_erofs_pcluster) + +struct z_erofs_unzip_io { atomic_t pending_bios; z_erofs_next_pcluster_t head; @@ -95,6 +94,11 @@ struct z_erofs_decompressqueue { } u; }; +struct z_erofs_unzip_io_sb { + struct z_erofs_unzip_io io; + struct super_block *sb; +}; + #define MNGD_MAPPING(sbi) ((sbi)->managed_cache->i_mapping) static inline bool erofs_page_is_managed(const struct erofs_sb_info *sbi, struct page *page) @@ -173,7 +177,6 @@ static inline void z_erofs_onlinepage_endio(struct page *page) v = atomic_dec_return(u.o); if (!(v & Z_EROFS_ONLINEPAGE_COUNT_MASK)) { - set_page_private(page, 0); ClearPagePrivate(page); if (!PageError(page)) SetPageUptodate(page); diff --git a/fs/erofs/zmap.c b/fs/erofs/zmap.c index adc4b4bcf51e..6553f58fb289 100644 --- a/fs/erofs/zmap.c +++ b/fs/erofs/zmap.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2018-2019 HUAWEI, Inc. - * https://www.huawei.com/ + * http://www.huawei.com/ * Created by Gao Xiang */ #include "internal.h" @@ -11,21 +11,22 @@ int z_erofs_fill_inode(struct inode *inode) { struct erofs_inode *const vi = EROFS_I(inode); - struct erofs_sb_info *sbi = EROFS_SB(inode->i_sb); - if (!erofs_sb_has_big_pcluster(sbi) && - vi->datalayout == EROFS_INODE_FLAT_COMPRESSION_LEGACY) { + if (vi->datalayout == EROFS_INODE_FLAT_COMPRESSION_LEGACY) { vi->z_advise = 0; vi->z_algorithmtype[0] = 0; vi->z_algorithmtype[1] = 0; vi->z_logical_clusterbits = LOG_BLOCK_SIZE; + vi->z_physical_clusterbits[0] = vi->z_logical_clusterbits; + vi->z_physical_clusterbits[1] = vi->z_logical_clusterbits; set_bit(EROFS_I_Z_INITED_BIT, &vi->flags); } - inode->i_mapping->a_ops = &z_erofs_aops; + + inode->i_mapping->a_ops = &z_erofs_vle_normalaccess_aops; return 0; } -static int z_erofs_fill_inode_lazy(struct inode *inode) +static int fill_inode_lazy(struct inode *inode) { struct erofs_inode *const vi = EROFS_I(inode); struct super_block *const sb = inode->i_sb; @@ -51,8 +52,7 @@ static int z_erofs_fill_inode_lazy(struct inode *inode) if (test_bit(EROFS_I_Z_INITED_BIT, &vi->flags)) goto out_unlock; - DBG_BUGON(!erofs_sb_has_big_pcluster(EROFS_SB(sb)) && - vi->datalayout == EROFS_INODE_FLAT_COMPRESSION_LEGACY); + DBG_BUGON(vi->datalayout == EROFS_INODE_FLAT_COMPRESSION_LEGACY); pos = ALIGN(iloc(EROFS_SB(sb), vi->nid) + vi->inode_isize + vi->xattr_isize, 8); @@ -77,22 +77,18 @@ static int z_erofs_fill_inode_lazy(struct inode *inode) } vi->z_logical_clusterbits = LOG_BLOCK_SIZE + (h->h_clusterbits & 7); - if (!erofs_sb_has_big_pcluster(EROFS_SB(sb)) && - vi->z_advise & (Z_EROFS_ADVISE_BIG_PCLUSTER_1 | - Z_EROFS_ADVISE_BIG_PCLUSTER_2)) { - erofs_err(sb, "per-inode big pcluster without sb feature for nid %llu", - vi->nid); - err = -EFSCORRUPTED; - goto unmap_done; - } - if (vi->datalayout == EROFS_INODE_FLAT_COMPRESSION && - !(vi->z_advise & Z_EROFS_ADVISE_BIG_PCLUSTER_1) ^ - !(vi->z_advise & Z_EROFS_ADVISE_BIG_PCLUSTER_2)) { - erofs_err(sb, "big pcluster head1/2 of compact indexes should be consistent for nid %llu", - vi->nid); - err = -EFSCORRUPTED; + vi->z_physical_clusterbits[0] = vi->z_logical_clusterbits + + ((h->h_clusterbits >> 3) & 3); + + if (vi->z_physical_clusterbits[0] != LOG_BLOCK_SIZE) { + erofs_err(sb, "unsupported physical clusterbits %u for nid %llu, please upgrade kernel", + vi->z_physical_clusterbits[0], vi->nid); + err = -EOPNOTSUPP; goto unmap_done; } + + vi->z_physical_clusterbits[1] = vi->z_logical_clusterbits + + ((h->h_clusterbits >> 5) & 7); /* paired with smp_mb() at the beginning of the function */ smp_mb(); set_bit(EROFS_I_Z_INITED_BIT, &vi->flags); @@ -115,7 +111,7 @@ struct z_erofs_maprecorder { u8 type; u16 clusterofs; u16 delta[2]; - erofs_blk_t pblk, compressedlcs; + erofs_blk_t pblk; }; static int z_erofs_reload_indexes(struct z_erofs_maprecorder *m, @@ -150,8 +146,8 @@ static int z_erofs_reload_indexes(struct z_erofs_maprecorder *m, return 0; } -static int legacy_load_cluster_from_disk(struct z_erofs_maprecorder *m, - unsigned long lcn) +static int vle_legacy_load_cluster_from_disk(struct z_erofs_maprecorder *m, + unsigned long lcn) { struct inode *const inode = m->inode; struct erofs_inode *const vi = EROFS_I(inode); @@ -178,15 +174,6 @@ static int legacy_load_cluster_from_disk(struct z_erofs_maprecorder *m, case Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD: m->clusterofs = 1 << vi->z_logical_clusterbits; m->delta[0] = le16_to_cpu(di->di_u.delta[0]); - if (m->delta[0] & Z_EROFS_VLE_DI_D0_CBLKCNT) { - if (!(vi->z_advise & Z_EROFS_ADVISE_BIG_PCLUSTER_1)) { - DBG_BUGON(1); - return -EFSCORRUPTED; - } - m->compressedlcs = m->delta[0] & - ~Z_EROFS_VLE_DI_D0_CBLKCNT; - m->delta[0] = 1; - } m->delta[1] = le16_to_cpu(di->di_u.delta[1]); break; case Z_EROFS_VLE_CLUSTER_TYPE_PLAIN: @@ -227,7 +214,6 @@ static int unpack_compacted_index(struct z_erofs_maprecorder *m, unsigned int vcnt, base, lo, encodebits, nblk; int i; u8 *in, type; - bool big_pcluster; if (1 << amortizedshift == 4 && lclusterbits <= 14) vcnt = 2; @@ -236,7 +222,6 @@ static int unpack_compacted_index(struct z_erofs_maprecorder *m, else return -EOPNOTSUPP; - big_pcluster = vi->z_advise & Z_EROFS_ADVISE_BIG_PCLUSTER_1; encodebits = ((vcnt << amortizedshift) - sizeof(__le32)) * 8 / vcnt; base = round_down(eofs, vcnt << amortizedshift); in = m->kaddr + base; @@ -248,15 +233,7 @@ static int unpack_compacted_index(struct z_erofs_maprecorder *m, m->type = type; if (type == Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD) { m->clusterofs = 1 << lclusterbits; - if (lo & Z_EROFS_VLE_DI_D0_CBLKCNT) { - if (!big_pcluster) { - DBG_BUGON(1); - return -EFSCORRUPTED; - } - m->compressedlcs = lo & ~Z_EROFS_VLE_DI_D0_CBLKCNT; - m->delta[0] = 1; - return 0; - } else if (i + 1 != (int)vcnt) { + if (i + 1 != vcnt) { m->delta[0] = lo; return 0; } @@ -269,48 +246,22 @@ static int unpack_compacted_index(struct z_erofs_maprecorder *m, in, encodebits * (i - 1), &type); if (type != Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD) lo = 0; - else if (lo & Z_EROFS_VLE_DI_D0_CBLKCNT) - lo = 1; m->delta[0] = lo + 1; return 0; } m->clusterofs = lo; m->delta[0] = 0; /* figout out blkaddr (pblk) for HEAD lclusters */ - if (!big_pcluster) { - nblk = 1; - while (i > 0) { - --i; - lo = decode_compactedbits(lclusterbits, lomask, - in, encodebits * i, &type); - if (type == Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD) - i -= lo; + nblk = 1; + while (i > 0) { + --i; + lo = decode_compactedbits(lclusterbits, lomask, + in, encodebits * i, &type); + if (type == Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD) + i -= lo; - if (i >= 0) - ++nblk; - } - } else { - nblk = 0; - while (i > 0) { - --i; - lo = decode_compactedbits(lclusterbits, lomask, - in, encodebits * i, &type); - if (type == Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD) { - if (lo & Z_EROFS_VLE_DI_D0_CBLKCNT) { - --i; - nblk += lo & ~Z_EROFS_VLE_DI_D0_CBLKCNT; - continue; - } - /* bigpcluster shouldn't have plain d0 == 1 */ - if (lo <= 1) { - DBG_BUGON(1); - return -EFSCORRUPTED; - } - i -= lo - 2; - continue; - } + if (i >= 0) ++nblk; - } } in += (vcnt << amortizedshift) - sizeof(__le32); m->pblk = le32_to_cpu(*(__le32 *)in) + nblk; @@ -368,13 +319,13 @@ out: return unpack_compacted_index(m, amortizedshift, erofs_blkoff(pos)); } -static int z_erofs_load_cluster_from_disk(struct z_erofs_maprecorder *m, - unsigned int lcn) +static int vle_load_cluster_from_disk(struct z_erofs_maprecorder *m, + unsigned int lcn) { const unsigned int datamode = EROFS_I(m->inode)->datalayout; if (datamode == EROFS_INODE_FLAT_COMPRESSION_LEGACY) - return legacy_load_cluster_from_disk(m, lcn); + return vle_legacy_load_cluster_from_disk(m, lcn); if (datamode == EROFS_INODE_FLAT_COMPRESSION) return compacted_load_cluster_from_disk(m, lcn); @@ -382,8 +333,8 @@ static int z_erofs_load_cluster_from_disk(struct z_erofs_maprecorder *m, return -EINVAL; } -static int z_erofs_extent_lookback(struct z_erofs_maprecorder *m, - unsigned int lookback_distance) +static int vle_extent_lookback(struct z_erofs_maprecorder *m, + unsigned int lookback_distance) { struct erofs_inode *const vi = EROFS_I(m->inode); struct erofs_map_blocks *const map = m->map; @@ -400,7 +351,7 @@ static int z_erofs_extent_lookback(struct z_erofs_maprecorder *m, /* load extent head logical cluster if needed */ lcn -= lookback_distance; - err = z_erofs_load_cluster_from_disk(m, lcn); + err = vle_load_cluster_from_disk(m, lcn); if (err) return err; @@ -413,10 +364,10 @@ static int z_erofs_extent_lookback(struct z_erofs_maprecorder *m, DBG_BUGON(1); return -EFSCORRUPTED; } - return z_erofs_extent_lookback(m, m->delta[0]); + return vle_extent_lookback(m, m->delta[0]); case Z_EROFS_VLE_CLUSTER_TYPE_PLAIN: map->m_flags &= ~EROFS_MAP_ZIPPED; - fallthrough; + /* fallthrough */ case Z_EROFS_VLE_CLUSTER_TYPE_HEAD: map->m_la = (lcn << lclusterbits) | m->clusterofs; break; @@ -430,75 +381,6 @@ static int z_erofs_extent_lookback(struct z_erofs_maprecorder *m, return 0; } -static int z_erofs_get_extent_compressedlen(struct z_erofs_maprecorder *m, - unsigned int initial_lcn) -{ - struct erofs_inode *const vi = EROFS_I(m->inode); - struct erofs_map_blocks *const map = m->map; - const unsigned int lclusterbits = vi->z_logical_clusterbits; - unsigned long lcn; - int err; - - DBG_BUGON(m->type != Z_EROFS_VLE_CLUSTER_TYPE_PLAIN && - m->type != Z_EROFS_VLE_CLUSTER_TYPE_HEAD); - if (!(map->m_flags & EROFS_MAP_ZIPPED) || - !(vi->z_advise & Z_EROFS_ADVISE_BIG_PCLUSTER_1)) { - map->m_plen = 1 << lclusterbits; - return 0; - } - - lcn = m->lcn + 1; - if (m->compressedlcs) - goto out; - - err = z_erofs_load_cluster_from_disk(m, lcn); - if (err) - return err; - - /* - * If the 1st NONHEAD lcluster has already been handled initially w/o - * valid compressedlcs, which means at least it mustn't be CBLKCNT, or - * an internal implemenatation error is detected. - * - * The following code can also handle it properly anyway, but let's - * BUG_ON in the debugging mode only for developers to notice that. - */ - DBG_BUGON(lcn == initial_lcn && - m->type == Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD); - - switch (m->type) { - case Z_EROFS_VLE_CLUSTER_TYPE_PLAIN: - case Z_EROFS_VLE_CLUSTER_TYPE_HEAD: - /* - * if the 1st NONHEAD lcluster is actually PLAIN or HEAD type - * rather than CBLKCNT, it's a 1 lcluster-sized pcluster. - */ - m->compressedlcs = 1; - break; - case Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD: - if (m->delta[0] != 1) - goto err_bonus_cblkcnt; - if (m->compressedlcs) - break; - fallthrough; - default: - erofs_err(m->inode->i_sb, - "cannot found CBLKCNT @ lcn %lu of nid %llu", - lcn, vi->nid); - DBG_BUGON(1); - return -EFSCORRUPTED; - } -out: - map->m_plen = m->compressedlcs << lclusterbits; - return 0; -err_bonus_cblkcnt: - erofs_err(m->inode->i_sb, - "bogus CBLKCNT @ lcn %lu of nid %llu", - lcn, vi->nid); - DBG_BUGON(1); - return -EFSCORRUPTED; -} - int z_erofs_map_blocks_iter(struct inode *inode, struct erofs_map_blocks *map, int flags) @@ -510,7 +392,6 @@ int z_erofs_map_blocks_iter(struct inode *inode, }; int err = 0; unsigned int lclusterbits, endoff; - unsigned long initial_lcn; unsigned long long ofs, end; trace_z_erofs_map_blocks_iter_enter(inode, map, flags); @@ -523,16 +404,16 @@ int z_erofs_map_blocks_iter(struct inode *inode, goto out; } - err = z_erofs_fill_inode_lazy(inode); + err = fill_inode_lazy(inode); if (err) goto out; lclusterbits = vi->z_logical_clusterbits; ofs = map->m_la; - initial_lcn = ofs >> lclusterbits; + m.lcn = ofs >> lclusterbits; endoff = ofs & ((1 << lclusterbits) - 1); - err = z_erofs_load_cluster_from_disk(&m, initial_lcn); + err = vle_load_cluster_from_disk(&m, m.lcn); if (err) goto unmap_out; @@ -543,7 +424,7 @@ int z_erofs_map_blocks_iter(struct inode *inode, case Z_EROFS_VLE_CLUSTER_TYPE_PLAIN: if (endoff >= m.clusterofs) map->m_flags &= ~EROFS_MAP_ZIPPED; - fallthrough; + /* fallthrough */ case Z_EROFS_VLE_CLUSTER_TYPE_HEAD: if (endoff >= m.clusterofs) { map->m_la = (m.lcn << lclusterbits) | m.clusterofs; @@ -560,10 +441,10 @@ int z_erofs_map_blocks_iter(struct inode *inode, end = (m.lcn << lclusterbits) | m.clusterofs; map->m_flags |= EROFS_MAP_FULL_MAPPED; m.delta[0] = 1; - fallthrough; + /* fallthrough */ case Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD: - /* get the corresponding first chunk */ - err = z_erofs_extent_lookback(&m, m.delta[0]); + /* get the correspoinding first chunk */ + err = vle_extent_lookback(&m, m.delta[0]); if (err) goto unmap_out; break; @@ -576,12 +457,10 @@ int z_erofs_map_blocks_iter(struct inode *inode, } map->m_llen = end - map->m_la; + map->m_plen = 1 << lclusterbits; map->m_pa = blknr_to_addr(m.pblk); map->m_flags |= EROFS_MAP_MAPPED; - err = z_erofs_get_extent_compressedlen(&m, initial_lcn); - if (err) - goto out; unmap_out: if (m.kaddr) kunmap_atomic(m.kaddr); diff --git a/fs/erofs/zpvec.h b/fs/erofs/zpvec.h index 52898176ef31..6a20b2c3a24c 100644 --- a/fs/erofs/zpvec.h +++ b/fs/erofs/zpvec.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (C) 2018 HUAWEI, Inc. - * https://www.huawei.com/ + * http://www.huawei.com/ * Created by Gao Xiang */ #ifndef __EROFS_FS_ZPVEC_H From 6998b4889879c39ddb9d76abbd743dfcbd4518b8 Mon Sep 17 00:00:00 2001 From: Michael Bestas Date: Wed, 19 Mar 2025 07:24:59 +0200 Subject: [PATCH 685/698] Revert "msm: npu: Fix use after free issue" This reverts commit f6795b4ad6bb42a4ae20ac3428ec5c10dab6b09c. Reason for revert: Conflicts with upstream commits. Change-Id: I46f817266215e1bf230951f9ceee12a42083d62b --- drivers/media/platform/msm/npu/npu_mgr.c | 15 --------------- drivers/media/platform/msm/npu/npu_mgr.h | 1 - 2 files changed, 16 deletions(-) diff --git a/drivers/media/platform/msm/npu/npu_mgr.c b/drivers/media/platform/msm/npu/npu_mgr.c index e000242354dc..f36aff27ccc5 100644 --- a/drivers/media/platform/msm/npu/npu_mgr.c +++ b/drivers/media/platform/msm/npu/npu_mgr.c @@ -1641,13 +1641,6 @@ int32_t npu_host_unload_network(struct npu_client *client, return -EINVAL; } - if (network->is_unloading) { - NPU_ERR("network is unloading\n"); - network_put(network); - mutex_unlock(&host_ctx->lock); - return -EINVAL; - } - if (!network->is_active) { pr_err("network is not active\n"); network_put(network); @@ -1660,8 +1653,6 @@ int32_t npu_host_unload_network(struct npu_client *client, goto free_network; } - network->is_unloading = true; - pr_debug("Unload network %lld\n", network->id); /* prepare IPC packet for UNLOAD */ unload_packet.header.cmd_type = NPU_IPC_CMD_UNLOAD; @@ -1764,12 +1755,6 @@ int32_t npu_host_exec_network(struct npu_client *client, if (atomic_inc_return(&host_ctx->network_execute_cnt) == 1) npu_notify_cdsprm_cxlimit_activity(npu_dev, true); - if (network->is_unloading) { - NPU_ERR("network is unloading\n"); - ret = -EINVAL; - goto exec_v2_done; - } - if (!network->is_active) { pr_err("network is not active\n"); ret = -EINVAL; diff --git a/drivers/media/platform/msm/npu/npu_mgr.h b/drivers/media/platform/msm/npu/npu_mgr.h index 8845ed2696df..f0ab23267787 100644 --- a/drivers/media/platform/msm/npu/npu_mgr.h +++ b/drivers/media/platform/msm/npu/npu_mgr.h @@ -52,7 +52,6 @@ struct npu_network { atomic_t ref_cnt; bool is_valid; bool is_active; - bool is_unloading; bool fw_error; bool cmd_pending; bool cmd_async; From 6e34d778501b082b7c6d8995c47fdfc35ba5ca27 Mon Sep 17 00:00:00 2001 From: Michael Bestas Date: Wed, 19 Mar 2025 07:30:33 +0200 Subject: [PATCH 686/698] Revert "BACKPORT:sched: Provide sched_set_fifo()" This reverts commit 250751cadf055404905263146d8a9f8614f0cd67. Reason for revert: Conflicts with upstream commits. Change-Id: I3eac9acf461e6492ccae2870afebf03db3889632 --- include/linux/sched.h | 3 --- kernel/sched/core.c | 45 ------------------------------------------- 2 files changed, 48 deletions(-) diff --git a/include/linux/sched.h b/include/linux/sched.h index e18e03b541b2..74fe1d4e0807 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1814,9 +1814,6 @@ extern int idle_cpu(int cpu); extern int available_idle_cpu(int cpu); extern int sched_setscheduler(struct task_struct *, int, const struct sched_param *); extern int sched_setscheduler_nocheck(struct task_struct *, int, const struct sched_param *); -extern void sched_set_fifo(struct task_struct *p); -extern void sched_set_fifo_low(struct task_struct *p); -extern void sched_set_normal(struct task_struct *p, int nice); extern int sched_setattr(struct task_struct *, const struct sched_attr *); extern int sched_setattr_nocheck(struct task_struct *, const struct sched_attr *); extern struct task_struct *idle_task(int cpu); diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 82c12f4d588d..f45a1020fcd0 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -5380,51 +5380,6 @@ int sched_setscheduler_nocheck(struct task_struct *p, int policy, } EXPORT_SYMBOL_GPL(sched_setscheduler_nocheck); -/* - * SCHED_FIFO is a broken scheduler model; that is, it is fundamentally - * incapable of resource management, which is the one thing an OS really should - * be doing. - * - * This is of course the reason it is limited to privileged users only. - * - * Worse still; it is fundamentally impossible to compose static priority - * workloads. You cannot take two correctly working static prio workloads - * and smash them together and still expect them to work. - * - * For this reason 'all' FIFO tasks the kernel creates are basically at: - * - * MAX_RT_PRIO / 2 - * - * The administrator _MUST_ configure the system, the kernel simply doesn't - * know enough information to make a sensible choice. - */ -void sched_set_fifo(struct task_struct *p) -{ - struct sched_param sp = { .sched_priority = MAX_RT_PRIO / 2 }; - WARN_ON_ONCE(sched_setscheduler_nocheck(p, SCHED_FIFO, &sp) != 0); -} -EXPORT_SYMBOL_GPL(sched_set_fifo); - -/* - * For when you don't much care about FIFO, but want to be above SCHED_NORMAL. - */ -void sched_set_fifo_low(struct task_struct *p) -{ - struct sched_param sp = { .sched_priority = 1 }; - WARN_ON_ONCE(sched_setscheduler_nocheck(p, SCHED_FIFO, &sp) != 0); -} -EXPORT_SYMBOL_GPL(sched_set_fifo_low); - -void sched_set_normal(struct task_struct *p, int nice) -{ - struct sched_attr attr = { - .sched_policy = SCHED_NORMAL, - .sched_nice = nice, - }; - WARN_ON_ONCE(sched_setattr_nocheck(p, &attr) != 0); -} -EXPORT_SYMBOL_GPL(sched_set_normal); - static int do_sched_setscheduler(pid_t pid, int policy, struct sched_param __user *param) { From 34d9540ea167196cca6d6177bcba5a4e7d9cd518 Mon Sep 17 00:00:00 2001 From: Michael Bestas Date: Wed, 19 Mar 2025 07:31:51 +0200 Subject: [PATCH 687/698] Revert "ANDROID: ABI fixup for abi break in struct dst_ops" This reverts commit ec1b288e67aa590ff69f547172f3110e430d20d2. Reason for revert: Conflicts with upstream commits. Change-Id: I7dae59ba64170b508615e8ef7156c4eb3d840a96 --- include/net/dst_ops.h | 12 +----------- include/net/sock.h | 12 ++---------- net/ipv4/route.c | 2 +- net/ipv6/route.c | 2 +- net/xfrm/xfrm_policy.c | 2 +- 5 files changed, 6 insertions(+), 24 deletions(-) diff --git a/include/net/dst_ops.h b/include/net/dst_ops.h index 337479ab1356..b93799fe46e8 100644 --- a/include/net/dst_ops.h +++ b/include/net/dst_ops.h @@ -12,16 +12,6 @@ struct sk_buff; struct sock; struct net; -/* *** ANDROID FIXUP *** - * These typedefs are used to help fixup the ABI break caused by commit - * 92f1655aa2b2 ("net: fix __dst_negative_advice() race") where the - * negative_advice callback changed function signatures. - * See b/343727534 for more details. - * *** ANDROID FIXUP *** - */ -typedef void (*android_dst_ops_negative_advice_new_t)(struct sock *sk, struct dst_entry *); -typedef struct dst_entry * (*android_dst_ops_negative_advice_old_t)(struct dst_entry *); - struct dst_ops { unsigned short family; unsigned int gc_thresh; @@ -34,7 +24,7 @@ struct dst_ops { void (*destroy)(struct dst_entry *); void (*ifdown)(struct dst_entry *, struct net_device *dev, int how); - struct dst_entry * (*negative_advice)(struct dst_entry *); + void (*negative_advice)(struct sock *sk, struct dst_entry *); void (*link_failure)(struct sk_buff *); void (*update_pmtu)(struct dst_entry *dst, struct sock *sk, struct sk_buff *skb, u32 mtu, diff --git a/include/net/sock.h b/include/net/sock.h index b84ebc1ad206..f37ddce89483 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -1936,20 +1936,12 @@ sk_dst_get(struct sock *sk) static inline void dst_negative_advice(struct sock *sk) { - /* *** ANDROID FIXUP *** - * See b/343727534 for more details why this typedef is needed here. - * *** ANDROID FIXUP *** - */ - android_dst_ops_negative_advice_new_t negative_advice; - struct dst_entry *dst = __sk_dst_get(sk); sk_rethink_txhash(sk); - if (dst && dst->ops->negative_advice) { - negative_advice = (android_dst_ops_negative_advice_new_t)dst->ops->negative_advice; - negative_advice(sk, dst); - } + if (dst && dst->ops->negative_advice) + dst->ops->negative_advice(sk, dst); } static inline void diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 55448b6329c8..3a876eacb07d 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -165,7 +165,7 @@ static struct dst_ops ipv4_dst_ops = { .mtu = ipv4_mtu, .cow_metrics = ipv4_cow_metrics, .destroy = ipv4_dst_destroy, - .negative_advice = (android_dst_ops_negative_advice_old_t)ipv4_negative_advice, + .negative_advice = ipv4_negative_advice, .link_failure = ipv4_link_failure, .update_pmtu = ip_rt_update_pmtu, .redirect = ip_do_redirect, diff --git a/net/ipv6/route.c b/net/ipv6/route.c index c2c2fd7def03..3731d74e2b28 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -250,7 +250,7 @@ static struct dst_ops ip6_dst_ops_template = { .cow_metrics = dst_cow_metrics_generic, .destroy = ip6_dst_destroy, .ifdown = ip6_dst_ifdown, - .negative_advice = (android_dst_ops_negative_advice_old_t)ip6_negative_advice, + .negative_advice = ip6_negative_advice, .link_failure = ip6_link_failure, .update_pmtu = ip6_rt_update_pmtu, .redirect = rt6_do_redirect, diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 0fe167dca7c2..cbf9387b1650 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -3949,7 +3949,7 @@ int xfrm_policy_register_afinfo(const struct xfrm_policy_afinfo *afinfo, int fam if (likely(dst_ops->mtu == NULL)) dst_ops->mtu = xfrm_mtu; if (likely(dst_ops->negative_advice == NULL)) - dst_ops->negative_advice = (android_dst_ops_negative_advice_old_t)xfrm_negative_advice; + dst_ops->negative_advice = xfrm_negative_advice; if (likely(dst_ops->link_failure == NULL)) dst_ops->link_failure = xfrm_link_failure; if (likely(dst_ops->neigh_lookup == NULL)) From 5740e39ff54a450f9606e3af75e3330d248e51f4 Mon Sep 17 00:00:00 2001 From: Michael Bestas Date: Wed, 19 Mar 2025 07:32:00 +0200 Subject: [PATCH 688/698] Revert "BACKPORT: net: fix __dst_negative_advice() race" This reverts commit c17f8768101315c5c88e7092386d39fb2915295b. Reason for revert: Conflicts with upstream commits. Change-Id: Iee731e1eca0f9a2cef4d301f92bbff758c1afe02 --- include/net/dst_ops.h | 2 +- include/net/sock.h | 13 ++++++++++--- net/ipv4/route.c | 22 ++++++++++++++-------- net/ipv6/route.c | 29 ++++++++++++++--------------- net/xfrm/xfrm_policy.c | 11 ++++++++--- 5 files changed, 47 insertions(+), 30 deletions(-) diff --git a/include/net/dst_ops.h b/include/net/dst_ops.h index b93799fe46e8..443863c7b8da 100644 --- a/include/net/dst_ops.h +++ b/include/net/dst_ops.h @@ -24,7 +24,7 @@ struct dst_ops { void (*destroy)(struct dst_entry *); void (*ifdown)(struct dst_entry *, struct net_device *dev, int how); - void (*negative_advice)(struct sock *sk, struct dst_entry *); + struct dst_entry * (*negative_advice)(struct dst_entry *); void (*link_failure)(struct sk_buff *); void (*update_pmtu)(struct dst_entry *dst, struct sock *sk, struct sk_buff *skb, u32 mtu, diff --git a/include/net/sock.h b/include/net/sock.h index f37ddce89483..125b16200ca4 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -1936,12 +1936,19 @@ sk_dst_get(struct sock *sk) static inline void dst_negative_advice(struct sock *sk) { - struct dst_entry *dst = __sk_dst_get(sk); + struct dst_entry *ndst, *dst = __sk_dst_get(sk); sk_rethink_txhash(sk); - if (dst && dst->ops->negative_advice) - dst->ops->negative_advice(sk, dst); + if (dst && dst->ops->negative_advice) { + ndst = dst->ops->negative_advice(dst); + + if (ndst != dst) { + rcu_assign_pointer(sk->sk_dst_cache, ndst); + sk_tx_queue_clear(sk); + sk->sk_dst_pending_confirm = 0; + } + } } static inline void diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 3a876eacb07d..f82d456afd0e 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -137,8 +137,7 @@ static int ip_rt_gc_timeout __read_mostly = RT_GC_TIMEOUT; static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie); static unsigned int ipv4_default_advmss(const struct dst_entry *dst); static unsigned int ipv4_mtu(const struct dst_entry *dst); -static void ipv4_negative_advice(struct sock *sk, - struct dst_entry *dst); +static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst); static void ipv4_link_failure(struct sk_buff *skb); static void ip_rt_update_pmtu(struct dst_entry *dst, struct sock *sk, struct sk_buff *skb, u32 mtu, @@ -857,15 +856,22 @@ static void ip_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_buf __ip_do_redirect(rt, skb, &fl4, true); } -static void ipv4_negative_advice(struct sock *sk, - struct dst_entry *dst) +static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst) { struct rtable *rt = (struct rtable *)dst; + struct dst_entry *ret = dst; - if ((dst->obsolete > 0) || - (rt->rt_flags & RTCF_REDIRECTED) || - rt->dst.expires) - sk_dst_reset(sk); + if (rt) { + if (dst->obsolete > 0) { + ip_rt_put(rt); + ret = NULL; + } else if ((rt->rt_flags & RTCF_REDIRECTED) || + rt->dst.expires) { + ip_rt_put(rt); + ret = NULL; + } + } + return ret; } /* diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 3731d74e2b28..defd581ae9d6 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -84,8 +84,7 @@ enum rt6_nud_state { static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie); static unsigned int ip6_default_advmss(const struct dst_entry *dst); static unsigned int ip6_mtu(const struct dst_entry *dst); -static void ip6_negative_advice(struct sock *sk, - struct dst_entry *dst); +static struct dst_entry *ip6_negative_advice(struct dst_entry *); static void ip6_dst_destroy(struct dst_entry *); static void ip6_dst_ifdown(struct dst_entry *, struct net_device *dev, int how); @@ -2659,24 +2658,24 @@ static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie) return dst_ret; } -static void ip6_negative_advice(struct sock *sk, - struct dst_entry *dst) +static struct dst_entry *ip6_negative_advice(struct dst_entry *dst) { struct rt6_info *rt = (struct rt6_info *) dst; - if (rt->rt6i_flags & RTF_CACHE) { - rcu_read_lock(); - if (rt6_check_expired(rt)) { - /* counteract the dst_release() in sk_dst_reset() */ - dst_hold(dst); - sk_dst_reset(sk); - - rt6_remove_exception_rt(rt); + if (rt) { + if (rt->rt6i_flags & RTF_CACHE) { + rcu_read_lock(); + if (rt6_check_expired(rt)) { + rt6_remove_exception_rt(rt); + dst = NULL; + } + rcu_read_unlock(); + } else { + dst_release(dst); + dst = NULL; } - rcu_read_unlock(); - return; } - sk_dst_reset(sk); + return dst; } static void ip6_link_failure(struct sk_buff *skb) diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index cbf9387b1650..8632776ae4da 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -3778,10 +3778,15 @@ static void xfrm_link_failure(struct sk_buff *skb) /* Impossible. Such dst must be popped before reaches point of failure. */ } -static void xfrm_negative_advice(struct sock *sk, struct dst_entry *dst) +static struct dst_entry *xfrm_negative_advice(struct dst_entry *dst) { - if (dst->obsolete) - sk_dst_reset(sk); + if (dst) { + if (dst->obsolete) { + dst_release(dst); + dst = NULL; + } + } + return dst; } static void xfrm_init_pmtu(struct xfrm_dst **bundle, int nr) From 3628064f37559b7aafd94f47aba88bc0ad5f17e1 Mon Sep 17 00:00:00 2001 From: Michael Bestas Date: Wed, 19 Mar 2025 07:33:06 +0200 Subject: [PATCH 689/698] Revert "af_unix: Fix garbage collector racing against connect()" This reverts commit 6487f3d3468b5df030838ad7dc02d63ab99d81eb. Reason for revert: Conflicts with upstream commits. Change-Id: I5e1ccd8f68283fe88f90eebc33ade79fddf0054a --- net/unix/garbage.c | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/net/unix/garbage.c b/net/unix/garbage.c index 67b2c3bfa113..312474c23e9a 100644 --- a/net/unix/garbage.c +++ b/net/unix/garbage.c @@ -235,22 +235,11 @@ void unix_gc(void) * receive queues. Other, non candidate sockets _can_ be * added to queue, so we must make sure only to touch * candidates. - * - * Embryos, though never candidates themselves, affect which - * candidates are reachable by the garbage collector. Before - * being added to a listener's queue, an embryo may already - * receive data carrying SCM_RIGHTS, potentially making the - * passed socket a candidate that is not yet reachable by the - * collector. It becomes reachable once the embryo is - * enqueued. Therefore, we must ensure that no SCM-laden - * embryo appears in a (candidate) listener's queue between - * consecutive scan_children() calls. */ list_for_each_entry_safe(u, next, &gc_inflight_list, link) { - struct sock *sk = &u->sk; long total_refs; - total_refs = file_count(sk->sk_socket->file); + total_refs = file_count(u->sk.sk_socket->file); BUG_ON(!u->inflight); BUG_ON(total_refs < u->inflight); @@ -258,11 +247,6 @@ void unix_gc(void) list_move_tail(&u->link, &gc_candidates); __set_bit(UNIX_GC_CANDIDATE, &u->gc_flags); __set_bit(UNIX_GC_MAYBE_CYCLE, &u->gc_flags); - - if (sk->sk_state == TCP_LISTEN) { - unix_state_lock(sk); - unix_state_unlock(sk); - } } } From ce75ac8da42385c77b052fb10ea63f34fc328253 Mon Sep 17 00:00:00 2001 From: Michael Bestas Date: Wed, 19 Mar 2025 07:33:15 +0200 Subject: [PATCH 690/698] Revert "af_unix: Do not use atomic ops for unix_sk(sk)->inflight." This reverts commit 9ef7c24511b39a841fae4fa064349dddb9214c83. Reason for revert: Conflicts with upstream commits. Change-Id: Id7ec5e6a24fd6702a7525893b6e3b3f2428b4704 --- include/net/af_unix.h | 2 +- net/unix/af_unix.c | 4 ++-- net/unix/garbage.c | 17 +++++++++-------- net/unix/scm.c | 8 +++----- 4 files changed, 15 insertions(+), 16 deletions(-) diff --git a/include/net/af_unix.h b/include/net/af_unix.h index 1b3c59323002..3426d6dacc45 100644 --- a/include/net/af_unix.h +++ b/include/net/af_unix.h @@ -58,7 +58,7 @@ struct unix_sock { struct mutex iolock, bindlock; struct sock *peer; struct list_head link; - unsigned long inflight; + atomic_long_t inflight; spinlock_t lock; unsigned long gc_flags; #define UNIX_GC_CANDIDATE 0 diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 966856dbea88..304eb26b34dc 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -809,11 +809,11 @@ static struct sock *unix_create1(struct net *net, struct socket *sock, int kern) sk->sk_write_space = unix_write_space; sk->sk_max_ack_backlog = net->unx.sysctl_max_dgram_qlen; sk->sk_destruct = unix_sock_destructor; - u = unix_sk(sk); - u->inflight = 0; + u = unix_sk(sk); u->path.dentry = NULL; u->path.mnt = NULL; spin_lock_init(&u->lock); + atomic_long_set(&u->inflight, 0); INIT_LIST_HEAD(&u->link); mutex_init(&u->iolock); /* single task reading lock */ mutex_init(&u->bindlock); /* single task binding lock */ diff --git a/net/unix/garbage.c b/net/unix/garbage.c index 312474c23e9a..dc2763540393 100644 --- a/net/unix/garbage.c +++ b/net/unix/garbage.c @@ -166,18 +166,17 @@ static void scan_children(struct sock *x, void (*func)(struct unix_sock *), static void dec_inflight(struct unix_sock *usk) { - usk->inflight--; + atomic_long_dec(&usk->inflight); } static void inc_inflight(struct unix_sock *usk) { - usk->inflight++; + atomic_long_inc(&usk->inflight); } static void inc_inflight_move_tail(struct unix_sock *u) { - u->inflight++; - + atomic_long_inc(&u->inflight); /* If this still might be part of a cycle, move it to the end * of the list, so that it's checked even if it was already * passed over @@ -238,12 +237,14 @@ void unix_gc(void) */ list_for_each_entry_safe(u, next, &gc_inflight_list, link) { long total_refs; + long inflight_refs; total_refs = file_count(u->sk.sk_socket->file); + inflight_refs = atomic_long_read(&u->inflight); - BUG_ON(!u->inflight); - BUG_ON(total_refs < u->inflight); - if (total_refs == u->inflight) { + BUG_ON(inflight_refs < 1); + BUG_ON(total_refs < inflight_refs); + if (total_refs == inflight_refs) { list_move_tail(&u->link, &gc_candidates); __set_bit(UNIX_GC_CANDIDATE, &u->gc_flags); __set_bit(UNIX_GC_MAYBE_CYCLE, &u->gc_flags); @@ -270,7 +271,7 @@ void unix_gc(void) /* Move cursor to after the current position. */ list_move(&cursor, &u->link); - if (u->inflight) { + if (atomic_long_read(&u->inflight) > 0) { list_move_tail(&u->link, ¬_cycle_list); __clear_bit(UNIX_GC_MAYBE_CYCLE, &u->gc_flags); scan_children(&u->sk, inc_inflight_move_tail, NULL); diff --git a/net/unix/scm.c b/net/unix/scm.c index ab2d664b7528..e881a6e78af5 100644 --- a/net/unix/scm.c +++ b/net/unix/scm.c @@ -53,13 +53,12 @@ void unix_inflight(struct user_struct *user, struct file *fp) if (s) { struct unix_sock *u = unix_sk(s); - if (!u->inflight) { + if (atomic_long_inc_return(&u->inflight) == 1) { BUG_ON(!list_empty(&u->link)); list_add_tail(&u->link, &gc_inflight_list); } else { BUG_ON(list_empty(&u->link)); } - u->inflight++; /* Paired with READ_ONCE() in wait_for_unix_gc() */ WRITE_ONCE(unix_tot_inflight, unix_tot_inflight + 1); } @@ -76,11 +75,10 @@ void unix_notinflight(struct user_struct *user, struct file *fp) if (s) { struct unix_sock *u = unix_sk(s); - BUG_ON(!u->inflight); + BUG_ON(!atomic_long_read(&u->inflight)); BUG_ON(list_empty(&u->link)); - u->inflight--; - if (!u->inflight) + if (atomic_long_dec_and_test(&u->inflight)) list_del_init(&u->link); /* Paired with READ_ONCE() in wait_for_unix_gc() */ WRITE_ONCE(unix_tot_inflight, unix_tot_inflight - 1); From 4267e716d38c807f555be428a873f845712543b2 Mon Sep 17 00:00:00 2001 From: Michael Bestas Date: Wed, 19 Mar 2025 07:39:38 +0200 Subject: [PATCH 691/698] Revert "net: qrtr: get svc_id before queueing sk_buff" This reverts commit 836e3b0c9a1c14137ea826a6c5bcc5b18b9776a4. Reason for revert: Conflicts with upstream commits. Change-Id: I963f28698392f505661abcc115b86e3c4c8801be --- net/qrtr/qrtr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/qrtr/qrtr.c b/net/qrtr/qrtr.c index fa7610531358..0b4873903143 100644 --- a/net/qrtr/qrtr.c +++ b/net/qrtr/qrtr.c @@ -929,7 +929,6 @@ int qrtr_endpoint_post(struct qrtr_endpoint *ep, const void *data, size_t len) /* All control packets and non-local destined data packets should be * queued to the worker for forwarding handling. */ - svc_id = qrtr_get_service_id(cb->src_node, cb->src_port); if (cb->type != QRTR_TYPE_DATA || cb->dst_node != qrtr_local_nid) { skb_queue_tail(&node->rx_queue, skb); kthread_queue_work(&node->kworker, &node->read_data); @@ -942,6 +941,7 @@ int qrtr_endpoint_post(struct qrtr_endpoint *ep, const void *data, size_t len) } if (node->nid == 5) { + svc_id = qrtr_get_service_id(cb->src_node, cb->src_port); if (svc_id > 0){ for (i = 0; i < node->no_wake_svc.size; i++) { if (svc_id == node->no_wake_svc.arr[i]) { From 403aa4c00b2cf953e71b82004790ff065d1f4b89 Mon Sep 17 00:00:00 2001 From: Michael Bestas Date: Wed, 19 Mar 2025 07:39:49 +0200 Subject: [PATCH 692/698] Revert "penang: device suspend tests fail" This reverts commit 485bfce7488fd22eb8e777d51eb94a027b514e20. Reason for revert: Conflicts with upstream commits. Change-Id: I5ca8bffe070c918271543678401d2d9ab25e4897 --- net/qrtr/qrtr.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/net/qrtr/qrtr.c b/net/qrtr/qrtr.c index 0b4873903143..81a87bc224eb 100644 --- a/net/qrtr/qrtr.c +++ b/net/qrtr/qrtr.c @@ -192,6 +192,7 @@ struct qrtr_node { struct wakeup_source *ws; void *ilc; + u32 nonwake_svc[MAX_NON_WAKE_SVC_LEN]; struct qrtr_array no_wake_svc; }; @@ -942,11 +943,15 @@ int qrtr_endpoint_post(struct qrtr_endpoint *ep, const void *data, size_t len) if (node->nid == 5) { svc_id = qrtr_get_service_id(cb->src_node, cb->src_port); - if (svc_id > 0){ - for (i = 0; i < node->no_wake_svc.size; i++) { - if (svc_id == node->no_wake_svc.arr[i]) { - wake = false; - break; + if (svc_id > 0) { + for (i = 0; i < MAX_NON_WAKE_SVC_LEN; i++) { + if (svc_id == node->nonwake_svc[i]) { + for (i = 0; i < node->no_wake_svc.size; i++) { + if (svc_id == node->no_wake_svc.arr[i]) { + wake = false; + break; + } + } } } } @@ -1199,6 +1204,8 @@ int qrtr_endpoint_register(struct qrtr_endpoint *ep, unsigned int net_id, if (rt) sched_setscheduler(node->task, SCHED_FIFO, ¶m); + if (svc_arr) + memcpy(node->nonwake_svc, svc_arr, MAX_NON_WAKE_SVC_LEN * sizeof(int)); if(svc_arr && svc_arr->size) { node->no_wake_svc.arr = kmalloc_array(svc_arr->size, sizeof(u32), GFP_KERNEL); memcpy((void *)node->no_wake_svc.arr, (void *)svc_arr->arr, From 269e073bc3821038dc66a0018f384aee8907136b Mon Sep 17 00:00:00 2001 From: Michael Bestas Date: Wed, 19 Mar 2025 07:40:00 +0200 Subject: [PATCH 693/698] Revert "Penang: kasan panic" This reverts commit 0ab43c2ab514f765cb0e023fa955fc3c9bca841e. Reason for revert: Conflicts with upstream commits. Change-Id: I02d3e77f611b75bb22f48f1492f7b3bdeb426a8f --- net/qrtr/qrtr.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/net/qrtr/qrtr.c b/net/qrtr/qrtr.c index 81a87bc224eb..30584254f785 100644 --- a/net/qrtr/qrtr.c +++ b/net/qrtr/qrtr.c @@ -956,14 +956,16 @@ int qrtr_endpoint_post(struct qrtr_endpoint *ep, const void *data, size_t len) } } } + if (sock_queue_rcv_skb(&ipc->sk, skb)) goto err; + /** * Force wakeup for all packets except for sensors and blacklisted services * from adsp side */ if ((node->nid != 9 && node->nid != 5) || - (node->nid == 5 && wake)) + (node->nid == 5 && wake)) pm_wakeup_ws_event(node->ws, qrtr_wakeup_ms, true); qrtr_port_put(ipc); From 5585e8424d1a641a47d504709028d9a8e1a81d9d Mon Sep 17 00:00:00 2001 From: Michael Bestas Date: Wed, 19 Mar 2025 07:40:11 +0200 Subject: [PATCH 694/698] Revert "Penang: resolve kasan panic" This reverts commit a65aa65ad1c1520ebb405b1bd5ae8d5d3986f2d0. Reason for revert: Conflicts with upstream commits. Change-Id: Ib80fa2d49308fe7bf853a93b977370768212ae05 --- net/qrtr/qrtr.c | 20 +++++--------------- net/qrtr/qrtr.h | 14 +------------- net/qrtr/smd.c | 16 ++++++---------- 3 files changed, 12 insertions(+), 38 deletions(-) diff --git a/net/qrtr/qrtr.c b/net/qrtr/qrtr.c index 30584254f785..fd1591c3fbcf 100644 --- a/net/qrtr/qrtr.c +++ b/net/qrtr/qrtr.c @@ -193,7 +193,6 @@ struct qrtr_node { void *ilc; u32 nonwake_svc[MAX_NON_WAKE_SVC_LEN]; - struct qrtr_array no_wake_svc; }; struct qrtr_tx_flow_waiter { @@ -422,7 +421,6 @@ static void __qrtr_node_release(struct kref *kref) kthread_stop(node->task); skb_queue_purge(&node->rx_queue); - kfree(node->no_wake_svc.arr); kfree(node); } @@ -946,12 +944,8 @@ int qrtr_endpoint_post(struct qrtr_endpoint *ep, const void *data, size_t len) if (svc_id > 0) { for (i = 0; i < MAX_NON_WAKE_SVC_LEN; i++) { if (svc_id == node->nonwake_svc[i]) { - for (i = 0; i < node->no_wake_svc.size; i++) { - if (svc_id == node->no_wake_svc.arr[i]) { - wake = false; - break; - } - } + wake = false; + break; } } } @@ -970,6 +964,7 @@ int qrtr_endpoint_post(struct qrtr_endpoint *ep, const void *data, size_t len) qrtr_port_put(ipc); } + return 0; err: @@ -1175,7 +1170,7 @@ static void qrtr_hello_work(struct kthread_work *work) * The specified endpoint must have the xmit function pointer set on call. */ int qrtr_endpoint_register(struct qrtr_endpoint *ep, unsigned int net_id, - bool rt, struct qrtr_array *svc_arr) + bool rt, u32 *svc_arr) { struct qrtr_node *node; struct sched_param param = {.sched_priority = 1}; @@ -1208,12 +1203,7 @@ int qrtr_endpoint_register(struct qrtr_endpoint *ep, unsigned int net_id, if (svc_arr) memcpy(node->nonwake_svc, svc_arr, MAX_NON_WAKE_SVC_LEN * sizeof(int)); - if(svc_arr && svc_arr->size) { - node->no_wake_svc.arr = kmalloc_array(svc_arr->size, sizeof(u32), GFP_KERNEL); - memcpy((void *)node->no_wake_svc.arr, (void *)svc_arr->arr, - svc_arr->size * sizeof(u32)); - node->no_wake_svc.size = svc_arr->size; - } + mutex_init(&node->qrtr_tx_lock); INIT_RADIX_TREE(&node->qrtr_tx_flow, GFP_KERNEL); init_waitqueue_head(&node->resume_tx); diff --git a/net/qrtr/qrtr.h b/net/qrtr/qrtr.h index f58117d6fb03..449028c2ec93 100644 --- a/net/qrtr/qrtr.h +++ b/net/qrtr/qrtr.h @@ -28,20 +28,8 @@ struct qrtr_endpoint { struct qrtr_node *node; }; -/** - * struct qrtr_array - array with size - * @arr: elements in the array - * @size: number of elements - * - * An array with its size provided. - */ -struct qrtr_array { - u32 *arr; - size_t size; -}; - int qrtr_endpoint_register(struct qrtr_endpoint *ep, unsigned int net_id, - bool rt, struct qrtr_array *svc_arr); + bool rt, u32 *svc_arr); void qrtr_endpoint_unregister(struct qrtr_endpoint *ep); diff --git a/net/qrtr/smd.c b/net/qrtr/smd.c index 1939bc1c98bb..705e6523e1b2 100644 --- a/net/qrtr/smd.c +++ b/net/qrtr/smd.c @@ -64,9 +64,8 @@ static int qcom_smd_qrtr_probe(struct rpmsg_device *rpdev) struct qrtr_smd_dev *qdev; u32 net_id; bool rt; - int rc; - size_t size; - struct qrtr_array svc_arr = {NULL, 0}; + int rc, size; + u32 *svc_arr = NULL; pr_info("%s:Entered\n", __func__); qdev = devm_kzalloc(&rpdev->dev, sizeof(*qdev), GFP_KERNEL); @@ -88,16 +87,13 @@ static int qcom_smd_qrtr_probe(struct rpmsg_device *rpdev) if (size > 0) { if (size > MAX_NON_WAKE_SVC_LEN) size = MAX_NON_WAKE_SVC_LEN; - svc_arr.size = size; - svc_arr.arr = kmalloc_array(size, sizeof(u32), GFP_KERNEL); - if (!svc_arr.arr) - return -ENOMEM; + svc_arr = kmalloc_array(size, sizeof(u32), GFP_KERNEL); of_property_read_u32_array(rpdev->dev.of_node, "qcom,non-wake-svc", - svc_arr.arr, size); + svc_arr, size); } - rc = qrtr_endpoint_register(&qdev->ep, net_id, rt, &svc_arr); - kfree(svc_arr.arr); + rc = qrtr_endpoint_register(&qdev->ep, net_id, rt, svc_arr); + kfree(svc_arr); if (rc) return rc; From e3819f890059ec0eaf5ca386f7e59481fc215ceb Mon Sep 17 00:00:00 2001 From: Michael Bestas Date: Wed, 19 Mar 2025 07:40:23 +0200 Subject: [PATCH 695/698] Revert "Penang: fix for device suspend tests fail. [1/2]" This reverts commit f536ebe9fcccb97a4761b2a662802098d0c42a06. Reason for revert: Conflicts with upstream commits. Change-Id: Iba5cafaf37044b09e2fee65682881f0503c2c990 --- net/qrtr/mhi.c | 2 +- net/qrtr/ns.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/net/qrtr/mhi.c b/net/qrtr/mhi.c index ae9c3e0f3fc3..c9377d28d890 100644 --- a/net/qrtr/mhi.c +++ b/net/qrtr/mhi.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only -/* Copyright (c) 2018-2021, The Linux Foundation. All rights reserved. */ +/* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. */ #include #include diff --git a/net/qrtr/ns.c b/net/qrtr/ns.c index 28516cdeffb4..845f21c8e1d0 100644 --- a/net/qrtr/ns.c +++ b/net/qrtr/ns.c @@ -104,7 +104,7 @@ unsigned int qrtr_get_service_id(unsigned int node_id, unsigned int port_id) struct qrtr_node *node; unsigned long index; - node = xa_load(&nodes, node_id); + node = node_get(node_id); if (!node) return 0; From dab88fd873c9c4b411a9c8018735d8d92281486a Mon Sep 17 00:00:00 2001 From: Michael Bestas Date: Wed, 19 Mar 2025 07:42:47 +0200 Subject: [PATCH 696/698] Revert "qseecom: Suppress suspend warning if without bus scaling." This reverts commit 2208e80231bc2e65751f82849dbe30ef90c61764. Reason for revert: Conflicts with upstream commits. Change-Id: I976cd54c43319a28892efdfe078ad146204d2eb0 --- drivers/misc/qseecom.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c index 2c9b0232a465..423b96f0f0c3 100644 --- a/drivers/misc/qseecom.c +++ b/drivers/misc/qseecom.c @@ -9760,9 +9760,7 @@ static int qseecom_suspend(struct platform_device *pdev, pm_message_t state) mutex_unlock(&clk_access_lock); mutex_unlock(&qsee_bw_mutex); - if (qseecom.support_bus_scaling) { - cancel_work_sync(&qseecom.bw_inactive_req_ws); - } + cancel_work_sync(&qseecom.bw_inactive_req_ws); return 0; } From 408802114d147b1a28a0878d59454f19ae799b8c Mon Sep 17 00:00:00 2001 From: Michael Bestas Date: Wed, 19 Mar 2025 07:45:51 +0200 Subject: [PATCH 697/698] Reapply "UPSTREAM: binder: fix the missing BR_FROZEN_REPLY in binder_return_strings" This reverts commit 3777eba3b1dc4d691d8d23d3f963da56a95c2253. Reason for revert: Conflicts with upstream commits. Change-Id: Id2eca0ce74ffbd1ca7146757336bc1b4e8a76bc2 --- drivers/android/binder.c | 3 ++- drivers/android/binder_internal.h | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/android/binder.c b/drivers/android/binder.c index 00f6de623ffe..7766c4bd92d2 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -6168,7 +6168,8 @@ static const char * const binder_return_strings[] = { "BR_FINISHED", "BR_DEAD_BINDER", "BR_CLEAR_DEATH_NOTIFICATION_DONE", - "BR_FAILED_REPLY" + "BR_FAILED_REPLY", + "BR_FROZEN_REPLY", }; static const char * const binder_command_strings[] = { diff --git a/drivers/android/binder_internal.h b/drivers/android/binder_internal.h index 9f4392458792..8db58eb70f07 100644 --- a/drivers/android/binder_internal.h +++ b/drivers/android/binder_internal.h @@ -155,7 +155,7 @@ enum binder_stat_types { }; struct binder_stats { - atomic_t br[_IOC_NR(BR_FAILED_REPLY) + 1]; + atomic_t br[_IOC_NR(BR_FROZEN_REPLY) + 1]; atomic_t bc[_IOC_NR(BC_REPLY_SG) + 1]; atomic_t obj_created[BINDER_STAT_COUNT]; atomic_t obj_deleted[BINDER_STAT_COUNT]; From 8e590ea149f228274dc8b2080873d55eb0a218a9 Mon Sep 17 00:00:00 2001 From: Michael Bestas Date: Wed, 19 Mar 2025 09:16:15 +0200 Subject: [PATCH 698/698] mmc: sdhci-msm: Move MMC_CAP2_MAX_DISCARD_SIZE to prevent merge conflict Change-Id: I80acdb4f52811ebd371317acfc4afa41e4960656 --- drivers/mmc/host/sdhci-msm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c index c3109e864e6c..9e5a097c63ab 100644 --- a/drivers/mmc/host/sdhci-msm.c +++ b/drivers/mmc/host/sdhci-msm.c @@ -4555,12 +4555,13 @@ static int sdhci_msm_probe(struct platform_device *pdev) } sdhci_msm_set_caps(msm_host); + msm_host->mmc->caps2 |= MMC_CAP2_MAX_DISCARD_SIZE; #if defined(CONFIG_SDC_QTI) host->timeout_clk_div = 4; msm_host->mmc->caps2 |= MMC_CAP2_CLK_SCALE; #endif - msm_host->mmc->caps2 |= MMC_CAP2_MAX_DISCARD_SIZE; + sdhci_msm_setup_pm(pdev, msm_host); host->mmc_host_ops.execute_tuning = sdhci_msm_execute_tuning;