From 5f8d1e3b6f9b5971f9c06d5846ce00c49e3a8d94 Mon Sep 17 00:00:00 2001 From: Tony O'Brien Date: Wed, 22 Feb 2023 13:52:27 +1300 Subject: hwmon: (adt7475) Display smoothing attributes in correct order Throughout the ADT7475 driver, attributes relating to the temperature sensors are displayed in the order Remote 1, Local, Remote 2. Make temp_st_show() conform to this expectation so that values set by temp_st_store() can be displayed using the correct attribute. Fixes: 8f05bcc33e74 ("hwmon: (adt7475) temperature smoothing") Signed-off-by: Tony O'Brien Link: https://lore.kernel.org/r/20230222005228.158661-2-tony.obrien@alliedtelesis.co.nz Signed-off-by: Guenter Roeck --- drivers/hwmon/adt7475.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/hwmon/adt7475.c b/drivers/hwmon/adt7475.c index 51b3d16c3223..77222c35a38e 100644 --- a/drivers/hwmon/adt7475.c +++ b/drivers/hwmon/adt7475.c @@ -556,11 +556,11 @@ static ssize_t temp_st_show(struct device *dev, struct device_attribute *attr, val = data->enh_acoustics[0] & 0xf; break; case 1: - val = (data->enh_acoustics[1] >> 4) & 0xf; + val = data->enh_acoustics[1] & 0xf; break; case 2: default: - val = data->enh_acoustics[1] & 0xf; + val = (data->enh_acoustics[1] >> 4) & 0xf; break; } -- cgit From 48e8186870d9d0902e712d601ccb7098cb220688 Mon Sep 17 00:00:00 2001 From: Tony O'Brien Date: Wed, 22 Feb 2023 13:52:28 +1300 Subject: hwmon: (adt7475) Fix masking of hysteresis registers The wrong bits are masked in the hysteresis register; indices 0 and 2 should zero bits [7:4] and preserve bits [3:0], and index 1 should zero bits [3:0] and preserve bits [7:4]. Fixes: 1c301fc5394f ("hwmon: Add a driver for the ADT7475 hardware monitoring chip") Signed-off-by: Tony O'Brien Link: https://lore.kernel.org/r/20230222005228.158661-3-tony.obrien@alliedtelesis.co.nz Signed-off-by: Guenter Roeck --- drivers/hwmon/adt7475.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/hwmon/adt7475.c b/drivers/hwmon/adt7475.c index 77222c35a38e..6e4c92b500b8 100644 --- a/drivers/hwmon/adt7475.c +++ b/drivers/hwmon/adt7475.c @@ -488,10 +488,10 @@ static ssize_t temp_store(struct device *dev, struct device_attribute *attr, val = (temp - val) / 1000; if (sattr->index != 1) { - data->temp[HYSTERSIS][sattr->index] &= 0xF0; + data->temp[HYSTERSIS][sattr->index] &= 0x0F; data->temp[HYSTERSIS][sattr->index] |= (val & 0xF) << 4; } else { - data->temp[HYSTERSIS][sattr->index] &= 0x0F; + data->temp[HYSTERSIS][sattr->index] &= 0xF0; data->temp[HYSTERSIS][sattr->index] |= (val & 0xF); } -- cgit From f77ebdda0ee652124061c2ac42399bb6c367e729 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Thu, 5 Jan 2023 02:22:19 +0200 Subject: interconnect: qcom: osm-l3: fix icc_onecell_data allocation This is a struct with a trailing zero-length array of icc_node pointers but it's allocated as if it were a single array of icc_nodes instead. Fortunately this overallocates memory rather then allocating less memory than required. Fix by replacing devm_kcalloc() with devm_kzalloc() and struct_size() macro. Fixes: 5bc9900addaf ("interconnect: qcom: Add OSM L3 interconnect provider support") Signed-off-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20230105002221.1416479-2-dmitry.baryshkov@linaro.org Signed-off-by: Georgi Djakov --- drivers/interconnect/qcom/osm-l3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/interconnect/qcom/osm-l3.c b/drivers/interconnect/qcom/osm-l3.c index 5fa171087425..1bc01ff6e02a 100644 --- a/drivers/interconnect/qcom/osm-l3.c +++ b/drivers/interconnect/qcom/osm-l3.c @@ -236,7 +236,7 @@ static int qcom_osm_l3_probe(struct platform_device *pdev) qnodes = desc->nodes; num_nodes = desc->num_nodes; - data = devm_kcalloc(&pdev->dev, num_nodes, sizeof(*node), GFP_KERNEL); + data = devm_kzalloc(&pdev->dev, struct_size(data, nodes, num_nodes), GFP_KERNEL); if (!data) return -ENOMEM; -- cgit From 87e8fab1917a2b3f6e3dedfd1cdf22a1416e6676 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Thu, 5 Jan 2023 02:22:20 +0200 Subject: interconnect: qcom: sm8450: switch to qcom_icc_rpmh_* function Change sm8450 interconnect driver to use generic qcom_icc_rpmh_* functions rather than embedding a copy of thema. This also fixes an overallocation of memory for icc_onecell_data structure. Fixes: fafc114a468e ("interconnect: qcom: Add SM8450 interconnect provider driver") Signed-off-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20230105002221.1416479-3-dmitry.baryshkov@linaro.org Signed-off-by: Georgi Djakov --- drivers/interconnect/qcom/sm8450.c | 98 +------------------------------------- 1 file changed, 2 insertions(+), 96 deletions(-) diff --git a/drivers/interconnect/qcom/sm8450.c b/drivers/interconnect/qcom/sm8450.c index e3a12e3d6e06..2d7a8e7b85ec 100644 --- a/drivers/interconnect/qcom/sm8450.c +++ b/drivers/interconnect/qcom/sm8450.c @@ -1844,100 +1844,6 @@ static const struct qcom_icc_desc sm8450_system_noc = { .num_bcms = ARRAY_SIZE(system_noc_bcms), }; -static int qnoc_probe(struct platform_device *pdev) -{ - const struct qcom_icc_desc *desc; - struct icc_onecell_data *data; - struct icc_provider *provider; - struct qcom_icc_node * const *qnodes; - struct qcom_icc_provider *qp; - struct icc_node *node; - size_t num_nodes, i; - int ret; - - desc = device_get_match_data(&pdev->dev); - if (!desc) - return -EINVAL; - - qnodes = desc->nodes; - num_nodes = desc->num_nodes; - - qp = devm_kzalloc(&pdev->dev, sizeof(*qp), GFP_KERNEL); - if (!qp) - return -ENOMEM; - - data = devm_kcalloc(&pdev->dev, num_nodes, sizeof(*node), GFP_KERNEL); - if (!data) - return -ENOMEM; - - provider = &qp->provider; - provider->dev = &pdev->dev; - provider->set = qcom_icc_set; - provider->pre_aggregate = qcom_icc_pre_aggregate; - provider->aggregate = qcom_icc_aggregate; - provider->xlate_extended = qcom_icc_xlate_extended; - INIT_LIST_HEAD(&provider->nodes); - provider->data = data; - - qp->dev = &pdev->dev; - qp->bcms = desc->bcms; - qp->num_bcms = desc->num_bcms; - - qp->voter = of_bcm_voter_get(qp->dev, NULL); - if (IS_ERR(qp->voter)) - return PTR_ERR(qp->voter); - - ret = icc_provider_add(provider); - if (ret) { - dev_err(&pdev->dev, "error adding interconnect provider\n"); - return ret; - } - - for (i = 0; i < qp->num_bcms; i++) - qcom_icc_bcm_init(qp->bcms[i], &pdev->dev); - - for (i = 0; i < num_nodes; i++) { - size_t j; - - if (!qnodes[i]) - continue; - - node = icc_node_create(qnodes[i]->id); - if (IS_ERR(node)) { - ret = PTR_ERR(node); - goto err; - } - - node->name = qnodes[i]->name; - node->data = qnodes[i]; - icc_node_add(node, provider); - - for (j = 0; j < qnodes[i]->num_links; j++) - icc_link_create(node, qnodes[i]->links[j]); - - data->nodes[i] = node; - } - data->num_nodes = num_nodes; - - platform_set_drvdata(pdev, qp); - - return 0; -err: - icc_nodes_remove(provider); - icc_provider_del(provider); - return ret; -} - -static int qnoc_remove(struct platform_device *pdev) -{ - struct qcom_icc_provider *qp = platform_get_drvdata(pdev); - - icc_nodes_remove(&qp->provider); - icc_provider_del(&qp->provider); - - return 0; -} - static const struct of_device_id qnoc_of_match[] = { { .compatible = "qcom,sm8450-aggre1-noc", .data = &sm8450_aggre1_noc}, @@ -1966,8 +1872,8 @@ static const struct of_device_id qnoc_of_match[] = { MODULE_DEVICE_TABLE(of, qnoc_of_match); static struct platform_driver qnoc_driver = { - .probe = qnoc_probe, - .remove = qnoc_remove, + .probe = qcom_icc_rpmh_probe, + .remove = qcom_icc_rpmh_remove, .driver = { .name = "qnoc-sm8450", .of_match_table = qnoc_of_match, -- cgit From 0d00cd114f20e4a6db37e4b08435c27acc1d1db0 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Thu, 5 Jan 2023 02:22:21 +0200 Subject: interconnect: qcom: sm8550: switch to qcom_icc_rpmh_* function Change sm8550 interconnect driver to use generic qcom_icc_rpmh_* functions rather than embedding a copy of thema. This also fixes an overallocation of memory for icc_onecell_data structure. Fixes: e6f0d6a30f73 ("interconnect: qcom: Add SM8550 interconnect provider driver") Signed-off-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20230105002221.1416479-4-dmitry.baryshkov@linaro.org Signed-off-by: Georgi Djakov --- drivers/interconnect/qcom/sm8550.c | 99 +------------------------------------- 1 file changed, 2 insertions(+), 97 deletions(-) diff --git a/drivers/interconnect/qcom/sm8550.c b/drivers/interconnect/qcom/sm8550.c index 54fa027ab961..d823ba988ef6 100644 --- a/drivers/interconnect/qcom/sm8550.c +++ b/drivers/interconnect/qcom/sm8550.c @@ -2165,101 +2165,6 @@ static const struct qcom_icc_desc sm8550_system_noc = { .num_bcms = ARRAY_SIZE(system_noc_bcms), }; -static int qnoc_probe(struct platform_device *pdev) -{ - const struct qcom_icc_desc *desc; - struct icc_onecell_data *data; - struct icc_provider *provider; - struct qcom_icc_node * const *qnodes; - struct qcom_icc_provider *qp; - struct icc_node *node; - size_t num_nodes, i; - int ret; - - desc = device_get_match_data(&pdev->dev); - if (!desc) - return -EINVAL; - - qnodes = desc->nodes; - num_nodes = desc->num_nodes; - - qp = devm_kzalloc(&pdev->dev, sizeof(*qp), GFP_KERNEL); - if (!qp) - return -ENOMEM; - - data = devm_kcalloc(&pdev->dev, num_nodes, sizeof(*node), GFP_KERNEL); - if (!data) - return -ENOMEM; - - provider = &qp->provider; - provider->dev = &pdev->dev; - provider->set = qcom_icc_set; - provider->pre_aggregate = qcom_icc_pre_aggregate; - provider->aggregate = qcom_icc_aggregate; - provider->xlate_extended = qcom_icc_xlate_extended; - INIT_LIST_HEAD(&provider->nodes); - provider->data = data; - - qp->dev = &pdev->dev; - qp->bcms = desc->bcms; - qp->num_bcms = desc->num_bcms; - - qp->voter = of_bcm_voter_get(qp->dev, NULL); - if (IS_ERR(qp->voter)) - return PTR_ERR(qp->voter); - - ret = icc_provider_add(provider); - if (ret) { - dev_err_probe(&pdev->dev, ret, - "error adding interconnect provider\n"); - return ret; - } - - for (i = 0; i < qp->num_bcms; i++) - qcom_icc_bcm_init(qp->bcms[i], &pdev->dev); - - for (i = 0; i < num_nodes; i++) { - size_t j; - - if (!qnodes[i]) - continue; - - node = icc_node_create(qnodes[i]->id); - if (IS_ERR(node)) { - ret = PTR_ERR(node); - goto err; - } - - node->name = qnodes[i]->name; - node->data = qnodes[i]; - icc_node_add(node, provider); - - for (j = 0; j < qnodes[i]->num_links; j++) - icc_link_create(node, qnodes[i]->links[j]); - - data->nodes[i] = node; - } - data->num_nodes = num_nodes; - - platform_set_drvdata(pdev, qp); - - return 0; -err: - icc_nodes_remove(provider); - icc_provider_del(provider); - return ret; -} - -static int qnoc_remove(struct platform_device *pdev) -{ - struct qcom_icc_provider *qp = platform_get_drvdata(pdev); - - icc_nodes_remove(&qp->provider); - icc_provider_del(&qp->provider); - - return 0; -} - static const struct of_device_id qnoc_of_match[] = { { .compatible = "qcom,sm8550-aggre1-noc", .data = &sm8550_aggre1_noc}, @@ -2294,8 +2199,8 @@ static const struct of_device_id qnoc_of_match[] = { MODULE_DEVICE_TABLE(of, qnoc_of_match); static struct platform_driver qnoc_driver = { - .probe = qnoc_probe, - .remove = qnoc_remove, + .probe = qcom_icc_rpmh_probe, + .remove = qcom_icc_rpmh_remove, .driver = { .name = "qnoc-sm8550", .of_match_table = qnoc_of_match, -- cgit From ceac10c83b330680cc01ceaaab86cd49f4f30d81 Mon Sep 17 00:00:00 2001 From: Andrew Jeffery Date: Wed, 22 Feb 2023 00:10:14 +0100 Subject: ARM: 9290/1: uaccess: Fix KASAN false-positives __copy_to_user_memcpy() and __clear_user_memset() had been calling memcpy() and memset() respectively, leading to false-positive KASAN reports when starting userspace: [ 10.707901] Run /init as init process [ 10.731892] process '/bin/busybox' started with executable stack [ 10.745234] ================================================================== [ 10.745796] BUG: KASAN: user-memory-access in __clear_user_memset+0x258/0x3ac [ 10.747260] Write of size 2687 at addr 000de581 by task init/1 Use __memcpy() and __memset() instead to allow userspace access, which is of course the intent of these functions. Signed-off-by: Andrew Jeffery Signed-off-by: Zev Weiss Reviewed-by: Arnd Bergmann Signed-off-by: Russell King (Oracle) --- arch/arm/lib/uaccess_with_memcpy.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/lib/uaccess_with_memcpy.c b/arch/arm/lib/uaccess_with_memcpy.c index 14eecaaf295f..e4c2677cc1e9 100644 --- a/arch/arm/lib/uaccess_with_memcpy.c +++ b/arch/arm/lib/uaccess_with_memcpy.c @@ -116,7 +116,7 @@ __copy_to_user_memcpy(void __user *to, const void *from, unsigned long n) tocopy = n; ua_flags = uaccess_save_and_enable(); - memcpy((void *)to, from, tocopy); + __memcpy((void *)to, from, tocopy); uaccess_restore(ua_flags); to += tocopy; from += tocopy; @@ -178,7 +178,7 @@ __clear_user_memset(void __user *addr, unsigned long n) tocopy = n; ua_flags = uaccess_save_and_enable(); - memset((void *)addr, 0, tocopy); + __memset((void *)addr, 0, tocopy); uaccess_restore(ua_flags); addr += tocopy; n -= tocopy; -- cgit From 633a12fda6536a1a17bcea29502e777e86a4547e Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Tue, 3 Jan 2023 15:21:20 +0100 Subject: interconnect: qcom: qcm2290: Fix MASTER_SNOC_BIMC_NRT Due to what seems to be a copy-paste error, the _NRT master was identical to the _RT master, which should not be the case.. Fix it using the values available from the downstream kernel [1]. [1] https://android.googlesource.com/kernel/msm-extra/devicetree/+/refs/heads/android-msm-bramble-4.19-android11-qpr1/qcom/scuba-bus.dtsi#127 Fixes: 1a14b1ac3935 ("interconnect: qcom: Add QCM2290 driver support") Signed-off-by: Konrad Dybcio Acked-by: Shawn Guo Link: https://lore.kernel.org/r/20230103142120.15605-1-konrad.dybcio@linaro.org Signed-off-by: Georgi Djakov --- drivers/interconnect/qcom/qcm2290.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/interconnect/qcom/qcm2290.c b/drivers/interconnect/qcom/qcm2290.c index 0da612d6398c..a29cdb4fac03 100644 --- a/drivers/interconnect/qcom/qcm2290.c +++ b/drivers/interconnect/qcom/qcm2290.c @@ -147,9 +147,9 @@ static struct qcom_icc_node mas_snoc_bimc_nrt = { .name = "mas_snoc_bimc_nrt", .buswidth = 16, .qos.ap_owned = true, - .qos.qos_port = 2, + .qos.qos_port = 3, .qos.qos_mode = NOC_QOS_MODE_BYPASS, - .mas_rpm_id = 163, + .mas_rpm_id = 164, .slv_rpm_id = -1, .num_links = ARRAY_SIZE(mas_snoc_bimc_nrt_links), .links = mas_snoc_bimc_nrt_links, -- cgit From ced0f245ed951e2b8bd68f79c15238d7dd253662 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 6 Mar 2023 11:14:50 +0100 Subject: kallsyms: add kallsyms_seqs_of_names to list of special symbols My randconfig build setup ran into another kallsyms warning: Inconsistent kallsyms data Try make KALLSYMS_EXTRA_PASS=1 as a workaround After adding some debugging code to kallsyms.c, I saw that the recently added kallsyms_seqs_of_names symbol can sometimes cause the second stage table to be slightly longer than the first stage, which makes the build inconsistent. Add it to the exception table that contains all other kallsyms-generated symbols. Fixes: 60443c88f3a8 ("kallsyms: Improve the performance of kallsyms_lookup_name()") Signed-off-by: Arnd Bergmann Reviewed-by: Zhen Lei Signed-off-by: Masahiro Yamada --- scripts/kallsyms.c | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c index 8a68179a98a3..a239a87e7bec 100644 --- a/scripts/kallsyms.c +++ b/scripts/kallsyms.c @@ -119,6 +119,7 @@ static bool is_ignored_symbol(const char *name, char type) "kallsyms_markers", "kallsyms_token_table", "kallsyms_token_index", + "kallsyms_seqs_of_names", /* Exclude linker generated symbols which vary between passes */ "_SDA_BASE_", /* ppc */ "_SDA2_BASE_", /* ppc */ -- cgit From a5904f415e1af72fa8fe6665aa4f554dc2099a95 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 6 Mar 2023 08:56:29 +0100 Subject: interconnect: fix mem leak when freeing nodes The node link array is allocated when adding links to a node but is not deallocated when nodes are destroyed. Fixes: 11f1ceca7031 ("interconnect: Add generic on-chip interconnect API") Cc: stable@vger.kernel.org # 5.1 Reviewed-by: Konrad Dybcio Signed-off-by: Johan Hovold Tested-by: Luca Ceresoli # i.MX8MP MSC SM2-MB-EP1 Board Link: https://lore.kernel.org/r/20230306075651.2449-2-johan+linaro@kernel.org Signed-off-by: Georgi Djakov --- drivers/interconnect/core.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/interconnect/core.c b/drivers/interconnect/core.c index 0f392f59b135..5217f449eeec 100644 --- a/drivers/interconnect/core.c +++ b/drivers/interconnect/core.c @@ -850,6 +850,10 @@ void icc_node_destroy(int id) mutex_unlock(&icc_lock); + if (!node) + return; + + kfree(node->links); kfree(node); } EXPORT_SYMBOL_GPL(icc_node_destroy); -- cgit From e0e7089bf9a87bc5e3997422e4e24563424f9018 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 6 Mar 2023 08:56:30 +0100 Subject: interconnect: fix icc_provider_del() error handling The interconnect framework currently expects that providers are only removed when there are no users and after all nodes have been removed. There is currently nothing that guarantees this to be the case and the framework does not do any reference counting, but refusing to remove the provider is never correct as that would leave a dangling pointer to a resource that is about to be released in the global provider list (e.g. accessible through debugfs). Replace the current sanity checks with WARN_ON() so that the provider is always removed. Fixes: 11f1ceca7031 ("interconnect: Add generic on-chip interconnect API") Cc: stable@vger.kernel.org # 5.1: 680f8666baf6: interconnect: Make icc_provider_del() return void Reviewed-by: Konrad Dybcio Signed-off-by: Johan Hovold Tested-by: Luca Ceresoli # i.MX8MP MSC SM2-MB-EP1 Board Link: https://lore.kernel.org/r/20230306075651.2449-3-johan+linaro@kernel.org Signed-off-by: Georgi Djakov --- drivers/interconnect/core.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/drivers/interconnect/core.c b/drivers/interconnect/core.c index 5217f449eeec..cabb6f5df83e 100644 --- a/drivers/interconnect/core.c +++ b/drivers/interconnect/core.c @@ -1065,18 +1065,8 @@ EXPORT_SYMBOL_GPL(icc_provider_add); void icc_provider_del(struct icc_provider *provider) { mutex_lock(&icc_lock); - if (provider->users) { - pr_warn("interconnect provider still has %d users\n", - provider->users); - mutex_unlock(&icc_lock); - return; - } - - if (!list_empty(&provider->nodes)) { - pr_warn("interconnect provider still has nodes\n"); - mutex_unlock(&icc_lock); - return; - } + WARN_ON(provider->users); + WARN_ON(!list_empty(&provider->nodes)); list_del(&provider->provider_list); mutex_unlock(&icc_lock); -- cgit From eb59eca0d8ac15f8c1b7f1cd35999455a90292c0 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 6 Mar 2023 08:56:31 +0100 Subject: interconnect: fix provider registration API The current interconnect provider interface is inherently racy as providers are expected to be added before being fully initialised. Specifically, nodes are currently not added and the provider data is not initialised until after registering the provider which can cause racing DT lookups to fail. Add a new provider API which will be used to fix up the interconnect drivers. The old API is reimplemented using the new interface and will be removed once all drivers have been fixed. Fixes: 11f1ceca7031 ("interconnect: Add generic on-chip interconnect API") Fixes: 87e3031b6fbd ("interconnect: Allow endpoints translation via DT") Cc: stable@vger.kernel.org # 5.1 Reviewed-by: Konrad Dybcio Signed-off-by: Johan Hovold Tested-by: Luca Ceresoli # i.MX8MP MSC SM2-MB-EP1 Board Link: https://lore.kernel.org/r/20230306075651.2449-4-johan+linaro@kernel.org Signed-off-by: Georgi Djakov --- drivers/interconnect/core.c | 52 +++++++++++++++++++++++++---------- include/linux/interconnect-provider.h | 12 ++++++++ 2 files changed, 50 insertions(+), 14 deletions(-) diff --git a/drivers/interconnect/core.c b/drivers/interconnect/core.c index cabb6f5df83e..7a24c1444ace 100644 --- a/drivers/interconnect/core.c +++ b/drivers/interconnect/core.c @@ -1033,44 +1033,68 @@ int icc_nodes_remove(struct icc_provider *provider) EXPORT_SYMBOL_GPL(icc_nodes_remove); /** - * icc_provider_add() - add a new interconnect provider - * @provider: the interconnect provider that will be added into topology + * icc_provider_init() - initialize a new interconnect provider + * @provider: the interconnect provider to initialize + * + * Must be called before adding nodes to the provider. + */ +void icc_provider_init(struct icc_provider *provider) +{ + WARN_ON(!provider->set); + + INIT_LIST_HEAD(&provider->nodes); +} +EXPORT_SYMBOL_GPL(icc_provider_init); + +/** + * icc_provider_register() - register a new interconnect provider + * @provider: the interconnect provider to register * * Return: 0 on success, or an error code otherwise */ -int icc_provider_add(struct icc_provider *provider) +int icc_provider_register(struct icc_provider *provider) { - if (WARN_ON(!provider->set)) - return -EINVAL; if (WARN_ON(!provider->xlate && !provider->xlate_extended)) return -EINVAL; mutex_lock(&icc_lock); - - INIT_LIST_HEAD(&provider->nodes); list_add_tail(&provider->provider_list, &icc_providers); - mutex_unlock(&icc_lock); - dev_dbg(provider->dev, "interconnect provider added to topology\n"); + dev_dbg(provider->dev, "interconnect provider registered\n"); return 0; } -EXPORT_SYMBOL_GPL(icc_provider_add); +EXPORT_SYMBOL_GPL(icc_provider_register); /** - * icc_provider_del() - delete previously added interconnect provider - * @provider: the interconnect provider that will be removed from topology + * icc_provider_deregister() - deregister an interconnect provider + * @provider: the interconnect provider to deregister */ -void icc_provider_del(struct icc_provider *provider) +void icc_provider_deregister(struct icc_provider *provider) { mutex_lock(&icc_lock); WARN_ON(provider->users); - WARN_ON(!list_empty(&provider->nodes)); list_del(&provider->provider_list); mutex_unlock(&icc_lock); } +EXPORT_SYMBOL_GPL(icc_provider_deregister); + +int icc_provider_add(struct icc_provider *provider) +{ + icc_provider_init(provider); + + return icc_provider_register(provider); +} +EXPORT_SYMBOL_GPL(icc_provider_add); + +void icc_provider_del(struct icc_provider *provider) +{ + WARN_ON(!list_empty(&provider->nodes)); + + icc_provider_deregister(provider); +} EXPORT_SYMBOL_GPL(icc_provider_del); static const struct of_device_id __maybe_unused ignore_list[] = { diff --git a/include/linux/interconnect-provider.h b/include/linux/interconnect-provider.h index cd5c5a27557f..d12cd18aab3f 100644 --- a/include/linux/interconnect-provider.h +++ b/include/linux/interconnect-provider.h @@ -122,6 +122,9 @@ int icc_link_destroy(struct icc_node *src, struct icc_node *dst); void icc_node_add(struct icc_node *node, struct icc_provider *provider); void icc_node_del(struct icc_node *node); int icc_nodes_remove(struct icc_provider *provider); +void icc_provider_init(struct icc_provider *provider); +int icc_provider_register(struct icc_provider *provider); +void icc_provider_deregister(struct icc_provider *provider); int icc_provider_add(struct icc_provider *provider); void icc_provider_del(struct icc_provider *provider); struct icc_node_data *of_icc_get_from_provider(struct of_phandle_args *spec); @@ -167,6 +170,15 @@ static inline int icc_nodes_remove(struct icc_provider *provider) return -ENOTSUPP; } +static inline void icc_provider_init(struct icc_provider *provider) { } + +static inline int icc_provider_register(struct icc_provider *provider) +{ + return -ENOTSUPP; +} + +static inline void icc_provider_deregister(struct icc_provider *provider) { } + static inline int icc_provider_add(struct icc_provider *provider) { return -ENOTSUPP; -- cgit From 9fbd35520f1f7f3cbe1873939a27ad9b009f21f9 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 6 Mar 2023 08:56:32 +0100 Subject: interconnect: imx: fix registration race The current interconnect provider registration interface is inherently racy as nodes are not added until the after adding the provider. This can specifically cause racing DT lookups to fail. Switch to using the new API where the provider is not registered until after it has been fully initialised. Fixes: f0d8048525d7 ("interconnect: Add imx core driver") Cc: stable@vger.kernel.org # 5.8 Cc: Alexandre Bailon Reviewed-by: Konrad Dybcio Signed-off-by: Johan Hovold Tested-by: Luca Ceresoli # i.MX8MP MSC SM2-MB-EP1 Board Link: https://lore.kernel.org/r/20230306075651.2449-5-johan+linaro@kernel.org Signed-off-by: Georgi Djakov --- drivers/interconnect/imx/imx.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/interconnect/imx/imx.c b/drivers/interconnect/imx/imx.c index 823d9be9771a..979ed610f704 100644 --- a/drivers/interconnect/imx/imx.c +++ b/drivers/interconnect/imx/imx.c @@ -295,6 +295,9 @@ int imx_icc_register(struct platform_device *pdev, provider->xlate = of_icc_xlate_onecell; provider->data = data; provider->dev = dev->parent; + + icc_provider_init(provider); + platform_set_drvdata(pdev, imx_provider); if (settings) { @@ -306,20 +309,18 @@ int imx_icc_register(struct platform_device *pdev, } } - ret = icc_provider_add(provider); - if (ret) { - dev_err(dev, "error adding interconnect provider: %d\n", ret); + ret = imx_icc_register_nodes(imx_provider, nodes, nodes_count, settings); + if (ret) return ret; - } - ret = imx_icc_register_nodes(imx_provider, nodes, nodes_count, settings); + ret = icc_provider_register(provider); if (ret) - goto provider_del; + goto err_unregister_nodes; return 0; -provider_del: - icc_provider_del(provider); +err_unregister_nodes: + imx_icc_unregister_nodes(&imx_provider->provider); return ret; } EXPORT_SYMBOL_GPL(imx_icc_register); @@ -328,9 +329,8 @@ void imx_icc_unregister(struct platform_device *pdev) { struct imx_icc_provider *imx_provider = platform_get_drvdata(pdev); + icc_provider_deregister(&imx_provider->provider); imx_icc_unregister_nodes(&imx_provider->provider); - - icc_provider_del(&imx_provider->provider); } EXPORT_SYMBOL_GPL(imx_icc_unregister); -- cgit From 174941ed28a3573db075da46d95b4dcf9d4c49c2 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 6 Mar 2023 08:56:33 +0100 Subject: interconnect: qcom: osm-l3: fix registration race The current interconnect provider registration interface is inherently racy as nodes are not added until the after adding the provider. This can specifically cause racing DT lookups to fail: of_icc_xlate_onecell: invalid index 0 cpu cpu0: error -EINVAL: error finding src node cpu cpu0: dev_pm_opp_of_find_icc_paths: Unable to get path0: -22 qcom-cpufreq-hw: probe of 18591000.cpufreq failed with error -22 Switch to using the new API where the provider is not registered until after it has been fully initialised. Fixes: 5bc9900addaf ("interconnect: qcom: Add OSM L3 interconnect provider support") Cc: stable@vger.kernel.org # 5.7 Reviewed-by: Konrad Dybcio Signed-off-by: Johan Hovold Link: https://lore.kernel.org/r/20230306075651.2449-6-johan+linaro@kernel.org Signed-off-by: Georgi Djakov --- drivers/interconnect/qcom/osm-l3.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/interconnect/qcom/osm-l3.c b/drivers/interconnect/qcom/osm-l3.c index 1bc01ff6e02a..1bafb54f1432 100644 --- a/drivers/interconnect/qcom/osm-l3.c +++ b/drivers/interconnect/qcom/osm-l3.c @@ -158,8 +158,8 @@ static int qcom_osm_l3_remove(struct platform_device *pdev) { struct qcom_osm_l3_icc_provider *qp = platform_get_drvdata(pdev); + icc_provider_deregister(&qp->provider); icc_nodes_remove(&qp->provider); - icc_provider_del(&qp->provider); return 0; } @@ -245,14 +245,9 @@ static int qcom_osm_l3_probe(struct platform_device *pdev) provider->set = qcom_osm_l3_set; provider->aggregate = icc_std_aggregate; provider->xlate = of_icc_xlate_onecell; - INIT_LIST_HEAD(&provider->nodes); provider->data = data; - ret = icc_provider_add(provider); - if (ret) { - dev_err(&pdev->dev, "error adding interconnect provider\n"); - return ret; - } + icc_provider_init(provider); for (i = 0; i < num_nodes; i++) { size_t j; @@ -275,12 +270,15 @@ static int qcom_osm_l3_probe(struct platform_device *pdev) } data->num_nodes = num_nodes; + ret = icc_provider_register(provider); + if (ret) + goto err; + platform_set_drvdata(pdev, qp); return 0; err: icc_nodes_remove(provider); - icc_provider_del(provider); return ret; } -- cgit From bc463201f60803fa6bf2741d59441031cd0910e4 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 6 Mar 2023 08:56:34 +0100 Subject: interconnect: qcom: rpm: fix probe child-node error handling Make sure to clean up and release resources properly also in case probe fails when populating child devices. Fixes: e39bf2972c6e ("interconnect: icc-rpm: Support child NoC device probe") Cc: stable@vger.kernel.org # 5.17 Reviewed-by: Konrad Dybcio Signed-off-by: Johan Hovold Link: https://lore.kernel.org/r/20230306075651.2449-7-johan+linaro@kernel.org Signed-off-by: Georgi Djakov --- drivers/interconnect/qcom/icc-rpm.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/interconnect/qcom/icc-rpm.c b/drivers/interconnect/qcom/icc-rpm.c index df3196f72536..91778cfcbc65 100644 --- a/drivers/interconnect/qcom/icc-rpm.c +++ b/drivers/interconnect/qcom/icc-rpm.c @@ -541,8 +541,11 @@ regmap_done: platform_set_drvdata(pdev, qp); /* Populate child NoC devices if any */ - if (of_get_child_count(dev->of_node) > 0) - return of_platform_populate(dev->of_node, NULL, NULL, dev); + if (of_get_child_count(dev->of_node) > 0) { + ret = of_platform_populate(dev->of_node, NULL, NULL, dev); + if (ret) + goto err; + } return 0; err: -- cgit From 2d638be71155b2e036aca1966b6129e2d661e91f Mon Sep 17 00:00:00 2001 From: Tom Rix Date: Sun, 26 Feb 2023 12:38:46 -0500 Subject: Revert "tty: serial: fsl_lpuart: adjust SERIAL_FSL_LPUART_CONSOLE config dependency" This reverts commit 5779a072c248db7a40cfd0f5ea958097fd1d9a30. This results in a link error of ld: drivers/tty/serial/earlycon.o: in function `parse_options': drivers/tty/serial/earlycon.c:99: undefined reference to `uart_parse_earlycon' When the config is in this state CONFIG_SERIAL_CORE=m CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_SERIAL_EARLYCON=y CONFIG_SERIAL_FSL_LPUART=m CONFIG_SERIAL_FSL_LPUART_CONSOLE=y Fixes: 5779a072c248 ("tty: serial: fsl_lpuart: adjust SERIAL_FSL_LPUART_CONSOLE config dependency") Cc: stable Signed-off-by: Tom Rix Reviewed-by: Randy Dunlap Acked-by: Jiri Slaby Link: https://lore.kernel.org/r/20230226173846.236691-1-trix@redhat.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 625358f44419..0072892ca7fc 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -1313,7 +1313,7 @@ config SERIAL_FSL_LPUART config SERIAL_FSL_LPUART_CONSOLE bool "Console on Freescale lpuart serial port" - depends on SERIAL_FSL_LPUART + depends on SERIAL_FSL_LPUART=y select SERIAL_CORE_CONSOLE select SERIAL_EARLYCON help -- cgit From 2411fd94ceaa6e11326e95d6ebf876cbfed28d23 Mon Sep 17 00:00:00 2001 From: Sherry Sun Date: Thu, 23 Feb 2023 17:39:41 +0800 Subject: tty: serial: fsl_lpuart: skip waiting for transmission complete when UARTCTRL_SBK is asserted According to LPUART RM, Transmission Complete Flag becomes 0 if queuing a break character by writing 1 to CTRL[SBK], so here need to skip waiting for transmission complete when UARTCTRL_SBK is asserted, otherwise the kernel may stuck here. And actually set_termios() adds transmission completion waiting to avoid data loss or data breakage when changing the baud rate, but we don't need to worry about this when queuing break characters. Signed-off-by: Sherry Sun Cc: stable Link: https://lore.kernel.org/r/20230223093941.31790-1-sherry.sun@nxp.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/fsl_lpuart.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c index e945f41b93d4..f9e164abf920 100644 --- a/drivers/tty/serial/fsl_lpuart.c +++ b/drivers/tty/serial/fsl_lpuart.c @@ -2240,9 +2240,15 @@ lpuart32_set_termios(struct uart_port *port, struct ktermios *termios, /* update the per-port timeout */ uart_update_timeout(port, termios->c_cflag, baud); - /* wait transmit engin complete */ - lpuart32_write(&sport->port, 0, UARTMODIR); - lpuart32_wait_bit_set(&sport->port, UARTSTAT, UARTSTAT_TC); + /* + * LPUART Transmission Complete Flag may never be set while queuing a break + * character, so skip waiting for transmission complete when UARTCTRL_SBK is + * asserted. + */ + if (!(old_ctrl & UARTCTRL_SBK)) { + lpuart32_write(&sport->port, 0, UARTMODIR); + lpuart32_wait_bit_set(&sport->port, UARTSTAT, UARTSTAT_TC); + } /* disable transmit and receive */ lpuart32_write(&sport->port, old_ctrl & ~(UARTCTRL_TE | UARTCTRL_RE), -- cgit From f8086d1a65ac693e3fd863128352b4b11ee7324d Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sat, 25 Feb 2023 21:39:53 -0800 Subject: serial: 8250: ASPEED_VUART: select REGMAP instead of depending on it REGMAP is a hidden (not user visible) symbol. Users cannot set it directly thru "make *config", so drivers should select it instead of depending on it if they need it. Consistently using "select" or "depends on" can also help reduce Kconfig circular dependency issues. Therefore, change the use of "depends on REGMAP" to "select REGMAP". Fixes: 8d310c9107a2 ("drivers/tty/serial/8250: Make Aspeed VUART SIRQ polarity configurable") Cc: stable Signed-off-by: Randy Dunlap Cc: Greg Kroah-Hartman Cc: Oskar Senft Cc: linux-serial@vger.kernel.org Link: https://lore.kernel.org/r/20230226053953.4681-9-rdunlap@infradead.org Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig index 978dc196c29b..caeff76e58f2 100644 --- a/drivers/tty/serial/8250/Kconfig +++ b/drivers/tty/serial/8250/Kconfig @@ -257,8 +257,9 @@ config SERIAL_8250_ASPEED_VUART tristate "Aspeed Virtual UART" depends on SERIAL_8250 depends on OF - depends on REGMAP && MFD_SYSCON + depends on MFD_SYSCON depends on ARCH_ASPEED || COMPILE_TEST + select REGMAP help If you want to use the virtual UART (VUART) device on Aspeed BMC platforms, enable this option. This enables the 16550A- -- cgit From 32e293be736b853f168cd065d9cbc1b0c69f545d Mon Sep 17 00:00:00 2001 From: Biju Das Date: Mon, 27 Feb 2023 11:41:46 +0000 Subject: serial: 8250_em: Fix UART port type As per HW manual for EMEV2 "R19UH0040EJ0400 Rev.4.00", the UART IP found on EMMA mobile SoC is Register-compatible with the general-purpose 16750 UART chip. Fix UART port type as 16750 and enable 64-bytes fifo support. Fixes: 22886ee96895 ("serial8250-em: Emma Mobile UART driver V2") Cc: stable@vger.kernel.org Signed-off-by: Biju Das Link: https://lore.kernel.org/r/20230227114152.22265-2-biju.das.jz@bp.renesas.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_em.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/tty/serial/8250/8250_em.c b/drivers/tty/serial/8250/8250_em.c index f8e99995eee9..d94c3811a8f7 100644 --- a/drivers/tty/serial/8250/8250_em.c +++ b/drivers/tty/serial/8250/8250_em.c @@ -106,8 +106,8 @@ static int serial8250_em_probe(struct platform_device *pdev) memset(&up, 0, sizeof(up)); up.port.mapbase = regs->start; up.port.irq = irq; - up.port.type = PORT_UNKNOWN; - up.port.flags = UPF_BOOT_AUTOCONF | UPF_FIXED_PORT | UPF_IOREMAP; + up.port.type = PORT_16750; + up.port.flags = UPF_FIXED_PORT | UPF_IOREMAP | UPF_FIXED_TYPE; up.port.dev = &pdev->dev; up.port.private_data = priv; -- cgit From 6e01f9a594ee0f69fb52cc8d11971612b4817f0b Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 27 Feb 2023 09:50:46 +0100 Subject: serial: 8250_fsl: fix handle_irq locking The 8250 handle_irq callback is not just called from the interrupt handler but also from a timer callback when polling (e.g. for ports without an interrupt line). Consequently the callback must explicitly disable interrupts to avoid a potential deadlock with another interrupt in polled mode. Fix up the two paths in the freescale callback that failed to re-enable interrupts when polling. Fixes: 853a9ae29e97 ("serial: 8250: fix handle_irq locking") Cc: stable@vger.kernel.org # 5.13 Reported-by: Dan Carpenter Link: https://lore.kernel.org/r/Y/xYzqp4ogmOF5t0@kili Signed-off-by: Johan Hovold Acked-by: Jiri Slaby Link: https://lore.kernel.org/r/20230227085046.24282-1-johan@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_fsl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/tty/serial/8250/8250_fsl.c b/drivers/tty/serial/8250/8250_fsl.c index 8aad15622a2e..8adfaa183f77 100644 --- a/drivers/tty/serial/8250/8250_fsl.c +++ b/drivers/tty/serial/8250/8250_fsl.c @@ -34,7 +34,7 @@ int fsl8250_handle_irq(struct uart_port *port) iir = port->serial_in(port, UART_IIR); if (iir & UART_IIR_NO_INT) { - spin_unlock(&up->port.lock); + spin_unlock_irqrestore(&up->port.lock, flags); return 0; } @@ -42,7 +42,7 @@ int fsl8250_handle_irq(struct uart_port *port) if (unlikely(up->lsr_saved_flags & UART_LSR_BI)) { up->lsr_saved_flags &= ~UART_LSR_BI; port->serial_in(port, UART_RX); - spin_unlock(&up->port.lock); + spin_unlock_irqrestore(&up->port.lock, flags); return 1; } -- cgit From 5d943b5d69c032de7ce9cd625ac083a5c277b9c5 Mon Sep 17 00:00:00 2001 From: Kumaravel Thiagarajan Date: Sun, 5 Mar 2023 20:21:24 +0530 Subject: serial: 8250_pci1xxxx: Disable SERIAL_8250_PCI1XXXX config by default Commit 32bb477fa7bf ("serial: 8250_pci1xxxx: Add driver for quad-uart support") made the SERIAL_8250_PCI1XXXX driver enabled when SERIAL_8250 is enabled, disable it as this driver does not need to be enabled by default Fixes: 32bb477fa7bf ("serial: 8250_pci1xxxx: Add driver for quad-uart support") Reported-by: Linus Torvalds Link: https://lore.kernel.org/lkml/CAHk-=whhFCeeuo6vTEmNSx6S-KKkugxgzN_W5Z6v-9yH9gc3Zw@mail.gmail.com/ Signed-off-by: Kumaravel Thiagarajan Reviewed-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20230305145124.13444-1-kumaravel.thiagarajan@microchip.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig index caeff76e58f2..5313aa31930f 100644 --- a/drivers/tty/serial/8250/Kconfig +++ b/drivers/tty/serial/8250/Kconfig @@ -300,7 +300,6 @@ config SERIAL_8250_PCI1XXXX tristate "Microchip 8250 based serial port" depends on SERIAL_8250 && PCI select SERIAL_8250_PCILIB - default SERIAL_8250 help Select this option if you have a setup with Microchip PCIe Switch with serial port enabled and wish to enable 8250 -- cgit From 1be6f2b15f902c02e055ae0b419ca789200473c9 Mon Sep 17 00:00:00 2001 From: Alexander Sverdlin Date: Thu, 9 Mar 2023 14:43:02 +0100 Subject: tty: serial: fsl_lpuart: fix race on RX DMA shutdown From time to time DMA completion can come in the middle of DMA shutdown: : : lpuart32_shutdown() lpuart_dma_shutdown() del_timer_sync() lpuart_dma_rx_complete() lpuart_copy_rx_to_tty() mod_timer() lpuart_dma_rx_free() When the timer fires a bit later, sport->dma_rx_desc is NULL: Unable to handle kernel NULL pointer dereference at virtual address 0000000000000004 pc : lpuart_copy_rx_to_tty+0xcc/0x5bc lr : lpuart_timer_func+0x1c/0x2c Call trace: lpuart_copy_rx_to_tty lpuart_timer_func call_timer_fn __run_timers.part.0 run_timer_softirq __do_softirq __irq_exit_rcu irq_exit handle_domain_irq gic_handle_irq call_on_irq_stack do_interrupt_handler ... To fix this fold del_timer_sync() into lpuart_dma_rx_free() after dmaengine_terminate_sync() to make sure timer will not be re-started in lpuart_copy_rx_to_tty() <= lpuart_dma_rx_complete(). Fixes: 4a8588a1cf86 ("serial: fsl_lpuart: delete timer on shutdown") Cc: stable Signed-off-by: Alexander Sverdlin Link: https://lore.kernel.org/r/20230309134302.74940-2-alexander.sverdlin@siemens.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/fsl_lpuart.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c index f9e164abf920..56e6ba3250cd 100644 --- a/drivers/tty/serial/fsl_lpuart.c +++ b/drivers/tty/serial/fsl_lpuart.c @@ -1354,6 +1354,7 @@ static void lpuart_dma_rx_free(struct uart_port *port) struct dma_chan *chan = sport->dma_rx_chan; dmaengine_terminate_sync(chan); + del_timer_sync(&sport->lpuart_timer); dma_unmap_sg(chan->device->dev, &sport->rx_sgl, 1, DMA_FROM_DEVICE); kfree(sport->rx_ring.buf); sport->rx_ring.tail = 0; @@ -1813,7 +1814,6 @@ static int lpuart32_startup(struct uart_port *port) static void lpuart_dma_shutdown(struct lpuart_port *sport) { if (sport->lpuart_dma_rx_use) { - del_timer_sync(&sport->lpuart_timer); lpuart_dma_rx_free(&sport->port); sport->lpuart_dma_rx_use = false; } @@ -1973,10 +1973,8 @@ lpuart_set_termios(struct uart_port *port, struct ktermios *termios, * Since timer function acqures sport->port.lock, need to stop before * acquring same lock because otherwise del_timer_sync() can deadlock. */ - if (old && sport->lpuart_dma_rx_use) { - del_timer_sync(&sport->lpuart_timer); + if (old && sport->lpuart_dma_rx_use) lpuart_dma_rx_free(&sport->port); - } spin_lock_irqsave(&sport->port.lock, flags); @@ -2210,10 +2208,8 @@ lpuart32_set_termios(struct uart_port *port, struct ktermios *termios, * Since timer function acqures sport->port.lock, need to stop before * acquring same lock because otherwise del_timer_sync() can deadlock. */ - if (old && sport->lpuart_dma_rx_use) { - del_timer_sync(&sport->lpuart_timer); + if (old && sport->lpuart_dma_rx_use) lpuart_dma_rx_free(&sport->port); - } spin_lock_irqsave(&sport->port.lock, flags); @@ -3020,7 +3016,6 @@ static int lpuart_suspend(struct device *dev) * cannot resume as expected, hence gracefully release the * Rx DMA path before suspend and start Rx DMA path on resume. */ - del_timer_sync(&sport->lpuart_timer); lpuart_dma_rx_free(&sport->port); /* Disable Rx DMA to use UART port as wakeup source */ -- cgit From 1a5ecc73b2bfeffe036212d4a6bfacee053ab0a1 Mon Sep 17 00:00:00 2001 From: Saravana Kannan Date: Wed, 1 Mar 2023 18:35:09 -0800 Subject: serdev: Set fwnode for serdev devices This allow fw_devlink to do dependency tracking for serdev devices. Reported-by: Florian Fainelli Link: https://lore.kernel.org/lkml/03b70a8a-0591-f28b-a567-9d2f736f17e5@gmail.com/ Cc: Stefan Wahren Signed-off-by: Saravana Kannan Tested-by: Stefan Wahren Tested-by: Florian Fainelli Link: https://lore.kernel.org/r/20230302023509.319903-1-saravanak@google.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serdev/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/tty/serdev/core.c b/drivers/tty/serdev/core.c index aa80de3a8194..678014253b7b 100644 --- a/drivers/tty/serdev/core.c +++ b/drivers/tty/serdev/core.c @@ -534,7 +534,7 @@ static int of_serdev_register_devices(struct serdev_controller *ctrl) if (!serdev) continue; - serdev->dev.of_node = node; + device_set_node(&serdev->dev, of_fwnode_handle(node)); err = serdev_device_add(serdev); if (err) { -- cgit From 9aff74cc4e9eb841dde5fd009ed7ddca5db40e68 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 7 Mar 2023 17:44:02 +0100 Subject: serial: qcom-geni: fix console shutdown hang A recent commit added back the calls top stop tx and rx to shutdown() which had previously been removed by commit e83766334f96 ("tty: serial: qcom_geni_serial: No need to stop tx/rx on UART shutdown") in order to be able to use kgdb after stopping the getty. Not only did this again break kgdb, but it also broke serial consoles more generally by hanging TX when stopping the getty during reboot. The underlying problem has been there since the driver was first merged and fixing it is going to be a bit involved so simply stop calling the broken stop functions during shutdown for consoles for now. Fixes: d8aca2f96813 ("tty: serial: qcom-geni-serial: stop operations in progress at shutdown") Cc: stable Cc: Bartosz Golaszewski Signed-off-by: Johan Hovold Reviewed-by: Douglas Anderson Reviewed-by: Srinivas Kandagatla Tested-by: Srinivas Kandagatla Reviewed-by: Andrew Halaney Tested-by: Andrew Halaney # sa8540p-ride Link: https://lore.kernel.org/r/20230307164405.14218-2-johan+linaro@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/qcom_geni_serial.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/tty/serial/qcom_geni_serial.c b/drivers/tty/serial/qcom_geni_serial.c index d69592e5e2ec..11da05d8f848 100644 --- a/drivers/tty/serial/qcom_geni_serial.c +++ b/drivers/tty/serial/qcom_geni_serial.c @@ -1070,6 +1070,10 @@ static int setup_fifos(struct qcom_geni_serial_port *port) static void qcom_geni_serial_shutdown(struct uart_port *uport) { disable_irq(uport->irq); + + if (uart_console(uport)) + return; + qcom_geni_serial_stop_tx(uport); qcom_geni_serial_stop_rx(uport); } -- cgit From 95fcfc08537763bff21ec8c450d3d3cb1a60ad09 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 7 Mar 2023 17:44:03 +0100 Subject: serial: qcom-geni: fix DMA mapping leak on shutdown Fix what appears to be a copy-paste error that can lead to a leaked DMA mapping on close() and failure to restart TX after the port is reopened. Note that rx_dma_addr is generally NULL when qcom_geni_serial_stop_tx_dma() is called as part of shutdown() (but tx_dma_addr need not be). Fixes: 2aaa43c70778 ("tty: serial: qcom-geni-serial: add support for serial engine DMA") Cc: stable Cc: Bartosz Golaszewski Signed-off-by: Johan Hovold Reviewed-by: Douglas Anderson Reviewed-by: Srinivas Kandagatla Tested-by: Srinivas Kandagatla Reviewed-by: Andrew Halaney Tested-by: Andrew Halaney # sa8540p-ride Link: https://lore.kernel.org/r/20230307164405.14218-3-johan+linaro@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/qcom_geni_serial.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/tty/serial/qcom_geni_serial.c b/drivers/tty/serial/qcom_geni_serial.c index 11da05d8f848..2aa3872e6283 100644 --- a/drivers/tty/serial/qcom_geni_serial.c +++ b/drivers/tty/serial/qcom_geni_serial.c @@ -596,7 +596,7 @@ static void qcom_geni_serial_stop_tx_dma(struct uart_port *uport) if (!qcom_geni_serial_main_active(uport)) return; - if (port->rx_dma_addr) { + if (port->tx_dma_addr) { geni_se_tx_dma_unprep(&port->se, port->tx_dma_addr, port->tx_remaining); port->tx_dma_addr = 0; -- cgit From 97820780b723197d1b472f2bd39fd8593b5d4edc Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 7 Mar 2023 17:44:04 +0100 Subject: serial: qcom-geni: fix mapping of empty DMA buffer Make sure that there is data in the ring buffer before trying to set up a zero-length DMA transfer. This specifically fixes the following warning when unmapping the empty buffer on the sc8280xp-crd: WARNING: CPU: 0 PID: 138 at drivers/iommu/dma-iommu.c:1046 iommu_dma_unmap_page+0xbc/0xd8 ... Call trace: iommu_dma_unmap_page+0xbc/0xd8 dma_unmap_page_attrs+0x30/0x1c8 geni_se_tx_dma_unprep+0x28/0x38 qcom_geni_serial_isr+0x358/0x75c Fixes: 2aaa43c70778 ("tty: serial: qcom-geni-serial: add support for serial engine DMA") Cc: stable Cc: Bartosz Golaszewski Signed-off-by: Johan Hovold Reviewed-by: Douglas Anderson Reviewed-by: Srinivas Kandagatla Tested-by: Srinivas Kandagatla Reviewed-by: Andrew Halaney Tested-by: Andrew Halaney # sa8540p-ride Link: https://lore.kernel.org/r/20230307164405.14218-4-johan+linaro@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/qcom_geni_serial.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/tty/serial/qcom_geni_serial.c b/drivers/tty/serial/qcom_geni_serial.c index 2aa3872e6283..9871225b2f9b 100644 --- a/drivers/tty/serial/qcom_geni_serial.c +++ b/drivers/tty/serial/qcom_geni_serial.c @@ -631,6 +631,9 @@ static void qcom_geni_serial_start_tx_dma(struct uart_port *uport) if (port->tx_dma_addr) return; + if (uart_circ_empty(xmit)) + return; + xmit_size = uart_circ_chars_pending(xmit); if (xmit_size < WAKEUP_CHARS) uart_write_wakeup(uport); -- cgit From b6a7bac184472b5b79286a71a61c2f16ea4e86ad Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 7 Mar 2023 17:44:05 +0100 Subject: serial: qcom-geni: drop bogus uart_write_wakeup() Drop the bogus uart_write_wakeup() from when setting up a new DMA transfer, which does not free up any more space in the ring buffer. Any pending writers will be woken up when the transfer completes. Cc: stable Signed-off-by: Johan Hovold Reviewed-by: Douglas Anderson Reviewed-by: Srinivas Kandagatla Tested-by: Srinivas Kandagatla Reviewed-by: Andrew Halaney Tested-by: Andrew Halaney # sa8540p-ride Link: https://lore.kernel.org/r/20230307164405.14218-5-johan+linaro@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/qcom_geni_serial.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/tty/serial/qcom_geni_serial.c b/drivers/tty/serial/qcom_geni_serial.c index 9871225b2f9b..28fbc927a546 100644 --- a/drivers/tty/serial/qcom_geni_serial.c +++ b/drivers/tty/serial/qcom_geni_serial.c @@ -634,10 +634,6 @@ static void qcom_geni_serial_start_tx_dma(struct uart_port *uport) if (uart_circ_empty(xmit)) return; - xmit_size = uart_circ_chars_pending(xmit); - if (xmit_size < WAKEUP_CHARS) - uart_write_wakeup(uport); - xmit_size = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE); qcom_geni_serial_setup_tx(uport, xmit_size); -- cgit From 18365ebf23f3e713e5dd8e295c9a639295250f3c Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Mon, 6 Mar 2023 10:49:21 +0100 Subject: tty: vt: protect KD_FONT_OP_GET_TALL from unbound access In ioctl(KD_FONT_OP_GET_TALL), userland tells through op->height which vpitch should be used to copy over the font. In con_font_get, we were not checking that it is within the maximum height value, and thus userland could make the vc->vc_sw->con_font_get(vc, &font, vpitch); call possibly overflow the allocated max_font_size bytes, and the copy_to_user(op->data, font.data, c) call possibly read out of that allocated buffer. By checking vpitch against max_font_height, the max_font_size buffer will always be large enough for the vc->vc_sw->con_font_get(vc, &font, vpitch) call (since we already prevent loading a font larger than that), and c = (font.width+7)/8 * vpitch * font.charcount will always remain below max_font_size. Fixes: 24d69384bcd3 ("VT: Add KD_FONT_OP_SET/GET_TALL operations") Reported-by: syzbot+3af17071816b61e807ed@syzkaller.appspotmail.com Signed-off-by: Samuel Thibault Reviewed-by: Jiri Slaby Link: https://lore.kernel.org/r/20230306094921.tik5ewne4ft6mfpo@begin Signed-off-by: Greg Kroah-Hartman --- drivers/tty/vt/vt.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 57a5c23b51d4..3c2ea9c098f7 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -4545,6 +4545,9 @@ static int con_font_get(struct vc_data *vc, struct console_font_op *op) int c; unsigned int vpitch = op->op == KD_FONT_OP_GET_TALL ? op->height : 32; + if (vpitch > max_font_height) + return -EINVAL; + if (op->data) { font.data = kvmalloc(max_font_size, GFP_KERNEL); if (!font.data) -- cgit From 38ed310c22e7a0fc978b1f8292136a4a4a8b3051 Mon Sep 17 00:00:00 2001 From: Roman Gushchin Date: Wed, 8 Mar 2023 14:26:02 -0800 Subject: firmware: xilinx: don't make a sleepable memory allocation from an atomic context The following issue was discovered using lockdep: [ 6.691371] BUG: sleeping function called from invalid context at include/linux/sched/mm.h:209 [ 6.694602] in_atomic(): 1, irqs_disabled(): 128, non_block: 0, pid: 1, name: swapper/0 [ 6.702431] 2 locks held by swapper/0/1: [ 6.706300] #0: ffffff8800f6f188 (&dev->mutex){....}-{3:3}, at: __device_driver_lock+0x4c/0x90 [ 6.714900] #1: ffffffc009a2abb8 (enable_lock){....}-{2:2}, at: clk_enable_lock+0x4c/0x140 [ 6.723156] irq event stamp: 304030 [ 6.726596] hardirqs last enabled at (304029): [] _raw_spin_unlock_irqrestore+0xc0/0xd0 [ 6.736142] hardirqs last disabled at (304030): [] clk_enable_lock+0xfc/0x140 [ 6.744742] softirqs last enabled at (303958): [] _stext+0x4f0/0x894 [ 6.752655] softirqs last disabled at (303951): [] irq_exit+0x238/0x280 [ 6.760744] CPU: 1 PID: 1 Comm: swapper/0 Tainted: G U 5.15.36 #2 [ 6.768048] Hardware name: xlnx,zynqmp (DT) [ 6.772179] Call trace: [ 6.774584] dump_backtrace+0x0/0x300 [ 6.778197] show_stack+0x18/0x30 [ 6.781465] dump_stack_lvl+0xb8/0xec [ 6.785077] dump_stack+0x1c/0x38 [ 6.788345] ___might_sleep+0x1a8/0x2a0 [ 6.792129] __might_sleep+0x6c/0xd0 [ 6.795655] kmem_cache_alloc_trace+0x270/0x3d0 [ 6.800127] do_feature_check_call+0x100/0x220 [ 6.804513] zynqmp_pm_invoke_fn+0x8c/0xb0 [ 6.808555] zynqmp_pm_clock_getstate+0x90/0xe0 [ 6.813027] zynqmp_pll_is_enabled+0x8c/0x120 [ 6.817327] zynqmp_pll_enable+0x38/0xc0 [ 6.821197] clk_core_enable+0x144/0x400 [ 6.825067] clk_core_enable+0xd4/0x400 [ 6.828851] clk_core_enable+0xd4/0x400 [ 6.832635] clk_core_enable+0xd4/0x400 [ 6.836419] clk_core_enable+0xd4/0x400 [ 6.840203] clk_core_enable+0xd4/0x400 [ 6.843987] clk_core_enable+0xd4/0x400 [ 6.847771] clk_core_enable+0xd4/0x400 [ 6.851555] clk_core_enable_lock+0x24/0x50 [ 6.855683] clk_enable+0x24/0x40 [ 6.858952] fclk_probe+0x84/0xf0 [ 6.862220] platform_probe+0x8c/0x110 [ 6.865918] really_probe+0x110/0x5f0 [ 6.869530] __driver_probe_device+0xcc/0x210 [ 6.873830] driver_probe_device+0x64/0x140 [ 6.877958] __driver_attach+0x114/0x1f0 [ 6.881828] bus_for_each_dev+0xe8/0x160 [ 6.885698] driver_attach+0x34/0x50 [ 6.889224] bus_add_driver+0x228/0x300 [ 6.893008] driver_register+0xc0/0x1e0 [ 6.896792] __platform_driver_register+0x44/0x60 [ 6.901436] fclk_driver_init+0x1c/0x28 [ 6.905220] do_one_initcall+0x104/0x590 [ 6.909091] kernel_init_freeable+0x254/0x2bc [ 6.913390] kernel_init+0x24/0x130 [ 6.916831] ret_from_fork+0x10/0x20 Fix it by passing the GFP_ATOMIC gfp flag for the corresponding memory allocation. Fixes: acfdd18591ea ("firmware: xilinx: Use hash-table for api feature check") Cc: stable Signed-off-by: Roman Gushchin Cc: Amit Sunil Dhamne Cc: Michal Simek Cc: linux-arm-kernel@lists.infradead.org Cc: linux-kernel@vger.kernel.org Link: https://lore.kernel.org/r/20230308222602.123866-1-roman.gushchin@linux.dev Signed-off-by: Greg Kroah-Hartman --- drivers/firmware/xilinx/zynqmp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/firmware/xilinx/zynqmp.c b/drivers/firmware/xilinx/zynqmp.c index acd83d29c866..ce86a1850305 100644 --- a/drivers/firmware/xilinx/zynqmp.c +++ b/drivers/firmware/xilinx/zynqmp.c @@ -206,7 +206,7 @@ static int do_feature_check_call(const u32 api_id) } /* Add new entry if not present */ - feature_data = kmalloc(sizeof(*feature_data), GFP_KERNEL); + feature_data = kmalloc(sizeof(*feature_data), GFP_ATOMIC); if (!feature_data) return -ENOMEM; -- cgit From 06be62083c5308c76a891ca975d66d832e2afc07 Mon Sep 17 00:00:00 2001 From: Michael Walle Date: Fri, 10 Mar 2023 09:48:45 +0000 Subject: nvmem: core: return -ENOENT if nvmem cell is not found Prior to commit 5d8e6e6c10a3 ("nvmem: core: add an index parameter to the cell") of_nvmem_cell_get() would return -ENOENT if the cell wasn't found. Particularly, if of_property_match_string() returned -EINVAL, that return code was passed as the index to of_parse_phandle(), which then detected it as invalid and returned NULL. That led to an return code of -ENOENT. With the new code, the negative index will lead to an -EINVAL of of_parse_phandle_with_optional_args() which pass straight to the caller and break those who expect an -ENOENT. Fix it by always returning -ENOENT. Fixes: 5d8e6e6c10a3 ("nvmem: core: add an index parameter to the cell") Reported-by: Alexander Stein Link: https://lore.kernel.org/r/2143916.GUh0CODmnK@steina-w/ Signed-off-by: Michael Walle Tested-by: Alexander Stein Signed-off-by: Srinivas Kandagatla Link: https://lore.kernel.org/r/20230310094845.139400-1-srinivas.kandagatla@linaro.org Signed-off-by: Greg Kroah-Hartman --- drivers/nvmem/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c index 174ef3574e07..22024b830788 100644 --- a/drivers/nvmem/core.c +++ b/drivers/nvmem/core.c @@ -1231,7 +1231,7 @@ struct nvmem_cell *of_nvmem_cell_get(struct device_node *np, const char *id) "#nvmem-cell-cells", index, &cell_spec); if (ret) - return ERR_PTR(ret); + return ERR_PTR(-ENOENT); if (cell_spec.args_count > 1) return ERR_PTR(-EINVAL); -- cgit From e57d06527738798039b8e91af762fbd33881b34d Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Wed, 8 Mar 2023 09:45:09 -0500 Subject: NFS & NFSD: Update GSS dependencies Geert reports that: > On v6.2, "make ARCH=m68k defconfig" gives you > CONFIG_RPCSEC_GSS_KRB5=m > On v6.3, it became builtin, due to dropping the dependencies on > the individual crypto modules. > > $ grep -E "CRYPTO_(MD5|DES|CBC|CTS|ECB|HMAC|SHA1|AES)" .config > CONFIG_CRYPTO_AES=y > CONFIG_CRYPTO_AES_TI=m > CONFIG_CRYPTO_DES=m > CONFIG_CRYPTO_CBC=m > CONFIG_CRYPTO_CTS=m > CONFIG_CRYPTO_ECB=m > CONFIG_CRYPTO_HMAC=m > CONFIG_CRYPTO_MD5=m > CONFIG_CRYPTO_SHA1=m This behavior is triggered by the "default y" in the definition of RPCSEC_GSS. The "default y" was added in 2010 by commit df486a25900f ("NFS: Fix the selection of security flavours in Kconfig"). However, svc_gss_principal was removed in 2012 by commit 03a4e1f6ddf2 ("nfsd4: move principal name into svc_cred"), so the 2010 fix is no longer necessary. We can safely change the NFS_V4 and NFSD_V4 dependencies back to RPCSEC_GSS_KRB5 to get the nicer v6.2 behavior back. Selecting KRB5 symbolically represents the true requirement here: that all spec-compliant NFSv4 implementations must have Kerberos available to use. Reported-by: Geert Uytterhoeven Fixes: dfe9a123451a ("SUNRPC: Enable rpcsec_gss_krb5.ko to be built without CRYPTO_DES") Signed-off-by: Chuck Lever --- fs/nfs/Kconfig | 2 +- fs/nfsd/Kconfig | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/nfs/Kconfig b/fs/nfs/Kconfig index 14a72224b657..450d6c3bc05e 100644 --- a/fs/nfs/Kconfig +++ b/fs/nfs/Kconfig @@ -75,7 +75,7 @@ config NFS_V3_ACL config NFS_V4 tristate "NFS client support for NFS version 4" depends on NFS_FS - select SUNRPC_GSS + select RPCSEC_GSS_KRB5 select KEYS help This option enables support for version 4 of the NFS protocol diff --git a/fs/nfsd/Kconfig b/fs/nfsd/Kconfig index 7c441f2bd444..43b88eaf0673 100644 --- a/fs/nfsd/Kconfig +++ b/fs/nfsd/Kconfig @@ -73,7 +73,7 @@ config NFSD_V4 bool "NFS server support for NFS version 4" depends on NFSD && PROC_FS select FS_POSIX_ACL - select SUNRPC_GSS + select RPCSEC_GSS_KRB5 select CRYPTO select CRYPTO_MD5 select CRYPTO_SHA256 -- cgit From d6f7ff9dd387861fa30cbc6375d15b586da17d33 Mon Sep 17 00:00:00 2001 From: Jesus Sanchez-Palencia Date: Wed, 8 Mar 2023 16:48:36 -0800 Subject: libbpf: Revert poisoning of strlcpy This reverts commit 6d0c4b11e743("libbpf: Poison strlcpy()"). It added the pragma poison directive to libbpf_internal.h to protect against accidental usage of strlcpy but ended up breaking the build for toolchains based on libcs which provide the strlcpy() declaration from string.h (e.g. uClibc-ng). The include order which causes the issue is: string.h, from Iibbpf_common.h:12, from libbpf.h:20, from libbpf_internal.h:26, from strset.c:9: Fixes: 6d0c4b11e743 ("libbpf: Poison strlcpy()") Signed-off-by: Jesus Sanchez-Palencia Signed-off-by: Andrii Nakryiko Signed-off-by: Daniel Borkmann Link: https://lore.kernel.org/bpf/20230309004836.2808610-1-jesussanp@google.com Signed-off-by: Alexei Starovoitov --- tools/lib/bpf/libbpf_internal.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/lib/bpf/libbpf_internal.h b/tools/lib/bpf/libbpf_internal.h index fbaf68335394..e4d05662a96c 100644 --- a/tools/lib/bpf/libbpf_internal.h +++ b/tools/lib/bpf/libbpf_internal.h @@ -20,8 +20,8 @@ /* make sure libbpf doesn't use kernel-only integer typedefs */ #pragma GCC poison u8 u16 u32 u64 s8 s16 s32 s64 -/* prevent accidental re-addition of reallocarray()/strlcpy() */ -#pragma GCC poison reallocarray strlcpy +/* prevent accidental re-addition of reallocarray() */ +#pragma GCC poison reallocarray #include "libbpf.h" #include "btf.h" -- cgit From 32513d40d908b267508d37994753d9bd1600914b Mon Sep 17 00:00:00 2001 From: Alexei Starovoitov Date: Fri, 10 Mar 2023 12:41:18 -0800 Subject: selftests/bpf: Fix progs/find_vma_fail1.c build error. The commit 11e456cae91e ("selftests/bpf: Fix compilation errors: Assign a value to a constant") fixed the issue cleanly in bpf-next. This is an alternative fix in bpf tree to avoid merge conflict between bpf and bpf-next. Signed-off-by: Alexei Starovoitov --- tools/testing/selftests/bpf/progs/find_vma_fail1.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/testing/selftests/bpf/progs/find_vma_fail1.c b/tools/testing/selftests/bpf/progs/find_vma_fail1.c index b3b326b8e2d1..6dab9cffda13 100644 --- a/tools/testing/selftests/bpf/progs/find_vma_fail1.c +++ b/tools/testing/selftests/bpf/progs/find_vma_fail1.c @@ -2,6 +2,7 @@ /* Copyright (c) 2021 Facebook */ #include "vmlinux.h" #include +#define vm_flags vm_start char _license[] SEC("license") = "GPL"; -- cgit From e8c8361cfdbf450f760e8a2bdbd4222d1947366b Mon Sep 17 00:00:00 2001 From: Alexei Starovoitov Date: Fri, 10 Mar 2023 12:47:51 -0800 Subject: selftests/bpf: Fix progs/test_deny_namespace.c issues. The following build error can be seen: progs/test_deny_namespace.c:22:19: error: call to undeclared function 'BIT_LL'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration] __u64 cap_mask = BIT_LL(CAP_SYS_ADMIN); The struct kernel_cap_struct no longer exists in the kernel as well. Adjust bpf prog to fix both issues. Fixes: f122a08b197d ("capability: just use a 'u64' instead of a 'u32[2]' array") Signed-off-by: Alexei Starovoitov --- tools/testing/selftests/bpf/progs/test_deny_namespace.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/tools/testing/selftests/bpf/progs/test_deny_namespace.c b/tools/testing/selftests/bpf/progs/test_deny_namespace.c index 591104e79812..e96b901a733c 100644 --- a/tools/testing/selftests/bpf/progs/test_deny_namespace.c +++ b/tools/testing/selftests/bpf/progs/test_deny_namespace.c @@ -5,12 +5,10 @@ #include #include -struct kernel_cap_struct { - __u64 val; -} __attribute__((preserve_access_index)); +typedef struct { unsigned long long val; } kernel_cap_t; struct cred { - struct kernel_cap_struct cap_effective; + kernel_cap_t cap_effective; } __attribute__((preserve_access_index)); char _license[] SEC("license") = "GPL"; @@ -18,8 +16,8 @@ char _license[] SEC("license") = "GPL"; SEC("lsm.s/userns_create") int BPF_PROG(test_userns_create, const struct cred *cred, int ret) { - struct kernel_cap_struct caps = cred->cap_effective; - __u64 cap_mask = BIT_LL(CAP_SYS_ADMIN); + kernel_cap_t caps = cred->cap_effective; + __u64 cap_mask = 1ULL << CAP_SYS_ADMIN; if (ret) return 0; -- cgit From cb090e64cf25602b9adaf32d5dfc9c8bec493cd1 Mon Sep 17 00:00:00 2001 From: Zheng Wang Date: Fri, 10 Mar 2023 16:40:07 +0800 Subject: hwmon: (xgene) Fix use after free bug in xgene_hwmon_remove due to race condition In xgene_hwmon_probe, &ctx->workq is bound with xgene_hwmon_evt_work. Then it will be started. If we remove the driver which will call xgene_hwmon_remove to clean up, there may be unfinished work. The possible sequence is as follows: Fix it by finishing the work before cleanup in xgene_hwmon_remove. CPU0 CPU1 |xgene_hwmon_evt_work xgene_hwmon_remove | kfifo_free(&ctx->async_msg_fifo);| | |kfifo_out_spinlocked |//use &ctx->async_msg_fifo Fixes: 2ca492e22cb7 ("hwmon: (xgene) Fix crash when alarm occurs before driver probe") Signed-off-by: Zheng Wang Link: https://lore.kernel.org/r/20230310084007.1403388-1-zyytlz.wz@163.com Signed-off-by: Guenter Roeck --- drivers/hwmon/xgene-hwmon.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/hwmon/xgene-hwmon.c b/drivers/hwmon/xgene-hwmon.c index 5cde837bfd09..d1abea49f01b 100644 --- a/drivers/hwmon/xgene-hwmon.c +++ b/drivers/hwmon/xgene-hwmon.c @@ -761,6 +761,7 @@ static int xgene_hwmon_remove(struct platform_device *pdev) { struct xgene_hwmon_dev *ctx = platform_get_drvdata(pdev); + cancel_work_sync(&ctx->workq); hwmon_device_unregister(ctx->hwmon_dev); kfifo_free(&ctx->async_msg_fifo); if (acpi_disabled) -- cgit From c93f5e2ab53243b17febabb9422a697017d3d49a Mon Sep 17 00:00:00 2001 From: Marcus Folkesson Date: Fri, 10 Mar 2023 08:50:35 +0100 Subject: hwmon: (ina3221) return prober error code ret is set to 0 which do not indicate an error. Return -EINVAL instead. Fixes: a9e9dd9c6de5 ("hwmon: (ina3221) Read channel input source info from DT") Signed-off-by: Marcus Folkesson Link: https://lore.kernel.org/r/20230310075035.246083-1-marcus.folkesson@gmail.com Signed-off-by: Guenter Roeck --- drivers/hwmon/ina3221.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hwmon/ina3221.c b/drivers/hwmon/ina3221.c index e06186986444..f3a4c5633b1e 100644 --- a/drivers/hwmon/ina3221.c +++ b/drivers/hwmon/ina3221.c @@ -772,7 +772,7 @@ static int ina3221_probe_child_from_dt(struct device *dev, return ret; } else if (val > INA3221_CHANNEL3) { dev_err(dev, "invalid reg %d of %pOFn\n", val, child); - return ret; + return -EINVAL; } input = &ina->inputs[val]; -- cgit From 4783b9cb374af02d49740e00e2da19fd4ed6dec4 Mon Sep 17 00:00:00 2001 From: Yazen Ghannam Date: Wed, 1 Mar 2023 22:14:20 +0000 Subject: x86/mce: Make sure logged MCEs are processed after sysfs update A recent change introduced a flag to queue up errors found during boot-time polling. These errors will be processed during late init once the MCE subsystem is fully set up. A number of sysfs updates call mce_restart() which goes through a subset of the CPU init flow. This includes polling MCA banks and logging any errors found. Since the same function is used as boot-time polling, errors will be queued. However, the system is now past late init, so the errors will remain queued until another error is found and the workqueue is triggered. Call mce_schedule_work() at the end of mce_restart() so that queued errors are processed. Fixes: 3bff147b187d ("x86/mce: Defer processing of early errors") Signed-off-by: Yazen Ghannam Signed-off-by: Borislav Petkov (AMD) Reviewed-by: Tony Luck Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20230301221420.2203184-1-yazen.ghannam@amd.com --- arch/x86/kernel/cpu/mce/core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/kernel/cpu/mce/core.c b/arch/x86/kernel/cpu/mce/core.c index 7832a69d170e..2eec60f50057 100644 --- a/arch/x86/kernel/cpu/mce/core.c +++ b/arch/x86/kernel/cpu/mce/core.c @@ -2355,6 +2355,7 @@ static void mce_restart(void) { mce_timer_delete_all(); on_each_cpu(mce_cpu_restart, NULL, 1); + mce_schedule_work(); } /* Toggle features for corrected errors */ -- cgit From 8d655e65237643c48ada2c131b83679bf1105373 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sun, 12 Mar 2023 09:03:12 -0700 Subject: hwmon: (ucd90320) Add minimum delay between bus accesses When probing the ucd90320 access to some of the registers randomly fails. Sometimes it NACKs a transfer, sometimes it returns just random data and the PEC check fails. Experimentation shows that this seems to be triggered by a register access directly back to back with a previous register write. Experimentation also shows that inserting a small delay after register writes makes the issue go away. Use a similar solution to what the max15301 driver does to solve the same problem. Create a custom set of bus read and write functions that make sure that the delay is added. Fixes: a470f11c5ba2 ("hwmon: (pmbus/ucd9000) Add support for UCD90320 Power Sequencer") Signed-off-by: Lars-Peter Clausen Link: https://lore.kernel.org/r/20230312160312.2227405-1-lars@metafoo.de Signed-off-by: Guenter Roeck --- drivers/hwmon/pmbus/ucd9000.c | 75 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/drivers/hwmon/pmbus/ucd9000.c b/drivers/hwmon/pmbus/ucd9000.c index 75fc770c9e40..3daaf2237832 100644 --- a/drivers/hwmon/pmbus/ucd9000.c +++ b/drivers/hwmon/pmbus/ucd9000.c @@ -7,6 +7,7 @@ */ #include +#include #include #include #include @@ -16,6 +17,7 @@ #include #include #include +#include #include "pmbus.h" enum chips { ucd9000, ucd90120, ucd90124, ucd90160, ucd90320, ucd9090, @@ -65,6 +67,7 @@ struct ucd9000_data { struct gpio_chip gpio; #endif struct dentry *debugfs; + ktime_t write_time; }; #define to_ucd9000_data(_info) container_of(_info, struct ucd9000_data, info) @@ -73,6 +76,73 @@ struct ucd9000_debugfs_entry { u8 index; }; +/* + * It has been observed that the UCD90320 randomly fails register access when + * doing another access right on the back of a register write. To mitigate this + * make sure that there is a minimum delay between a write access and the + * following access. The 250us is based on experimental data. At a delay of + * 200us the issue seems to go away. Add a bit of extra margin to allow for + * system to system differences. + */ +#define UCD90320_WAIT_DELAY_US 250 + +static inline void ucd90320_wait(const struct ucd9000_data *data) +{ + s64 delta = ktime_us_delta(ktime_get(), data->write_time); + + if (delta < UCD90320_WAIT_DELAY_US) + udelay(UCD90320_WAIT_DELAY_US - delta); +} + +static int ucd90320_read_word_data(struct i2c_client *client, int page, + int phase, int reg) +{ + const struct pmbus_driver_info *info = pmbus_get_driver_info(client); + struct ucd9000_data *data = to_ucd9000_data(info); + + if (reg >= PMBUS_VIRT_BASE) + return -ENXIO; + + ucd90320_wait(data); + return pmbus_read_word_data(client, page, phase, reg); +} + +static int ucd90320_read_byte_data(struct i2c_client *client, int page, int reg) +{ + const struct pmbus_driver_info *info = pmbus_get_driver_info(client); + struct ucd9000_data *data = to_ucd9000_data(info); + + ucd90320_wait(data); + return pmbus_read_byte_data(client, page, reg); +} + +static int ucd90320_write_word_data(struct i2c_client *client, int page, + int reg, u16 word) +{ + const struct pmbus_driver_info *info = pmbus_get_driver_info(client); + struct ucd9000_data *data = to_ucd9000_data(info); + int ret; + + ucd90320_wait(data); + ret = pmbus_write_word_data(client, page, reg, word); + data->write_time = ktime_get(); + + return ret; +} + +static int ucd90320_write_byte(struct i2c_client *client, int page, u8 value) +{ + const struct pmbus_driver_info *info = pmbus_get_driver_info(client); + struct ucd9000_data *data = to_ucd9000_data(info); + int ret; + + ucd90320_wait(data); + ret = pmbus_write_byte(client, page, value); + data->write_time = ktime_get(); + + return ret; +} + static int ucd9000_get_fan_config(struct i2c_client *client, int fan) { int fan_config = 0; @@ -598,6 +668,11 @@ static int ucd9000_probe(struct i2c_client *client) info->read_byte_data = ucd9000_read_byte_data; info->func[0] |= PMBUS_HAVE_FAN12 | PMBUS_HAVE_STATUS_FAN12 | PMBUS_HAVE_FAN34 | PMBUS_HAVE_STATUS_FAN34; + } else if (mid->driver_data == ucd90320) { + info->read_byte_data = ucd90320_read_byte_data; + info->read_word_data = ucd90320_read_word_data; + info->write_byte = ucd90320_write_byte; + info->write_word_data = ucd90320_write_word_data; } ucd9000_probe_gpio(client, mid, data); -- cgit From 00d85e81796b17a29a0e096c5a4735daa47adef8 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sun, 12 Mar 2023 20:37:23 +0100 Subject: hwmon: tmp512: drop of_match_ptr for ID table MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The driver will match mostly by DT table (even thought there is regular ID table) so there is little benefit in of_match_ptr (this also allows ACPI matching via PRP0001, even though it might not be relevant here). This also fixes !CONFIG_OF error: drivers/hwmon/tmp513.c:610:34: error: ‘tmp51x_of_match’ defined but not used [-Werror=unused-const-variable=] Fixes: 59dfa75e5d82 ("hwmon: Add driver for Texas Instruments TMP512/513 sensor chips.") Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20230312193723.478032-2-krzysztof.kozlowski@linaro.org Signed-off-by: Guenter Roeck --- drivers/hwmon/tmp513.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hwmon/tmp513.c b/drivers/hwmon/tmp513.c index 47bbe47e062f..7d5f7441aceb 100644 --- a/drivers/hwmon/tmp513.c +++ b/drivers/hwmon/tmp513.c @@ -758,7 +758,7 @@ static int tmp51x_probe(struct i2c_client *client) static struct i2c_driver tmp51x_driver = { .driver = { .name = "tmp51x", - .of_match_table = of_match_ptr(tmp51x_of_match), + .of_match_table = tmp51x_of_match, }, .probe_new = tmp51x_probe, .id_table = tmp51x_id, -- cgit From d6fd48eff7506bb866a54e40369df8899f2078a9 Mon Sep 17 00:00:00 2001 From: "Borislav Petkov (AMD)" Date: Wed, 15 Feb 2023 11:01:42 +0100 Subject: virt/coco/sev-guest: Check SEV_SNP attribute at probe time No need to check it on every ioctl. And yes, this is a common SEV driver but it does only SNP-specific operations currently. This can be revisited later, when more use cases appear. No functional changes. Signed-off-by: Borislav Petkov (AMD) Reviewed-by: Tom Lendacky Link: https://lore.kernel.org/r/20230307192449.24732-3-bp@alien8.de --- arch/x86/kernel/sev.c | 3 --- drivers/virt/coco/sev-guest/sev-guest.c | 3 +++ 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/x86/kernel/sev.c b/arch/x86/kernel/sev.c index 679026a640ef..c644c34372e8 100644 --- a/arch/x86/kernel/sev.c +++ b/arch/x86/kernel/sev.c @@ -2183,9 +2183,6 @@ int snp_issue_guest_request(u64 exit_code, struct snp_req_data *input, unsigned struct ghcb *ghcb; int ret; - if (!cc_platform_has(CC_ATTR_GUEST_SEV_SNP)) - return -ENODEV; - if (!fw_err) return -EINVAL; diff --git a/drivers/virt/coco/sev-guest/sev-guest.c b/drivers/virt/coco/sev-guest/sev-guest.c index 7b4e9009f335..ed5d6ae1a144 100644 --- a/drivers/virt/coco/sev-guest/sev-guest.c +++ b/drivers/virt/coco/sev-guest/sev-guest.c @@ -703,6 +703,9 @@ static int __init sev_guest_probe(struct platform_device *pdev) void __iomem *mapping; int ret; + if (!cc_platform_has(CC_ATTR_GUEST_SEV_SNP)) + return -ENODEV; + if (!dev->platform_data) return -ENODEV; -- cgit From 970ab823743fb54b42002ec76c51481f67436444 Mon Sep 17 00:00:00 2001 From: "Borislav Petkov (AMD)" Date: Wed, 15 Feb 2023 11:39:41 +0100 Subject: virt/coco/sev-guest: Simplify extended guest request handling Return a specific error code - -ENOSPC - to signal the too small cert data buffer instead of checking exit code and exitinfo2. While at it, hoist the *fw_err assignment in snp_issue_guest_request() so that a proper error value is returned to the callers. [ Tom: check override_err instead of err. ] Signed-off-by: Borislav Petkov (AMD) Signed-off-by: Tom Lendacky Signed-off-by: Borislav Petkov (AMD) Link: https://lore.kernel.org/r/20230307192449.24732-4-bp@alien8.de --- arch/x86/kernel/sev.c | 11 ++++---- drivers/virt/coco/sev-guest/sev-guest.c | 48 ++++++++++++++++++--------------- 2 files changed, 32 insertions(+), 27 deletions(-) diff --git a/arch/x86/kernel/sev.c b/arch/x86/kernel/sev.c index c644c34372e8..6a3e1425ba17 100644 --- a/arch/x86/kernel/sev.c +++ b/arch/x86/kernel/sev.c @@ -2209,15 +2209,16 @@ int snp_issue_guest_request(u64 exit_code, struct snp_req_data *input, unsigned if (ret) goto e_put; + *fw_err = ghcb->save.sw_exit_info_2; if (ghcb->save.sw_exit_info_2) { /* Number of expected pages are returned in RBX */ if (exit_code == SVM_VMGEXIT_EXT_GUEST_REQUEST && - ghcb->save.sw_exit_info_2 == SNP_GUEST_REQ_INVALID_LEN) + ghcb->save.sw_exit_info_2 == SNP_GUEST_REQ_INVALID_LEN) { input->data_npages = ghcb_get_rbx(ghcb); - - *fw_err = ghcb->save.sw_exit_info_2; - - ret = -EIO; + ret = -ENOSPC; + } else { + ret = -EIO; + } } e_put: diff --git a/drivers/virt/coco/sev-guest/sev-guest.c b/drivers/virt/coco/sev-guest/sev-guest.c index ed5d6ae1a144..e61db0b15b7a 100644 --- a/drivers/virt/coco/sev-guest/sev-guest.c +++ b/drivers/virt/coco/sev-guest/sev-guest.c @@ -322,7 +322,8 @@ static int handle_guest_request(struct snp_guest_dev *snp_dev, u64 exit_code, in u8 type, void *req_buf, size_t req_sz, void *resp_buf, u32 resp_sz, __u64 *fw_err) { - unsigned long err; + unsigned long err, override_err = 0; + unsigned int override_npages = 0; u64 seqno; int rc; @@ -338,6 +339,7 @@ static int handle_guest_request(struct snp_guest_dev *snp_dev, u64 exit_code, in if (rc) return rc; +retry_request: /* * Call firmware to process the request. In this function the encrypted * message enters shared memory with the host. So after this call the @@ -346,17 +348,24 @@ static int handle_guest_request(struct snp_guest_dev *snp_dev, u64 exit_code, in */ rc = snp_issue_guest_request(exit_code, &snp_dev->input, &err); - /* - * If the extended guest request fails due to having too small of a - * certificate data buffer, retry the same guest request without the - * extended data request in order to increment the sequence number - * and thus avoid IV reuse. - */ - if (exit_code == SVM_VMGEXIT_EXT_GUEST_REQUEST && - err == SNP_GUEST_REQ_INVALID_LEN) { - const unsigned int certs_npages = snp_dev->input.data_npages; + switch (rc) { + case -ENOSPC: + /* + * If the extended guest request fails due to having too + * small of a certificate data buffer, retry the same + * guest request without the extended data request in + * order to increment the sequence number and thus avoid + * IV reuse. + */ + override_npages = snp_dev->input.data_npages; + exit_code = SVM_VMGEXIT_GUEST_REQUEST; - exit_code = SVM_VMGEXIT_GUEST_REQUEST; + /* + * Override the error to inform callers the given extended + * request buffer size was too small and give the caller the + * required buffer size. + */ + override_err = SNP_GUEST_REQ_INVALID_LEN; /* * If this call to the firmware succeeds, the sequence number can @@ -366,15 +375,7 @@ static int handle_guest_request(struct snp_guest_dev *snp_dev, u64 exit_code, in * of the VMPCK and the error code being propagated back to the * user as an ioctl() return code. */ - rc = snp_issue_guest_request(exit_code, &snp_dev->input, &err); - - /* - * Override the error to inform callers the given extended - * request buffer size was too small and give the caller the - * required buffer size. - */ - err = SNP_GUEST_REQ_INVALID_LEN; - snp_dev->input.data_npages = certs_npages; + goto retry_request; } /* @@ -386,7 +387,10 @@ static int handle_guest_request(struct snp_guest_dev *snp_dev, u64 exit_code, in snp_inc_msg_seqno(snp_dev); if (fw_err) - *fw_err = err; + *fw_err = override_err ?: err; + + if (override_npages) + snp_dev->input.data_npages = override_npages; /* * If an extended guest request was issued and the supplied certificate @@ -394,7 +398,7 @@ static int handle_guest_request(struct snp_guest_dev *snp_dev, u64 exit_code, in * prevent IV reuse. If the standard request was successful, return -EIO * back to the caller as would have originally been returned. */ - if (!rc && err == SNP_GUEST_REQ_INVALID_LEN) + if (!rc && override_err == SNP_GUEST_REQ_INVALID_LEN) return -EIO; if (rc) { -- cgit From c5a338274bdb894f088767bea856be344d0ccaef Mon Sep 17 00:00:00 2001 From: "Borislav Petkov (AMD)" Date: Wed, 15 Feb 2023 11:43:43 +0100 Subject: virt/coco/sev-guest: Remove the disable_vmpck label in handle_guest_request() Call the function directly instead. No functional changes. Signed-off-by: Borislav Petkov (AMD) Reviewed-by: Tom Lendacky Link: https://lore.kernel.org/r/20230307192449.24732-5-bp@alien8.de --- drivers/virt/coco/sev-guest/sev-guest.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/virt/coco/sev-guest/sev-guest.c b/drivers/virt/coco/sev-guest/sev-guest.c index e61db0b15b7a..a51bd4afd5ab 100644 --- a/drivers/virt/coco/sev-guest/sev-guest.c +++ b/drivers/virt/coco/sev-guest/sev-guest.c @@ -405,7 +405,8 @@ retry_request: dev_alert(snp_dev->dev, "Detected error from ASP request. rc: %d, fw_err: %llu\n", rc, *fw_err); - goto disable_vmpck; + snp_disable_vmpck(snp_dev); + return rc; } rc = verify_and_dec_payload(snp_dev, resp_buf, resp_sz); @@ -413,14 +414,11 @@ retry_request: dev_alert(snp_dev->dev, "Detected unexpected decode failure from ASP. rc: %d\n", rc); - goto disable_vmpck; + snp_disable_vmpck(snp_dev); + return rc; } return 0; - -disable_vmpck: - snp_disable_vmpck(snp_dev); - return rc; } static int get_report(struct snp_guest_dev *snp_dev, struct snp_guest_request_ioctl *arg) -- cgit From 0fdb6cc7c89cb5e0cbc45dbdbafb8e3fb92ddc95 Mon Sep 17 00:00:00 2001 From: "Borislav Petkov (AMD)" Date: Tue, 7 Mar 2023 09:19:19 -0600 Subject: virt/coco/sev-guest: Carve out the request issuing logic into a helper This makes the code flow a lot easier to follow. No functional changes. [ Tom: touchups. ] Signed-off-by: Borislav Petkov (AMD) Signed-off-by: Tom Lendacky Signed-off-by: Borislav Petkov (AMD) Link: https://lore.kernel.org/r/20230307192449.24732-6-bp@alien8.de --- drivers/virt/coco/sev-guest/sev-guest.c | 44 ++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/drivers/virt/coco/sev-guest/sev-guest.c b/drivers/virt/coco/sev-guest/sev-guest.c index a51bd4afd5ab..07dafe22b27a 100644 --- a/drivers/virt/coco/sev-guest/sev-guest.c +++ b/drivers/virt/coco/sev-guest/sev-guest.c @@ -318,27 +318,12 @@ static int enc_payload(struct snp_guest_dev *snp_dev, u64 seqno, int version, u8 return __enc_payload(snp_dev, req, payload, sz); } -static int handle_guest_request(struct snp_guest_dev *snp_dev, u64 exit_code, int msg_ver, - u8 type, void *req_buf, size_t req_sz, void *resp_buf, - u32 resp_sz, __u64 *fw_err) +static int __handle_guest_request(struct snp_guest_dev *snp_dev, u64 exit_code, __u64 *fw_err) { unsigned long err, override_err = 0; unsigned int override_npages = 0; - u64 seqno; int rc; - /* Get message sequence and verify that its a non-zero */ - seqno = snp_get_msg_seqno(snp_dev); - if (!seqno) - return -EIO; - - memset(snp_dev->response, 0, sizeof(struct snp_guest_msg)); - - /* Encrypt the userspace provided payload */ - rc = enc_payload(snp_dev, seqno, msg_ver, type, req_buf, req_sz); - if (rc) - return rc; - retry_request: /* * Call firmware to process the request. In this function the encrypted @@ -347,7 +332,6 @@ retry_request: * prevent reuse of the IV. */ rc = snp_issue_guest_request(exit_code, &snp_dev->input, &err); - switch (rc) { case -ENOSPC: /* @@ -401,7 +385,33 @@ retry_request: if (!rc && override_err == SNP_GUEST_REQ_INVALID_LEN) return -EIO; + return rc; +} + +static int handle_guest_request(struct snp_guest_dev *snp_dev, u64 exit_code, int msg_ver, + u8 type, void *req_buf, size_t req_sz, void *resp_buf, + u32 resp_sz, __u64 *fw_err) +{ + u64 seqno; + int rc; + + /* Get message sequence and verify that its a non-zero */ + seqno = snp_get_msg_seqno(snp_dev); + if (!seqno) + return -EIO; + + memset(snp_dev->response, 0, sizeof(struct snp_guest_msg)); + + /* Encrypt the userspace provided payload */ + rc = enc_payload(snp_dev, seqno, msg_ver, type, req_buf, req_sz); + if (rc) + return rc; + + rc = __handle_guest_request(snp_dev, exit_code, fw_err); if (rc) { + if (rc == -EIO && *fw_err == SNP_GUEST_REQ_INVALID_LEN) + return rc; + dev_alert(snp_dev->dev, "Detected error from ASP request. rc: %d, fw_err: %llu\n", rc, *fw_err); -- cgit From d25bae7dc7b0668cb2a1325c64eb32d5fea4e5a9 Mon Sep 17 00:00:00 2001 From: "Borislav Petkov (AMD)" Date: Wed, 15 Feb 2023 11:54:59 +0100 Subject: virt/coco/sev-guest: Do some code style cleanups Remove unnecessary linebreaks, make the code more compact. No functional changes. Signed-off-by: Borislav Petkov (AMD) Reviewed-by: Tom Lendacky Link: https://lore.kernel.org/r/20230307192449.24732-7-bp@alien8.de --- drivers/virt/coco/sev-guest/sev-guest.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/virt/coco/sev-guest/sev-guest.c b/drivers/virt/coco/sev-guest/sev-guest.c index 07dafe22b27a..81a53c31ff46 100644 --- a/drivers/virt/coco/sev-guest/sev-guest.c +++ b/drivers/virt/coco/sev-guest/sev-guest.c @@ -412,18 +412,14 @@ static int handle_guest_request(struct snp_guest_dev *snp_dev, u64 exit_code, in if (rc == -EIO && *fw_err == SNP_GUEST_REQ_INVALID_LEN) return rc; - dev_alert(snp_dev->dev, - "Detected error from ASP request. rc: %d, fw_err: %llu\n", - rc, *fw_err); + dev_alert(snp_dev->dev, "Detected error from ASP request. rc: %d, fw_err: %llu\n", rc, *fw_err); snp_disable_vmpck(snp_dev); return rc; } rc = verify_and_dec_payload(snp_dev, resp_buf, resp_sz); if (rc) { - dev_alert(snp_dev->dev, - "Detected unexpected decode failure from ASP. rc: %d\n", - rc); + dev_alert(snp_dev->dev, "Detected unexpected decode failure from ASP. rc: %d\n", rc); snp_disable_vmpck(snp_dev); return rc; } -- cgit From fa4ae42cc60a7dea30e8f2db444b808d80862345 Mon Sep 17 00:00:00 2001 From: "Borislav Petkov (AMD)" Date: Thu, 16 Feb 2023 10:50:11 +0100 Subject: virt/coco/sev-guest: Convert the sw_exit_info_2 checking to a switch-case snp_issue_guest_request() checks the value returned by the hypervisor in sw_exit_info_2 and returns a different error depending on it. Convert those checks into a switch-case to make it more readable when more error values are going to be checked in the future. No functional changes. Signed-off-by: Borislav Petkov (AMD) Reviewed-by: Tom Lendacky Link: https://lore.kernel.org/r/20230307192449.24732-8-bp@alien8.de --- arch/x86/kernel/sev.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/arch/x86/kernel/sev.c b/arch/x86/kernel/sev.c index 6a3e1425ba17..d67884fb38c1 100644 --- a/arch/x86/kernel/sev.c +++ b/arch/x86/kernel/sev.c @@ -2210,15 +2210,21 @@ int snp_issue_guest_request(u64 exit_code, struct snp_req_data *input, unsigned goto e_put; *fw_err = ghcb->save.sw_exit_info_2; - if (ghcb->save.sw_exit_info_2) { + switch (*fw_err) { + case 0: + break; + + case SNP_GUEST_REQ_INVALID_LEN: /* Number of expected pages are returned in RBX */ - if (exit_code == SVM_VMGEXIT_EXT_GUEST_REQUEST && - ghcb->save.sw_exit_info_2 == SNP_GUEST_REQ_INVALID_LEN) { + if (exit_code == SVM_VMGEXIT_EXT_GUEST_REQUEST) { input->data_npages = ghcb_get_rbx(ghcb); ret = -ENOSPC; - } else { - ret = -EIO; + break; } + fallthrough; + default: + ret = -EIO; + break; } e_put: -- cgit From 72f7754dcf31c87c92c0c353dcf747814cc5ce10 Mon Sep 17 00:00:00 2001 From: Dionna Glaze Date: Thu, 16 Feb 2023 11:08:02 +0100 Subject: virt/coco/sev-guest: Add throttling awareness A potentially malicious SEV guest can constantly hammer the hypervisor using this driver to send down requests and thus prevent or at least considerably hinder other guests from issuing requests to the secure processor which is a shared platform resource. Therefore, the host is permitted and encouraged to throttle such guest requests. Add the capability to handle the case when the hypervisor throttles excessive numbers of requests issued by the guest. Otherwise, the VM platform communication key will be disabled, preventing the guest from attesting itself. Realistically speaking, a well-behaved guest should not even care about throttling. During its lifetime, it would end up issuing a handful of requests which the hardware can easily handle. This is more to address the case of a malicious guest. Such guest should get throttled and if its VMPCK gets disabled, then that's its own wrongdoing and perhaps that guest even deserves it. To the implementation: the hypervisor signals with SNP_GUEST_REQ_ERR_BUSY that the guest requests should be throttled. That error code is returned in the upper 32-bit half of exitinfo2 and this is part of the GHCB spec v2. So the guest is given a throttling period of 1 minute in which it retries the request every 2 seconds. This is a good default but if it turns out to not pan out in practice, it can be tweaked later. For safety, since the encryption algorithm in GHCBv2 is AES_GCM, control must remain in the kernel to complete the request with the current sequence number. Returning without finishing the request allows the guest to make another request but with different message contents. This is IV reuse, and breaks cryptographic protections. [ bp: - Rewrite commit message and do a simplified version. - The stable tags are supposed to denote that a cleanup should go upfront before backporting this so that any future fixes to this can preserve the sanity of the backporter(s). ] Fixes: d5af44dde546 ("x86/sev: Provide support for SNP guest request NAEs") Signed-off-by: Dionna Glaze Co-developed-by: Borislav Petkov (AMD) Signed-off-by: Borislav Petkov (AMD) Reviewed-by: Tom Lendacky Cc: # d6fd48eff750 ("virt/coco/sev-guest: Check SEV_SNP attribute at probe time") Cc: # 970ab823743f (" virt/coco/sev-guest: Simplify extended guest request handling") Cc: # c5a338274bdb ("virt/coco/sev-guest: Remove the disable_vmpck label in handle_guest_request()") Cc: # 0fdb6cc7c89c ("virt/coco/sev-guest: Carve out the request issuing logic into a helper") Cc: # d25bae7dc7b0 ("virt/coco/sev-guest: Do some code style cleanups") Cc: # fa4ae42cc60a ("virt/coco/sev-guest: Convert the sw_exit_info_2 checking to a switch-case") Link: https://lore.kernel.org/r/20230214164638.1189804-2-dionnaglaze@google.com --- arch/x86/include/asm/sev-common.h | 3 ++- arch/x86/kernel/sev.c | 4 ++++ drivers/virt/coco/sev-guest/sev-guest.c | 19 ++++++++++++++++++- 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/sev-common.h b/arch/x86/include/asm/sev-common.h index b8357d6ecd47..b63be696b776 100644 --- a/arch/x86/include/asm/sev-common.h +++ b/arch/x86/include/asm/sev-common.h @@ -128,8 +128,9 @@ struct snp_psc_desc { struct psc_entry entries[VMGEXIT_PSC_MAX_ENTRY]; } __packed; -/* Guest message request error code */ +/* Guest message request error codes */ #define SNP_GUEST_REQ_INVALID_LEN BIT_ULL(32) +#define SNP_GUEST_REQ_ERR_BUSY BIT_ULL(33) #define GHCB_MSR_TERM_REQ 0x100 #define GHCB_MSR_TERM_REASON_SET_POS 12 diff --git a/arch/x86/kernel/sev.c b/arch/x86/kernel/sev.c index d67884fb38c1..3f664ab277c4 100644 --- a/arch/x86/kernel/sev.c +++ b/arch/x86/kernel/sev.c @@ -2214,6 +2214,10 @@ int snp_issue_guest_request(u64 exit_code, struct snp_req_data *input, unsigned case 0: break; + case SNP_GUEST_REQ_ERR_BUSY: + ret = -EAGAIN; + break; + case SNP_GUEST_REQ_INVALID_LEN: /* Number of expected pages are returned in RBX */ if (exit_code == SVM_VMGEXIT_EXT_GUEST_REQUEST) { diff --git a/drivers/virt/coco/sev-guest/sev-guest.c b/drivers/virt/coco/sev-guest/sev-guest.c index 81a53c31ff46..46f1a8d558b0 100644 --- a/drivers/virt/coco/sev-guest/sev-guest.c +++ b/drivers/virt/coco/sev-guest/sev-guest.c @@ -31,6 +31,9 @@ #define AAD_LEN 48 #define MSG_HDR_VER 1 +#define SNP_REQ_MAX_RETRY_DURATION (60*HZ) +#define SNP_REQ_RETRY_DELAY (2*HZ) + struct snp_guest_crypto { struct crypto_aead *tfm; u8 *iv, *authtag; @@ -320,7 +323,8 @@ static int enc_payload(struct snp_guest_dev *snp_dev, u64 seqno, int version, u8 static int __handle_guest_request(struct snp_guest_dev *snp_dev, u64 exit_code, __u64 *fw_err) { - unsigned long err, override_err = 0; + unsigned long err = 0xff, override_err = 0; + unsigned long req_start = jiffies; unsigned int override_npages = 0; int rc; @@ -360,6 +364,19 @@ retry_request: * user as an ioctl() return code. */ goto retry_request; + + /* + * The host may return SNP_GUEST_REQ_ERR_EBUSY if the request has been + * throttled. Retry in the driver to avoid returning and reusing the + * message sequence number on a different message. + */ + case -EAGAIN: + if (jiffies - req_start > SNP_REQ_MAX_RETRY_DURATION) { + rc = -ETIMEDOUT; + break; + } + schedule_timeout_killable(SNP_REQ_RETRY_DELAY); + goto retry_request; } /* -- cgit From 41130c32f3a18fcc930316da17f3a5f3bc326aa1 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Thu, 23 Feb 2023 00:10:25 +0100 Subject: wifi: mt76: do not run mt76_unregister_device() on unregistered hw Trying to probe a mt7921e pci card without firmware results in a successful probe where ieee80211_register_hw hasn't been called. When removing the driver, ieee802111_unregister_hw is called unconditionally leading to a kernel NULL pointer dereference. Fix the issue running mt76_unregister_device routine just for registered hw. Link: https://bugs.debian.org/1029116 Link: https://bugs.kali.org/view.php?id=8140 Reported-by: Stuart Hayhurst Fixes: 1c71e03afe4b ("mt76: mt7921: move mt7921_init_hw in a dedicated work") Tested-by: Helmut Grohne Signed-off-by: Lorenzo Bianconi Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/be3457d82f4e44bb71a22b2b5db27b644a37b1e1.1677107277.git.lorenzo@kernel.org --- drivers/net/wireless/mediatek/mt76/mac80211.c | 8 ++++++++ drivers/net/wireless/mediatek/mt76/mt76.h | 1 + 2 files changed, 9 insertions(+) diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c index b117e4467c87..34abf70f44af 100644 --- a/drivers/net/wireless/mediatek/mt76/mac80211.c +++ b/drivers/net/wireless/mediatek/mt76/mac80211.c @@ -539,6 +539,7 @@ int mt76_register_phy(struct mt76_phy *phy, bool vht, if (ret) return ret; + set_bit(MT76_STATE_REGISTERED, &phy->state); phy->dev->phys[phy->band_idx] = phy; return 0; @@ -549,6 +550,9 @@ void mt76_unregister_phy(struct mt76_phy *phy) { struct mt76_dev *dev = phy->dev; + if (!test_bit(MT76_STATE_REGISTERED, &phy->state)) + return; + if (IS_ENABLED(CONFIG_MT76_LEDS)) mt76_led_cleanup(phy); mt76_tx_status_check(dev, true); @@ -719,6 +723,7 @@ int mt76_register_device(struct mt76_dev *dev, bool vht, return ret; WARN_ON(mt76_worker_setup(hw, &dev->tx_worker, NULL, "tx")); + set_bit(MT76_STATE_REGISTERED, &phy->state); sched_set_fifo_low(dev->tx_worker.task); return 0; @@ -729,6 +734,9 @@ void mt76_unregister_device(struct mt76_dev *dev) { struct ieee80211_hw *hw = dev->hw; + if (!test_bit(MT76_STATE_REGISTERED, &dev->phy.state)) + return; + if (IS_ENABLED(CONFIG_MT76_LEDS)) mt76_led_cleanup(&dev->phy); mt76_tx_status_check(dev, true); diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index ccca0162c8f8..183b0fc5a2d4 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -402,6 +402,7 @@ struct mt76_tx_cb { enum { MT76_STATE_INITIALIZED, + MT76_STATE_REGISTERED, MT76_STATE_RUNNING, MT76_STATE_MCU_RUNNING, MT76_SCANNING, -- cgit From c2f73eacee3bf1df2cfe25e1f08a3cae98b1df3d Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 1 Mar 2023 17:37:39 +0100 Subject: wifi: mt76: mt7915: add back 160MHz channel width support for MT7915 A number of users reported that this support was working fine before it got removed. Add it back, but leave out the unsupported 80+80 mode. Fixes: ac922bd60ace ("wifi: mt76: mt7915: remove BW160 and BW80+80 support") Signed-off-by: Felix Fietkau Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230301163739.52314-1-nbd@nbd.name --- drivers/net/wireless/mediatek/mt76/mt7915/init.c | 40 ++++++++++++++++++------ 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/init.c b/drivers/net/wireless/mediatek/mt76/mt7915/init.c index 1ab768feccaa..5e288116b1b0 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c @@ -383,7 +383,6 @@ mt7915_init_wiphy(struct mt7915_phy *phy) ieee80211_hw_set(hw, SUPPORTS_RX_DECAP_OFFLOAD); ieee80211_hw_set(hw, SUPPORTS_MULTI_BSSID); ieee80211_hw_set(hw, WANT_MONITOR_VIF); - ieee80211_hw_set(hw, SUPPORTS_VHT_EXT_NSS_BW); hw->max_tx_fragments = 4; @@ -396,6 +395,9 @@ mt7915_init_wiphy(struct mt7915_phy *phy) } if (phy->mt76->cap.has_5ghz) { + struct ieee80211_sta_vht_cap *vht_cap; + + vht_cap = &phy->mt76->sband_5g.sband.vht_cap; phy->mt76->sband_5g.sband.ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING | IEEE80211_HT_CAP_MAX_AMSDU; @@ -403,19 +405,28 @@ mt7915_init_wiphy(struct mt7915_phy *phy) IEEE80211_HT_MPDU_DENSITY_4; if (is_mt7915(&dev->mt76)) { - phy->mt76->sband_5g.sband.vht_cap.cap |= + vht_cap->cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 | IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK; + + if (!dev->dbdc_support) + vht_cap->cap |= + IEEE80211_VHT_CAP_SHORT_GI_160 | + IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ | + FIELD_PREP(IEEE80211_VHT_CAP_EXT_NSS_BW_MASK, 1); } else { - phy->mt76->sband_5g.sband.vht_cap.cap |= + vht_cap->cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 | IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK; /* mt7916 dbdc with 2g 2x2 bw40 and 5g 2x2 bw160c */ - phy->mt76->sband_5g.sband.vht_cap.cap |= + vht_cap->cap |= IEEE80211_VHT_CAP_SHORT_GI_160 | IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ; } + + if (!is_mt7915(&dev->mt76) || !dev->dbdc_support) + ieee80211_hw_set(hw, SUPPORTS_VHT_EXT_NSS_BW); } mt76_set_stream_caps(phy->mt76, true); @@ -841,9 +852,13 @@ mt7915_set_stream_he_txbf_caps(struct mt7915_phy *phy, int sts = hweight8(phy->mt76->chainmask); u8 c, sts_160 = sts; - /* mt7915 doesn't support bw160 */ - if (is_mt7915(&dev->mt76)) - sts_160 = 0; + /* Can do 1/2 of STS in 160Mhz mode for mt7915 */ + if (is_mt7915(&dev->mt76)) { + if (!dev->dbdc_support) + sts_160 /= 2; + else + sts_160 = 0; + } #ifdef CONFIG_MAC80211_MESH if (vif == NL80211_IFTYPE_MESH_POINT) @@ -944,10 +959,15 @@ mt7915_init_he_caps(struct mt7915_phy *phy, enum nl80211_band band, int i, idx = 0, nss = hweight8(phy->mt76->antenna_mask); u16 mcs_map = 0; u16 mcs_map_160 = 0; - u8 nss_160 = nss; + u8 nss_160; - /* Can't do 160MHz with mt7915 */ - if (is_mt7915(&dev->mt76)) + if (!is_mt7915(&dev->mt76)) + nss_160 = nss; + else if (!dev->dbdc_support) + /* Can do 1/2 of NSS streams in 160Mhz mode for mt7915 */ + nss_160 = nss / 2; + else + /* Can't do 160MHz with mt7915 dbdc */ nss_160 = 0; for (i = 0; i < 8; i++) { -- cgit From 5683e1488aa9b0805a9403d215e48fed29d6d923 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Mon, 6 Mar 2023 18:42:51 +0100 Subject: wifi: mt76: connac: do not check WED status for non-mmio devices WED is supported just for mmio devices, so do not check it for usb or sdio devices. This patch fixes the crash reported below: [ 21.946627] wlp0s3u1i3: authenticate with c4:41:1e:f5:2b:1d [ 22.525298] wlp0s3u1i3: send auth to c4:41:1e:f5:2b:1d (try 1/3) [ 22.548274] wlp0s3u1i3: authenticate with c4:41:1e:f5:2b:1d [ 22.557694] wlp0s3u1i3: send auth to c4:41:1e:f5:2b:1d (try 1/3) [ 22.565885] wlp0s3u1i3: authenticated [ 22.569502] wlp0s3u1i3: associate with c4:41:1e:f5:2b:1d (try 1/3) [ 22.578966] wlp0s3u1i3: RX AssocResp from c4:41:1e:f5:2b:1d (capab=0x11 status=30 aid=3) [ 22.579113] wlp0s3u1i3: c4:41:1e:f5:2b:1d rejected association temporarily; comeback duration 1000 TU (1024 ms) [ 23.649518] wlp0s3u1i3: associate with c4:41:1e:f5:2b:1d (try 2/3) [ 23.752528] wlp0s3u1i3: RX AssocResp from c4:41:1e:f5:2b:1d (capab=0x11 status=0 aid=3) [ 23.797450] wlp0s3u1i3: associated [ 24.959527] kernel tried to execute NX-protected page - exploit attempt? (uid: 0) [ 24.959640] BUG: unable to handle page fault for address: ffff88800c223200 [ 24.959706] #PF: supervisor instruction fetch in kernel mode [ 24.959788] #PF: error_code(0x0011) - permissions violation [ 24.959846] PGD 2c01067 P4D 2c01067 PUD 2c02067 PMD c2a8063 PTE 800000000c223163 [ 24.959957] Oops: 0011 [#1] PREEMPT SMP [ 24.960009] CPU: 0 PID: 391 Comm: wpa_supplicant Not tainted 6.2.0-kvm #18 [ 24.960089] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.1-2.fc37 04/01/2014 [ 24.960191] RIP: 0010:0xffff88800c223200 [ 24.960446] RSP: 0018:ffffc90000ff7698 EFLAGS: 00010282 [ 24.960513] RAX: ffff888028397010 RBX: ffff88800c26e630 RCX: 0000000000000058 [ 24.960598] RDX: ffff88800c26f844 RSI: 0000000000000006 RDI: ffff888028397010 [ 24.960682] RBP: ffff88800ea72f00 R08: 18b873fbab2b964c R09: be06b38235f3c63c [ 24.960766] R10: 18b873fbab2b964c R11: be06b38235f3c63c R12: 0000000000000001 [ 24.960853] R13: ffff88800c26f84c R14: ffff8880063f0ff8 R15: ffff88800c26e644 [ 24.960950] FS: 00007effcea327c0(0000) GS:ffff88807dc00000(0000) knlGS:0000000000000000 [ 24.961036] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 24.961106] CR2: ffff88800c223200 CR3: 000000000eaa2000 CR4: 00000000000006b0 [ 24.961190] Call Trace: [ 24.961219] [ 24.961245] ? mt76_connac_mcu_add_key+0x2cf/0x310 [ 24.961313] ? mt7921_set_key+0x150/0x200 [ 24.961365] ? drv_set_key+0xa9/0x1b0 [ 24.961418] ? ieee80211_key_enable_hw_accel+0xd9/0x240 [ 24.961485] ? ieee80211_key_replace+0x3f3/0x730 [ 24.961541] ? crypto_shash_setkey+0x89/0xd0 [ 24.961597] ? ieee80211_key_link+0x2d7/0x3a0 [ 24.961664] ? crypto_aead_setauthsize+0x31/0x50 [ 24.961730] ? sta_info_hash_lookup+0xa6/0xf0 [ 24.961785] ? ieee80211_add_key+0x1fc/0x250 [ 24.961842] ? rdev_add_key+0x41/0x140 [ 24.961882] ? nl80211_parse_key+0x6c/0x2f0 [ 24.961940] ? nl80211_new_key+0x24a/0x290 [ 24.961984] ? genl_rcv_msg+0x36c/0x3a0 [ 24.962036] ? rdev_mod_link_station+0xe0/0xe0 [ 24.962102] ? nl80211_set_key+0x410/0x410 [ 24.962143] ? nl80211_pre_doit+0x200/0x200 [ 24.962187] ? genl_bind+0xc0/0xc0 [ 24.962217] ? netlink_rcv_skb+0xaa/0xd0 [ 24.962259] ? genl_rcv+0x24/0x40 [ 24.962300] ? netlink_unicast+0x224/0x2f0 [ 24.962345] ? netlink_sendmsg+0x30b/0x3d0 [ 24.962388] ? ____sys_sendmsg+0x109/0x1b0 [ 24.962388] ? ____sys_sendmsg+0x109/0x1b0 [ 24.962440] ? __import_iovec+0x2e/0x110 [ 24.962482] ? ___sys_sendmsg+0xbe/0xe0 [ 24.962525] ? mod_objcg_state+0x25c/0x330 [ 24.962576] ? __dentry_kill+0x19e/0x1d0 [ 24.962618] ? call_rcu+0x18f/0x270 [ 24.962660] ? __dentry_kill+0x19e/0x1d0 [ 24.962702] ? __x64_sys_sendmsg+0x70/0x90 [ 24.962744] ? do_syscall_64+0x3d/0x80 [ 24.962796] ? exit_to_user_mode_prepare+0x1b/0x70 [ 24.962852] ? entry_SYSCALL_64_after_hwframe+0x46/0xb0 [ 24.962913] [ 24.962939] Modules linked in: [ 24.962981] CR2: ffff88800c223200 [ 24.963022] ---[ end trace 0000000000000000 ]--- [ 24.963087] RIP: 0010:0xffff88800c223200 [ 24.963323] RSP: 0018:ffffc90000ff7698 EFLAGS: 00010282 [ 24.963376] RAX: ffff888028397010 RBX: ffff88800c26e630 RCX: 0000000000000058 [ 24.963458] RDX: ffff88800c26f844 RSI: 0000000000000006 RDI: ffff888028397010 [ 24.963538] RBP: ffff88800ea72f00 R08: 18b873fbab2b964c R09: be06b38235f3c63c [ 24.963622] R10: 18b873fbab2b964c R11: be06b38235f3c63c R12: 0000000000000001 [ 24.963705] R13: ffff88800c26f84c R14: ffff8880063f0ff8 R15: ffff88800c26e644 [ 24.963788] FS: 00007effcea327c0(0000) GS:ffff88807dc00000(0000) knlGS:0000000000000000 [ 24.963871] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 24.963941] CR2: ffff88800c223200 CR3: 000000000eaa2000 CR4: 00000000000006b0 [ 24.964018] note: wpa_supplicant[391] exited with irqs disabled Fixes: d1369e515efe ("wifi: mt76: connac: introduce mt76_connac_mcu_sta_wed_update utility routine") Signed-off-by: Lorenzo Bianconi Acked-by: Felix Fietkau Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/c42168429453474213fa8244bf4b069de4531f40.1678124335.git.lorenzo@kernel.org --- drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c index efb9bfaa187f..008ece1b16f8 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c @@ -1221,6 +1221,9 @@ EXPORT_SYMBOL_GPL(mt76_connac_mcu_sta_ba_tlv); int mt76_connac_mcu_sta_wed_update(struct mt76_dev *dev, struct sk_buff *skb) { + if (!mt76_is_mmio(dev)) + return 0; + if (!mtk_wed_device_active(&dev->mmio.wed)) return 0; -- cgit From ee06a3ef7e3cddb62b90ac40aa661d3c12f7cabc Mon Sep 17 00:00:00 2001 From: Jurica Vukadin Date: Tue, 7 Mar 2023 20:40:39 +0100 Subject: kconfig: Update config changed flag before calling callback Prior to commit 5ee546594025 ("kconfig: change sym_change_count to a boolean flag"), the conf_updated flag was set to the new value *before* calling the callback. xconfig's save action depends on this behaviour, because xconfig calls conf_get_changed() directly from the callback and now sees the old value, thus never enabling the save button or the shortcut. Restore the previous behaviour. Fixes: 5ee546594025 ("kconfig: change sym_change_count to a boolean flag") Signed-off-by: Jurica Vukadin Acked-by: Randy Dunlap Tested-by: Randy Dunlap Signed-off-by: Masahiro Yamada --- scripts/kconfig/confdata.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c index b7c9f1dd5e42..992575f1e976 100644 --- a/scripts/kconfig/confdata.c +++ b/scripts/kconfig/confdata.c @@ -1226,10 +1226,12 @@ static void (*conf_changed_callback)(void); void conf_set_changed(bool val) { - if (conf_changed_callback && conf_changed != val) - conf_changed_callback(); + bool changed = conf_changed != val; conf_changed = val; + + if (conf_changed_callback && changed) + conf_changed_callback(); } bool conf_get_changed(void) -- cgit From 4928f67bc911e46a43004251a4d7eb2259ba6077 Mon Sep 17 00:00:00 2001 From: Yishai Hadas Date: Wed, 8 Mar 2023 17:57:23 +0200 Subject: vfio/mlx5: Fix the report of dirty_bytes upon pre-copy Fix the report of dirty_bytes upon pre-copy to include both the existing data on the migration file and the device extra bytes. This gives a better close estimation to what can be passed any more as part of pre-copy. Fixes: 0dce165b1adf ("vfio/mlx5: Introduce vfio precopy ioctl implementation") Signed-off-by: Yishai Hadas Link: https://lore.kernel.org/r/20230308155723.108218-1-yishaih@nvidia.com Signed-off-by: Alex Williamson --- drivers/vfio/pci/mlx5/main.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/drivers/vfio/pci/mlx5/main.c b/drivers/vfio/pci/mlx5/main.c index e897537a9e8a..d95fd382814c 100644 --- a/drivers/vfio/pci/mlx5/main.c +++ b/drivers/vfio/pci/mlx5/main.c @@ -442,16 +442,10 @@ static long mlx5vf_precopy_ioctl(struct file *filp, unsigned int cmd, if (migf->pre_copy_initial_bytes > *pos) { info.initial_bytes = migf->pre_copy_initial_bytes - *pos; } else { - buf = mlx5vf_get_data_buff_from_pos(migf, *pos, &end_of_data); - if (buf) { - info.dirty_bytes = buf->start_pos + buf->length - *pos; - } else { - if (!end_of_data) { - ret = -EINVAL; - goto err_migf_unlock; - } - info.dirty_bytes = inc_length; - } + info.dirty_bytes = migf->max_pos - *pos; + if (!info.dirty_bytes) + end_of_data = true; + info.dirty_bytes += inc_length; } if (!end_of_data || !inc_length) { -- cgit From 90ae93d8affc1061cd87ca8ddd9a838c7d31a158 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 6 Mar 2023 08:56:36 +0100 Subject: interconnect: qcom: rpm: fix registration race The current interconnect provider registration interface is inherently racy as nodes are not added until the after adding the provider. This can specifically cause racing DT lookups to fail. Switch to using the new API where the provider is not registered until after it has been fully initialised. Fixes: 62feb14ee8a3 ("interconnect: qcom: Consolidate interconnect RPM support") Fixes: 30c8fa3ec61a ("interconnect: qcom: Add MSM8916 interconnect provider driver") Cc: stable@vger.kernel.org # 5.7 Reviewed-by: Konrad Dybcio Reviewed-by: Jun Nie Signed-off-by: Johan Hovold Link: https://lore.kernel.org/r/20230306075651.2449-9-johan+linaro@kernel.org Signed-off-by: Georgi Djakov --- drivers/interconnect/qcom/icc-rpm.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/interconnect/qcom/icc-rpm.c b/drivers/interconnect/qcom/icc-rpm.c index 91778cfcbc65..4180a06681b2 100644 --- a/drivers/interconnect/qcom/icc-rpm.c +++ b/drivers/interconnect/qcom/icc-rpm.c @@ -503,7 +503,6 @@ regmap_done: } provider = &qp->provider; - INIT_LIST_HEAD(&provider->nodes); provider->dev = dev; provider->set = qcom_icc_set; provider->pre_aggregate = qcom_icc_pre_bw_aggregate; @@ -511,12 +510,7 @@ regmap_done: provider->xlate_extended = qcom_icc_xlate_extended; provider->data = data; - ret = icc_provider_add(provider); - if (ret) { - dev_err(dev, "error adding interconnect provider: %d\n", ret); - clk_bulk_disable_unprepare(qp->num_clks, qp->bus_clks); - return ret; - } + icc_provider_init(provider); for (i = 0; i < num_nodes; i++) { size_t j; @@ -524,7 +518,7 @@ regmap_done: node = icc_node_create(qnodes[i]->id); if (IS_ERR(node)) { ret = PTR_ERR(node); - goto err; + goto err_remove_nodes; } node->name = qnodes[i]->name; @@ -538,20 +532,26 @@ regmap_done: } data->num_nodes = num_nodes; + ret = icc_provider_register(provider); + if (ret) + goto err_remove_nodes; + platform_set_drvdata(pdev, qp); /* Populate child NoC devices if any */ if (of_get_child_count(dev->of_node) > 0) { ret = of_platform_populate(dev->of_node, NULL, NULL, dev); if (ret) - goto err; + goto err_deregister_provider; } return 0; -err: + +err_deregister_provider: + icc_provider_deregister(provider); +err_remove_nodes: icc_nodes_remove(provider); clk_bulk_disable_unprepare(qp->num_clks, qp->bus_clks); - icc_provider_del(provider); return ret; } @@ -561,9 +561,9 @@ int qnoc_remove(struct platform_device *pdev) { struct qcom_icc_provider *qp = platform_get_drvdata(pdev); + icc_provider_deregister(&qp->provider); icc_nodes_remove(&qp->provider); clk_bulk_disable_unprepare(qp->num_clks, qp->bus_clks); - icc_provider_del(&qp->provider); return 0; } -- cgit From 6570d1d46eeade82965ccc4a3ab7d778898ef4bf Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 6 Mar 2023 08:56:37 +0100 Subject: interconnect: qcom: rpmh: fix probe child-node error handling Make sure to clean up and release resources properly also in case probe fails when populating child devices. Fixes: 57eb14779dfd ("interconnect: qcom: icc-rpmh: Support child NoC device probe") Cc: stable@vger.kernel.org # 6.0 Cc: Luca Weiss Reviewed-by: Konrad Dybcio Signed-off-by: Johan Hovold Link: https://lore.kernel.org/r/20230306075651.2449-10-johan+linaro@kernel.org Signed-off-by: Georgi Djakov --- drivers/interconnect/qcom/icc-rpmh.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/interconnect/qcom/icc-rpmh.c b/drivers/interconnect/qcom/icc-rpmh.c index fd17291c61eb..5168bbf3d92f 100644 --- a/drivers/interconnect/qcom/icc-rpmh.c +++ b/drivers/interconnect/qcom/icc-rpmh.c @@ -235,8 +235,11 @@ int qcom_icc_rpmh_probe(struct platform_device *pdev) platform_set_drvdata(pdev, qp); /* Populate child NoC devices if any */ - if (of_get_child_count(dev->of_node) > 0) - return of_platform_populate(dev->of_node, NULL, NULL, dev); + if (of_get_child_count(dev->of_node) > 0) { + ret = of_platform_populate(dev->of_node, NULL, NULL, dev); + if (ret) + goto err; + } return 0; err: -- cgit From 74240a5bebd48d8b843c6d0f1acfaa722a5abeb7 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 6 Mar 2023 08:56:38 +0100 Subject: interconnect: qcom: rpmh: fix registration race The current interconnect provider registration interface is inherently racy as nodes are not added until the after adding the provider. This can specifically cause racing DT lookups to fail. Switch to using the new API where the provider is not registered until after it has been fully initialised. Fixes: 976daac4a1c5 ("interconnect: qcom: Consolidate interconnect RPMh support") Cc: stable@vger.kernel.org # 5.7 Reviewed-by: Konrad Dybcio Signed-off-by: Johan Hovold Link: https://lore.kernel.org/r/20230306075651.2449-11-johan+linaro@kernel.org Signed-off-by: Georgi Djakov --- drivers/interconnect/qcom/icc-rpmh.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/drivers/interconnect/qcom/icc-rpmh.c b/drivers/interconnect/qcom/icc-rpmh.c index 5168bbf3d92f..fdb5e58e408b 100644 --- a/drivers/interconnect/qcom/icc-rpmh.c +++ b/drivers/interconnect/qcom/icc-rpmh.c @@ -192,9 +192,10 @@ int qcom_icc_rpmh_probe(struct platform_device *pdev) provider->pre_aggregate = qcom_icc_pre_aggregate; provider->aggregate = qcom_icc_aggregate; provider->xlate_extended = qcom_icc_xlate_extended; - INIT_LIST_HEAD(&provider->nodes); provider->data = data; + icc_provider_init(provider); + qp->dev = dev; qp->bcms = desc->bcms; qp->num_bcms = desc->num_bcms; @@ -203,10 +204,6 @@ int qcom_icc_rpmh_probe(struct platform_device *pdev) if (IS_ERR(qp->voter)) return PTR_ERR(qp->voter); - ret = icc_provider_add(provider); - if (ret) - return ret; - for (i = 0; i < qp->num_bcms; i++) qcom_icc_bcm_init(qp->bcms[i], dev); @@ -218,7 +215,7 @@ int qcom_icc_rpmh_probe(struct platform_device *pdev) node = icc_node_create(qn->id); if (IS_ERR(node)) { ret = PTR_ERR(node); - goto err; + goto err_remove_nodes; } node->name = qn->name; @@ -232,19 +229,27 @@ int qcom_icc_rpmh_probe(struct platform_device *pdev) } data->num_nodes = num_nodes; + + ret = icc_provider_register(provider); + if (ret) + goto err_remove_nodes; + platform_set_drvdata(pdev, qp); /* Populate child NoC devices if any */ if (of_get_child_count(dev->of_node) > 0) { ret = of_platform_populate(dev->of_node, NULL, NULL, dev); if (ret) - goto err; + goto err_deregister_provider; } return 0; -err: + +err_deregister_provider: + icc_provider_deregister(provider); +err_remove_nodes: icc_nodes_remove(provider); - icc_provider_del(provider); + return ret; } EXPORT_SYMBOL_GPL(qcom_icc_rpmh_probe); @@ -253,8 +258,8 @@ int qcom_icc_rpmh_remove(struct platform_device *pdev) { struct qcom_icc_provider *qp = platform_get_drvdata(pdev); + icc_provider_deregister(&qp->provider); icc_nodes_remove(&qp->provider); - icc_provider_del(&qp->provider); return 0; } -- cgit From bfe7bcd2b9f5215de2144f097f39971180e7ea54 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 6 Mar 2023 08:56:39 +0100 Subject: interconnect: qcom: msm8974: fix registration race The current interconnect provider registration interface is inherently racy as nodes are not added until the after adding the provider. This can specifically cause racing DT lookups to fail. Switch to using the new API where the provider is not registered until after it has been fully initialised. Fixes: 4e60a9568dc6 ("interconnect: qcom: add msm8974 driver") Cc: stable@vger.kernel.org # 5.5 Reviewed-by: Brian Masney Reviewed-by: Konrad Dybcio Signed-off-by: Johan Hovold Link: https://lore.kernel.org/r/20230306075651.2449-12-johan+linaro@kernel.org Signed-off-by: Georgi Djakov --- drivers/interconnect/qcom/msm8974.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/drivers/interconnect/qcom/msm8974.c b/drivers/interconnect/qcom/msm8974.c index 5ea192f1141d..1828deaca443 100644 --- a/drivers/interconnect/qcom/msm8974.c +++ b/drivers/interconnect/qcom/msm8974.c @@ -692,7 +692,6 @@ static int msm8974_icc_probe(struct platform_device *pdev) return ret; provider = &qp->provider; - INIT_LIST_HEAD(&provider->nodes); provider->dev = dev; provider->set = msm8974_icc_set; provider->aggregate = icc_std_aggregate; @@ -700,11 +699,7 @@ static int msm8974_icc_probe(struct platform_device *pdev) provider->data = data; provider->get_bw = msm8974_get_bw; - ret = icc_provider_add(provider); - if (ret) { - dev_err(dev, "error adding interconnect provider: %d\n", ret); - goto err_disable_clks; - } + icc_provider_init(provider); for (i = 0; i < num_nodes; i++) { size_t j; @@ -712,7 +707,7 @@ static int msm8974_icc_probe(struct platform_device *pdev) node = icc_node_create(qnodes[i]->id); if (IS_ERR(node)) { ret = PTR_ERR(node); - goto err_del_icc; + goto err_remove_nodes; } node->name = qnodes[i]->name; @@ -729,15 +724,16 @@ static int msm8974_icc_probe(struct platform_device *pdev) } data->num_nodes = num_nodes; + ret = icc_provider_register(provider); + if (ret) + goto err_remove_nodes; + platform_set_drvdata(pdev, qp); return 0; -err_del_icc: +err_remove_nodes: icc_nodes_remove(provider); - icc_provider_del(provider); - -err_disable_clks: clk_bulk_disable_unprepare(qp->num_clks, qp->bus_clks); return ret; @@ -747,9 +743,9 @@ static int msm8974_icc_remove(struct platform_device *pdev) { struct msm8974_icc_provider *qp = platform_get_drvdata(pdev); + icc_provider_deregister(&qp->provider); icc_nodes_remove(&qp->provider); clk_bulk_disable_unprepare(qp->num_clks, qp->bus_clks); - icc_provider_del(&qp->provider); return 0; } -- cgit From 3aab264875bf3c915ea2517fae1eec213e0b4987 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 6 Mar 2023 08:56:42 +0100 Subject: interconnect: exynos: fix node leak in probe PM QoS error path Make sure to add the newly allocated interconnect node to the provider before adding the PM QoS request so that the node is freed on errors. Fixes: 2f95b9d5cf0b ("interconnect: Add generic interconnect driver for Exynos SoCs") Cc: stable@vger.kernel.org # 5.11 Cc: Sylwester Nawrocki Reviewed-by: Krzysztof Kozlowski Signed-off-by: Johan Hovold Link: https://lore.kernel.org/r/20230306075651.2449-15-johan+linaro@kernel.org Signed-off-by: Georgi Djakov --- drivers/interconnect/samsung/exynos.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/interconnect/samsung/exynos.c b/drivers/interconnect/samsung/exynos.c index 6559d8cf8068..e70665899482 100644 --- a/drivers/interconnect/samsung/exynos.c +++ b/drivers/interconnect/samsung/exynos.c @@ -149,6 +149,9 @@ static int exynos_generic_icc_probe(struct platform_device *pdev) &priv->bus_clk_ratio)) priv->bus_clk_ratio = EXYNOS_ICC_DEFAULT_BUS_CLK_RATIO; + icc_node->data = priv; + icc_node_add(icc_node, provider); + /* * Register a PM QoS request for the parent (devfreq) device. */ @@ -157,9 +160,6 @@ static int exynos_generic_icc_probe(struct platform_device *pdev) if (ret < 0) goto err_node_del; - icc_node->data = priv; - icc_node_add(icc_node, provider); - icc_parent_node = exynos_icc_get_parent(bus_dev->of_node); if (IS_ERR(icc_parent_node)) { ret = PTR_ERR(icc_parent_node); -- cgit From c9e46ca612cfbb0cf890f7ae7389b742e90efe64 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 6 Mar 2023 08:56:43 +0100 Subject: interconnect: exynos: fix registration race The current interconnect provider registration interface is inherently racy as nodes are not added until the after adding the provider. This can specifically cause racing DT lookups to trigger a NULL-pointer deference when either a NULL pointer or not fully initialised node is returned from exynos_generic_icc_xlate(). Switch to using the new API where the provider is not registered until after it has been fully initialised. Fixes: 2f95b9d5cf0b ("interconnect: Add generic interconnect driver for Exynos SoCs") Cc: stable@vger.kernel.org # 5.11 Cc: Sylwester Nawrocki Reviewed-by: Krzysztof Kozlowski Signed-off-by: Johan Hovold Link: https://lore.kernel.org/r/20230306075651.2449-16-johan+linaro@kernel.org Signed-off-by: Georgi Djakov --- drivers/interconnect/samsung/exynos.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/interconnect/samsung/exynos.c b/drivers/interconnect/samsung/exynos.c index e70665899482..72e42603823b 100644 --- a/drivers/interconnect/samsung/exynos.c +++ b/drivers/interconnect/samsung/exynos.c @@ -98,12 +98,13 @@ static int exynos_generic_icc_remove(struct platform_device *pdev) struct exynos_icc_priv *priv = platform_get_drvdata(pdev); struct icc_node *parent_node, *node = priv->node; + icc_provider_deregister(&priv->provider); + parent_node = exynos_icc_get_parent(priv->dev->parent->of_node); if (parent_node && !IS_ERR(parent_node)) icc_link_destroy(node, parent_node); icc_nodes_remove(&priv->provider); - icc_provider_del(&priv->provider); return 0; } @@ -132,15 +133,11 @@ static int exynos_generic_icc_probe(struct platform_device *pdev) provider->inter_set = true; provider->data = priv; - ret = icc_provider_add(provider); - if (ret < 0) - return ret; + icc_provider_init(provider); icc_node = icc_node_create(pdev->id); - if (IS_ERR(icc_node)) { - ret = PTR_ERR(icc_node); - goto err_prov_del; - } + if (IS_ERR(icc_node)) + return PTR_ERR(icc_node); priv->node = icc_node; icc_node->name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%pOFn", @@ -171,14 +168,17 @@ static int exynos_generic_icc_probe(struct platform_device *pdev) goto err_pmqos_del; } + ret = icc_provider_register(provider); + if (ret < 0) + goto err_pmqos_del; + return 0; err_pmqos_del: dev_pm_qos_remove_request(&priv->qos_req); err_node_del: icc_nodes_remove(provider); -err_prov_del: - icc_provider_del(provider); + return ret; } -- cgit From 859ad5f177efa59f6b8a2fac20561ca5cb13c89f Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 6 Mar 2023 08:56:44 +0100 Subject: interconnect: exynos: drop redundant link destroy There is no longer any need to explicitly destroy node links as this is now done when the node is destroyed as part of icc_nodes_remove(). Reviewed-by: Krzysztof Kozlowski Signed-off-by: Johan Hovold Link: https://lore.kernel.org/r/20230306075651.2449-17-johan+linaro@kernel.org Signed-off-by: Georgi Djakov --- drivers/interconnect/samsung/exynos.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/interconnect/samsung/exynos.c b/drivers/interconnect/samsung/exynos.c index 72e42603823b..ebf09bbf725b 100644 --- a/drivers/interconnect/samsung/exynos.c +++ b/drivers/interconnect/samsung/exynos.c @@ -96,14 +96,8 @@ static struct icc_node *exynos_generic_icc_xlate(struct of_phandle_args *spec, static int exynos_generic_icc_remove(struct platform_device *pdev) { struct exynos_icc_priv *priv = platform_get_drvdata(pdev); - struct icc_node *parent_node, *node = priv->node; icc_provider_deregister(&priv->provider); - - parent_node = exynos_icc_get_parent(priv->dev->parent->of_node); - if (parent_node && !IS_ERR(parent_node)) - icc_link_destroy(node, parent_node); - icc_nodes_remove(&priv->provider); return 0; -- cgit From 5553055c62683ce339f9ef5fb2a26c8331485d68 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 6 Mar 2023 08:56:45 +0100 Subject: memory: tegra: fix interconnect registration race The current interconnect provider registration interface is inherently racy as nodes are not added until the after adding the provider. This can specifically cause racing DT lookups to fail. Switch to using the new API where the provider is not registered until after it has been fully initialised. Fixes: 06f079816d4c ("memory: tegra-mc: Add interconnect framework") Cc: stable@vger.kernel.org # 5.11 Cc: Dmitry Osipenko Acked-by: Krzysztof Kozlowski Signed-off-by: Johan Hovold Link: https://lore.kernel.org/r/20230306075651.2449-18-johan+linaro@kernel.org Signed-off-by: Georgi Djakov --- drivers/memory/tegra/mc.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/drivers/memory/tegra/mc.c b/drivers/memory/tegra/mc.c index 592907546ee6..5cd28619ea9f 100644 --- a/drivers/memory/tegra/mc.c +++ b/drivers/memory/tegra/mc.c @@ -794,16 +794,12 @@ static int tegra_mc_interconnect_setup(struct tegra_mc *mc) mc->provider.aggregate = mc->soc->icc_ops->aggregate; mc->provider.xlate_extended = mc->soc->icc_ops->xlate_extended; - err = icc_provider_add(&mc->provider); - if (err) - return err; + icc_provider_init(&mc->provider); /* create Memory Controller node */ node = icc_node_create(TEGRA_ICC_MC); - if (IS_ERR(node)) { - err = PTR_ERR(node); - goto del_provider; - } + if (IS_ERR(node)) + return PTR_ERR(node); node->name = "Memory Controller"; icc_node_add(node, &mc->provider); @@ -830,12 +826,14 @@ static int tegra_mc_interconnect_setup(struct tegra_mc *mc) goto remove_nodes; } + err = icc_provider_register(&mc->provider); + if (err) + goto remove_nodes; + return 0; remove_nodes: icc_nodes_remove(&mc->provider); -del_provider: - icc_provider_del(&mc->provider); return err; } -- cgit From abd9f1b49cf25eebeaba193c7707355be3f48dae Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 6 Mar 2023 08:56:46 +0100 Subject: memory: tegra124-emc: fix interconnect registration race The current interconnect provider registration interface is inherently racy as nodes are not added until the after adding the provider. This can specifically cause racing DT lookups to fail. Switch to using the new API where the provider is not registered until after it has been fully initialised. Fixes: 380def2d4cf2 ("memory: tegra124: Support interconnect framework") Cc: stable@vger.kernel.org # 5.12 Cc: Dmitry Osipenko Acked-by: Krzysztof Kozlowski Signed-off-by: Johan Hovold Link: https://lore.kernel.org/r/20230306075651.2449-19-johan+linaro@kernel.org Signed-off-by: Georgi Djakov --- drivers/memory/tegra/tegra124-emc.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/memory/tegra/tegra124-emc.c b/drivers/memory/tegra/tegra124-emc.c index 85bc936c02f9..00ed2b6a0d1b 100644 --- a/drivers/memory/tegra/tegra124-emc.c +++ b/drivers/memory/tegra/tegra124-emc.c @@ -1351,15 +1351,13 @@ static int tegra_emc_interconnect_init(struct tegra_emc *emc) emc->provider.aggregate = soc->icc_ops->aggregate; emc->provider.xlate_extended = emc_of_icc_xlate_extended; - err = icc_provider_add(&emc->provider); - if (err) - goto err_msg; + icc_provider_init(&emc->provider); /* create External Memory Controller node */ node = icc_node_create(TEGRA_ICC_EMC); if (IS_ERR(node)) { err = PTR_ERR(node); - goto del_provider; + goto err_msg; } node->name = "External Memory Controller"; @@ -1380,12 +1378,14 @@ static int tegra_emc_interconnect_init(struct tegra_emc *emc) node->name = "External Memory (DRAM)"; icc_node_add(node, &emc->provider); + err = icc_provider_register(&emc->provider); + if (err) + goto remove_nodes; + return 0; remove_nodes: icc_nodes_remove(&emc->provider); -del_provider: - icc_provider_del(&emc->provider); err_msg: dev_err(emc->dev, "failed to initialize ICC: %d\n", err); -- cgit From c5587f61ec050f7e9ebb3e2da29d12af63e833d3 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 6 Mar 2023 08:56:47 +0100 Subject: memory: tegra20-emc: fix interconnect registration race The current interconnect provider registration interface is inherently racy as nodes are not added until the after adding the provider. This can specifically cause racing DT lookups to fail. Switch to using the new API where the provider is not registered until after it has been fully initialised. Fixes: d5ef16ba5fbe ("memory: tegra20: Support interconnect framework") Cc: stable@vger.kernel.org # 5.11 Cc: Dmitry Osipenko Acked-by: Krzysztof Kozlowski Signed-off-by: Johan Hovold Link: https://lore.kernel.org/r/20230306075651.2449-20-johan+linaro@kernel.org Signed-off-by: Georgi Djakov --- drivers/memory/tegra/tegra20-emc.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/memory/tegra/tegra20-emc.c b/drivers/memory/tegra/tegra20-emc.c index bd4e37b6552d..fd595c851a27 100644 --- a/drivers/memory/tegra/tegra20-emc.c +++ b/drivers/memory/tegra/tegra20-emc.c @@ -1021,15 +1021,13 @@ static int tegra_emc_interconnect_init(struct tegra_emc *emc) emc->provider.aggregate = soc->icc_ops->aggregate; emc->provider.xlate_extended = emc_of_icc_xlate_extended; - err = icc_provider_add(&emc->provider); - if (err) - goto err_msg; + icc_provider_init(&emc->provider); /* create External Memory Controller node */ node = icc_node_create(TEGRA_ICC_EMC); if (IS_ERR(node)) { err = PTR_ERR(node); - goto del_provider; + goto err_msg; } node->name = "External Memory Controller"; @@ -1050,12 +1048,14 @@ static int tegra_emc_interconnect_init(struct tegra_emc *emc) node->name = "External Memory (DRAM)"; icc_node_add(node, &emc->provider); + err = icc_provider_register(&emc->provider); + if (err) + goto remove_nodes; + return 0; remove_nodes: icc_nodes_remove(&emc->provider); -del_provider: - icc_provider_del(&emc->provider); err_msg: dev_err(emc->dev, "failed to initialize ICC: %d\n", err); -- cgit From 9db481c909dd6312ccfbdc7e343b50e41c727483 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 6 Mar 2023 08:56:48 +0100 Subject: memory: tegra30-emc: fix interconnect registration race The current interconnect provider registration interface is inherently racy as nodes are not added until the after adding the provider. This can specifically cause racing DT lookups to fail. Switch to using the new API where the provider is not registered until after it has been fully initialised. Fixes: d5ef16ba5fbe ("memory: tegra20: Support interconnect framework") Cc: stable@vger.kernel.org # 5.11 Cc: Dmitry Osipenko Acked-by: Krzysztof Kozlowski Signed-off-by: Johan Hovold Link: https://lore.kernel.org/r/20230306075651.2449-21-johan+linaro@kernel.org Signed-off-by: Georgi Djakov --- drivers/memory/tegra/tegra30-emc.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/memory/tegra/tegra30-emc.c b/drivers/memory/tegra/tegra30-emc.c index 77706e9bc543..c91e9b7e2e01 100644 --- a/drivers/memory/tegra/tegra30-emc.c +++ b/drivers/memory/tegra/tegra30-emc.c @@ -1533,15 +1533,13 @@ static int tegra_emc_interconnect_init(struct tegra_emc *emc) emc->provider.aggregate = soc->icc_ops->aggregate; emc->provider.xlate_extended = emc_of_icc_xlate_extended; - err = icc_provider_add(&emc->provider); - if (err) - goto err_msg; + icc_provider_init(&emc->provider); /* create External Memory Controller node */ node = icc_node_create(TEGRA_ICC_EMC); if (IS_ERR(node)) { err = PTR_ERR(node); - goto del_provider; + goto err_msg; } node->name = "External Memory Controller"; @@ -1562,12 +1560,14 @@ static int tegra_emc_interconnect_init(struct tegra_emc *emc) node->name = "External Memory (DRAM)"; icc_node_add(node, &emc->provider); + err = icc_provider_register(&emc->provider); + if (err) + goto remove_nodes; + return 0; remove_nodes: icc_nodes_remove(&emc->provider); -del_provider: - icc_provider_del(&emc->provider); err_msg: dev_err(emc->dev, "failed to initialize ICC: %d\n", err); -- cgit From ccb820dc7d2236b1af0d54ae038a27b5b6d5ae5a Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 13 Mar 2023 15:12:29 -0700 Subject: fscrypt: destroy keyring after security_sb_delete() fscrypt_destroy_keyring() must be called after all potentially-encrypted inodes were evicted; otherwise it cannot safely destroy the keyring. Since inodes that are in-use by the Landlock LSM don't get evicted until security_sb_delete(), this means that fscrypt_destroy_keyring() must be called *after* security_sb_delete(). This fixes a WARN_ON followed by a NULL dereference, only possible if Landlock was being used on encrypted files. Fixes: d7e7b9af104c ("fscrypt: stop using keyrings subsystem for fscrypt_master_key") Cc: stable@vger.kernel.org Reported-by: syzbot+93e495f6a4f748827c88@syzkaller.appspotmail.com Link: https://lore.kernel.org/r/00000000000044651705f6ca1e30@google.com Reviewed-by: Christian Brauner Link: https://lore.kernel.org/r/20230313221231.272498-2-ebiggers@kernel.org Signed-off-by: Eric Biggers --- fs/super.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/fs/super.c b/fs/super.c index 84332d5cb817..04bc62ab7dfe 100644 --- a/fs/super.c +++ b/fs/super.c @@ -475,13 +475,22 @@ void generic_shutdown_super(struct super_block *sb) cgroup_writeback_umount(); - /* evict all inodes with zero refcount */ + /* Evict all inodes with zero refcount. */ evict_inodes(sb); - /* only nonzero refcount inodes can have marks */ + + /* + * Clean up and evict any inodes that still have references due + * to fsnotify or the security policy. + */ fsnotify_sb_delete(sb); - fscrypt_destroy_keyring(sb); security_sb_delete(sb); + /* + * Now that all potentially-encrypted inodes have been evicted, + * the fscrypt keyring can be destroyed. + */ + fscrypt_destroy_keyring(sb); + if (sb->s_dio_done_wq) { destroy_workqueue(sb->s_dio_done_wq); sb->s_dio_done_wq = NULL; -- cgit From 9c88ea00fef03031ce6554531e89be82f6a42835 Mon Sep 17 00:00:00 2001 From: Dave Wysochanski Date: Thu, 9 Mar 2023 13:58:52 -0500 Subject: NFS: Fix /proc/PID/io read_bytes for buffered reads Prior to commit 8786fde8421c ("Convert NFS from readpages to readahead"), nfs_readpages() used the old mm interface read_cache_pages() which called task_io_account_read() for each NFS page read. After this commit, nfs_readpages() is converted to nfs_readahead(), which now uses the new mm interface readahead_page(). The new interface requires callers to call task_io_account_read() themselves. In addition, to nfs_readahead() task_io_account_read() should also be called from nfs_read_folio(). Fixes: 8786fde8421c ("Convert NFS from readpages to readahead") Link: https://lore.kernel.org/linux-nfs/CAPt2mGNEYUk5u8V4abe=5MM5msZqmvzCVrtCP4Qw1n=gCHCnww@mail.gmail.com/ Signed-off-by: Dave Wysochanski Signed-off-by: Anna Schumaker --- fs/nfs/read.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fs/nfs/read.c b/fs/nfs/read.c index c380cff4108e..e90988591df4 100644 --- a/fs/nfs/read.c +++ b/fs/nfs/read.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -337,6 +338,7 @@ int nfs_read_folio(struct file *file, struct folio *folio) trace_nfs_aop_readpage(inode, folio); nfs_inc_stats(inode, NFSIOS_VFSREADPAGE); + task_io_account_read(folio_size(folio)); /* * Try to flush any pending writes to the file.. @@ -393,6 +395,7 @@ void nfs_readahead(struct readahead_control *ractl) trace_nfs_aop_readahead(inode, readahead_pos(ractl), nr_pages); nfs_inc_stats(inode, NFSIOS_VFSREADPAGES); + task_io_account_read(readahead_length(ractl)); ret = -ESTALE; if (NFS_STALE(inode)) -- cgit From 044b14b51d78a549664efac3a5a4c9edd1211b79 Mon Sep 17 00:00:00 2001 From: Nikita Romanyuk Date: Sat, 25 Feb 2023 10:12:28 +0300 Subject: drivers: video: logo: fix code style issues in pnmtologo.c Signed-off-by: Nikita Romanyuk Signed-off-by: Helge Deller --- drivers/video/logo/pnmtologo.c | 667 +++++++++++++++++++++-------------------- 1 file changed, 334 insertions(+), 333 deletions(-) diff --git a/drivers/video/logo/pnmtologo.c b/drivers/video/logo/pnmtologo.c index 4718d7895f0b..78cb95f3cfce 100644 --- a/drivers/video/logo/pnmtologo.c +++ b/drivers/video/logo/pnmtologo.c @@ -1,4 +1,3 @@ - /* * Convert a logo in ASCII PNM format to C source suitable for inclusion in * the Linux kernel @@ -34,37 +33,37 @@ static FILE *out; #define LINUX_LOGO_GRAY256 4 /* 256 levels grayscale */ static const char *logo_types[LINUX_LOGO_GRAY256+1] = { - [LINUX_LOGO_MONO] = "LINUX_LOGO_MONO", - [LINUX_LOGO_VGA16] = "LINUX_LOGO_VGA16", - [LINUX_LOGO_CLUT224] = "LINUX_LOGO_CLUT224", - [LINUX_LOGO_GRAY256] = "LINUX_LOGO_GRAY256" + [LINUX_LOGO_MONO] = "LINUX_LOGO_MONO", + [LINUX_LOGO_VGA16] = "LINUX_LOGO_VGA16", + [LINUX_LOGO_CLUT224] = "LINUX_LOGO_CLUT224", + [LINUX_LOGO_GRAY256] = "LINUX_LOGO_GRAY256" }; #define MAX_LINUX_LOGO_COLORS 224 struct color { - unsigned char red; - unsigned char green; - unsigned char blue; + unsigned char red; + unsigned char green; + unsigned char blue; }; static const struct color clut_vga16[16] = { - { 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0xaa }, - { 0x00, 0xaa, 0x00 }, - { 0x00, 0xaa, 0xaa }, - { 0xaa, 0x00, 0x00 }, - { 0xaa, 0x00, 0xaa }, - { 0xaa, 0x55, 0x00 }, - { 0xaa, 0xaa, 0xaa }, - { 0x55, 0x55, 0x55 }, - { 0x55, 0x55, 0xff }, - { 0x55, 0xff, 0x55 }, - { 0x55, 0xff, 0xff }, - { 0xff, 0x55, 0x55 }, - { 0xff, 0x55, 0xff }, - { 0xff, 0xff, 0x55 }, - { 0xff, 0xff, 0xff }, + { 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0xaa }, + { 0x00, 0xaa, 0x00 }, + { 0x00, 0xaa, 0xaa }, + { 0xaa, 0x00, 0x00 }, + { 0xaa, 0x00, 0xaa }, + { 0xaa, 0x55, 0x00 }, + { 0xaa, 0xaa, 0xaa }, + { 0x55, 0x55, 0x55 }, + { 0x55, 0x55, 0xff }, + { 0x55, 0xff, 0x55 }, + { 0x55, 0xff, 0xff }, + { 0xff, 0x55, 0x55 }, + { 0xff, 0x55, 0xff }, + { 0xff, 0xff, 0x55 }, + { 0xff, 0xff, 0xff }, }; @@ -77,438 +76,440 @@ static unsigned int logo_clutsize; static int is_plain_pbm = 0; static void die(const char *fmt, ...) - __attribute__ ((noreturn)) __attribute ((format (printf, 1, 2))); -static void usage(void) __attribute ((noreturn)); +__attribute__((noreturn)) __attribute((format (printf, 1, 2))); +static void usage(void) __attribute((noreturn)); static unsigned int get_number(FILE *fp) { - int c, val; - - /* Skip leading whitespace */ - do { - c = fgetc(fp); - if (c == EOF) - die("%s: end of file\n", filename); - if (c == '#') { - /* Ignore comments 'till end of line */ - do { + int c, val; + + /* Skip leading whitespace */ + do { + c = fgetc(fp); + if (c == EOF) + die("%s: end of file\n", filename); + if (c == '#') { + /* Ignore comments 'till end of line */ + do { + c = fgetc(fp); + if (c == EOF) + die("%s: end of file\n", filename); + } while (c != '\n'); + } + } while (isspace(c)); + + /* Parse decimal number */ + val = 0; + while (isdigit(c)) { + val = 10*val+c-'0'; + /* some PBM are 'broken'; GiMP for example exports a PBM without space + * between the digits. This is Ok cause we know a PBM can only have a '1' + * or a '0' for the digit. + */ + if (is_plain_pbm) + break; c = fgetc(fp); if (c == EOF) - die("%s: end of file\n", filename); - } while (c != '\n'); + die("%s: end of file\n", filename); } - } while (isspace(c)); - - /* Parse decimal number */ - val = 0; - while (isdigit(c)) { - val = 10*val+c-'0'; - /* some PBM are 'broken'; GiMP for example exports a PBM without space - * between the digits. This is Ok cause we know a PBM can only have a '1' - * or a '0' for the digit. */ - if (is_plain_pbm) - break; - c = fgetc(fp); - if (c == EOF) - die("%s: end of file\n", filename); - } - return val; + return val; } static unsigned int get_number255(FILE *fp, unsigned int maxval) { - unsigned int val = get_number(fp); - return (255*val+maxval/2)/maxval; + unsigned int val = get_number(fp); + + return (255*val+maxval/2)/maxval; } static void read_image(void) { - FILE *fp; - unsigned int i, j; - int magic; - unsigned int maxval; - - /* open image file */ - fp = fopen(filename, "r"); - if (!fp) - die("Cannot open file %s: %s\n", filename, strerror(errno)); - - /* check file type and read file header */ - magic = fgetc(fp); - if (magic != 'P') - die("%s is not a PNM file\n", filename); - magic = fgetc(fp); - switch (magic) { + FILE *fp; + unsigned int i, j; + int magic; + unsigned int maxval; + + /* open image file */ + fp = fopen(filename, "r"); + if (!fp) + die("Cannot open file %s: %s\n", filename, strerror(errno)); + + /* check file type and read file header */ + magic = fgetc(fp); + if (magic != 'P') + die("%s is not a PNM file\n", filename); + magic = fgetc(fp); + switch (magic) { case '1': case '2': case '3': - /* Plain PBM/PGM/PPM */ - break; + /* Plain PBM/PGM/PPM */ + break; case '4': case '5': case '6': - /* Binary PBM/PGM/PPM */ - die("%s: Binary PNM is not supported\n" + /* Binary PBM/PGM/PPM */ + die("%s: Binary PNM is not supported\n" "Use pnmnoraw(1) to convert it to ASCII PNM\n", filename); default: - die("%s is not a PNM file\n", filename); - } - logo_width = get_number(fp); - logo_height = get_number(fp); - - /* allocate image data */ - logo_data = (struct color **)malloc(logo_height*sizeof(struct color *)); - if (!logo_data) - die("%s\n", strerror(errno)); - for (i = 0; i < logo_height; i++) { - logo_data[i] = malloc(logo_width*sizeof(struct color)); + die("%s is not a PNM file\n", filename); + } + logo_width = get_number(fp); + logo_height = get_number(fp); + + /* allocate image data */ + logo_data = (struct color **)malloc(logo_height*sizeof(struct color *)); + if (!logo_data) + die("%s\n", strerror(errno)); + for (i = 0; i < logo_height; i++) { + logo_data[i] = malloc(logo_width*sizeof(struct color)); if (!logo_data[i]) - die("%s\n", strerror(errno)); - } + die("%s\n", strerror(errno)); + } - /* read image data */ - switch (magic) { + /* read image data */ + switch (magic) { case '1': - /* Plain PBM */ - is_plain_pbm = 1; - for (i = 0; i < logo_height; i++) - for (j = 0; j < logo_width; j++) - logo_data[i][j].red = logo_data[i][j].green = - logo_data[i][j].blue = 255*(1-get_number(fp)); - break; + /* Plain PBM */ + is_plain_pbm = 1; + for (i = 0; i < logo_height; i++) + for (j = 0; j < logo_width; j++) + logo_data[i][j].red = logo_data[i][j].green = + logo_data[i][j].blue = 255*(1-get_number(fp)); + break; case '2': - /* Plain PGM */ - maxval = get_number(fp); - for (i = 0; i < logo_height; i++) - for (j = 0; j < logo_width; j++) - logo_data[i][j].red = logo_data[i][j].green = - logo_data[i][j].blue = get_number255(fp, maxval); - break; + /* Plain PGM */ + maxval = get_number(fp); + for (i = 0; i < logo_height; i++) + for (j = 0; j < logo_width; j++) + logo_data[i][j].red = logo_data[i][j].green = + logo_data[i][j].blue = get_number255(fp, maxval); + break; case '3': - /* Plain PPM */ - maxval = get_number(fp); - for (i = 0; i < logo_height; i++) - for (j = 0; j < logo_width; j++) { - logo_data[i][j].red = get_number255(fp, maxval); - logo_data[i][j].green = get_number255(fp, maxval); - logo_data[i][j].blue = get_number255(fp, maxval); - } - break; - } + /* Plain PPM */ + maxval = get_number(fp); + for (i = 0; i < logo_height; i++) + for (j = 0; j < logo_width; j++) { + logo_data[i][j].red = get_number255(fp, maxval); + logo_data[i][j].green = get_number255(fp, maxval); + logo_data[i][j].blue = get_number255(fp, maxval); + } + break; + } - /* close file */ - fclose(fp); + /* close file */ + fclose(fp); } static inline int is_black(struct color c) { - return c.red == 0 && c.green == 0 && c.blue == 0; + return c.red == 0 && c.green == 0 && c.blue == 0; } static inline int is_white(struct color c) { - return c.red == 255 && c.green == 255 && c.blue == 255; + return c.red == 255 && c.green == 255 && c.blue == 255; } static inline int is_gray(struct color c) { - return c.red == c.green && c.red == c.blue; + return c.red == c.green && c.red == c.blue; } static inline int is_equal(struct color c1, struct color c2) { - return c1.red == c2.red && c1.green == c2.green && c1.blue == c2.blue; + return c1.red == c2.red && c1.green == c2.green && c1.blue == c2.blue; } static void write_header(void) { - /* open logo file */ - if (outputname) { - out = fopen(outputname, "w"); - if (!out) - die("Cannot create file %s: %s\n", outputname, strerror(errno)); - } else { - out = stdout; - } - - fputs("/*\n", out); - fputs(" * DO NOT EDIT THIS FILE!\n", out); - fputs(" *\n", out); - fprintf(out, " * It was automatically generated from %s\n", filename); - fputs(" *\n", out); - fprintf(out, " * Linux logo %s\n", logoname); - fputs(" */\n\n", out); - fputs("#include \n\n", out); - fprintf(out, "static unsigned char %s_data[] __initdata = {\n", - logoname); + /* open logo file */ + if (outputname) { + out = fopen(outputname, "w"); + if (!out) + die("Cannot create file %s: %s\n", outputname, strerror(errno)); + } else { + out = stdout; + } + + fputs("/*\n", out); + fputs(" * DO NOT EDIT THIS FILE!\n", out); + fputs(" *\n", out); + fprintf(out, " * It was automatically generated from %s\n", filename); + fputs(" *\n", out); + fprintf(out, " * Linux logo %s\n", logoname); + fputs(" */\n\n", out); + fputs("#include \n\n", out); + fprintf(out, "static unsigned char %s_data[] __initdata = {\n", + logoname); } static void write_footer(void) { - fputs("\n};\n\n", out); - fprintf(out, "const struct linux_logo %s __initconst = {\n", logoname); - fprintf(out, "\t.type\t\t= %s,\n", logo_types[logo_type]); - fprintf(out, "\t.width\t\t= %d,\n", logo_width); - fprintf(out, "\t.height\t\t= %d,\n", logo_height); - if (logo_type == LINUX_LOGO_CLUT224) { - fprintf(out, "\t.clutsize\t= %d,\n", logo_clutsize); - fprintf(out, "\t.clut\t\t= %s_clut,\n", logoname); - } - fprintf(out, "\t.data\t\t= %s_data\n", logoname); - fputs("};\n\n", out); - - /* close logo file */ - if (outputname) - fclose(out); + fputs("\n};\n\n", out); + fprintf(out, "const struct linux_logo %s __initconst = {\n", logoname); + fprintf(out, "\t.type\t\t= %s,\n", logo_types[logo_type]); + fprintf(out, "\t.width\t\t= %d,\n", logo_width); + fprintf(out, "\t.height\t\t= %d,\n", logo_height); + if (logo_type == LINUX_LOGO_CLUT224) { + fprintf(out, "\t.clutsize\t= %d,\n", logo_clutsize); + fprintf(out, "\t.clut\t\t= %s_clut,\n", logoname); + } + fprintf(out, "\t.data\t\t= %s_data\n", logoname); + fputs("};\n\n", out); + + /* close logo file */ + if (outputname) + fclose(out); } static int write_hex_cnt; static void write_hex(unsigned char byte) { - if (write_hex_cnt % 12) - fprintf(out, ", 0x%02x", byte); - else if (write_hex_cnt) - fprintf(out, ",\n\t0x%02x", byte); - else - fprintf(out, "\t0x%02x", byte); - write_hex_cnt++; + if (write_hex_cnt % 12) + fprintf(out, ", 0x%02x", byte); + else if (write_hex_cnt) + fprintf(out, ",\n\t0x%02x", byte); + else + fprintf(out, "\t0x%02x", byte); + write_hex_cnt++; } static void write_logo_mono(void) { - unsigned int i, j; - unsigned char val, bit; - - /* validate image */ - for (i = 0; i < logo_height; i++) - for (j = 0; j < logo_width; j++) - if (!is_black(logo_data[i][j]) && !is_white(logo_data[i][j])) - die("Image must be monochrome\n"); - - /* write file header */ - write_header(); - - /* write logo data */ - for (i = 0; i < logo_height; i++) { - for (j = 0; j < logo_width;) { - for (val = 0, bit = 0x80; bit && j < logo_width; j++, bit >>= 1) - if (logo_data[i][j].red) - val |= bit; - write_hex(val); + unsigned int i, j; + unsigned char val, bit; + + /* validate image */ + for (i = 0; i < logo_height; i++) + for (j = 0; j < logo_width; j++) + if (!is_black(logo_data[i][j]) && !is_white(logo_data[i][j])) + die("Image must be monochrome\n"); + + /* write file header */ + write_header(); + + /* write logo data */ + for (i = 0; i < logo_height; i++) { + for (j = 0; j < logo_width;) { + for (val = 0, bit = 0x80; bit && j < logo_width; j++, bit >>= 1) + if (logo_data[i][j].red) + val |= bit; + write_hex(val); + } } - } - /* write logo structure and file footer */ - write_footer(); + /* write logo structure and file footer */ + write_footer(); } static void write_logo_vga16(void) { - unsigned int i, j, k; - unsigned char val; - - /* validate image */ - for (i = 0; i < logo_height; i++) - for (j = 0; j < logo_width; j++) { - for (k = 0; k < 16; k++) - if (is_equal(logo_data[i][j], clut_vga16[k])) - break; - if (k == 16) - die("Image must use the 16 console colors only\n" - "Use ppmquant(1) -map clut_vga16.ppm to reduce the number " - "of colors\n"); - } + unsigned int i, j, k; + unsigned char val; - /* write file header */ - write_header(); - - /* write logo data */ - for (i = 0; i < logo_height; i++) - for (j = 0; j < logo_width; j++) { - for (k = 0; k < 16; k++) - if (is_equal(logo_data[i][j], clut_vga16[k])) - break; - val = k<<4; - if (++j < logo_width) { - for (k = 0; k < 16; k++) - if (is_equal(logo_data[i][j], clut_vga16[k])) - break; - val |= k; - } - write_hex(val); - } + /* validate image */ + for (i = 0; i < logo_height; i++) + for (j = 0; j < logo_width; j++) { + for (k = 0; k < 16; k++) + if (is_equal(logo_data[i][j], clut_vga16[k])) + break; + if (k == 16) + die("Image must use the 16 console colors only\n" + "Use ppmquant(1) -map clut_vga16.ppm to reduce the number " + "of colors\n"); + } + + /* write file header */ + write_header(); - /* write logo structure and file footer */ - write_footer(); + /* write logo data */ + for (i = 0; i < logo_height; i++) + for (j = 0; j < logo_width; j++) { + for (k = 0; k < 16; k++) + if (is_equal(logo_data[i][j], clut_vga16[k])) + break; + val = k<<4; + if (++j < logo_width) { + for (k = 0; k < 16; k++) + if (is_equal(logo_data[i][j], clut_vga16[k])) + break; + val |= k; + } + write_hex(val); + } + + /* write logo structure and file footer */ + write_footer(); } static void write_logo_clut224(void) { - unsigned int i, j, k; - - /* validate image */ - for (i = 0; i < logo_height; i++) - for (j = 0; j < logo_width; j++) { - for (k = 0; k < logo_clutsize; k++) - if (is_equal(logo_data[i][j], logo_clut[k])) - break; - if (k == logo_clutsize) { - if (logo_clutsize == MAX_LINUX_LOGO_COLORS) - die("Image has more than %d colors\n" - "Use ppmquant(1) to reduce the number of colors\n", - MAX_LINUX_LOGO_COLORS); - logo_clut[logo_clutsize++] = logo_data[i][j]; - } - } + unsigned int i, j, k; - /* write file header */ - write_header(); + /* validate image */ + for (i = 0; i < logo_height; i++) + for (j = 0; j < logo_width; j++) { + for (k = 0; k < logo_clutsize; k++) + if (is_equal(logo_data[i][j], logo_clut[k])) + break; + if (k == logo_clutsize) { + if (logo_clutsize == MAX_LINUX_LOGO_COLORS) + die("Image has more than %d colors\n" + "Use ppmquant(1) to reduce the number of colors\n", + MAX_LINUX_LOGO_COLORS); + logo_clut[logo_clutsize++] = logo_data[i][j]; + } + } - /* write logo data */ - for (i = 0; i < logo_height; i++) - for (j = 0; j < logo_width; j++) { - for (k = 0; k < logo_clutsize; k++) - if (is_equal(logo_data[i][j], logo_clut[k])) - break; - write_hex(k+32); + /* write file header */ + write_header(); + + /* write logo data */ + for (i = 0; i < logo_height; i++) + for (j = 0; j < logo_width; j++) { + for (k = 0; k < logo_clutsize; k++) + if (is_equal(logo_data[i][j], logo_clut[k])) + break; + write_hex(k+32); + } + fputs("\n};\n\n", out); + + /* write logo clut */ + fprintf(out, "static unsigned char %s_clut[] __initdata = {\n", + logoname); + write_hex_cnt = 0; + for (i = 0; i < logo_clutsize; i++) { + write_hex(logo_clut[i].red); + write_hex(logo_clut[i].green); + write_hex(logo_clut[i].blue); } - fputs("\n};\n\n", out); - - /* write logo clut */ - fprintf(out, "static unsigned char %s_clut[] __initdata = {\n", - logoname); - write_hex_cnt = 0; - for (i = 0; i < logo_clutsize; i++) { - write_hex(logo_clut[i].red); - write_hex(logo_clut[i].green); - write_hex(logo_clut[i].blue); - } - - /* write logo structure and file footer */ - write_footer(); + + /* write logo structure and file footer */ + write_footer(); } static void write_logo_gray256(void) { - unsigned int i, j; + unsigned int i, j; - /* validate image */ - for (i = 0; i < logo_height; i++) - for (j = 0; j < logo_width; j++) - if (!is_gray(logo_data[i][j])) - die("Image must be grayscale\n"); + /* validate image */ + for (i = 0; i < logo_height; i++) + for (j = 0; j < logo_width; j++) + if (!is_gray(logo_data[i][j])) + die("Image must be grayscale\n"); - /* write file header */ - write_header(); + /* write file header */ + write_header(); - /* write logo data */ - for (i = 0; i < logo_height; i++) - for (j = 0; j < logo_width; j++) - write_hex(logo_data[i][j].red); + /* write logo data */ + for (i = 0; i < logo_height; i++) + for (j = 0; j < logo_width; j++) + write_hex(logo_data[i][j].red); - /* write logo structure and file footer */ - write_footer(); + /* write logo structure and file footer */ + write_footer(); } static void die(const char *fmt, ...) { - va_list ap; + va_list ap; - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); - exit(1); + exit(1); } static void usage(void) { - die("\n" + die("\n" "Usage: %s [options] \n" "\n" "Valid options:\n" - " -h : display this usage information\n" - " -n : specify logo name (default: linux_logo)\n" - " -o : output to file instead of stdout\n" - " -t : specify logo type, one of\n" - " mono : monochrome black/white\n" - " vga16 : 16 colors VGA text palette\n" - " clut224 : 224 colors (default)\n" - " gray256 : 256 levels grayscale\n" + " -h : display this usage information\n" + " -n : specify logo name (default: linux_logo)\n" + " -o : output to file instead of stdout\n" + " -t : specify logo type, one of\n" + " mono : monochrome black/white\n" + " vga16 : 16 colors VGA text palette\n" + " clut224 : 224 colors (default)\n" + " gray256 : 256 levels grayscale\n" "\n", programname); } int main(int argc, char *argv[]) { - int opt; + int opt; - programname = argv[0]; + programname = argv[0]; - opterr = 0; - while (1) { - opt = getopt(argc, argv, "hn:o:t:"); - if (opt == -1) - break; + opterr = 0; + while (1) { + opt = getopt(argc, argv, "hn:o:t:"); + if (opt == -1) + break; - switch (opt) { - case 'h': - usage(); - break; + switch (opt) { + case 'h': + usage(); + break; - case 'n': - logoname = optarg; - break; + case 'n': + logoname = optarg; + break; - case 'o': - outputname = optarg; - break; + case 'o': + outputname = optarg; + break; - case 't': - if (!strcmp(optarg, "mono")) - logo_type = LINUX_LOGO_MONO; - else if (!strcmp(optarg, "vga16")) - logo_type = LINUX_LOGO_VGA16; - else if (!strcmp(optarg, "clut224")) - logo_type = LINUX_LOGO_CLUT224; - else if (!strcmp(optarg, "gray256")) - logo_type = LINUX_LOGO_GRAY256; - else - usage(); - break; + case 't': + if (!strcmp(optarg, "mono")) + logo_type = LINUX_LOGO_MONO; + else if (!strcmp(optarg, "vga16")) + logo_type = LINUX_LOGO_VGA16; + else if (!strcmp(optarg, "clut224")) + logo_type = LINUX_LOGO_CLUT224; + else if (!strcmp(optarg, "gray256")) + logo_type = LINUX_LOGO_GRAY256; + else + usage(); + break; - default: - usage(); - break; + default: + usage(); + break; + } } - } - if (optind != argc-1) - usage(); + if (optind != argc-1) + usage(); - filename = argv[optind]; + filename = argv[optind]; - read_image(); - switch (logo_type) { + read_image(); + switch (logo_type) { case LINUX_LOGO_MONO: - write_logo_mono(); - break; + write_logo_mono(); + break; case LINUX_LOGO_VGA16: - write_logo_vga16(); - break; + write_logo_vga16(); + break; case LINUX_LOGO_CLUT224: - write_logo_clut224(); - break; + write_logo_clut224(); + break; case LINUX_LOGO_GRAY256: - write_logo_gray256(); - break; - } - exit(0); + write_logo_gray256(); + break; + } + exit(0); } -- cgit From 8f0e056068f26c0f1121f7f96a6b4515f59160f2 Mon Sep 17 00:00:00 2001 From: Nikita Romanyuk Date: Sat, 25 Feb 2023 10:12:29 +0300 Subject: drivers: video: logo: add SPDX comment, remove GPL notice in pnmtologo.c Signed-off-by: Nikita Romanyuk Reviewed-by: Geert Uytterhoeven Signed-off-by: Helge Deller --- drivers/video/logo/pnmtologo.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/video/logo/pnmtologo.c b/drivers/video/logo/pnmtologo.c index 78cb95f3cfce..ada5ef6e51b7 100644 --- a/drivers/video/logo/pnmtologo.c +++ b/drivers/video/logo/pnmtologo.c @@ -1,14 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Convert a logo in ASCII PNM format to C source suitable for inclusion in * the Linux kernel * * (C) Copyright 2001-2003 by Geert Uytterhoeven - * - * -------------------------------------------------------------------------- - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of the Linux - * distribution for more details. */ #include -- cgit From 7f501aa71da9dc2eaae2b0118a151cad018d33b0 Mon Sep 17 00:00:00 2001 From: Lucy Mielke Date: Tue, 7 Feb 2023 11:06:30 +0100 Subject: fbdev: omapfb: cleanup inconsistent indentation This cleans up the indentation according to the Linux kernel coding style, and should fix the warning created by the kernel test robot. Fixes: 8b08cf2b64f5 ("OMAP: add TI OMAP framebuffer driver") Reported-by: kernel test robot Signed-off-by: Lucy Mielke Signed-off-by: Helge Deller --- drivers/video/fbdev/omap/omapfb_main.c | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/drivers/video/fbdev/omap/omapfb_main.c b/drivers/video/fbdev/omap/omapfb_main.c index 1f3df2055ff0..18736079843d 100644 --- a/drivers/video/fbdev/omap/omapfb_main.c +++ b/drivers/video/fbdev/omap/omapfb_main.c @@ -544,19 +544,25 @@ static int set_fb_var(struct fb_info *fbi, var->yoffset = var->yres_virtual - var->yres; if (plane->color_mode == OMAPFB_COLOR_RGB444) { - var->red.offset = 8; var->red.length = 4; - var->red.msb_right = 0; - var->green.offset = 4; var->green.length = 4; - var->green.msb_right = 0; - var->blue.offset = 0; var->blue.length = 4; - var->blue.msb_right = 0; + var->red.offset = 8; + var->red.length = 4; + var->red.msb_right = 0; + var->green.offset = 4; + var->green.length = 4; + var->green.msb_right = 0; + var->blue.offset = 0; + var->blue.length = 4; + var->blue.msb_right = 0; } else { - var->red.offset = 11; var->red.length = 5; - var->red.msb_right = 0; - var->green.offset = 5; var->green.length = 6; - var->green.msb_right = 0; - var->blue.offset = 0; var->blue.length = 5; - var->blue.msb_right = 0; + var->red.offset = 11; + var->red.length = 5; + var->red.msb_right = 0; + var->green.offset = 5; + var->green.length = 6; + var->green.msb_right = 0; + var->blue.offset = 0; + var->blue.length = 5; + var->blue.msb_right = 0; } var->height = -1; -- cgit From 33bf61c0a1a97e2abff3117751eabad28106a7c5 Mon Sep 17 00:00:00 2001 From: Lukas Bulwahn Date: Wed, 8 Mar 2023 08:19:21 +0100 Subject: MAINTAINERS: orphan SIS FRAMEBUFFER DRIVER This was triggered by the fact that the webpage: http://www.winischhofer.net/linuxsisvga.shtml cannot be reached anymore. Thomas Winischhofer is still reachable at the given email address, but he has not been active since 2005. Mark the SIS FRAMEBUFFER DRIVER as orphan to reflect the current state. Signed-off-by: Lukas Bulwahn Acked-by: Thomas Zimmermann Signed-off-by: Helge Deller --- MAINTAINERS | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index ec57c42ed544..d603402b0810 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -19150,9 +19150,7 @@ W: http://www.brownhat.org/sis900.html F: drivers/net/ethernet/sis/sis900.* SIS FRAMEBUFFER DRIVER -M: Thomas Winischhofer -S: Maintained -W: http://www.winischhofer.net/linuxsisvga.shtml +S: Orphan F: Documentation/fb/sisfb.rst F: drivers/video/fbdev/sis/ F: include/video/sisfb.h -- cgit From f90bd245de82c095187d8c2cabb8b488a39eaecc Mon Sep 17 00:00:00 2001 From: Wei Chen Date: Tue, 7 Mar 2023 13:08:56 +0000 Subject: fbdev: tgafb: Fix potential divide by zero fb_set_var would by called when user invokes ioctl with cmd FBIOPUT_VSCREENINFO. User-provided data would finally reach tgafb_check_var. In case var->pixclock is assigned to zero, divide by zero would occur when checking whether reciprocal of var->pixclock is too high. Similar crashes have happened in other fbdev drivers. There is no check and modification on var->pixclock along the call chain to tgafb_check_var. We believe it could also be triggered in driver tgafb from user site. Signed-off-by: Wei Chen Signed-off-by: Helge Deller --- drivers/video/fbdev/tgafb.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/video/fbdev/tgafb.c b/drivers/video/fbdev/tgafb.c index 14d37c49633c..b44004880f0d 100644 --- a/drivers/video/fbdev/tgafb.c +++ b/drivers/video/fbdev/tgafb.c @@ -173,6 +173,9 @@ tgafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) { struct tga_par *par = (struct tga_par *)info->par; + if (!var->pixclock) + return -EINVAL; + if (par->tga_type == TGA_TYPE_8PLANE) { if (var->bits_per_pixel != 8) return -EINVAL; -- cgit From 7eb1220f4bde36a15b26e8f54480406c72081bfa Mon Sep 17 00:00:00 2001 From: Yang Li Date: Wed, 8 Mar 2023 13:49:50 +0800 Subject: fbdev: clps711x-fb: Use devm_platform_get_and_ioremap_resource() According to commit 890cc39a8799 ("drivers: provide devm_platform_get_and_ioremap_resource()"), convert platform_get_resource(), devm_ioremap_resource() to a single call to devm_platform_get_and_ioremap_resource(), as this is exactly what this function does. Signed-off-by: Yang Li Signed-off-by: Helge Deller --- drivers/video/fbdev/clps711x-fb.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/video/fbdev/clps711x-fb.c b/drivers/video/fbdev/clps711x-fb.c index 45c75ff01eca..c8bfc608bd9c 100644 --- a/drivers/video/fbdev/clps711x-fb.c +++ b/drivers/video/fbdev/clps711x-fb.c @@ -238,8 +238,7 @@ static int clps711x_fb_probe(struct platform_device *pdev) info->fix.mmio_start = res->start; info->fix.mmio_len = resource_size(res); - res = platform_get_resource(pdev, IORESOURCE_MEM, 1); - info->screen_base = devm_ioremap_resource(dev, res); + info->screen_base = devm_platform_get_and_ioremap_resource(pdev, 1, &res); if (IS_ERR(info->screen_base)) { ret = PTR_ERR(info->screen_base); goto out_fb_release; -- cgit From 096dc32bb73d20e0854b3a471379f577f903f0ee Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Fri, 10 Mar 2023 08:47:30 -0600 Subject: fbdev: Use of_property_read_bool() for boolean properties It is preferred to use typed property access functions (i.e. of_property_read_ functions) rather than low-level of_get_property/of_find_property functions for reading properties. Convert reading boolean properties to to of_property_read_bool(). Signed-off-by: Rob Herring Signed-off-by: Helge Deller --- drivers/video/fbdev/offb.c | 4 ++-- drivers/video/fbdev/sm501fb.c | 4 ++-- drivers/video/fbdev/tcx.c | 3 +-- drivers/video/fbdev/xilinxfb.c | 3 +-- 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/video/fbdev/offb.c b/drivers/video/fbdev/offb.c index f7ad6bc9d02d..b97d251d894b 100644 --- a/drivers/video/fbdev/offb.c +++ b/drivers/video/fbdev/offb.c @@ -549,10 +549,10 @@ static void offb_init_nodriver(struct platform_device *parent, struct device_nod int foreign_endian = 0; #ifdef __BIG_ENDIAN - if (of_get_property(dp, "little-endian", NULL)) + if (of_property_read_bool(dp, "little-endian")) foreign_endian = FBINFO_FOREIGN_ENDIAN; #else - if (of_get_property(dp, "big-endian", NULL)) + if (of_property_read_bool(dp, "big-endian")) foreign_endian = FBINFO_FOREIGN_ENDIAN; #endif diff --git a/drivers/video/fbdev/sm501fb.c b/drivers/video/fbdev/sm501fb.c index f743bfbde2a6..1f3cbe723def 100644 --- a/drivers/video/fbdev/sm501fb.c +++ b/drivers/video/fbdev/sm501fb.c @@ -1737,10 +1737,10 @@ static int sm501fb_init_fb(struct fb_info *fb, enum sm501_controller head, #if defined(CONFIG_OF) #ifdef __BIG_ENDIAN - if (of_get_property(info->dev->parent->of_node, "little-endian", NULL)) + if (of_property_read_bool(info->dev->parent->of_node, "little-endian")) fb->flags |= FBINFO_FOREIGN_ENDIAN; #else - if (of_get_property(info->dev->parent->of_node, "big-endian", NULL)) + if (of_property_read_bool(info->dev->parent->of_node, "big-endian")) fb->flags |= FBINFO_FOREIGN_ENDIAN; #endif #endif diff --git a/drivers/video/fbdev/tcx.c b/drivers/video/fbdev/tcx.c index 01d87f53324d..f2eaf6e7fff6 100644 --- a/drivers/video/fbdev/tcx.c +++ b/drivers/video/fbdev/tcx.c @@ -379,8 +379,7 @@ static int tcx_probe(struct platform_device *op) spin_lock_init(&par->lock); - par->lowdepth = - (of_find_property(dp, "tcx-8-bit", NULL) != NULL); + par->lowdepth = of_property_read_bool(dp, "tcx-8-bit"); sbusfb_fill_var(&info->var, dp, 8); info->var.red.length = 8; diff --git a/drivers/video/fbdev/xilinxfb.c b/drivers/video/fbdev/xilinxfb.c index 1ac83900a21c..c17cfffd9a84 100644 --- a/drivers/video/fbdev/xilinxfb.c +++ b/drivers/video/fbdev/xilinxfb.c @@ -469,8 +469,7 @@ static int xilinxfb_of_probe(struct platform_device *pdev) pdata.yvirt = prop[1]; } - if (of_find_property(pdev->dev.of_node, "rotate-display", NULL)) - pdata.rotate_screen = 1; + pdata.rotate_screen = of_property_read_bool(pdev->dev.of_node, "rotate-display"); platform_set_drvdata(pdev, drvdata); return xilinxfb_assign(pdev, drvdata, &pdata); -- cgit From 0db0a1eb444dc9f79241d673ea611741211acdae Mon Sep 17 00:00:00 2001 From: Yang Li Date: Tue, 14 Mar 2023 13:42:17 +0800 Subject: fbdev: pxa3xx-gcu: Use devm_platform_get_and_ioremap_resource() According to commit 890cc39a8799 ("drivers: provide devm_platform_get_and_ioremap_resource()"), convert platform_get_resource(), devm_ioremap_resource() to a single call to devm_platform_get_and_ioremap_resource(), as this is exactly what this function does. Signed-off-by: Yang Li Signed-off-by: Helge Deller --- drivers/video/fbdev/pxa3xx-gcu.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/video/fbdev/pxa3xx-gcu.c b/drivers/video/fbdev/pxa3xx-gcu.c index c3cd1e1cc01b..d16729215423 100644 --- a/drivers/video/fbdev/pxa3xx-gcu.c +++ b/drivers/video/fbdev/pxa3xx-gcu.c @@ -599,8 +599,7 @@ static int pxa3xx_gcu_probe(struct platform_device *pdev) priv->misc_dev.fops = &pxa3xx_gcu_miscdev_fops; /* handle IO resources */ - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - priv->mmio_base = devm_ioremap_resource(dev, r); + priv->mmio_base = devm_platform_get_and_ioremap_resource(pdev, 0, &r); if (IS_ERR(priv->mmio_base)) return PTR_ERR(priv->mmio_base); -- cgit From be66c2cbc05ed84821f3dde6439044ab44506525 Mon Sep 17 00:00:00 2001 From: Yang Li Date: Tue, 14 Mar 2023 13:42:18 +0800 Subject: fbdev: wm8505fb: Use devm_platform_ioremap_resource() According to commit 7945f929f1a7 ("drivers: provide devm_platform_ioremap_resource()"), convert platform_get_resource(), devm_ioremap_resource() to a single call to Use devm_platform_ioremap_resource(), as this is exactly what this function does. Signed-off-by: Yang Li Signed-off-by: Helge Deller --- drivers/video/fbdev/wm8505fb.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/video/fbdev/wm8505fb.c b/drivers/video/fbdev/wm8505fb.c index 8f4d674fa0d0..96a6f7623e19 100644 --- a/drivers/video/fbdev/wm8505fb.c +++ b/drivers/video/fbdev/wm8505fb.c @@ -261,7 +261,6 @@ static const struct fb_ops wm8505fb_ops = { static int wm8505fb_probe(struct platform_device *pdev) { struct wm8505fb_info *fbi; - struct resource *res; struct display_timings *disp_timing; void *addr; int ret; @@ -299,8 +298,7 @@ static int wm8505fb_probe(struct platform_device *pdev) addr = addr + sizeof(struct wm8505fb_info); fbi->fb.pseudo_palette = addr; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - fbi->regbase = devm_ioremap_resource(&pdev->dev, res); + fbi->regbase = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(fbi->regbase)) return PTR_ERR(fbi->regbase); -- cgit From 4c7e8e05bca577380d03a2731a14b3cb5652b4f3 Mon Sep 17 00:00:00 2001 From: Yang Li Date: Tue, 14 Mar 2023 13:42:19 +0800 Subject: fbdev: xilinxfb: Use devm_platform_get_and_ioremap_resource() According to commit 890cc39a8799 ("drivers: provide devm_platform_get_and_ioremap_resource()"), convert platform_get_resource(), devm_ioremap_resource() to a single call to devm_platform_get_and_ioremap_resource(), as this is exactly what this function does. Signed-off-by: Yang Li Signed-off-by: Helge Deller --- drivers/video/fbdev/xilinxfb.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/video/fbdev/xilinxfb.c b/drivers/video/fbdev/xilinxfb.c index c17cfffd9a84..7911354827dc 100644 --- a/drivers/video/fbdev/xilinxfb.c +++ b/drivers/video/fbdev/xilinxfb.c @@ -273,8 +273,7 @@ static int xilinxfb_assign(struct platform_device *pdev, if (drvdata->flags & BUS_ACCESS_FLAG) { struct resource *res; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - drvdata->regs = devm_ioremap_resource(&pdev->dev, res); + drvdata->regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res); if (IS_ERR(drvdata->regs)) return PTR_ERR(drvdata->regs); -- cgit From e140980ef211d537833500377ae411c3f232b41d Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 14 Mar 2023 17:27:10 +0100 Subject: fbdev: omapfb: remove omap1 osk driver Commit 21a3e6eed423 ("ARM: omap1: remove osk-mistral add-on board support") removed the platform_device definition for the "lcd_osk" device, so this driver is now unused and can be removed as well. Signed-off-by: Arnd Bergmann Signed-off-by: Helge Deller --- drivers/video/fbdev/omap/Makefile | 1 - drivers/video/fbdev/omap/lcd_osk.c | 86 -------------------------------------- 2 files changed, 87 deletions(-) delete mode 100644 drivers/video/fbdev/omap/lcd_osk.c diff --git a/drivers/video/fbdev/omap/Makefile b/drivers/video/fbdev/omap/Makefile index 504edb9c09dd..6d5082c76919 100644 --- a/drivers/video/fbdev/omap/Makefile +++ b/drivers/video/fbdev/omap/Makefile @@ -18,7 +18,6 @@ objs-y$(CONFIG_FB_OMAP_LCDC_HWA742) += hwa742.o lcds-y$(CONFIG_MACH_AMS_DELTA) += lcd_ams_delta.o lcds-y$(CONFIG_MACH_OMAP_PALMTE) += lcd_palmte.o -lcds-y$(CONFIG_MACH_OMAP_OSK) += lcd_osk.o lcds-y$(CONFIG_FB_OMAP_LCD_MIPID) += lcd_mipid.o diff --git a/drivers/video/fbdev/omap/lcd_osk.c b/drivers/video/fbdev/omap/lcd_osk.c deleted file mode 100644 index 8168ba0d47fd..000000000000 --- a/drivers/video/fbdev/omap/lcd_osk.c +++ /dev/null @@ -1,86 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * LCD panel support for the TI OMAP OSK board - * - * Copyright (C) 2004 Nokia Corporation - * Author: Imre Deak - * Adapted for OSK by - */ - -#include -#include -#include - -#include -#include - -#include "omapfb.h" - -static int osk_panel_enable(struct lcd_panel *panel) -{ - /* configure PWL pin */ - omap_cfg_reg(PWL); - - /* Enable PWL unit */ - omap_writeb(0x01, OMAP_PWL_CLK_ENABLE); - - /* Set PWL level */ - omap_writeb(0xFF, OMAP_PWL_ENABLE); - - /* set GPIO2 high (lcd power enabled) */ - gpio_set_value(2, 1); - - return 0; -} - -static void osk_panel_disable(struct lcd_panel *panel) -{ - /* Set PWL level to zero */ - omap_writeb(0x00, OMAP_PWL_ENABLE); - - /* Disable PWL unit */ - omap_writeb(0x00, OMAP_PWL_CLK_ENABLE); - - /* set GPIO2 low */ - gpio_set_value(2, 0); -} - -static struct lcd_panel osk_panel = { - .name = "osk", - .config = OMAP_LCDC_PANEL_TFT, - - .bpp = 16, - .data_lines = 16, - .x_res = 240, - .y_res = 320, - .pixel_clock = 12500, - .hsw = 40, - .hfp = 40, - .hbp = 72, - .vsw = 1, - .vfp = 1, - .vbp = 0, - .pcd = 12, - - .enable = osk_panel_enable, - .disable = osk_panel_disable, -}; - -static int osk_panel_probe(struct platform_device *pdev) -{ - omapfb_register_panel(&osk_panel); - return 0; -} - -static struct platform_driver osk_panel_driver = { - .probe = osk_panel_probe, - .driver = { - .name = "lcd_osk", - }, -}; - -module_platform_driver(osk_panel_driver); - -MODULE_AUTHOR("Imre Deak"); -MODULE_DESCRIPTION("LCD panel support for the TI OMAP OSK board"); -MODULE_LICENSE("GPL"); -- cgit From 7ff84910c66c9144cc0de9d9deed9fb84c03aff0 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Tue, 14 Mar 2023 06:20:58 -0400 Subject: lockd: set file_lock start and end when decoding nlm4 testargs Commit 6930bcbfb6ce dropped the setting of the file_lock range when decoding a nlm_lock off the wire. This causes the client side grant callback to miss matching blocks and reject the lock, only to rerequest it 30s later. Add a helper function to set the file_lock range from the start and end values that the protocol uses, and have the nlm_lock decoder call that to set up the file_lock args properly. Fixes: 6930bcbfb6ce ("lockd: detect and reject lock arguments that overflow") Reported-by: Amir Goldstein Signed-off-by: Jeff Layton Tested-by: Amir Goldstein Cc: stable@vger.kernel.org #6.0 Signed-off-by: Anna Schumaker --- fs/lockd/clnt4xdr.c | 9 +-------- fs/lockd/xdr4.c | 13 ++++++++++++- include/linux/lockd/xdr4.h | 1 + 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/fs/lockd/clnt4xdr.c b/fs/lockd/clnt4xdr.c index 7df6324ccb8a..8161667c976f 100644 --- a/fs/lockd/clnt4xdr.c +++ b/fs/lockd/clnt4xdr.c @@ -261,7 +261,6 @@ static int decode_nlm4_holder(struct xdr_stream *xdr, struct nlm_res *result) u32 exclusive; int error; __be32 *p; - s32 end; memset(lock, 0, sizeof(*lock)); locks_init_lock(fl); @@ -285,13 +284,7 @@ static int decode_nlm4_holder(struct xdr_stream *xdr, struct nlm_res *result) fl->fl_type = exclusive != 0 ? F_WRLCK : F_RDLCK; p = xdr_decode_hyper(p, &l_offset); xdr_decode_hyper(p, &l_len); - end = l_offset + l_len - 1; - - fl->fl_start = (loff_t)l_offset; - if (l_len == 0 || end < 0) - fl->fl_end = OFFSET_MAX; - else - fl->fl_end = (loff_t)end; + nlm4svc_set_file_lock_range(fl, l_offset, l_len); error = 0; out: return error; diff --git a/fs/lockd/xdr4.c b/fs/lockd/xdr4.c index 712fdfeb8ef0..5fcbf30cd275 100644 --- a/fs/lockd/xdr4.c +++ b/fs/lockd/xdr4.c @@ -33,6 +33,17 @@ loff_t_to_s64(loff_t offset) return res; } +void nlm4svc_set_file_lock_range(struct file_lock *fl, u64 off, u64 len) +{ + s64 end = off + len - 1; + + fl->fl_start = off; + if (len == 0 || end < 0) + fl->fl_end = OFFSET_MAX; + else + fl->fl_end = end; +} + /* * NLM file handles are defined by specification to be a variable-length * XDR opaque no longer than 1024 bytes. However, this implementation @@ -80,7 +91,7 @@ svcxdr_decode_lock(struct xdr_stream *xdr, struct nlm_lock *lock) locks_init_lock(fl); fl->fl_flags = FL_POSIX; fl->fl_type = F_RDLCK; - + nlm4svc_set_file_lock_range(fl, lock->lock_start, lock->lock_len); return true; } diff --git a/include/linux/lockd/xdr4.h b/include/linux/lockd/xdr4.h index 9a6b55da8fd6..72831e35dca3 100644 --- a/include/linux/lockd/xdr4.h +++ b/include/linux/lockd/xdr4.h @@ -22,6 +22,7 @@ #define nlm4_fbig cpu_to_be32(NLM_FBIG) #define nlm4_failed cpu_to_be32(NLM_FAILED) +void nlm4svc_set_file_lock_range(struct file_lock *fl, u64 off, u64 len); bool nlm4svc_decode_void(struct svc_rqst *rqstp, struct xdr_stream *xdr); bool nlm4svc_decode_testargs(struct svc_rqst *rqstp, struct xdr_stream *xdr); bool nlm4svc_decode_lockargs(struct svc_rqst *rqstp, struct xdr_stream *xdr); -- cgit From 21fd9e8700de86d1169f6336e97d7a74916ed04a Mon Sep 17 00:00:00 2001 From: Chengen Du Date: Wed, 8 Mar 2023 16:03:27 +0800 Subject: NFS: Correct timing for assigning access cache timestamp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the user's login time is newer than the cache's timestamp, the original entry in the RB-tree will be replaced by a new entry. Currently, the timestamp is only set if the entry is not found in the RB-tree, which can cause the timestamp to be undefined when the entry exists. This may result in a significant increase in ACCESS operations if the timestamp is set to zero. Signed-off-by: Chengen Du Fixes: 0eb43812c027 ("NFS: Clear the file access cache upon login”) Reviewed-by: Benjamin Coddington Signed-off-by: Anna Schumaker --- fs/nfs/dir.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index a41c3ee4549c..6fbcbb8d6587 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -3089,7 +3089,6 @@ static void nfs_access_add_rbtree(struct inode *inode, else goto found; } - set->timestamp = ktime_get_ns(); rb_link_node(&set->rb_node, parent, p); rb_insert_color(&set->rb_node, root_node); list_add_tail(&set->lru, &nfsi->access_cache_entry_lru); @@ -3114,6 +3113,7 @@ void nfs_access_add_cache(struct inode *inode, struct nfs_access_entry *set, cache->fsgid = cred->fsgid; cache->group_info = get_group_info(cred->group_info); cache->mask = set->mask; + cache->timestamp = ktime_get_ns(); /* The above field assignments must be visible * before this item appears on the lru. We cannot easily -- cgit From f959325e6ac3f499450088b8d9c626d1177be160 Mon Sep 17 00:00:00 2001 From: Nathan Huckleberry Date: Fri, 10 Mar 2023 11:33:25 -0800 Subject: fsverity: Remove WQ_UNBOUND from fsverity read workqueue WQ_UNBOUND causes significant scheduler latency on ARM64/Android. This is problematic for latency sensitive workloads, like I/O post-processing. Removing WQ_UNBOUND gives a 96% reduction in fsverity workqueue related scheduler latency and improves app cold startup times by ~30ms. WQ_UNBOUND was also removed from the dm-verity workqueue for the same reason [1]. This code was tested by running Android app startup benchmarks and measuring how long the fsverity workqueue spent in the runnable state. Before Total workqueue scheduler latency: 553800us After Total workqueue scheduler latency: 18962us [1]: https://lore.kernel.org/all/20230202012348.885402-1-nhuck@google.com/ Signed-off-by: Nathan Huckleberry Fixes: 8a1d0f9cacc9 ("fs-verity: add data verification hooks for ->readpages()") Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20230310193325.620493-1-nhuck@google.com Signed-off-by: Eric Biggers --- fs/verity/verify.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/fs/verity/verify.c b/fs/verity/verify.c index f50e3b5b52c9..e2508222750b 100644 --- a/fs/verity/verify.c +++ b/fs/verity/verify.c @@ -387,15 +387,15 @@ EXPORT_SYMBOL_GPL(fsverity_enqueue_verify_work); int __init fsverity_init_workqueue(void) { /* - * Use an unbound workqueue to allow bios to be verified in parallel - * even when they happen to complete on the same CPU. This sacrifices - * locality, but it's worthwhile since hashing is CPU-intensive. + * Use a high-priority workqueue to prioritize verification work, which + * blocks reads from completing, over regular application tasks. * - * Also use a high-priority workqueue to prioritize verification work, - * which blocks reads from completing, over regular application tasks. + * For performance reasons, don't use an unbound workqueue. Using an + * unbound workqueue for crypto operations causes excessive scheduler + * latency on ARM64. */ fsverity_read_workqueue = alloc_workqueue("fsverity_read_queue", - WQ_UNBOUND | WQ_HIGHPRI, + WQ_HIGHPRI, num_online_cpus()); if (!fsverity_read_workqueue) return -ENOMEM; -- cgit From dc472c7612297ffc9aea655bf6e9538bec5bfedf Mon Sep 17 00:00:00 2001 From: Ondrej Zary Date: Sat, 11 Mar 2023 20:25:38 +0100 Subject: ata: pata_parport: fix parport release without claim When adapter is not found, pi->disconnect() is called without previous pi->connect(). This results in error like this: parport0: pata_parport tried to release parport when not owner Add missing out_disconnect label and use it correctly. Signed-off-by: Ondrej Zary Reviewed-by: Sergey Shtylyov Signed-off-by: Damien Le Moal --- drivers/ata/pata_parport/pata_parport.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/ata/pata_parport/pata_parport.c b/drivers/ata/pata_parport/pata_parport.c index 294a266a0dda..31c9677a45e3 100644 --- a/drivers/ata/pata_parport/pata_parport.c +++ b/drivers/ata/pata_parport/pata_parport.c @@ -487,12 +487,13 @@ static struct pi_adapter *pi_init_one(struct parport *parport, pi_connect(pi); if (ata_host_activate(host, 0, NULL, 0, &pata_parport_sht)) - goto out_unreg_parport; + goto out_disconnect; return pi; -out_unreg_parport: +out_disconnect: pi_disconnect(pi); +out_unreg_parport: parport_unregister_device(pi->pardev); if (pi->proto->release_proto) pi->proto->release_proto(pi); -- cgit From c753ccb2629f536b8c4feae5c223d5873c814d23 Mon Sep 17 00:00:00 2001 From: Tzafrir Cohen Date: Tue, 14 Mar 2023 15:02:48 +0200 Subject: Makefile: Make kernelrelease target work with M= That commit required the use of filechk_kernel.release for the kernelrelease Makefile target. It is currently only being set when KBUILD_EXTMOD is not set. Make sure it is set in that case as well. Fixes: 1cb86b6c3136 ("kbuild: save overridden KERNELRELEASE in include/config/kernel.release") Signed-off-by: Tzafrir Cohen Signed-off-by: Masahiro Yamada --- Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Makefile b/Makefile index d7bd0eb9b346..d0a0ba8e5a2e 100644 --- a/Makefile +++ b/Makefile @@ -1886,6 +1886,8 @@ endif else # KBUILD_EXTMOD +filechk_kernel.release = echo $(KERNELRELEASE) + ### # External module support. # When building external modules the kernel used as basis is considered -- cgit From 2fd6c4553c962ec7ea8a60c0a3632c7e984800f0 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Mon, 13 Mar 2023 05:07:26 +0900 Subject: kbuild: deb-pkg: make debian source package working again Since commit c5bf2efb058d ("kbuild: deb-pkg: fix binary-arch and clean in debian/rules"), the source package generated by 'make deb-pkg' fails to build. I terribly missed the fact that the intdeb-pkg target may regenerate include/config/kernel.release due to the following in the top Makefile: %pkg: include/config/kernel.release FORCE Restore KERNELRELEASE= option to avoid the kernel.release disagreement between build-arch and binary-arch. Fixes: c5bf2efb058d ("kbuild: deb-pkg: fix binary-arch and clean in debian/rules") Signed-off-by: Masahiro Yamada --- scripts/package/mkdebian | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/scripts/package/mkdebian b/scripts/package/mkdebian index f74380036bb5..c6fbfb9f74ba 100755 --- a/scripts/package/mkdebian +++ b/scripts/package/mkdebian @@ -239,6 +239,7 @@ cat < debian/rules #!$(command -v $MAKE) -f srctree ?= . +KERNELRELEASE = ${KERNELRELEASE} build-indep: build-arch: @@ -250,7 +251,9 @@ build: build-arch binary-indep: binary-arch: build-arch - \$(MAKE) -f \$(srctree)/Makefile ARCH=${ARCH} intdeb-pkg + \$(MAKE) -f \$(srctree)/Makefile ARCH=${ARCH} \ + KERNELRELEASE=\$(KERNELRELEASE) intdeb-pkg + clean: rm -rf debian/files debian/linux-* \$(MAKE) -f \$(srctree)/Makefile ARCH=${ARCH} clean -- cgit From 7a531c21f83d7c62825d00bee3a76c1ccfb5de9f Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Mon, 13 Mar 2023 05:07:27 +0900 Subject: kbuild: deb-pkg: do not take KERNELRELEASE from the source version MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit KERNELRELEASE does not need to match the package version in changelog. Rather, it conventially matches what is called 'ABINAME', which is a part of the binary package names. Both are the same by default, but the former might be overridden by KDEB_PKGVERSION. In this case, the resulting package would not boot because /lib/modules/$(uname -r) does not point the module directory. Partially revert 3ab18a625ce4 ("kbuild: deb-pkg: improve the usability of source package"). Reported-by: Péter Ujfalusi Fixes: 3ab18a625ce4 ("kbuild: deb-pkg: improve the usability of source package") Signed-off-by: Masahiro Yamada Tested-by: Peter Ujfalusi --- scripts/package/deb-build-option | 9 ++++----- scripts/package/mkdebian | 1 + 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/scripts/package/deb-build-option b/scripts/package/deb-build-option index b079b0d121d4..bd53624318f2 100755 --- a/scripts/package/deb-build-option +++ b/scripts/package/deb-build-option @@ -8,9 +8,8 @@ if [ -z "${CROSS_COMPILE}${cross_compiling}" -a "${DEB_HOST_ARCH}" != "${DEB_BUI fi version=$(dpkg-parsechangelog -S Version) -version_upstream="${version%-*}" -debian_revision="${version#${version_upstream}}" -debian_revision="${debian_revision#*-}" +debian_revision="${version##*-}" -echo KERNELRELEASE=${version_upstream} -echo KBUILD_BUILD_VERSION=${debian_revision} +if [ "${version}" != "${debian_revision}" ]; then + echo KBUILD_BUILD_VERSION=${debian_revision} +fi diff --git a/scripts/package/mkdebian b/scripts/package/mkdebian index c6fbfb9f74ba..31b050368cd0 100755 --- a/scripts/package/mkdebian +++ b/scripts/package/mkdebian @@ -244,6 +244,7 @@ KERNELRELEASE = ${KERNELRELEASE} build-indep: build-arch: \$(MAKE) -f \$(srctree)/Makefile ARCH=${ARCH} \ + KERNELRELEASE=\$(KERNELRELEASE) \ \$(shell \$(srctree)/scripts/package/deb-build-option) \ olddefconfig all -- cgit From f50aa51c4498d7886cfd9dbf439a2332f234a755 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Mon, 13 Mar 2023 05:07:28 +0900 Subject: kbuild: deb-pkg: set CROSS_COMPILE only when undefined Commit 3ab18a625ce4 ("kbuild: deb-pkg: improve the usability of source package") set needless CROSS_COMPILE. For example, 'make allnoconfig bindeb-pkg' on a x86_64 system will set CROSS_COMPILE=i686-linux-gnu-, where the biarch compiler 'gcc' should work for building the i386 kernel. $ uname -m x86_64 $ make allnoconfig bindeb-pkg >/dev/null dpkg-architecture: warning: specified GNU system type i686-linux-gnu does not match CC system type x86_64-linux-gnu, try setting a correct CC environment variable dpkg-source --before-build . debian/rules binary scripts/Kconfig.include:39: C compiler 'i686-linux-gnu-gcc' not found make[6]: *** [scripts/kconfig/Makefile:77: olddefconfig] Error 1 make[5]: *** [Makefile:693: olddefconfig] Error 2 make[4]: *** [Makefile:358: __build_one_by_one] Error 2 make[3]: *** [debian/rules:7: build-arch] Error 2 dpkg-buildpackage: error: debian/rules binary subprocess returned exit status 2 make[2]: *** [scripts/Makefile.package:127: bindeb-pkg] Error 2 make[1]: *** [Makefile:1657: bindeb-pkg] Error 2 make: *** [Makefile:358: __build_one_by_one] Error 2 Check whether CROSS_COMPILE is defined, instead of whether it is non-empty. If you invoke debian/rules via Kbuild, CROSS_COMPILE is always defined in the top Makefile. Fixes: 3ab18a625ce4 ("kbuild: deb-pkg: improve the usability of source package") Signed-off-by: Masahiro Yamada --- scripts/package/deb-build-option | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/scripts/package/deb-build-option b/scripts/package/deb-build-option index bd53624318f2..7950eff01781 100755 --- a/scripts/package/deb-build-option +++ b/scripts/package/deb-build-option @@ -1,9 +1,8 @@ #!/bin/sh # SPDX-License-Identifier: GPL-2.0-only -# Set up CROSS_COMPILE if we are cross-compiling, but not called from the -# kernel toplevel Makefile -if [ -z "${CROSS_COMPILE}${cross_compiling}" -a "${DEB_HOST_ARCH}" != "${DEB_BUILD_ARCH}" ]; then +# Set up CROSS_COMPILE if not defined yet +if [ "${CROSS_COMPILE+set}" != "set" -a "${DEB_HOST_ARCH}" != "${DEB_BUILD_ARCH}" ]; then echo CROSS_COMPILE=${DEB_HOST_GNU_TYPE}- fi -- cgit From b611daae5efc64e817171a54021d3b334cc1bc41 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Mon, 13 Mar 2023 05:07:29 +0900 Subject: kbuild: deb-pkg: split image and debug objects staging out into functions Prepare for the refactoring in the next commit. Signed-off-by: Masahiro Yamada --- scripts/package/builddeb | 222 +++++++++++++++++++++++++---------------------- 1 file changed, 116 insertions(+), 106 deletions(-) diff --git a/scripts/package/builddeb b/scripts/package/builddeb index ff5e7d8e380b..906889b304a4 100755 --- a/scripts/package/builddeb +++ b/scripts/package/builddeb @@ -51,6 +51,115 @@ create_package() { dpkg-deb $dpkg_deb_opts ${KDEB_COMPRESS:+-Z$KDEB_COMPRESS} --build "$pdir" .. } +install_linux_image () { + pdir=$1 + pname=$2 + + rm -rf ${pdir} + + # Only some architectures with OF support have this target + if is_enabled CONFIG_OF_EARLY_FLATTREE && [ -d "${srctree}/arch/${SRCARCH}/boot/dts" ]; then + ${MAKE} -f ${srctree}/Makefile INSTALL_DTBS_PATH="${pdir}/usr/lib/linux-image-${KERNELRELEASE}" dtbs_install + fi + + if is_enabled CONFIG_MODULES; then + ${MAKE} -f ${srctree}/Makefile INSTALL_MOD_PATH="${pdir}" modules_install + rm -f "${pdir}/lib/modules/${KERNELRELEASE}/build" + rm -f "${pdir}/lib/modules/${KERNELRELEASE}/source" + if [ "${SRCARCH}" = um ] ; then + mkdir -p "${pdir}/usr/lib/uml/modules" + mv "${pdir}/lib/modules/${KERNELRELEASE}" "${pdir}/usr/lib/uml/modules/${KERNELRELEASE}" + fi + fi + + # Install the kernel + if [ "${ARCH}" = um ] ; then + mkdir -p "${pdir}/usr/bin" "${pdir}/usr/share/doc/${pname}" + cp System.map "${pdir}/usr/lib/uml/modules/${KERNELRELEASE}/System.map" + cp ${KCONFIG_CONFIG} "${pdir}/usr/share/doc/${pname}/config" + gzip "${pdir}/usr/share/doc/${pname}/config" + else + mkdir -p "${pdir}/boot" + cp System.map "${pdir}/boot/System.map-${KERNELRELEASE}" + cp ${KCONFIG_CONFIG} "${pdir}/boot/config-${KERNELRELEASE}" + fi + + # Not all arches have the same installed path in debian + # XXX: have each arch Makefile export a variable of the canonical image install + # path instead + case "${SRCARCH}" in + um) + installed_image_path="usr/bin/linux-${KERNELRELEASE}";; + parisc|mips|powerpc) + installed_image_path="boot/vmlinux-${KERNELRELEASE}";; + *) + installed_image_path="boot/vmlinuz-${KERNELRELEASE}";; + esac + cp "$(${MAKE} -s -f ${srctree}/Makefile image_name)" "${pdir}/${installed_image_path}" + + # Install the maintainer scripts + # Note: hook scripts under /etc/kernel are also executed by official Debian + # kernel packages, as well as kernel packages built using make-kpkg. + # make-kpkg sets $INITRD to indicate whether an initramfs is wanted, and + # so do we; recent versions of dracut and initramfs-tools will obey this. + debhookdir=${KDEB_HOOKDIR:-/etc/kernel} + for script in postinst postrm preinst prerm; do + mkdir -p "${pdir}${debhookdir}/${script}.d" + + mkdir -p "${pdir}/DEBIAN" + cat <<-EOF > "${pdir}/DEBIAN/${script}" + + #!/bin/sh + + set -e + + # Pass maintainer script parameters to hook scripts + export DEB_MAINT_PARAMS="\$*" + + # Tell initramfs builder whether it's wanted + export INITRD=$(if_enabled_echo CONFIG_BLK_DEV_INITRD Yes No) + + test -d ${debhookdir}/${script}.d && run-parts --arg="${KERNELRELEASE}" --arg="/${installed_image_path}" ${debhookdir}/${script}.d + exit 0 + EOF + chmod 755 "${pdir}/DEBIAN/${script}" + done +} + +install_linux_image_dbg () { + pdir=$1 + image_pdir=$2 + + rm -rf ${pdir} + + for module in $(find ${image_pdir}/lib/modules/ -name *.ko -printf '%P\n'); do + module=lib/modules/${module} + mkdir -p $(dirname ${pdir}/usr/lib/debug/${module}) + # only keep debug symbols in the debug file + ${OBJCOPY} --only-keep-debug ${image_pdir}/${module} ${pdir}/usr/lib/debug/${module} + # strip original module from debug symbols + ${OBJCOPY} --strip-debug ${image_pdir}/${module} + # then add a link to those + ${OBJCOPY} --add-gnu-debuglink=${pdir}/usr/lib/debug/${module} ${image_pdir}/${module} + done + + # re-sign stripped modules + if is_enabled CONFIG_MODULE_SIG_ALL; then + ${MAKE} -f ${srctree}/Makefile INSTALL_MOD_PATH="${image_pdir}" modules_sign + fi + + # Build debug package + # Different tools want the image in different locations + # perf + mkdir -p ${pdir}/usr/lib/debug/lib/modules/${KERNELRELEASE}/ + cp vmlinux ${pdir}/usr/lib/debug/lib/modules/${KERNELRELEASE}/ + # systemtap + mkdir -p ${pdir}/usr/lib/debug/boot/ + ln -s ../lib/modules/${KERNELRELEASE}/vmlinux ${pdir}/usr/lib/debug/boot/vmlinux-${KERNELRELEASE} + # kdump-tools + ln -s lib/modules/${KERNELRELEASE}/vmlinux ${pdir}/usr/lib/debug/vmlinux-${KERNELRELEASE} +} + deploy_kernel_headers () { pdir=$1 @@ -105,8 +214,6 @@ deploy_libc_headers () { } version=$KERNELRELEASE -tmpdir=debian/linux-image -dbg_dir=debian/linux-image-dbg packagename=linux-image-$version dbg_packagename=$packagename-dbg @@ -114,97 +221,7 @@ if [ "$ARCH" = "um" ] ; then packagename=user-mode-linux-$version fi -# Not all arches have the same installed path in debian -# XXX: have each arch Makefile export a variable of the canonical image install -# path instead -case $ARCH in -um) - installed_image_path="usr/bin/linux-$version" - ;; -parisc|mips|powerpc) - installed_image_path="boot/vmlinux-$version" - ;; -*) - installed_image_path="boot/vmlinuz-$version" -esac - -BUILD_DEBUG=$(if_enabled_echo CONFIG_DEBUG_INFO Yes) - -# Setup the directory structure -rm -rf "$tmpdir" "$dbg_dir" debian/files -mkdir -m 755 -p "$tmpdir/DEBIAN" -mkdir -p "$tmpdir/lib" "$tmpdir/boot" - -# Install the kernel -if [ "$ARCH" = "um" ] ; then - mkdir -p "$tmpdir/usr/lib/uml/modules/$version" "$tmpdir/usr/bin" "$tmpdir/usr/share/doc/$packagename" - cp System.map "$tmpdir/usr/lib/uml/modules/$version/System.map" - cp $KCONFIG_CONFIG "$tmpdir/usr/share/doc/$packagename/config" - gzip "$tmpdir/usr/share/doc/$packagename/config" -else - cp System.map "$tmpdir/boot/System.map-$version" - cp $KCONFIG_CONFIG "$tmpdir/boot/config-$version" -fi -cp "$($MAKE -s -f $srctree/Makefile image_name)" "$tmpdir/$installed_image_path" - -if is_enabled CONFIG_OF_EARLY_FLATTREE; then - # Only some architectures with OF support have this target - if [ -d "${srctree}/arch/$SRCARCH/boot/dts" ]; then - $MAKE -f $srctree/Makefile INSTALL_DTBS_PATH="$tmpdir/usr/lib/$packagename" dtbs_install - fi -fi - -if is_enabled CONFIG_MODULES; then - INSTALL_MOD_PATH="$tmpdir" $MAKE -f $srctree/Makefile modules_install - rm -f "$tmpdir/lib/modules/$version/build" - rm -f "$tmpdir/lib/modules/$version/source" - if [ "$ARCH" = "um" ] ; then - mv "$tmpdir/lib/modules/$version"/* "$tmpdir/usr/lib/uml/modules/$version/" - rmdir "$tmpdir/lib/modules/$version" - fi - if [ -n "$BUILD_DEBUG" ] ; then - for module in $(find $tmpdir/lib/modules/ -name *.ko -printf '%P\n'); do - module=lib/modules/$module - mkdir -p $(dirname $dbg_dir/usr/lib/debug/$module) - # only keep debug symbols in the debug file - $OBJCOPY --only-keep-debug $tmpdir/$module $dbg_dir/usr/lib/debug/$module - # strip original module from debug symbols - $OBJCOPY --strip-debug $tmpdir/$module - # then add a link to those - $OBJCOPY --add-gnu-debuglink=$dbg_dir/usr/lib/debug/$module $tmpdir/$module - done - - # resign stripped modules - if is_enabled CONFIG_MODULE_SIG_ALL; then - INSTALL_MOD_PATH="$tmpdir" $MAKE -f $srctree/Makefile modules_sign - fi - fi -fi - -# Install the maintainer scripts -# Note: hook scripts under /etc/kernel are also executed by official Debian -# kernel packages, as well as kernel packages built using make-kpkg. -# make-kpkg sets $INITRD to indicate whether an initramfs is wanted, and -# so do we; recent versions of dracut and initramfs-tools will obey this. -debhookdir=${KDEB_HOOKDIR:-/etc/kernel} -for script in postinst postrm preinst prerm ; do - mkdir -p "$tmpdir$debhookdir/$script.d" - cat < "$tmpdir/DEBIAN/$script" -#!/bin/sh - -set -e - -# Pass maintainer script parameters to hook scripts -export DEB_MAINT_PARAMS="\$*" - -# Tell initramfs builder whether it's wanted -export INITRD=$(if_enabled_echo CONFIG_BLK_DEV_INITRD Yes No) - -test -d $debhookdir/$script.d && run-parts --arg="$version" --arg="/$installed_image_path" $debhookdir/$script.d -exit 0 -EOF - chmod 755 "$tmpdir/DEBIAN/$script" -done +rm -f debian/files if [ "$ARCH" != "um" ]; then if is_enabled CONFIG_MODULES; then @@ -216,20 +233,13 @@ if [ "$ARCH" != "um" ]; then create_package linux-libc-dev debian/linux-libc-dev fi -create_package "$packagename" "$tmpdir" +install_linux_image debian/linux-image "$packagename" -if [ -n "$BUILD_DEBUG" ] ; then - # Build debug package - # Different tools want the image in different locations - # perf - mkdir -p $dbg_dir/usr/lib/debug/lib/modules/$version/ - cp vmlinux $dbg_dir/usr/lib/debug/lib/modules/$version/ - # systemtap - mkdir -p $dbg_dir/usr/lib/debug/boot/ - ln -s ../lib/modules/$version/vmlinux $dbg_dir/usr/lib/debug/boot/vmlinux-$version - # kdump-tools - ln -s lib/modules/$version/vmlinux $dbg_dir/usr/lib/debug/vmlinux-$version - create_package "$dbg_packagename" "$dbg_dir" +if is_enabled CONFIG_DEBUG_INFO; then + install_linux_image_dbg debian/linux-image-dbg debian/linux-image + create_package "$dbg_packagename" debian/linux-image-dbg fi +create_package "$packagename" debian/linux-image + exit 0 -- cgit From 36862e14e31611f9786622db366327209a7aede7 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Mon, 13 Mar 2023 05:07:30 +0900 Subject: kbuild: deb-pkg: use dh_listpackages to know enabled packages Use dh_listpackages to get a list of all binary packages. With this, debian/control lists which binary packages will be produced. Previously, ARCH=um listed linux-libc-dev in debian/control, but it was not generated because each of mkdebian and builddeb independently maintained the if-conditionals. Another motivation is to allow scripts/package/builddeb to get the package name (linux-image-*, etc.) dynamically from debian/control. This will also allow the BuildProfile to control the generation of the binary packages. Signed-off-by: Masahiro Yamada --- scripts/package/builddeb | 61 ++++++++++++++++++++++++++---------------------- scripts/package/mkdebian | 7 +++++- 2 files changed, 39 insertions(+), 29 deletions(-) diff --git a/scripts/package/builddeb b/scripts/package/builddeb index 906889b304a4..c5ae57167d7c 100755 --- a/scripts/package/builddeb +++ b/scripts/package/builddeb @@ -160,7 +160,7 @@ install_linux_image_dbg () { ln -s lib/modules/${KERNELRELEASE}/vmlinux ${pdir}/usr/lib/debug/vmlinux-${KERNELRELEASE} } -deploy_kernel_headers () { +install_kernel_headers () { pdir=$1 rm -rf $pdir @@ -198,7 +198,7 @@ deploy_kernel_headers () { ln -s /usr/src/linux-headers-$version $pdir/lib/modules/$version/build } -deploy_libc_headers () { +install_libc_headers () { pdir=$1 rm -rf $pdir @@ -213,33 +213,38 @@ deploy_libc_headers () { mv $pdir/usr/include/asm $pdir/usr/include/$host_arch/ } -version=$KERNELRELEASE -packagename=linux-image-$version -dbg_packagename=$packagename-dbg - -if [ "$ARCH" = "um" ] ; then - packagename=user-mode-linux-$version -fi - rm -f debian/files -if [ "$ARCH" != "um" ]; then - if is_enabled CONFIG_MODULES; then - deploy_kernel_headers debian/linux-headers - create_package linux-headers-$version debian/linux-headers - fi - - deploy_libc_headers debian/linux-libc-dev - create_package linux-libc-dev debian/linux-libc-dev -fi - -install_linux_image debian/linux-image "$packagename" - -if is_enabled CONFIG_DEBUG_INFO; then - install_linux_image_dbg debian/linux-image-dbg debian/linux-image - create_package "$dbg_packagename" debian/linux-image-dbg -fi - -create_package "$packagename" debian/linux-image +packages_enabled=$(dh_listpackages) + +for package in ${packages_enabled} +do + case ${package} in + *-dbg) + # This must be done after linux-image, that is, we expect the + # debug package appears after linux-image in debian/control. + install_linux_image_dbg debian/linux-image-dbg debian/linux-image;; + linux-image-*|user-mode-linux-*) + install_linux_image debian/linux-image ${package};; + linux-libc-dev) + install_libc_headers debian/linux-libc-dev;; + linux-headers-*) + install_kernel_headers debian/linux-headers;; + esac +done + +for package in ${packages_enabled} +do + case ${package} in + *-dbg) + create_package ${package} debian/linux-image-dbg;; + linux-image-*|user-mode-linux-*) + create_package ${package} debian/linux-image;; + linux-libc-dev) + create_package ${package} debian/linux-libc-dev;; + linux-headers-*) + create_package ${package} debian/linux-headers;; + esac +done exit 0 diff --git a/scripts/package/mkdebian b/scripts/package/mkdebian index 31b050368cd0..e80a661a79ee 100755 --- a/scripts/package/mkdebian +++ b/scripts/package/mkdebian @@ -192,7 +192,7 @@ Section: kernel Priority: optional Maintainer: $maintainer Rules-Requires-Root: no -Build-Depends: bc, rsync, kmod, cpio, bison, flex $extra_build_depends +Build-Depends: bc, debhelper, rsync, kmod, cpio, bison, flex $extra_build_depends Homepage: https://www.kernel.org/ Package: $packagename-$version @@ -200,6 +200,10 @@ Architecture: $debarch Description: Linux kernel, version $version This package contains the Linux kernel, modules and corresponding other files, version: $version. +EOF + +if [ "${SRCARCH}" != um ]; then +cat <> debian/control Package: linux-libc-dev Section: devel @@ -222,6 +226,7 @@ Description: Linux kernel headers for $version on $debarch This is useful for people who need to build external modules EOF fi +fi if is_enabled CONFIG_DEBUG_INFO; then cat <> debian/control -- cgit From 139f6973bf140c65d4d1d4bde5485badb4454d7a Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sun, 12 Mar 2023 14:25:23 +0100 Subject: wifi: mwifiex: mark OF related data as maybe unused MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The driver can be compile tested with !CONFIG_OF making certain data unused: drivers/net/wireless/marvell/mwifiex/sdio.c:498:34: error: ‘mwifiex_sdio_of_match_table’ defined but not used [-Werror=unused-const-variable=] drivers/net/wireless/marvell/mwifiex/pcie.c:175:34: error: ‘mwifiex_pcie_of_match_table’ defined but not used [-Werror=unused-const-variable=] Signed-off-by: Krzysztof Kozlowski Reviewed-by: Simon Horman Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20230312132523.352182-1-krzysztof.kozlowski@linaro.org --- drivers/net/wireless/marvell/mwifiex/pcie.c | 2 +- drivers/net/wireless/marvell/mwifiex/sdio.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c index 5dcf61761a16..9a698a16a8f3 100644 --- a/drivers/net/wireless/marvell/mwifiex/pcie.c +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c @@ -172,7 +172,7 @@ static const struct mwifiex_pcie_device mwifiex_pcie8997 = { .can_ext_scan = true, }; -static const struct of_device_id mwifiex_pcie_of_match_table[] = { +static const struct of_device_id mwifiex_pcie_of_match_table[] __maybe_unused = { { .compatible = "pci11ab,2b42" }, { .compatible = "pci1b4b,2b42" }, { } diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.c b/drivers/net/wireless/marvell/mwifiex/sdio.c index c64e24c10ea6..a24bd40dd41a 100644 --- a/drivers/net/wireless/marvell/mwifiex/sdio.c +++ b/drivers/net/wireless/marvell/mwifiex/sdio.c @@ -495,7 +495,7 @@ static struct memory_type_mapping mem_type_mapping_tbl[] = { {"EXTLAST", NULL, 0, 0xFE}, }; -static const struct of_device_id mwifiex_sdio_of_match_table[] = { +static const struct of_device_id mwifiex_sdio_of_match_table[] __maybe_unused = { { .compatible = "marvell,sd8787" }, { .compatible = "marvell,sd8897" }, { .compatible = "marvell,sd8978" }, -- cgit From 007ae9b268ba7553e479608cf9735d3c4672a2ab Mon Sep 17 00:00:00 2001 From: Alexander Wetzel Date: Tue, 14 Mar 2023 22:11:22 +0100 Subject: wifi: mac80211: Serialize ieee80211_handle_wake_tx_queue() ieee80211_handle_wake_tx_queue must not run concurrent multiple times. It calls ieee80211_txq_schedule_start() and the drivers migrated to iTXQ do not expect overlapping drv_tx() calls. This fixes 'c850e31f79f0 ("wifi: mac80211: add internal handler for wake_tx_queue")', which introduced ieee80211_handle_wake_tx_queue. Drivers started to use it with 'a790cc3a4fad ("wifi: mac80211: add wake_tx_queue callback to drivers")'. But only after fixing an independent bug with '4444bc2116ae ("wifi: mac80211: Proper mark iTXQs for resumption")' problematic concurrent calls really happened and exposed the initial issue. Fixes: c850e31f79f0 ("wifi: mac80211: add internal handler for wake_tx_queue") Reported-by: Thomas Mann Link: https://bugzilla.kernel.org/show_bug.cgi?id=217119 Link: https://lore.kernel.org/r/b8efebc6-4399-d0b8-b2a0-66843314616b@leemhuis.info/ Link: https://lore.kernel.org/r/b7445607128a6b9ed7c17fcdcf3679bfaf4aaea.camel@sipsolutions.net> CC: Signed-off-by: Alexander Wetzel Link: https://lore.kernel.org/r/20230314211122.111688-1-alexander@wetzel-home.de [add missing spin_lock_init() noticed by Felix] Signed-off-by: Johannes Berg --- net/mac80211/ieee80211_i.h | 3 +++ net/mac80211/main.c | 2 ++ net/mac80211/util.c | 3 +++ 3 files changed, 8 insertions(+) diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index ecc232eb1ee8..e082582e0aa2 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -1284,6 +1284,9 @@ struct ieee80211_local { struct list_head active_txqs[IEEE80211_NUM_ACS]; u16 schedule_round[IEEE80211_NUM_ACS]; + /* serializes ieee80211_handle_wake_tx_queue */ + spinlock_t handle_wake_tx_queue_lock; + u16 airtime_flags; u32 aql_txq_limit_low[IEEE80211_NUM_ACS]; u32 aql_txq_limit_high[IEEE80211_NUM_ACS]; diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 846528850612..ddf2b7811c55 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -802,6 +802,8 @@ struct ieee80211_hw *ieee80211_alloc_hw_nm(size_t priv_data_len, local->aql_threshold = IEEE80211_AQL_THRESHOLD; atomic_set(&local->aql_total_pending_airtime, 0); + spin_lock_init(&local->handle_wake_tx_queue_lock); + INIT_LIST_HEAD(&local->chanctx_list); mutex_init(&local->chanctx_mtx); diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 1a28fe5cb614..3aceb3b731bf 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -314,6 +314,8 @@ void ieee80211_handle_wake_tx_queue(struct ieee80211_hw *hw, struct ieee80211_sub_if_data *sdata = vif_to_sdata(txq->vif); struct ieee80211_txq *queue; + spin_lock(&local->handle_wake_tx_queue_lock); + /* Use ieee80211_next_txq() for airtime fairness accounting */ ieee80211_txq_schedule_start(hw, txq->ac); while ((queue = ieee80211_next_txq(hw, txq->ac))) { @@ -321,6 +323,7 @@ void ieee80211_handle_wake_tx_queue(struct ieee80211_hw *hw, ieee80211_return_txq(hw, queue, false); } ieee80211_txq_schedule_end(hw, txq->ac); + spin_unlock(&local->handle_wake_tx_queue_lock); } EXPORT_SYMBOL(ieee80211_handle_wake_tx_queue); -- cgit From 1c3ab6dfa0692c3626580a508cf84e794201b357 Mon Sep 17 00:00:00 2001 From: Qu Wenruo Date: Thu, 2 Mar 2023 09:54:12 +0800 Subject: btrfs: handle missing chunk mapping more gracefully [BUG] During my scrub rework, I did a stupid thing like this: bio->bi_iter.bi_sector = stripe->logical; btrfs_submit_bio(fs_info, bio, stripe->mirror_num); Above bi_sector assignment is using logical address directly, which lacks ">> SECTOR_SHIFT". This results a read on a range which has no chunk mapping. This results the following crash: BTRFS critical (device dm-1): unable to find logical 11274289152 length 65536 assertion failed: !IS_ERR(em), in fs/btrfs/volumes.c:6387 Sure this is all my fault, but this shows a possible problem in real world, that some bit flip in file extents/tree block can point to unmapped ranges, and trigger above ASSERT(), or if CONFIG_BTRFS_ASSERT is not configured, cause invalid pointer access. [PROBLEMS] In the above call chain, we just don't handle the possible error from btrfs_get_chunk_map() inside __btrfs_map_block(). [FIX] The fix is straightforward, replace the ASSERT() with proper error handling (callers handle errors already). Reviewed-by: Anand Jain Signed-off-by: Qu Wenruo Signed-off-by: David Sterba --- fs/btrfs/volumes.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 7823168c08a6..6d0124b6e79e 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -6363,7 +6363,8 @@ int __btrfs_map_block(struct btrfs_fs_info *fs_info, enum btrfs_map_op op, ASSERT(op != BTRFS_MAP_DISCARD); em = btrfs_get_chunk_map(fs_info, logical, *length); - ASSERT(!IS_ERR(em)); + if (IS_ERR(em)) + return PTR_ERR(em); map = em->map_lookup; data_stripes = nr_data_stripes(map); -- cgit From 10a8857a1beaa015efba7d56e06243d484549fb6 Mon Sep 17 00:00:00 2001 From: Sweet Tea Dorminy Date: Wed, 8 Mar 2023 10:58:36 -0500 Subject: btrfs: fix compiler warning on SPARC/PA-RISC handling fscrypt_setup_filename Commit 1ec49744ba83 ("btrfs: turn on -Wmaybe-uninitialized") exposed that on SPARC and PA-RISC, gcc is unaware that fscrypt_setup_filename() only returns negative error values or 0. This ultimately results in a maybe-uninitialized warning in btrfs_lookup_dentry(). Change to only return negative error values or 0 from fscrypt_setup_filename() at the relevant call site, and assert that no positive error codes are returned (which would have wider implications involving other users). Reported-by: Guenter Roeck Link: https://lore.kernel.org/all/481b19b5-83a0-4793-b4fd-194ad7b978c3@roeck-us.net/ Signed-off-by: Sweet Tea Dorminy Reviewed-by: David Sterba Signed-off-by: David Sterba --- fs/btrfs/inode.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 44e9acc77a74..e99432e4912e 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -5421,8 +5421,13 @@ static int btrfs_inode_by_name(struct btrfs_inode *dir, struct dentry *dentry, return -ENOMEM; ret = fscrypt_setup_filename(&dir->vfs_inode, &dentry->d_name, 1, &fname); - if (ret) + if (ret < 0) goto out; + /* + * fscrypt_setup_filename() should never return a positive value, but + * gcc on sparc/parisc thinks it can, so assert that doesn't happen. + */ + ASSERT(ret == 0); /* This needs to handle no-key deletions later on */ -- cgit From 9e1cdf0c354e46e428c0e0cab008abbe81b6013d Mon Sep 17 00:00:00 2001 From: Naohiro Aota Date: Mon, 13 Mar 2023 16:29:49 +0900 Subject: btrfs: zoned: fix btrfs_can_activate_zone() to support DUP profile btrfs_can_activate_zone() returns true if at least one device has one zone available for activation. This is OK for the single profile, but not OK for DUP profile. We need two zones to create a DUP block group. Fix it by properly handling the case with the profile flags. Fixes: 265f7237dd25 ("btrfs: zoned: allow DUP on meta-data block groups") CC: stable@vger.kernel.org # 6.1+ Reviewed-by: Johannes Thumshirn Signed-off-by: Naohiro Aota Reviewed-by: David Sterba Signed-off-by: David Sterba --- fs/btrfs/zoned.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/fs/btrfs/zoned.c b/fs/btrfs/zoned.c index f95b2c94d619..0a330d5410a0 100644 --- a/fs/btrfs/zoned.c +++ b/fs/btrfs/zoned.c @@ -2086,11 +2086,21 @@ bool btrfs_can_activate_zone(struct btrfs_fs_devices *fs_devices, u64 flags) if (!device->bdev) continue; - if (!zinfo->max_active_zones || - atomic_read(&zinfo->active_zones_left)) { + if (!zinfo->max_active_zones) { ret = true; break; } + + switch (flags & BTRFS_BLOCK_GROUP_PROFILE_MASK) { + case 0: /* single */ + ret = (atomic_read(&zinfo->active_zones_left) >= 1); + break; + case BTRFS_BLOCK_GROUP_DUP: + ret = (atomic_read(&zinfo->active_zones_left) >= 2); + break; + } + if (ret) + break; } mutex_unlock(&fs_info->chunk_mutex); -- cgit From bf1f1fec2724a33b67ec12032402ea75f2a83622 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Wed, 1 Mar 2023 16:14:42 -0500 Subject: btrfs: rename BTRFS_FS_NO_OVERCOMMIT to BTRFS_FS_ACTIVE_ZONE_TRACKING This flag only gets set when we're doing active zone tracking, and we're going to need to use this flag for things related to this behavior. Rename the flag to represent what it actually means for the file system so it can be used in other ways and still make sense. Reviewed-by: Naohiro Aota Reviewed-by: Johannes Thumshirn Reviewed-by: Anand Jain Signed-off-by: Josef Bacik Reviewed-by: David Sterba Signed-off-by: David Sterba --- fs/btrfs/fs.h | 7 ++----- fs/btrfs/space-info.c | 2 +- fs/btrfs/zoned.c | 3 +-- 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/fs/btrfs/fs.h b/fs/btrfs/fs.h index 4c477eae6891..24cd49229408 100644 --- a/fs/btrfs/fs.h +++ b/fs/btrfs/fs.h @@ -120,11 +120,8 @@ enum { /* Indicate that we want to commit the transaction. */ BTRFS_FS_NEED_TRANS_COMMIT, - /* - * Indicate metadata over-commit is disabled. This is set when active - * zone tracking is needed. - */ - BTRFS_FS_NO_OVERCOMMIT, + /* This is set when active zone tracking is needed. */ + BTRFS_FS_ACTIVE_ZONE_TRACKING, /* * Indicate if we have some features changed, this is mostly for diff --git a/fs/btrfs/space-info.c b/fs/btrfs/space-info.c index 69c09508afb5..2237685d1ed0 100644 --- a/fs/btrfs/space-info.c +++ b/fs/btrfs/space-info.c @@ -407,7 +407,7 @@ int btrfs_can_overcommit(struct btrfs_fs_info *fs_info, return 0; used = btrfs_space_info_used(space_info, true); - if (test_bit(BTRFS_FS_NO_OVERCOMMIT, &fs_info->flags) && + if (test_bit(BTRFS_FS_ACTIVE_ZONE_TRACKING, &fs_info->flags) && (space_info->flags & BTRFS_BLOCK_GROUP_METADATA)) avail = 0; else diff --git a/fs/btrfs/zoned.c b/fs/btrfs/zoned.c index 0a330d5410a0..22d1e930a916 100644 --- a/fs/btrfs/zoned.c +++ b/fs/btrfs/zoned.c @@ -524,8 +524,7 @@ int btrfs_get_dev_zone_info(struct btrfs_device *device, bool populate_cache) } atomic_set(&zone_info->active_zones_left, max_active_zones - nactive); - /* Overcommit does not work well with active zone tacking. */ - set_bit(BTRFS_FS_NO_OVERCOMMIT, &fs_info->flags); + set_bit(BTRFS_FS_ACTIVE_ZONE_TRACKING, &fs_info->flags); } /* Validate superblock log */ -- cgit From df384da5a49cace5c5e3100803dfd563fd982f93 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Wed, 1 Mar 2023 16:14:43 -0500 Subject: btrfs: use temporary variable for space_info in btrfs_update_block_group We do cache->space_info->counter += num_bytes; everywhere in here. This is makes the lines longer than they need to be, and will be especially noticeable when we add the active tracking in, so add a temp variable for the space_info so this is cleaner. Reviewed-by: Naohiro Aota Reviewed-by: Johannes Thumshirn Reviewed-by: Anand Jain Signed-off-by: Josef Bacik Reviewed-by: David Sterba Signed-off-by: David Sterba --- fs/btrfs/block-group.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/fs/btrfs/block-group.c b/fs/btrfs/block-group.c index 0ef8b8926bfa..1a31bcd554d0 100644 --- a/fs/btrfs/block-group.c +++ b/fs/btrfs/block-group.c @@ -3476,6 +3476,7 @@ int btrfs_update_block_group(struct btrfs_trans_handle *trans, spin_unlock(&info->delalloc_root_lock); while (total) { + struct btrfs_space_info *space_info; bool reclaim = false; cache = btrfs_lookup_block_group(info, bytenr); @@ -3483,6 +3484,7 @@ int btrfs_update_block_group(struct btrfs_trans_handle *trans, ret = -ENOENT; break; } + space_info = cache->space_info; factor = btrfs_bg_type_to_factor(cache->flags); /* @@ -3497,7 +3499,7 @@ int btrfs_update_block_group(struct btrfs_trans_handle *trans, byte_in_group = bytenr - cache->start; WARN_ON(byte_in_group > cache->length); - spin_lock(&cache->space_info->lock); + spin_lock(&space_info->lock); spin_lock(&cache->lock); if (btrfs_test_opt(info, SPACE_CACHE) && @@ -3510,24 +3512,24 @@ int btrfs_update_block_group(struct btrfs_trans_handle *trans, old_val += num_bytes; cache->used = old_val; cache->reserved -= num_bytes; - cache->space_info->bytes_reserved -= num_bytes; - cache->space_info->bytes_used += num_bytes; - cache->space_info->disk_used += num_bytes * factor; + space_info->bytes_reserved -= num_bytes; + space_info->bytes_used += num_bytes; + space_info->disk_used += num_bytes * factor; spin_unlock(&cache->lock); - spin_unlock(&cache->space_info->lock); + spin_unlock(&space_info->lock); } else { old_val -= num_bytes; cache->used = old_val; cache->pinned += num_bytes; - btrfs_space_info_update_bytes_pinned(info, - cache->space_info, num_bytes); - cache->space_info->bytes_used -= num_bytes; - cache->space_info->disk_used -= num_bytes * factor; + btrfs_space_info_update_bytes_pinned(info, space_info, + num_bytes); + space_info->bytes_used -= num_bytes; + space_info->disk_used -= num_bytes * factor; reclaim = should_reclaim_block_group(cache, num_bytes); spin_unlock(&cache->lock); - spin_unlock(&cache->space_info->lock); + spin_unlock(&space_info->lock); set_extent_dirty(&trans->transaction->pinned_extents, bytenr, bytenr + num_bytes - 1, -- cgit From fa2068d7e922b434eba5bfb0131e6d39febfdb48 Mon Sep 17 00:00:00 2001 From: Naohiro Aota Date: Mon, 13 Mar 2023 16:06:13 +0900 Subject: btrfs: zoned: count fresh BG region as zone unusable The naming of space_info->active_total_bytes is misleading. It counts not only active block groups but also full ones which are previously active but now inactive. That confusion results in a bug not counting the full BGs into active_total_bytes on mount time. For a background, there are three kinds of block groups in terms of activation. 1. Block groups never activated 2. Block groups currently active 3. Block groups previously active and currently inactive (due to fully written or zone finish) What we really wanted to exclude from "total_bytes" is the total size of BGs #1. They seem empty and allocatable but since they are not activated, we cannot rely on them to do the space reservation. And, since BGs #1 never get activated, they should have no "used", "reserved" and "pinned" bytes. OTOH, BGs #3 can be counted in the "total", since they are already full we cannot allocate from them anyway. For them, "total_bytes == used + reserved + pinned + zone_unusable" should hold. Tracking #2 and #3 as "active_total_bytes" (current implementation) is confusing. And, tracking #1 and subtract that properly from "total_bytes" every time you need space reservation is cumbersome. Instead, we can count the whole region of a newly allocated block group as zone_unusable. Then, once that block group is activated, release [0 .. zone_capacity] from the zone_unusable counters. With this, we can eliminate the confusing ->active_total_bytes and the code will be common among regular and the zoned mode. Also, no additional counter is needed with this approach. Fixes: 6a921de58992 ("btrfs: zoned: introduce space_info->active_total_bytes") CC: stable@vger.kernel.org # 6.1+ Signed-off-by: Naohiro Aota Signed-off-by: David Sterba --- fs/btrfs/free-space-cache.c | 8 +++++++- fs/btrfs/zoned.c | 24 +++++++++++++++++++----- 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index 0d250d052487..d84cef89cdff 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c @@ -2693,8 +2693,13 @@ static int __btrfs_add_free_space_zoned(struct btrfs_block_group *block_group, bg_reclaim_threshold = READ_ONCE(sinfo->bg_reclaim_threshold); spin_lock(&ctl->tree_lock); + /* Count initial region as zone_unusable until it gets activated. */ if (!used) to_free = size; + else if (initial && + test_bit(BTRFS_FS_ACTIVE_ZONE_TRACKING, &block_group->fs_info->flags) && + (block_group->flags & (BTRFS_BLOCK_GROUP_METADATA | BTRFS_BLOCK_GROUP_SYSTEM))) + to_free = 0; else if (initial) to_free = block_group->zone_capacity; else if (offset >= block_group->alloc_offset) @@ -2722,7 +2727,8 @@ static int __btrfs_add_free_space_zoned(struct btrfs_block_group *block_group, reclaimable_unusable = block_group->zone_unusable - (block_group->length - block_group->zone_capacity); /* All the region is now unusable. Mark it as unused and reclaim */ - if (block_group->zone_unusable == block_group->length) { + if (block_group->zone_unusable == block_group->length && + block_group->alloc_offset) { btrfs_mark_bg_unused(block_group); } else if (bg_reclaim_threshold && reclaimable_unusable >= diff --git a/fs/btrfs/zoned.c b/fs/btrfs/zoned.c index 22d1e930a916..6828712578ca 100644 --- a/fs/btrfs/zoned.c +++ b/fs/btrfs/zoned.c @@ -1580,9 +1580,19 @@ void btrfs_calc_zone_unusable(struct btrfs_block_group *cache) return; WARN_ON(cache->bytes_super != 0); - unusable = (cache->alloc_offset - cache->used) + - (cache->length - cache->zone_capacity); - free = cache->zone_capacity - cache->alloc_offset; + + /* Check for block groups never get activated */ + if (test_bit(BTRFS_FS_ACTIVE_ZONE_TRACKING, &cache->fs_info->flags) && + cache->flags & (BTRFS_BLOCK_GROUP_METADATA | BTRFS_BLOCK_GROUP_SYSTEM) && + !test_bit(BLOCK_GROUP_FLAG_ZONE_IS_ACTIVE, &cache->runtime_flags) && + cache->alloc_offset == 0) { + unusable = cache->length; + free = 0; + } else { + unusable = (cache->alloc_offset - cache->used) + + (cache->length - cache->zone_capacity); + free = cache->zone_capacity - cache->alloc_offset; + } /* We only need ->free_space in ALLOC_SEQ block groups */ cache->cached = BTRFS_CACHE_FINISHED; @@ -1901,7 +1911,11 @@ bool btrfs_zone_activate(struct btrfs_block_group *block_group) /* Successfully activated all the zones */ set_bit(BLOCK_GROUP_FLAG_ZONE_IS_ACTIVE, &block_group->runtime_flags); - space_info->active_total_bytes += block_group->length; + WARN_ON(block_group->alloc_offset != 0); + if (block_group->zone_unusable == block_group->length) { + block_group->zone_unusable = block_group->length - block_group->zone_capacity; + space_info->bytes_zone_unusable -= block_group->zone_capacity; + } spin_unlock(&block_group->lock); btrfs_try_granting_tickets(fs_info, space_info); spin_unlock(&space_info->lock); @@ -2265,7 +2279,7 @@ int btrfs_zone_finish_one_bg(struct btrfs_fs_info *fs_info) u64 avail; spin_lock(&block_group->lock); - if (block_group->reserved || + if (block_group->reserved || block_group->alloc_offset == 0 || (block_group->flags & BTRFS_BLOCK_GROUP_SYSTEM)) { spin_unlock(&block_group->lock); continue; -- cgit From e15acc25880cf048dba9df94d76ed7e7e10040e6 Mon Sep 17 00:00:00 2001 From: Naohiro Aota Date: Mon, 13 Mar 2023 16:06:14 +0900 Subject: btrfs: zoned: drop space_info->active_total_bytes The space_info->active_total_bytes is no longer necessary as we now count the region of newly allocated block group as zone_unusable. Drop its usage. Fixes: 6a921de58992 ("btrfs: zoned: introduce space_info->active_total_bytes") CC: stable@vger.kernel.org # 6.1+ Signed-off-by: Naohiro Aota Signed-off-by: David Sterba --- fs/btrfs/block-group.c | 6 ------ fs/btrfs/space-info.c | 40 +++++++++------------------------------- fs/btrfs/space-info.h | 2 -- fs/btrfs/zoned.c | 4 ---- 4 files changed, 9 insertions(+), 43 deletions(-) diff --git a/fs/btrfs/block-group.c b/fs/btrfs/block-group.c index 1a31bcd554d0..5fc670c27f86 100644 --- a/fs/btrfs/block-group.c +++ b/fs/btrfs/block-group.c @@ -1175,14 +1175,8 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans, < block_group->zone_unusable); WARN_ON(block_group->space_info->disk_total < block_group->length * factor); - WARN_ON(test_bit(BLOCK_GROUP_FLAG_ZONE_IS_ACTIVE, - &block_group->runtime_flags) && - block_group->space_info->active_total_bytes - < block_group->length); } block_group->space_info->total_bytes -= block_group->length; - if (test_bit(BLOCK_GROUP_FLAG_ZONE_IS_ACTIVE, &block_group->runtime_flags)) - block_group->space_info->active_total_bytes -= block_group->length; block_group->space_info->bytes_readonly -= (block_group->length - block_group->zone_unusable); block_group->space_info->bytes_zone_unusable -= diff --git a/fs/btrfs/space-info.c b/fs/btrfs/space-info.c index 2237685d1ed0..3eecce86f63f 100644 --- a/fs/btrfs/space-info.c +++ b/fs/btrfs/space-info.c @@ -308,8 +308,6 @@ void btrfs_add_bg_to_space_info(struct btrfs_fs_info *info, ASSERT(found); spin_lock(&found->lock); found->total_bytes += block_group->length; - if (test_bit(BLOCK_GROUP_FLAG_ZONE_IS_ACTIVE, &block_group->runtime_flags)) - found->active_total_bytes += block_group->length; found->disk_total += block_group->length * factor; found->bytes_used += block_group->used; found->disk_used += block_group->used * factor; @@ -379,22 +377,6 @@ static u64 calc_available_free_space(struct btrfs_fs_info *fs_info, return avail; } -static inline u64 writable_total_bytes(struct btrfs_fs_info *fs_info, - struct btrfs_space_info *space_info) -{ - /* - * On regular filesystem, all total_bytes are always writable. On zoned - * filesystem, there may be a limitation imposed by max_active_zones. - * For metadata allocation, we cannot finish an existing active block - * group to avoid a deadlock. Thus, we need to consider only the active - * groups to be writable for metadata space. - */ - if (!btrfs_is_zoned(fs_info) || (space_info->flags & BTRFS_BLOCK_GROUP_DATA)) - return space_info->total_bytes; - - return space_info->active_total_bytes; -} - int btrfs_can_overcommit(struct btrfs_fs_info *fs_info, struct btrfs_space_info *space_info, u64 bytes, enum btrfs_reserve_flush_enum flush) @@ -413,7 +395,7 @@ int btrfs_can_overcommit(struct btrfs_fs_info *fs_info, else avail = calc_available_free_space(fs_info, space_info, flush); - if (used + bytes < writable_total_bytes(fs_info, space_info) + avail) + if (used + bytes < space_info->total_bytes + avail) return 1; return 0; } @@ -449,7 +431,7 @@ again: ticket = list_first_entry(head, struct reserve_ticket, list); /* Check and see if our ticket can be satisfied now. */ - if ((used + ticket->bytes <= writable_total_bytes(fs_info, space_info)) || + if ((used + ticket->bytes <= space_info->total_bytes) || btrfs_can_overcommit(fs_info, space_info, ticket->bytes, flush)) { btrfs_space_info_update_bytes_may_use(fs_info, @@ -829,7 +811,6 @@ btrfs_calc_reclaim_metadata_size(struct btrfs_fs_info *fs_info, { u64 used; u64 avail; - u64 total; u64 to_reclaim = space_info->reclaim_size; lockdep_assert_held(&space_info->lock); @@ -844,9 +825,8 @@ btrfs_calc_reclaim_metadata_size(struct btrfs_fs_info *fs_info, * space. If that's the case add in our overage so we make sure to put * appropriate pressure on the flushing state machine. */ - total = writable_total_bytes(fs_info, space_info); - if (total + avail < used) - to_reclaim += used - (total + avail); + if (space_info->total_bytes + avail < used) + to_reclaim += used - (space_info->total_bytes + avail); return to_reclaim; } @@ -856,11 +836,10 @@ static bool need_preemptive_reclaim(struct btrfs_fs_info *fs_info, { u64 global_rsv_size = fs_info->global_block_rsv.reserved; u64 ordered, delalloc; - u64 total = writable_total_bytes(fs_info, space_info); u64 thresh; u64 used; - thresh = mult_perc(total, 90); + thresh = mult_perc(space_info->total_bytes, 90); lockdep_assert_held(&space_info->lock); @@ -923,8 +902,8 @@ static bool need_preemptive_reclaim(struct btrfs_fs_info *fs_info, BTRFS_RESERVE_FLUSH_ALL); used = space_info->bytes_used + space_info->bytes_reserved + space_info->bytes_readonly + global_rsv_size; - if (used < total) - thresh += total - used; + if (used < space_info->total_bytes) + thresh += space_info->total_bytes - used; thresh >>= space_info->clamp; used = space_info->bytes_pinned; @@ -1651,7 +1630,7 @@ static int __reserve_bytes(struct btrfs_fs_info *fs_info, * can_overcommit() to ensure we can overcommit to continue. */ if (!pending_tickets && - ((used + orig_bytes <= writable_total_bytes(fs_info, space_info)) || + ((used + orig_bytes <= space_info->total_bytes) || btrfs_can_overcommit(fs_info, space_info, orig_bytes, flush))) { btrfs_space_info_update_bytes_may_use(fs_info, space_info, orig_bytes); @@ -1665,8 +1644,7 @@ static int __reserve_bytes(struct btrfs_fs_info *fs_info, */ if (ret && unlikely(flush == BTRFS_RESERVE_FLUSH_EMERGENCY)) { used = btrfs_space_info_used(space_info, false); - if (used + orig_bytes <= - writable_total_bytes(fs_info, space_info)) { + if (used + orig_bytes <= space_info->total_bytes) { btrfs_space_info_update_bytes_may_use(fs_info, space_info, orig_bytes); ret = 0; diff --git a/fs/btrfs/space-info.h b/fs/btrfs/space-info.h index fc99ea2b0c34..2033b71b18ce 100644 --- a/fs/btrfs/space-info.h +++ b/fs/btrfs/space-info.h @@ -96,8 +96,6 @@ struct btrfs_space_info { u64 bytes_may_use; /* number of bytes that may be used for delalloc/allocations */ u64 bytes_readonly; /* total bytes that are read only */ - /* Total bytes in the space, but only accounts active block groups. */ - u64 active_total_bytes; u64 bytes_zone_unusable; /* total bytes that are unusable until resetting the device zone */ diff --git a/fs/btrfs/zoned.c b/fs/btrfs/zoned.c index 6828712578ca..45d04092f2f8 100644 --- a/fs/btrfs/zoned.c +++ b/fs/btrfs/zoned.c @@ -2316,10 +2316,6 @@ int btrfs_zoned_activate_one_bg(struct btrfs_fs_info *fs_info, if (!btrfs_is_zoned(fs_info) || (space_info->flags & BTRFS_BLOCK_GROUP_DATA)) return 0; - /* No more block groups to activate */ - if (space_info->active_total_bytes == space_info->total_bytes) - return 0; - for (;;) { int ret; bool need_finish = false; -- cgit From eb81a2ed4f52be831c9fb879752d89645a312c13 Mon Sep 17 00:00:00 2001 From: Yang Jihong Date: Tue, 14 Mar 2023 04:47:35 +0000 Subject: perf/core: Fix perf_output_begin parameter is incorrectly invoked in perf_event_bpf_output syzkaller reportes a KASAN issue with stack-out-of-bounds. The call trace is as follows: dump_stack+0x9c/0xd3 print_address_description.constprop.0+0x19/0x170 __kasan_report.cold+0x6c/0x84 kasan_report+0x3a/0x50 __perf_event_header__init_id+0x34/0x290 perf_event_header__init_id+0x48/0x60 perf_output_begin+0x4a4/0x560 perf_event_bpf_output+0x161/0x1e0 perf_iterate_sb_cpu+0x29e/0x340 perf_iterate_sb+0x4c/0xc0 perf_event_bpf_event+0x194/0x2c0 __bpf_prog_put.constprop.0+0x55/0xf0 __cls_bpf_delete_prog+0xea/0x120 [cls_bpf] cls_bpf_delete_prog_work+0x1c/0x30 [cls_bpf] process_one_work+0x3c2/0x730 worker_thread+0x93/0x650 kthread+0x1b8/0x210 ret_from_fork+0x1f/0x30 commit 267fb27352b6 ("perf: Reduce stack usage of perf_output_begin()") use on-stack struct perf_sample_data of the caller function. However, perf_event_bpf_output uses incorrect parameter to convert small-sized data (struct perf_bpf_event) into large-sized data (struct perf_sample_data), which causes memory overwriting occurs in __perf_event_header__init_id. Fixes: 267fb27352b6 ("perf: Reduce stack usage of perf_output_begin()") Signed-off-by: Yang Jihong Signed-off-by: Peter Zijlstra (Intel) Link: https://lkml.kernel.org/r/20230314044735.56551-1-yangjihong1@huawei.com --- kernel/events/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/events/core.c b/kernel/events/core.c index f79fd8b87f75..296617edbda1 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -9187,7 +9187,7 @@ static void perf_event_bpf_output(struct perf_event *event, void *data) perf_event_header__init_id(&bpf_event->event_id.header, &sample, event); - ret = perf_output_begin(&handle, data, event, + ret = perf_output_begin(&handle, &sample, event, bpf_event->event_id.header.size); if (ret) return; -- cgit From baf1b12a67f5b24f395baca03e442ce27cab0c18 Mon Sep 17 00:00:00 2001 From: Song Liu Date: Mon, 13 Mar 2023 10:16:08 -0700 Subject: perf: fix perf_event_context->time Time readers rely on perf_event_context->[time|timestamp|timeoffset] to get accurate time_enabled and time_running for an event. The difference between ctx->timestamp and ctx->time is the among of time when the context is not enabled. __update_context_time(ctx, false) is used to increase timestamp, but not time. Therefore, it should only be called in ctx_sched_in() when EVENT_TIME was not enabled. Fixes: 09f5e7dc7ad7 ("perf: Fix perf_event_read_local() time") Signed-off-by: Song Liu Signed-off-by: Peter Zijlstra (Intel) Acked-by: Namhyung Kim Link: https://lkml.kernel.org/r/20230313171608.298734-1-song@kernel.org --- kernel/events/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/events/core.c b/kernel/events/core.c index 296617edbda1..52b4aa0b3bd1 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -3872,7 +3872,7 @@ ctx_sched_in(struct perf_event_context *ctx, enum event_type_t event_type) if (likely(!ctx->nr_events)) return; - if (is_active ^ EVENT_TIME) { + if (!(is_active & EVENT_TIME)) { /* start ctx time */ __update_context_time(ctx, false); perf_cgroup_set_timestamp(cpuctx); -- cgit From fd0815f632c24878e325821943edccc7fde947a2 Mon Sep 17 00:00:00 2001 From: Budimir Markovic Date: Wed, 15 Mar 2023 00:29:01 -0700 Subject: perf: Fix check before add_event_to_groups() in perf_group_detach() Events should only be added to a groups rb tree if they have not been removed from their context by list_del_event(). Since remove_on_exec made it possible to call list_del_event() on individual events before they are detached from their group, perf_group_detach() should check each sibling's attach_state before calling add_event_to_groups() on it. Fixes: 2e498d0a74e5 ("perf: Add support for event removal on exec") Signed-off-by: Budimir Markovic Signed-off-by: Peter Zijlstra (Intel) Link: https://lkml.kernel.org/r/ZBFzvQV9tEqoHEtH@gentoo --- kernel/events/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/events/core.c b/kernel/events/core.c index 52b4aa0b3bd1..fb3e436bcd4a 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -2163,7 +2163,7 @@ static void perf_group_detach(struct perf_event *event) /* Inherit group flags from the previous leader */ sibling->group_caps = event->group_caps; - if (!RB_EMPTY_NODE(&event->group_node)) { + if (sibling->attach_state & PERF_ATTACH_CONTEXT) { add_event_to_groups(sibling, event->ctx); if (sibling->state == PERF_EVENT_STATE_ACTIVE) -- cgit From 0424a7dfe9129b93f29b277511a60e87f052ac6b Mon Sep 17 00:00:00 2001 From: Shawn Wang Date: Tue, 17 Jan 2023 13:14:50 -0800 Subject: x86/resctrl: Clear staged_config[] before and after it is used As a temporary storage, staged_config[] in rdt_domain should be cleared before and after it is used. The stale value in staged_config[] could cause an MSR access error. Here is a reproducer on a system with 16 usable CLOSIDs for a 15-way L3 Cache (MBA should be disabled if the number of CLOSIDs for MB is less than 16.) : mount -t resctrl resctrl -o cdp /sys/fs/resctrl mkdir /sys/fs/resctrl/p{1..7} umount /sys/fs/resctrl/ mount -t resctrl resctrl /sys/fs/resctrl mkdir /sys/fs/resctrl/p{1..8} An error occurs when creating resource group named p8: unchecked MSR access error: WRMSR to 0xca0 (tried to write 0x00000000000007ff) at rIP: 0xffffffff82249142 (cat_wrmsr+0x32/0x60) Call Trace: __flush_smp_call_function_queue+0x11d/0x170 __sysvec_call_function+0x24/0xd0 sysvec_call_function+0x89/0xc0 asm_sysvec_call_function+0x16/0x20 When creating a new resource control group, hardware will be configured by the following process: rdtgroup_mkdir() rdtgroup_mkdir_ctrl_mon() rdtgroup_init_alloc() resctrl_arch_update_domains() resctrl_arch_update_domains() iterates and updates all resctrl_conf_type whose have_new_ctrl is true. Since staged_config[] holds the same values as when CDP was enabled, it will continue to update the CDP_CODE and CDP_DATA configurations. When group p8 is created, get_config_index() called in resctrl_arch_update_domains() will return 16 and 17 as the CLOSIDs for CDP_CODE and CDP_DATA, which will be translated to an invalid register - 0xca0 in this scenario. Fix it by clearing staged_config[] before and after it is used. [reinette: re-order commit tags] Fixes: 75408e43509e ("x86/resctrl: Allow different CODE/DATA configurations to be staged") Suggested-by: Xin Hao Signed-off-by: Shawn Wang Signed-off-by: Reinette Chatre Signed-off-by: Dave Hansen Tested-by: Reinette Chatre Cc:stable@vger.kernel.org Link: https://lore.kernel.org/all/2fad13f49fbe89687fc40e9a5a61f23a28d1507a.1673988935.git.reinette.chatre%40intel.com --- arch/x86/kernel/cpu/resctrl/ctrlmondata.c | 7 ++----- arch/x86/kernel/cpu/resctrl/internal.h | 1 + arch/x86/kernel/cpu/resctrl/rdtgroup.c | 25 +++++++++++++++++++++---- 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/arch/x86/kernel/cpu/resctrl/ctrlmondata.c b/arch/x86/kernel/cpu/resctrl/ctrlmondata.c index eb07d4435391..b44c487727d4 100644 --- a/arch/x86/kernel/cpu/resctrl/ctrlmondata.c +++ b/arch/x86/kernel/cpu/resctrl/ctrlmondata.c @@ -368,7 +368,6 @@ ssize_t rdtgroup_schemata_write(struct kernfs_open_file *of, { struct resctrl_schema *s; struct rdtgroup *rdtgrp; - struct rdt_domain *dom; struct rdt_resource *r; char *tok, *resname; int ret = 0; @@ -397,10 +396,7 @@ ssize_t rdtgroup_schemata_write(struct kernfs_open_file *of, goto out; } - list_for_each_entry(s, &resctrl_schema_all, list) { - list_for_each_entry(dom, &s->res->domains, list) - memset(dom->staged_config, 0, sizeof(dom->staged_config)); - } + rdt_staged_configs_clear(); while ((tok = strsep(&buf, "\n")) != NULL) { resname = strim(strsep(&tok, ":")); @@ -445,6 +441,7 @@ ssize_t rdtgroup_schemata_write(struct kernfs_open_file *of, } out: + rdt_staged_configs_clear(); rdtgroup_kn_unlock(of->kn); cpus_read_unlock(); return ret ?: nbytes; diff --git a/arch/x86/kernel/cpu/resctrl/internal.h b/arch/x86/kernel/cpu/resctrl/internal.h index 8edecc5763d8..85ceaf9a31ac 100644 --- a/arch/x86/kernel/cpu/resctrl/internal.h +++ b/arch/x86/kernel/cpu/resctrl/internal.h @@ -555,5 +555,6 @@ void __check_limbo(struct rdt_domain *d, bool force_free); void rdt_domain_reconfigure_cdp(struct rdt_resource *r); void __init thread_throttle_mode_init(void); void __init mbm_config_rftype_init(const char *config); +void rdt_staged_configs_clear(void); #endif /* _ASM_X86_RESCTRL_INTERNAL_H */ diff --git a/arch/x86/kernel/cpu/resctrl/rdtgroup.c b/arch/x86/kernel/cpu/resctrl/rdtgroup.c index 884b6e9a7e31..6ad33f355861 100644 --- a/arch/x86/kernel/cpu/resctrl/rdtgroup.c +++ b/arch/x86/kernel/cpu/resctrl/rdtgroup.c @@ -78,6 +78,19 @@ void rdt_last_cmd_printf(const char *fmt, ...) va_end(ap); } +void rdt_staged_configs_clear(void) +{ + struct rdt_resource *r; + struct rdt_domain *dom; + + lockdep_assert_held(&rdtgroup_mutex); + + for_each_alloc_capable_rdt_resource(r) { + list_for_each_entry(dom, &r->domains, list) + memset(dom->staged_config, 0, sizeof(dom->staged_config)); + } +} + /* * Trivial allocator for CLOSIDs. Since h/w only supports a small number, * we can keep a bitmap of free CLOSIDs in a single integer. @@ -3107,7 +3120,9 @@ static int rdtgroup_init_alloc(struct rdtgroup *rdtgrp) { struct resctrl_schema *s; struct rdt_resource *r; - int ret; + int ret = 0; + + rdt_staged_configs_clear(); list_for_each_entry(s, &resctrl_schema_all, list) { r = s->res; @@ -3119,20 +3134,22 @@ static int rdtgroup_init_alloc(struct rdtgroup *rdtgrp) } else { ret = rdtgroup_init_cat(s, rdtgrp->closid); if (ret < 0) - return ret; + goto out; } ret = resctrl_arch_update_domains(r, rdtgrp->closid); if (ret < 0) { rdt_last_cmd_puts("Failed to initialize allocations\n"); - return ret; + goto out; } } rdtgrp->mode = RDT_MODE_SHAREABLE; - return 0; +out: + rdt_staged_configs_clear(); + return ret; } static int mkdir_rdt_prepare(struct kernfs_node *parent_kn, -- cgit From a5bb73b3f5db1a4e91402ad132b59b13d2651ed9 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 14 Mar 2023 02:31:45 -0700 Subject: hwmon: (adm1266) Set `can_sleep` flag for GPIO chip The adm1266 driver uses I2C bus access in its GPIO chip `set` and `get` implementation. This means these functions can sleep and the GPIO chip should set the `can_sleep` property to true. This will ensure that a warning is printed when trying to set or get the GPIO value from a context that potentially can't sleep. Fixes: d98dfad35c38 ("hwmon: (pmbus/adm1266) Add support for GPIOs") Signed-off-by: Lars-Peter Clausen Link: https://lore.kernel.org/r/20230314093146.2443845-1-lars@metafoo.de Signed-off-by: Guenter Roeck --- drivers/hwmon/pmbus/adm1266.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/hwmon/pmbus/adm1266.c b/drivers/hwmon/pmbus/adm1266.c index ec5f932fc6f0..1ac2b2f4c570 100644 --- a/drivers/hwmon/pmbus/adm1266.c +++ b/drivers/hwmon/pmbus/adm1266.c @@ -301,6 +301,7 @@ static int adm1266_config_gpio(struct adm1266_data *data) data->gc.label = name; data->gc.parent = &data->client->dev; data->gc.owner = THIS_MODULE; + data->gc.can_sleep = true; data->gc.base = -1; data->gc.names = data->gpio_names; data->gc.ngpio = ARRAY_SIZE(data->gpio_names); -- cgit From ab00709310eedcd8dae0df1f66d332f9bc64c99e Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 14 Mar 2023 02:31:46 -0700 Subject: hwmon: (ltc2992) Set `can_sleep` flag for GPIO chip The ltc2992 drivers uses a mutex and I2C bus access in its GPIO chip `set` and `get` implementation. This means these functions can sleep and the GPIO chip should set the `can_sleep` property to true. This will ensure that a warning is printed when trying to set or get the GPIO value from a context that potentially can't sleep. Fixes: 9ca26df1ba25 ("hwmon: (ltc2992) Add support for GPIOs.") Signed-off-by: Lars-Peter Clausen Link: https://lore.kernel.org/r/20230314093146.2443845-2-lars@metafoo.de Signed-off-by: Guenter Roeck --- drivers/hwmon/ltc2992.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/hwmon/ltc2992.c b/drivers/hwmon/ltc2992.c index 88514152d930..69341de397cb 100644 --- a/drivers/hwmon/ltc2992.c +++ b/drivers/hwmon/ltc2992.c @@ -323,6 +323,7 @@ static int ltc2992_config_gpio(struct ltc2992_state *st) st->gc.label = name; st->gc.parent = &st->client->dev; st->gc.owner = THIS_MODULE; + st->gc.can_sleep = true; st->gc.base = -1; st->gc.names = st->gpio_names; st->gc.ngpio = ARRAY_SIZE(st->gpio_names); -- cgit From a075bacde257f755bea0e53400c9f1cdd1b8e8e6 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Tue, 14 Mar 2023 16:31:32 -0700 Subject: fsverity: don't drop pagecache at end of FS_IOC_ENABLE_VERITY The full pagecache drop at the end of FS_IOC_ENABLE_VERITY is causing performance problems and is hindering adoption of fsverity. It was intended to solve a race condition where unverified pages might be left in the pagecache. But actually it doesn't solve it fully. Since the incomplete solution for this race condition has too much performance impact for it to be worth it, let's remove it for now. Fixes: 3fda4c617e84 ("fs-verity: implement FS_IOC_ENABLE_VERITY ioctl") Cc: stable@vger.kernel.org Reviewed-by: Victor Hsieh Link: https://lore.kernel.org/r/20230314235332.50270-1-ebiggers@kernel.org Signed-off-by: Eric Biggers --- fs/verity/enable.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/fs/verity/enable.c b/fs/verity/enable.c index e13db6507b38..7a0e3a84d370 100644 --- a/fs/verity/enable.c +++ b/fs/verity/enable.c @@ -8,7 +8,6 @@ #include "fsverity_private.h" #include -#include #include #include @@ -367,25 +366,27 @@ int fsverity_ioctl_enable(struct file *filp, const void __user *uarg) goto out_drop_write; err = enable_verity(filp, &arg); - if (err) - goto out_allow_write_access; /* - * Some pages of the file may have been evicted from pagecache after - * being used in the Merkle tree construction, then read into pagecache - * again by another process reading from the file concurrently. Since - * these pages didn't undergo verification against the file digest which - * fs-verity now claims to be enforcing, we have to wipe the pagecache - * to ensure that all future reads are verified. + * We no longer drop the inode's pagecache after enabling verity. This + * used to be done to try to avoid a race condition where pages could be + * evicted after being used in the Merkle tree construction, then + * re-instantiated by a concurrent read. Such pages are unverified, and + * the backing storage could have filled them with different content, so + * they shouldn't be used to fulfill reads once verity is enabled. + * + * But, dropping the pagecache has a big performance impact, and it + * doesn't fully solve the race condition anyway. So for those reasons, + * and also because this race condition isn't very important relatively + * speaking (especially for small-ish files, where the chance of a page + * being used, evicted, *and* re-instantiated all while enabling verity + * is quite small), we no longer drop the inode's pagecache. */ - filemap_write_and_wait(inode->i_mapping); - invalidate_inode_pages2(inode->i_mapping); /* * allow_write_access() is needed to pair with deny_write_access(). * Regardless, the filesystem won't allow writing to verity files. */ -out_allow_write_access: allow_write_access(filp); out_drop_write: mnt_drop_write_file(filp); -- cgit From 5bc9e2d43f86105a95f86fa096fb4e517bb0ce73 Mon Sep 17 00:00:00 2001 From: Ondrej Zary Date: Tue, 14 Mar 2023 23:58:05 +0100 Subject: ata: pata_parport: fix memory leaks When ida_alloc() fails, "pi" is not freed although the misleading comment says otherwise. Move the ida_alloc() call up so we really don't have to free "pi" in case of ida_alloc() failure. Also move ida_free() call from pi_remove_one() to pata_parport_dev_release(). It was dereferencing already freed dev pointer. Testing revealed leak even in non-failure case which was tracked down to missing put_device() call after bus_find_device_by_name(). As a result, pata_parport_dev_release() was never called. Reported-by: kernel test robot Reported-by: Dan Carpenter Link: https://lore.kernel.org/r/202303111822.IHNchbkp-lkp@intel.com/ Signed-off-by: Ondrej Zary Signed-off-by: Damien Le Moal --- drivers/ata/pata_parport/pata_parport.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/drivers/ata/pata_parport/pata_parport.c b/drivers/ata/pata_parport/pata_parport.c index 31c9677a45e3..c1576d943b43 100644 --- a/drivers/ata/pata_parport/pata_parport.c +++ b/drivers/ata/pata_parport/pata_parport.c @@ -381,6 +381,7 @@ static void pata_parport_dev_release(struct device *dev) { struct pi_adapter *pi = container_of(dev, struct pi_adapter, dev); + ida_free(&pata_parport_bus_dev_ids, dev->id); kfree(pi); } @@ -433,23 +434,27 @@ static struct pi_adapter *pi_init_one(struct parport *parport, if (bus_for_each_dev(&pata_parport_bus_type, NULL, &match, pi_find_dev)) return NULL; + id = ida_alloc(&pata_parport_bus_dev_ids, GFP_KERNEL); + if (id < 0) + return NULL; + pi = kzalloc(sizeof(struct pi_adapter), GFP_KERNEL); - if (!pi) + if (!pi) { + ida_free(&pata_parport_bus_dev_ids, id); return NULL; + } /* set up pi->dev before pi_probe_unit() so it can use dev_printk() */ pi->dev.parent = &pata_parport_bus; pi->dev.bus = &pata_parport_bus_type; pi->dev.driver = &pr->driver; pi->dev.release = pata_parport_dev_release; - id = ida_alloc(&pata_parport_bus_dev_ids, GFP_KERNEL); - if (id < 0) - return NULL; /* pata_parport_dev_release will do kfree(pi) */ pi->dev.id = id; dev_set_name(&pi->dev, "pata_parport.%u", pi->dev.id); if (device_register(&pi->dev)) { put_device(&pi->dev); - goto out_ida_free; + /* pata_parport_dev_release will do ida_free(dev->id) and kfree(pi) */ + return NULL; } pi->proto = pr; @@ -464,8 +469,7 @@ static struct pi_adapter *pi_init_one(struct parport *parport, pi->port = parport->base; par_cb.private = pi; - pi->pardev = parport_register_dev_model(parport, DRV_NAME, &par_cb, - pi->dev.id); + pi->pardev = parport_register_dev_model(parport, DRV_NAME, &par_cb, id); if (!pi->pardev) goto out_module_put; @@ -501,8 +505,7 @@ out_module_put: module_put(pi->proto->owner); out_unreg_dev: device_unregister(&pi->dev); -out_ida_free: - ida_free(&pata_parport_bus_dev_ids, pi->dev.id); + /* pata_parport_dev_release will do ida_free(dev->id) and kfree(pi) */ return NULL; } @@ -627,8 +630,7 @@ static void pi_remove_one(struct device *dev) pi_disconnect(pi); pi_release(pi); device_unregister(dev); - ida_free(&pata_parport_bus_dev_ids, dev->id); - /* pata_parport_dev_release will do kfree(pi) */ + /* pata_parport_dev_release will do ida_free(dev->id) and kfree(pi) */ } static ssize_t delete_device_store(struct bus_type *bus, const char *buf, @@ -644,6 +646,7 @@ static ssize_t delete_device_store(struct bus_type *bus, const char *buf, } pi_remove_one(dev); + put_device(dev); mutex_unlock(&pi_mutex); return count; -- cgit From cbebd68f59f03633469f3ecf9bea99cd6cce3854 Mon Sep 17 00:00:00 2001 From: Nikita Zhandarovich Date: Mon, 6 Mar 2023 08:06:56 -0800 Subject: x86/mm: Fix use of uninitialized buffer in sme_enable() cmdline_find_option() may fail before doing any initialization of the buffer array. This may lead to unpredictable results when the same buffer is used later in calls to strncmp() function. Fix the issue by returning early if cmdline_find_option() returns an error. Found by Linux Verification Center (linuxtesting.org) with static analysis tool SVACE. Fixes: aca20d546214 ("x86/mm: Add support to make use of Secure Memory Encryption") Signed-off-by: Nikita Zhandarovich Signed-off-by: Borislav Petkov (AMD) Acked-by: Tom Lendacky Cc: Link: https://lore.kernel.org/r/20230306160656.14844-1-n.zhandarovich@fintech.ru --- arch/x86/mm/mem_encrypt_identity.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/x86/mm/mem_encrypt_identity.c b/arch/x86/mm/mem_encrypt_identity.c index 88cccd65029d..c6efcf559d88 100644 --- a/arch/x86/mm/mem_encrypt_identity.c +++ b/arch/x86/mm/mem_encrypt_identity.c @@ -600,7 +600,8 @@ void __init sme_enable(struct boot_params *bp) cmdline_ptr = (const char *)((u64)bp->hdr.cmd_line_ptr | ((u64)bp->ext_cmd_line_ptr << 32)); - cmdline_find_option(cmdline_ptr, cmdline_arg, buffer, sizeof(buffer)); + if (cmdline_find_option(cmdline_ptr, cmdline_arg, buffer, sizeof(buffer)) < 0) + return; if (!strncmp(buffer, cmdline_on, sizeof(buffer))) sme_me_mask = me_mask; -- cgit From 81f59a26f3d59c6aeb137b7b5546848779222c65 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Thu, 16 Mar 2023 00:50:17 +0900 Subject: kbuild: rpm-pkg: move source components to rpmbuild/SOURCES Prepare to add more files to the source RPM. Also, fix the build error when KCONFIG_CONFIG is set: error: Bad file: ./.config: No such file or directory Signed-off-by: Masahiro Yamada --- .gitignore | 1 + Makefile | 2 +- scripts/Makefile.package | 2 +- scripts/package/mkspec | 12 ++++++++---- 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index 8fe465f251c0..70ec6037fa7a 100644 --- a/.gitignore +++ b/.gitignore @@ -78,6 +78,7 @@ modules.order # RPM spec file (make rpm-pkg) # /*.spec +/rpmbuild/ # # Debian directory (make deb-pkg) diff --git a/Makefile b/Makefile index d0a0ba8e5a2e..dfff9f8d28e5 100644 --- a/Makefile +++ b/Makefile @@ -1605,7 +1605,7 @@ MRPROPER_FILES += include/config include/generated \ certs/signing_key.pem \ certs/x509.genkey \ vmlinux-gdb.py \ - *.spec \ + *.spec rpmbuild \ rust/libmacros.so # clean - Delete most, but leave enough to build external modules diff --git a/scripts/Makefile.package b/scripts/Makefile.package index b941e6341b36..a0355bdeebff 100644 --- a/scripts/Makefile.package +++ b/scripts/Makefile.package @@ -89,7 +89,7 @@ PHONY += srcrpm-pkg srcrpm-pkg: linux.tar.gz $(CONFIG_SHELL) $(MKSPEC) >$(objtree)/kernel.spec +rpmbuild $(RPMOPTS) --target $(UTS_MACHINE)-linux -bs kernel.spec \ - --define='_smp_mflags %{nil}' --define='_sourcedir .' --define='_srcrpmdir .' + --define='_smp_mflags %{nil}' --define='_sourcedir rpmbuild/SOURCES' --define='_srcrpmdir .' # binrpm-pkg # --------------------------------------------------------------------------- diff --git a/scripts/package/mkspec b/scripts/package/mkspec index 3c550960dd39..5f007137f5a0 100755 --- a/scripts/package/mkspec +++ b/scripts/package/mkspec @@ -15,15 +15,19 @@ if [ "$1" = prebuilt ]; then MAKE="$MAKE -f $srctree/Makefile" else S= + + mkdir -p rpmbuild/SOURCES + cp linux.tar.gz rpmbuild/SOURCES + cp "${KCONFIG_CONFIG}" rpmbuild/SOURCES/config fi -if grep -q CONFIG_MODULES=y .config; then +if grep -q CONFIG_MODULES=y include/config/auto.conf; then M= else M=DEL fi -if grep -q CONFIG_DRM=y .config; then +if grep -q CONFIG_DRM=y include/config/auto.conf; then PROVIDES=kernel-drm fi @@ -48,7 +52,7 @@ sed -e '/^DEL/d' -e 's/^\t*//' < Date: Thu, 16 Mar 2023 00:50:18 +0900 Subject: kbuild: use git-archive for source package creation Commit 5c3d1d0abb12 ("kbuild: add a tool to list files ignored by git") added a new tool, scripts/list-gitignored. My intention was to create source packages without cleaning the source tree, without relying on git. Linus strongly objected to it, and suggested using 'git archive' instead. [1] [2] [3] This commit goes in that direction - Remove scripts/list-gitignored.c and rewrites Makefiles and scripts to use 'git archive' for building Debian and RPM source packages. It also makes 'make perf-tar*-src-pkg' use 'git archive' again. Going forward, building source packages is only possible in a git-managed tree. Building binary packages does not require git. [1]: https://lore.kernel.org/lkml/CAHk-=wi49sMaC7vY1yMagk7eqLK=1jHeHQ=yZ_k45P=xBccnmA@mail.gmail.com/ [2]: https://lore.kernel.org/lkml/CAHk-=wh5AixGsLeT0qH2oZHKq0FLUTbyTw4qY921L=PwYgoGVw@mail.gmail.com/ [3]: https://lore.kernel.org/lkml/CAHk-=wgM-W6Fu==EoAVCabxyX8eYBz9kNC88-tm9ExRQwA79UQ@mail.gmail.com/ Fixes: 5c3d1d0abb12 ("kbuild: add a tool to list files ignored by git") Fixes: e0ca16749ac3 ("kbuild: make perf-tar*-src-pkg work without relying on git") Suggested-by: Linus Torvalds Signed-off-by: Masahiro Yamada --- Makefile | 7 +- scripts/.gitignore | 1 - scripts/Makefile | 2 +- scripts/Makefile.package | 146 +++--- scripts/check-git | 14 + scripts/list-gitignored.c | 1057 ---------------------------------------- scripts/package/gen-diff-patch | 44 ++ scripts/package/mkdebian | 10 +- scripts/package/mkspec | 10 + scripts/setlocalversion | 45 +- 10 files changed, 181 insertions(+), 1155 deletions(-) create mode 100755 scripts/check-git delete mode 100644 scripts/list-gitignored.c create mode 100755 scripts/package/gen-diff-patch diff --git a/Makefile b/Makefile index dfff9f8d28e5..0de1288dc451 100644 --- a/Makefile +++ b/Makefile @@ -274,8 +274,7 @@ no-dot-config-targets := $(clean-targets) \ cscope gtags TAGS tags help% %docs check% coccicheck \ $(version_h) headers headers_% archheaders archscripts \ %asm-generic kernelversion %src-pkg dt_binding_check \ - outputmakefile rustavailable rustfmt rustfmtcheck \ - scripts_package + outputmakefile rustavailable rustfmt rustfmtcheck # Installation targets should not require compiler. Unfortunately, vdso_install # is an exception where build artifacts may be updated. This must be fixed. no-compiler-targets := $(no-dot-config-targets) install dtbs_install \ @@ -1656,10 +1655,6 @@ distclean: mrproper %pkg: include/config/kernel.release FORCE $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.package $@ -PHONY += scripts_package -scripts_package: scripts_basic - $(Q)$(MAKE) $(build)=scripts scripts/list-gitignored - # Brief documentation of the typical targets used # --------------------------------------------------------------------------- diff --git a/scripts/.gitignore b/scripts/.gitignore index feb43045d1b1..6e9ce6720a05 100644 --- a/scripts/.gitignore +++ b/scripts/.gitignore @@ -3,7 +3,6 @@ /generate_rust_target /insert-sys-cert /kallsyms -/list-gitignored /module.lds /recordmcount /sign-file diff --git a/scripts/Makefile b/scripts/Makefile index e8917975905c..32b6ba722728 100644 --- a/scripts/Makefile +++ b/scripts/Makefile @@ -38,7 +38,7 @@ HOSTCFLAGS_sorttable.o += -DMCOUNT_SORT_ENABLED endif # The following programs are only built on demand -hostprogs += list-gitignored unifdef +hostprogs += unifdef # The module linker script is preprocessed on demand targets += module.lds diff --git a/scripts/Makefile.package b/scripts/Makefile.package index a0355bdeebff..61f72eb8d9be 100644 --- a/scripts/Makefile.package +++ b/scripts/Makefile.package @@ -2,6 +2,7 @@ # Makefile for the different targets used to generate full packages of a kernel include $(srctree)/scripts/Kbuild.include +include $(srctree)/scripts/Makefile.lib KERNELPATH := kernel-$(subst -,_,$(KERNELRELEASE)) KBUILD_PKG_ROOTCMD ?="fakeroot -u" @@ -26,54 +27,46 @@ fi ; \ tar -I $(KGZIP) -c $(RCS_TAR_IGNORE) -f $(2).tar.gz \ --transform 's:^:$(2)/:S' $(TAR_CONTENT) $(3) -# .tmp_filelist .tmp_filelist_exclude +# tarball compression # --------------------------------------------------------------------------- -scripts/list-gitignored: FORCE - $(Q)$(MAKE) -f $(srctree)/Makefile scripts_package +%.tar.gz: %.tar + $(call cmd,gzip) -# 1f5d3a6b6532e25a5cdf1f311956b2b03d343a48 removed '*.rej' from .gitignore, -# but it is definitely a generated file. -filechk_filelist = \ - $< --exclude='*.rej' --output=$@_exclude --prefix=./ --rootdir=$(srctree) --stat=- +%.tar.bz2: %.tar + $(call cmd,bzip2) -.tmp_filelist: scripts/list-gitignored FORCE - $(call filechk,filelist) +%.tar.xz: %.tar + $(call cmd,xzmisc) -# tarball -# --------------------------------------------------------------------------- - -quiet_cmd_tar = TAR $@ - cmd_tar = tar -c -f $@ $(tar-compress-opt) $(tar-exclude-opt) \ - --owner=0 --group=0 --sort=name \ - --transform 's:^\.:$*:S' -C $(tar-rootdir) . - -tar-rootdir := $(srctree) +%.tar.zst: %.tar + $(call cmd,zstd) -%.tar: - $(call cmd,tar) - -%.tar.gz: private tar-compress-opt := -I $(KGZIP) -%.tar.gz: - $(call cmd,tar) +# Git +# --------------------------------------------------------------------------- -%.tar.bz2: private tar-compress-opt := -I $(KBZIP2) -%.tar.bz2: - $(call cmd,tar) +filechk_HEAD = git -C $(srctree) rev-parse --verify HEAD 2>/dev/null -%.tar.xz: private tar-compress-opt := -I $(XZ) -%.tar.xz: - $(call cmd,tar) +.tmp_HEAD: check-git FORCE + $(call filechk,HEAD) -%.tar.zst: private tar-compress-opt := -I $(ZSTD) -%.tar.zst: - $(call cmd,tar) +PHONY += check-git +check-git: + @if ! $(srctree)/scripts/check-git; then \ + echo >&2 "error: creating source package requires git repository"; \ + false; \ + fi # Linux source tarball # --------------------------------------------------------------------------- -linux.tar.gz: tar-exclude-opt = --exclude=./$@ --exclude-from=$<_exclude -linux.tar.gz: .tmp_filelist +quiet_cmd_archive_linux = ARCHIVE $@ + cmd_archive_linux = \ + git -C $(srctree) archive --output=$$(realpath $@) --prefix=$(basename $@)/ $$(cat $<) + +targets += linux.tar +linux.tar: .tmp_HEAD FORCE + $(call if_changed,archive_linux) # rpm-pkg # --------------------------------------------------------------------------- @@ -148,74 +141,62 @@ snap-pkg: # dir-pkg tar*-pkg - tarball targets # --------------------------------------------------------------------------- -tar-pkg-tarball = linux-$(KERNELRELEASE)-$(ARCH).$(1) -tar-pkg-phony = $(subst .,,$(1))-pkg - tar-install: FORCE $(Q)$(MAKE) -f $(srctree)/Makefile +$(Q)$(srctree)/scripts/package/buildtar $@ +quiet_cmd_tar = TAR $@ + cmd_tar = cd $<; tar cf ../$@ --owner=root --group=root --sort=name * + +linux-$(KERNELRELEASE)-$(ARCH).tar: tar-install + $(call cmd,tar) + PHONY += dir-pkg dir-pkg: tar-install @echo "Kernel tree successfully created in $<" -define tar-pkg-rule -PHONY += $(tar-pkg-phony) -$(tar-pkg-phony): $(tar-pkg-tarball) +PHONY += tar-pkg +tar-pkg: linux-$(KERNELRELEASE)-$(ARCH).tar @: -$(tar-pkg-tarball): private tar-rootdir := tar-install -$(tar-pkg-tarball): tar-install -endef - -$(foreach x, tar tar.gz tar.bz2 tar.xz tar.zst, $(eval $(call tar-pkg-rule,$(x)))) +tar%-pkg: linux-$(KERNELRELEASE)-$(ARCH).tar.% FORCE + @: # perf-tar*-src-pkg - generate a source tarball with perf source # --------------------------------------------------------------------------- -perf-tar-src-pkg-tarball = perf-$(KERNELVERSION).$(1) -perf-tar-src-pkg-phony = perf-$(subst .,,$(1))-src-pkg - -quiet_cmd_stage_perf_src = STAGE $@ - cmd_stage_perf_src = \ - rm -rf $@; \ - mkdir -p $@; \ - tar -c -f - --exclude-from=$<_exclude -C $(srctree) --files-from=$(srctree)/tools/perf/MANIFEST | \ - tar -x -f - -C $@ - -.tmp_perf: .tmp_filelist - $(call cmd,stage_perf_src) - -filechk_perf_head = \ - if test -z "$(git -C $(srctree) rev-parse --show-cdup 2>/dev/null)" && \ - head=$$(git -C $(srctree) rev-parse --verify HEAD 2>/dev/null); then \ - echo $$head; \ - else \ - echo "not a git tree"; \ - fi +.tmp_perf: + $(Q)mkdir .tmp_perf -.tmp_perf/HEAD: .tmp_perf FORCE - $(call filechk,perf_head) +.tmp_perf/HEAD: .tmp_HEAD | .tmp_perf + $(call cmd,copy) quiet_cmd_perf_version_file = GEN $@ cmd_perf_version_file = cd $(srctree)/tools/perf; util/PERF-VERSION-GEN $(dir $(abspath $@)) -# PERF-VERSION-FILE and HEAD are independent, but this avoids updating the +# PERF-VERSION-FILE and .tmp_HEAD are independent, but this avoids updating the # timestamp of PERF-VERSION-FILE. # The best is to fix tools/perf/util/PERF-VERSION-GEN. -.tmp_perf/PERF-VERSION-FILE: .tmp_perf/HEAD $(srctree)/tools/perf/util/PERF-VERSION-GEN +.tmp_perf/PERF-VERSION-FILE: .tmp_HEAD $(srctree)/tools/perf/util/PERF-VERSION-GEN | .tmp_perf $(call cmd,perf_version_file) -define perf-tar-src-pkg-rule -PHONY += $(perf-tar-src-pkg-phony) -$(perf-tar-src-pkg-phony): $(perf-tar-src-pkg-tarball) - @: +quiet_cmd_archive_perf = ARCHIVE $@ + cmd_archive_perf = \ + git -C $(srctree) archive --output=$$(realpath $@) --prefix=$(basename $@)/ \ + --add-file=$$(realpath $(word 2, $^)) \ + --add-file=$$(realpath $(word 3, $^)) \ + $$(cat $(word 2, $^))^{tree} $$(cat $<) -$(perf-tar-src-pkg-tarball): private tar-rootdir := .tmp_perf -$(perf-tar-src-pkg-tarball): .tmp_filelist .tmp_perf/HEAD .tmp_perf/PERF-VERSION-FILE -endef +targets += perf-$(KERNELVERSION).tar +perf-$(KERNELVERSION).tar: tools/perf/MANIFEST .tmp_perf/HEAD .tmp_perf/PERF-VERSION-FILE FORCE + $(call if_changed,archive_perf) + +PHONY += perf-tar-src-pkg +perf-tar-src-pkg: perf-$(KERNELVERSION).tar + @: -$(foreach x, tar tar.gz tar.bz2 tar.xz tar.zst, $(eval $(call perf-tar-src-pkg-rule,$(x)))) +perf-tar%-src-pkg: perf-$(KERNELVERSION).tar.% FORCE + @: # Help text displayed when executing 'make help' # --------------------------------------------------------------------------- @@ -243,4 +224,13 @@ help: PHONY += FORCE FORCE: +# Read all saved command lines and dependencies for the $(targets) we +# may be building above, using $(if_changed{,_dep}). As an +# optimization, we don't need to read them if the target does not +# exist, we will rebuild anyway in that case. + +existing-targets := $(wildcard $(sort $(targets))) + +-include $(foreach f,$(existing-targets),$(dir $(f)).$(notdir $(f)).cmd) + .PHONY: $(PHONY) diff --git a/scripts/check-git b/scripts/check-git new file mode 100755 index 000000000000..2ca6c5df10dd --- /dev/null +++ b/scripts/check-git @@ -0,0 +1,14 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0-only +# +# succeed if we are in a git repository + +srctree="$(dirname $0)/.." + +if ! git -C "${srctree}" rev-parse --verify HEAD >/dev/null 2>/dev/null; then + exit 1 +fi + +if ! test -z $(git -C "${srctree}" rev-parse --show-cdup 2>/dev/null); then + exit 1 +fi diff --git a/scripts/list-gitignored.c b/scripts/list-gitignored.c deleted file mode 100644 index f9941f8dcd2b..000000000000 --- a/scripts/list-gitignored.c +++ /dev/null @@ -1,1057 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -// -// Traverse the source tree, parsing all .gitignore files, and print file paths -// that are ignored by git. -// The output is suitable to the --exclude-from option of tar. -// This is useful until the --exclude-vcs-ignores option gets working correctly. -// -// Copyright (C) 2023 Masahiro Yamada -// (a lot of code imported from GIT) - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// Imported from commit 23c56f7bd5f1667f8b793d796bf30e39545920f6 in GIT -// -//---------------------------(IMPORT FROM GIT BEGIN)--------------------------- - -// Copied from environment.c - -static bool ignore_case; - -// Copied from git-compat-util.h - -/* Sane ctype - no locale, and works with signed chars */ -#undef isascii -#undef isspace -#undef isdigit -#undef isalpha -#undef isalnum -#undef isprint -#undef islower -#undef isupper -#undef tolower -#undef toupper -#undef iscntrl -#undef ispunct -#undef isxdigit - -static const unsigned char sane_ctype[256]; -#define GIT_SPACE 0x01 -#define GIT_DIGIT 0x02 -#define GIT_ALPHA 0x04 -#define GIT_GLOB_SPECIAL 0x08 -#define GIT_REGEX_SPECIAL 0x10 -#define GIT_PATHSPEC_MAGIC 0x20 -#define GIT_CNTRL 0x40 -#define GIT_PUNCT 0x80 -#define sane_istest(x,mask) ((sane_ctype[(unsigned char)(x)] & (mask)) != 0) -#define isascii(x) (((x) & ~0x7f) == 0) -#define isspace(x) sane_istest(x,GIT_SPACE) -#define isdigit(x) sane_istest(x,GIT_DIGIT) -#define isalpha(x) sane_istest(x,GIT_ALPHA) -#define isalnum(x) sane_istest(x,GIT_ALPHA | GIT_DIGIT) -#define isprint(x) ((x) >= 0x20 && (x) <= 0x7e) -#define islower(x) sane_iscase(x, 1) -#define isupper(x) sane_iscase(x, 0) -#define is_glob_special(x) sane_istest(x,GIT_GLOB_SPECIAL) -#define iscntrl(x) (sane_istest(x,GIT_CNTRL)) -#define ispunct(x) sane_istest(x, GIT_PUNCT | GIT_REGEX_SPECIAL | \ - GIT_GLOB_SPECIAL | GIT_PATHSPEC_MAGIC) -#define isxdigit(x) (hexval_table[(unsigned char)(x)] != -1) -#define tolower(x) sane_case((unsigned char)(x), 0x20) -#define toupper(x) sane_case((unsigned char)(x), 0) - -static inline int sane_case(int x, int high) -{ - if (sane_istest(x, GIT_ALPHA)) - x = (x & ~0x20) | high; - return x; -} - -static inline int sane_iscase(int x, int is_lower) -{ - if (!sane_istest(x, GIT_ALPHA)) - return 0; - - if (is_lower) - return (x & 0x20) != 0; - else - return (x & 0x20) == 0; -} - -// Copied from ctype.c - -enum { - S = GIT_SPACE, - A = GIT_ALPHA, - D = GIT_DIGIT, - G = GIT_GLOB_SPECIAL, /* *, ?, [, \\ */ - R = GIT_REGEX_SPECIAL, /* $, (, ), +, ., ^, {, | */ - P = GIT_PATHSPEC_MAGIC, /* other non-alnum, except for ] and } */ - X = GIT_CNTRL, - U = GIT_PUNCT, - Z = GIT_CNTRL | GIT_SPACE -}; - -static const unsigned char sane_ctype[256] = { - X, X, X, X, X, X, X, X, X, Z, Z, X, X, Z, X, X, /* 0.. 15 */ - X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, /* 16.. 31 */ - S, P, P, P, R, P, P, P, R, R, G, R, P, P, R, P, /* 32.. 47 */ - D, D, D, D, D, D, D, D, D, D, P, P, P, P, P, G, /* 48.. 63 */ - P, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, /* 64.. 79 */ - A, A, A, A, A, A, A, A, A, A, A, G, G, U, R, P, /* 80.. 95 */ - P, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, /* 96..111 */ - A, A, A, A, A, A, A, A, A, A, A, R, R, U, P, X, /* 112..127 */ - /* Nothing in the 128.. range */ -}; - -// Copied from hex.c - -static const signed char hexval_table[256] = { - -1, -1, -1, -1, -1, -1, -1, -1, /* 00-07 */ - -1, -1, -1, -1, -1, -1, -1, -1, /* 08-0f */ - -1, -1, -1, -1, -1, -1, -1, -1, /* 10-17 */ - -1, -1, -1, -1, -1, -1, -1, -1, /* 18-1f */ - -1, -1, -1, -1, -1, -1, -1, -1, /* 20-27 */ - -1, -1, -1, -1, -1, -1, -1, -1, /* 28-2f */ - 0, 1, 2, 3, 4, 5, 6, 7, /* 30-37 */ - 8, 9, -1, -1, -1, -1, -1, -1, /* 38-3f */ - -1, 10, 11, 12, 13, 14, 15, -1, /* 40-47 */ - -1, -1, -1, -1, -1, -1, -1, -1, /* 48-4f */ - -1, -1, -1, -1, -1, -1, -1, -1, /* 50-57 */ - -1, -1, -1, -1, -1, -1, -1, -1, /* 58-5f */ - -1, 10, 11, 12, 13, 14, 15, -1, /* 60-67 */ - -1, -1, -1, -1, -1, -1, -1, -1, /* 68-67 */ - -1, -1, -1, -1, -1, -1, -1, -1, /* 70-77 */ - -1, -1, -1, -1, -1, -1, -1, -1, /* 78-7f */ - -1, -1, -1, -1, -1, -1, -1, -1, /* 80-87 */ - -1, -1, -1, -1, -1, -1, -1, -1, /* 88-8f */ - -1, -1, -1, -1, -1, -1, -1, -1, /* 90-97 */ - -1, -1, -1, -1, -1, -1, -1, -1, /* 98-9f */ - -1, -1, -1, -1, -1, -1, -1, -1, /* a0-a7 */ - -1, -1, -1, -1, -1, -1, -1, -1, /* a8-af */ - -1, -1, -1, -1, -1, -1, -1, -1, /* b0-b7 */ - -1, -1, -1, -1, -1, -1, -1, -1, /* b8-bf */ - -1, -1, -1, -1, -1, -1, -1, -1, /* c0-c7 */ - -1, -1, -1, -1, -1, -1, -1, -1, /* c8-cf */ - -1, -1, -1, -1, -1, -1, -1, -1, /* d0-d7 */ - -1, -1, -1, -1, -1, -1, -1, -1, /* d8-df */ - -1, -1, -1, -1, -1, -1, -1, -1, /* e0-e7 */ - -1, -1, -1, -1, -1, -1, -1, -1, /* e8-ef */ - -1, -1, -1, -1, -1, -1, -1, -1, /* f0-f7 */ - -1, -1, -1, -1, -1, -1, -1, -1, /* f8-ff */ -}; - -// Copied from wildmatch.h - -#define WM_CASEFOLD 1 -#define WM_PATHNAME 2 - -#define WM_NOMATCH 1 -#define WM_MATCH 0 -#define WM_ABORT_ALL -1 -#define WM_ABORT_TO_STARSTAR -2 - -// Copied from wildmatch.c - -typedef unsigned char uchar; - -// local modification: remove NEGATE_CLASS(2) - -#define CC_EQ(class, len, litmatch) ((len) == sizeof (litmatch)-1 \ - && *(class) == *(litmatch) \ - && strncmp((char*)class, litmatch, len) == 0) - -// local modification: simpilify macros -#define ISBLANK(c) ((c) == ' ' || (c) == '\t') -#define ISGRAPH(c) (isprint(c) && !isspace(c)) -#define ISPRINT(c) isprint(c) -#define ISDIGIT(c) isdigit(c) -#define ISALNUM(c) isalnum(c) -#define ISALPHA(c) isalpha(c) -#define ISCNTRL(c) iscntrl(c) -#define ISLOWER(c) islower(c) -#define ISPUNCT(c) ispunct(c) -#define ISSPACE(c) isspace(c) -#define ISUPPER(c) isupper(c) -#define ISXDIGIT(c) isxdigit(c) - -/* Match pattern "p" against "text" */ -static int dowild(const uchar *p, const uchar *text, unsigned int flags) -{ - uchar p_ch; - const uchar *pattern = p; - - for ( ; (p_ch = *p) != '\0'; text++, p++) { - int matched, match_slash, negated; - uchar t_ch, prev_ch; - if ((t_ch = *text) == '\0' && p_ch != '*') - return WM_ABORT_ALL; - if ((flags & WM_CASEFOLD) && ISUPPER(t_ch)) - t_ch = tolower(t_ch); - if ((flags & WM_CASEFOLD) && ISUPPER(p_ch)) - p_ch = tolower(p_ch); - switch (p_ch) { - case '\\': - /* Literal match with following character. Note that the test - * in "default" handles the p[1] == '\0' failure case. */ - p_ch = *++p; - /* FALLTHROUGH */ - default: - if (t_ch != p_ch) - return WM_NOMATCH; - continue; - case '?': - /* Match anything but '/'. */ - if ((flags & WM_PATHNAME) && t_ch == '/') - return WM_NOMATCH; - continue; - case '*': - if (*++p == '*') { - const uchar *prev_p = p - 2; - while (*++p == '*') {} - if (!(flags & WM_PATHNAME)) - /* without WM_PATHNAME, '*' == '**' */ - match_slash = 1; - else if ((prev_p < pattern || *prev_p == '/') && - (*p == '\0' || *p == '/' || - (p[0] == '\\' && p[1] == '/'))) { - /* - * Assuming we already match 'foo/' and are at - * , just assume it matches - * nothing and go ahead match the rest of the - * pattern with the remaining string. This - * helps make foo/<*><*>/bar (<> because - * otherwise it breaks C comment syntax) match - * both foo/bar and foo/a/bar. - */ - if (p[0] == '/' && - dowild(p + 1, text, flags) == WM_MATCH) - return WM_MATCH; - match_slash = 1; - } else /* WM_PATHNAME is set */ - match_slash = 0; - } else - /* without WM_PATHNAME, '*' == '**' */ - match_slash = flags & WM_PATHNAME ? 0 : 1; - if (*p == '\0') { - /* Trailing "**" matches everything. Trailing "*" matches - * only if there are no more slash characters. */ - if (!match_slash) { - if (strchr((char *)text, '/')) - return WM_NOMATCH; - } - return WM_MATCH; - } else if (!match_slash && *p == '/') { - /* - * _one_ asterisk followed by a slash - * with WM_PATHNAME matches the next - * directory - */ - const char *slash = strchr((char*)text, '/'); - if (!slash) - return WM_NOMATCH; - text = (const uchar*)slash; - /* the slash is consumed by the top-level for loop */ - break; - } - while (1) { - if (t_ch == '\0') - break; - /* - * Try to advance faster when an asterisk is - * followed by a literal. We know in this case - * that the string before the literal - * must belong to "*". - * If match_slash is false, do not look past - * the first slash as it cannot belong to '*'. - */ - if (!is_glob_special(*p)) { - p_ch = *p; - if ((flags & WM_CASEFOLD) && ISUPPER(p_ch)) - p_ch = tolower(p_ch); - while ((t_ch = *text) != '\0' && - (match_slash || t_ch != '/')) { - if ((flags & WM_CASEFOLD) && ISUPPER(t_ch)) - t_ch = tolower(t_ch); - if (t_ch == p_ch) - break; - text++; - } - if (t_ch != p_ch) - return WM_NOMATCH; - } - if ((matched = dowild(p, text, flags)) != WM_NOMATCH) { - if (!match_slash || matched != WM_ABORT_TO_STARSTAR) - return matched; - } else if (!match_slash && t_ch == '/') - return WM_ABORT_TO_STARSTAR; - t_ch = *++text; - } - return WM_ABORT_ALL; - case '[': - p_ch = *++p; - if (p_ch == '^') - p_ch = '!'; - /* Assign literal 1/0 because of "matched" comparison. */ - negated = p_ch == '!' ? 1 : 0; - if (negated) { - /* Inverted character class. */ - p_ch = *++p; - } - prev_ch = 0; - matched = 0; - do { - if (!p_ch) - return WM_ABORT_ALL; - if (p_ch == '\\') { - p_ch = *++p; - if (!p_ch) - return WM_ABORT_ALL; - if (t_ch == p_ch) - matched = 1; - } else if (p_ch == '-' && prev_ch && p[1] && p[1] != ']') { - p_ch = *++p; - if (p_ch == '\\') { - p_ch = *++p; - if (!p_ch) - return WM_ABORT_ALL; - } - if (t_ch <= p_ch && t_ch >= prev_ch) - matched = 1; - else if ((flags & WM_CASEFOLD) && ISLOWER(t_ch)) { - uchar t_ch_upper = toupper(t_ch); - if (t_ch_upper <= p_ch && t_ch_upper >= prev_ch) - matched = 1; - } - p_ch = 0; /* This makes "prev_ch" get set to 0. */ - } else if (p_ch == '[' && p[1] == ':') { - const uchar *s; - int i; - for (s = p += 2; (p_ch = *p) && p_ch != ']'; p++) {} /*SHARED ITERATOR*/ - if (!p_ch) - return WM_ABORT_ALL; - i = p - s - 1; - if (i < 0 || p[-1] != ':') { - /* Didn't find ":]", so treat like a normal set. */ - p = s - 2; - p_ch = '['; - if (t_ch == p_ch) - matched = 1; - continue; - } - if (CC_EQ(s,i, "alnum")) { - if (ISALNUM(t_ch)) - matched = 1; - } else if (CC_EQ(s,i, "alpha")) { - if (ISALPHA(t_ch)) - matched = 1; - } else if (CC_EQ(s,i, "blank")) { - if (ISBLANK(t_ch)) - matched = 1; - } else if (CC_EQ(s,i, "cntrl")) { - if (ISCNTRL(t_ch)) - matched = 1; - } else if (CC_EQ(s,i, "digit")) { - if (ISDIGIT(t_ch)) - matched = 1; - } else if (CC_EQ(s,i, "graph")) { - if (ISGRAPH(t_ch)) - matched = 1; - } else if (CC_EQ(s,i, "lower")) { - if (ISLOWER(t_ch)) - matched = 1; - } else if (CC_EQ(s,i, "print")) { - if (ISPRINT(t_ch)) - matched = 1; - } else if (CC_EQ(s,i, "punct")) { - if (ISPUNCT(t_ch)) - matched = 1; - } else if (CC_EQ(s,i, "space")) { - if (ISSPACE(t_ch)) - matched = 1; - } else if (CC_EQ(s,i, "upper")) { - if (ISUPPER(t_ch)) - matched = 1; - else if ((flags & WM_CASEFOLD) && ISLOWER(t_ch)) - matched = 1; - } else if (CC_EQ(s,i, "xdigit")) { - if (ISXDIGIT(t_ch)) - matched = 1; - } else /* malformed [:class:] string */ - return WM_ABORT_ALL; - p_ch = 0; /* This makes "prev_ch" get set to 0. */ - } else if (t_ch == p_ch) - matched = 1; - } while (prev_ch = p_ch, (p_ch = *++p) != ']'); - if (matched == negated || - ((flags & WM_PATHNAME) && t_ch == '/')) - return WM_NOMATCH; - continue; - } - } - - return *text ? WM_NOMATCH : WM_MATCH; -} - -/* Match the "pattern" against the "text" string. */ -static int wildmatch(const char *pattern, const char *text, unsigned int flags) -{ - // local modification: move WM_CASEFOLD here - if (ignore_case) - flags |= WM_CASEFOLD; - - return dowild((const uchar*)pattern, (const uchar*)text, flags); -} - -// Copied from dir.h - -#define PATTERN_FLAG_NODIR 1 -#define PATTERN_FLAG_ENDSWITH 4 -#define PATTERN_FLAG_MUSTBEDIR 8 -#define PATTERN_FLAG_NEGATIVE 16 - -// Copied from dir.c - -static int fspathncmp(const char *a, const char *b, size_t count) -{ - return ignore_case ? strncasecmp(a, b, count) : strncmp(a, b, count); -} - -static int simple_length(const char *match) -{ - int len = -1; - - for (;;) { - unsigned char c = *match++; - len++; - if (c == '\0' || is_glob_special(c)) - return len; - } -} - -static int no_wildcard(const char *string) -{ - return string[simple_length(string)] == '\0'; -} - -static void parse_path_pattern(const char **pattern, - int *patternlen, - unsigned *flags, - int *nowildcardlen) -{ - const char *p = *pattern; - size_t i, len; - - *flags = 0; - if (*p == '!') { - *flags |= PATTERN_FLAG_NEGATIVE; - p++; - } - len = strlen(p); - if (len && p[len - 1] == '/') { - len--; - *flags |= PATTERN_FLAG_MUSTBEDIR; - } - for (i = 0; i < len; i++) { - if (p[i] == '/') - break; - } - if (i == len) - *flags |= PATTERN_FLAG_NODIR; - *nowildcardlen = simple_length(p); - /* - * we should have excluded the trailing slash from 'p' too, - * but that's one more allocation. Instead just make sure - * nowildcardlen does not exceed real patternlen - */ - if (*nowildcardlen > len) - *nowildcardlen = len; - if (*p == '*' && no_wildcard(p + 1)) - *flags |= PATTERN_FLAG_ENDSWITH; - *pattern = p; - *patternlen = len; -} - -static void trim_trailing_spaces(char *buf) -{ - char *p, *last_space = NULL; - - for (p = buf; *p; p++) - switch (*p) { - case ' ': - if (!last_space) - last_space = p; - break; - case '\\': - p++; - if (!*p) - return; - /* fallthrough */ - default: - last_space = NULL; - } - - if (last_space) - *last_space = '\0'; -} - -static int match_basename(const char *basename, int basenamelen, - const char *pattern, int prefix, int patternlen, - unsigned flags) -{ - if (prefix == patternlen) { - if (patternlen == basenamelen && - !fspathncmp(pattern, basename, basenamelen)) - return 1; - } else if (flags & PATTERN_FLAG_ENDSWITH) { - /* "*literal" matching against "fooliteral" */ - if (patternlen - 1 <= basenamelen && - !fspathncmp(pattern + 1, - basename + basenamelen - (patternlen - 1), - patternlen - 1)) - return 1; - } else { - // local modification: call wildmatch() directly - if (!wildmatch(pattern, basename, flags)) - return 1; - } - return 0; -} - -static int match_pathname(const char *pathname, int pathlen, - const char *base, int baselen, - const char *pattern, int prefix, int patternlen) -{ - // local modification: remove local variables - - /* - * match with FNM_PATHNAME; the pattern has base implicitly - * in front of it. - */ - if (*pattern == '/') { - pattern++; - patternlen--; - prefix--; - } - - /* - * baselen does not count the trailing slash. base[] may or - * may not end with a trailing slash though. - */ - if (pathlen < baselen + 1 || - (baselen && pathname[baselen] != '/') || - fspathncmp(pathname, base, baselen)) - return 0; - - // local modification: simplified because always baselen > 0 - pathname += baselen + 1; - pathlen -= baselen + 1; - - if (prefix) { - /* - * if the non-wildcard part is longer than the - * remaining pathname, surely it cannot match. - */ - if (prefix > pathlen) - return 0; - - if (fspathncmp(pattern, pathname, prefix)) - return 0; - pattern += prefix; - patternlen -= prefix; - pathname += prefix; - pathlen -= prefix; - - /* - * If the whole pattern did not have a wildcard, - * then our prefix match is all we need; we - * do not need to call fnmatch at all. - */ - if (!patternlen && !pathlen) - return 1; - } - - // local modification: call wildmatch() directly - return !wildmatch(pattern, pathname, WM_PATHNAME); -} - -// Copied from git/utf8.c - -static const char utf8_bom[] = "\357\273\277"; - -//----------------------------(IMPORT FROM GIT END)---------------------------- - -struct pattern { - unsigned int flags; - int nowildcardlen; - int patternlen; - int dirlen; - char pattern[]; -}; - -static struct pattern **pattern_list; -static int nr_patterns, alloced_patterns; - -// Remember the number of patterns at each directory level -static int *nr_patterns_at; -// Track the current/max directory level; -static int depth, max_depth; -static bool debug_on; -static FILE *out_fp, *stat_fp; -static char *prefix = ""; -static char *progname; - -static void __attribute__((noreturn)) perror_exit(const char *s) -{ - perror(s); - - exit(EXIT_FAILURE); -} - -static void __attribute__((noreturn)) error_exit(const char *fmt, ...) -{ - va_list args; - - fprintf(stderr, "%s: error: ", progname); - - va_start(args, fmt); - vfprintf(stderr, fmt, args); - va_end(args); - - exit(EXIT_FAILURE); -} - -static void debug(const char *fmt, ...) -{ - va_list args; - int i; - - if (!debug_on) - return; - - fprintf(stderr, "[DEBUG] "); - - for (i = 0; i < depth * 2; i++) - fputc(' ', stderr); - - va_start(args, fmt); - vfprintf(stderr, fmt, args); - va_end(args); -} - -static void *xrealloc(void *ptr, size_t size) -{ - ptr = realloc(ptr, size); - if (!ptr) - perror_exit(progname); - - return ptr; -} - -static void *xmalloc(size_t size) -{ - return xrealloc(NULL, size); -} - -// similar to last_matching_pattern_from_list() in GIT -static bool is_ignored(const char *path, int pathlen, int dirlen, bool is_dir) -{ - int i; - - // Search in the reverse order because the last matching pattern wins. - for (i = nr_patterns - 1; i >= 0; i--) { - struct pattern *p = pattern_list[i]; - unsigned int flags = p->flags; - const char *gitignore_dir = p->pattern + p->patternlen + 1; - bool ignored; - - if ((flags & PATTERN_FLAG_MUSTBEDIR) && !is_dir) - continue; - - if (flags & PATTERN_FLAG_NODIR) { - if (!match_basename(path + dirlen + 1, - pathlen - dirlen - 1, - p->pattern, - p->nowildcardlen, - p->patternlen, - p->flags)) - continue; - } else { - if (!match_pathname(path, pathlen, - gitignore_dir, p->dirlen, - p->pattern, - p->nowildcardlen, - p->patternlen)) - continue; - } - - debug("%s: matches %s%s%s (%s/.gitignore)\n", path, - flags & PATTERN_FLAG_NEGATIVE ? "!" : "", p->pattern, - flags & PATTERN_FLAG_MUSTBEDIR ? "/" : "", - gitignore_dir); - - ignored = (flags & PATTERN_FLAG_NEGATIVE) == 0; - if (ignored) - debug("Ignore: %s\n", path); - - return ignored; - } - - debug("%s: no match\n", path); - - return false; -} - -static void add_pattern(const char *string, const char *dir, int dirlen) -{ - struct pattern *p; - int patternlen, nowildcardlen; - unsigned int flags; - - parse_path_pattern(&string, &patternlen, &flags, &nowildcardlen); - - if (patternlen == 0) - return; - - p = xmalloc(sizeof(*p) + patternlen + dirlen + 2); - - memcpy(p->pattern, string, patternlen); - p->pattern[patternlen] = 0; - memcpy(p->pattern + patternlen + 1, dir, dirlen); - p->pattern[patternlen + 1 + dirlen] = 0; - - p->patternlen = patternlen; - p->nowildcardlen = nowildcardlen; - p->dirlen = dirlen; - p->flags = flags; - - debug("Add pattern: %s%s%s\n", - flags & PATTERN_FLAG_NEGATIVE ? "!" : "", p->pattern, - flags & PATTERN_FLAG_MUSTBEDIR ? "/" : ""); - - if (nr_patterns >= alloced_patterns) { - alloced_patterns += 128; - pattern_list = xrealloc(pattern_list, - sizeof(*pattern_list) * alloced_patterns); - } - - pattern_list[nr_patterns++] = p; -} - -// similar to add_patterns_from_buffer() in GIT -static void add_patterns_from_gitignore(const char *dir, int dirlen) -{ - struct stat st; - char path[PATH_MAX], *buf, *entry; - size_t size; - int fd, pathlen, i; - - pathlen = snprintf(path, sizeof(path), "%s/.gitignore", dir); - if (pathlen >= sizeof(path)) - error_exit("%s: too long path was truncated\n", path); - - fd = open(path, O_RDONLY | O_NOFOLLOW); - if (fd < 0) { - if (errno != ENOENT) - return perror_exit(path); - return; - } - - if (fstat(fd, &st) < 0) - perror_exit(path); - - size = st.st_size; - - buf = xmalloc(size + 1); - if (read(fd, buf, st.st_size) != st.st_size) - perror_exit(path); - - buf[st.st_size] = '\n'; - if (close(fd)) - perror_exit(path); - - debug("Parse %s\n", path); - - entry = buf; - - // skip utf8 bom - if (!strncmp(entry, utf8_bom, strlen(utf8_bom))) - entry += strlen(utf8_bom); - - for (i = entry - buf; i < size; i++) { - if (buf[i] == '\n') { - if (entry != buf + i && entry[0] != '#') { - buf[i - (i && buf[i-1] == '\r')] = 0; - trim_trailing_spaces(entry); - add_pattern(entry, dir, dirlen); - } - entry = buf + i + 1; - } - } - - free(buf); -} - -// Save the current number of patterns and increment the depth -static void increment_depth(void) -{ - if (depth >= max_depth) { - max_depth += 1; - nr_patterns_at = xrealloc(nr_patterns_at, - sizeof(*nr_patterns_at) * max_depth); - } - - nr_patterns_at[depth] = nr_patterns; - depth++; -} - -// Decrement the depth, and free up the patterns of this directory level. -static void decrement_depth(void) -{ - depth--; - assert(depth >= 0); - - while (nr_patterns > nr_patterns_at[depth]) - free(pattern_list[--nr_patterns]); -} - -static void print_path(const char *path) -{ - // The path always starts with "./" - assert(strlen(path) >= 2); - - // Replace the root directory with a preferred prefix. - // This is useful for the tar command. - fprintf(out_fp, "%s%s\n", prefix, path + 2); -} - -static void print_stat(const char *path, struct stat *st) -{ - if (!stat_fp) - return; - - if (!S_ISREG(st->st_mode) && !S_ISLNK(st->st_mode)) - return; - - assert(strlen(path) >= 2); - - fprintf(stat_fp, "%c %9ld %10ld %s\n", - S_ISLNK(st->st_mode) ? 'l' : '-', - st->st_size, st->st_mtim.tv_sec, path + 2); -} - -// Traverse the entire directory tree, parsing .gitignore files. -// Print file paths that are not tracked by git. -// -// Return true if all files under the directory are ignored, false otherwise. -static bool traverse_directory(const char *dir, int dirlen) -{ - bool all_ignored = true; - DIR *dirp; - - debug("Enter[%d]: %s\n", depth, dir); - increment_depth(); - - add_patterns_from_gitignore(dir, dirlen); - - dirp = opendir(dir); - if (!dirp) - perror_exit(dir); - - while (1) { - struct dirent *d; - struct stat st; - char path[PATH_MAX]; - int pathlen; - bool ignored; - - errno = 0; - d = readdir(dirp); - if (!d) { - if (errno) - perror_exit(dir); - break; - } - - if (!strcmp(d->d_name, "..") || !strcmp(d->d_name, ".")) - continue; - - pathlen = snprintf(path, sizeof(path), "%s/%s", dir, d->d_name); - if (pathlen >= sizeof(path)) - error_exit("%s: too long path was truncated\n", path); - - if (lstat(path, &st) < 0) - perror_exit(path); - - if ((!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode) && !S_ISLNK(st.st_mode)) || - is_ignored(path, pathlen, dirlen, S_ISDIR(st.st_mode))) { - ignored = true; - } else { - if (S_ISDIR(st.st_mode) && !S_ISLNK(st.st_mode)) - // If all the files in a directory are ignored, - // let's ignore that directory as well. This - // will avoid empty directories in the tarball. - ignored = traverse_directory(path, pathlen); - else - ignored = false; - } - - if (ignored) { - print_path(path); - } else { - print_stat(path, &st); - all_ignored = false; - } - } - - if (closedir(dirp)) - perror_exit(dir); - - decrement_depth(); - debug("Leave[%d]: %s\n", depth, dir); - - return all_ignored; -} - -static void usage(void) -{ - fprintf(stderr, - "usage: %s [options]\n" - "\n" - "Show files that are ignored by git\n" - "\n" - "options:\n" - " -d, --debug print debug messages to stderr\n" - " -e, --exclude PATTERN add the given exclude pattern\n" - " -h, --help show this help message and exit\n" - " -i, --ignore-case Ignore case differences between the patterns and the files\n" - " -o, --output FILE output the ignored files to a file (default: '-', i.e. stdout)\n" - " -p, --prefix PREFIX prefix added to each path (default: empty string)\n" - " -r, --rootdir DIR root of the source tree (default: current working directory)\n" - " -s, --stat FILE output the file stat of non-ignored files to a file\n", - progname); -} - -static void open_output(const char *pathname, FILE **fp) -{ - if (strcmp(pathname, "-")) { - *fp = fopen(pathname, "w"); - if (!*fp) - perror_exit(pathname); - } else { - *fp = stdout; - } -} - -static void close_output(const char *pathname, FILE *fp) -{ - fflush(fp); - - if (ferror(fp)) - error_exit("not all data was written to the output\n"); - - if (fclose(fp)) - perror_exit(pathname); -} - -int main(int argc, char *argv[]) -{ - const char *output = "-"; - const char *rootdir = "."; - const char *stat = NULL; - - progname = strrchr(argv[0], '/'); - if (progname) - progname++; - else - progname = argv[0]; - - while (1) { - static struct option long_options[] = { - {"debug", no_argument, NULL, 'd'}, - {"help", no_argument, NULL, 'h'}, - {"ignore-case", no_argument, NULL, 'i'}, - {"output", required_argument, NULL, 'o'}, - {"prefix", required_argument, NULL, 'p'}, - {"rootdir", required_argument, NULL, 'r'}, - {"stat", required_argument, NULL, 's'}, - {"exclude", required_argument, NULL, 'x'}, - {}, - }; - - int c = getopt_long(argc, argv, "dhino:p:r:s:x:", long_options, NULL); - - if (c == -1) - break; - - switch (c) { - case 'd': - debug_on = true; - break; - case 'h': - usage(); - exit(0); - case 'i': - ignore_case = true; - break; - case 'o': - output = optarg; - break; - case 'p': - prefix = optarg; - break; - case 'r': - rootdir = optarg; - break; - case 's': - stat = optarg; - break; - case 'x': - add_pattern(optarg, ".", strlen(".")); - break; - case '?': - usage(); - /* fallthrough */ - default: - exit(EXIT_FAILURE); - } - } - - open_output(output, &out_fp); - if (stat && stat[0]) - open_output(stat, &stat_fp); - - if (chdir(rootdir)) - perror_exit(rootdir); - - add_pattern(".git/", ".", strlen(".")); - - if (traverse_directory(".", strlen("."))) - print_path("./"); - - assert(depth == 0); - - while (nr_patterns > 0) - free(pattern_list[--nr_patterns]); - free(pattern_list); - free(nr_patterns_at); - - close_output(output, out_fp); - if (stat_fp) - close_output(stat, stat_fp); - - return 0; -} diff --git a/scripts/package/gen-diff-patch b/scripts/package/gen-diff-patch new file mode 100755 index 000000000000..f842ab50a780 --- /dev/null +++ b/scripts/package/gen-diff-patch @@ -0,0 +1,44 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0-only + +diff_patch="${1}" +untracked_patch="${2}" +srctree=$(dirname $0)/../.. + +rm -f ${diff_patch} ${untracked_patch} + +if ! ${srctree}/scripts/check-git; then + exit +fi + +mkdir -p "$(dirname ${diff_patch})" "$(dirname ${untracked_patch})" + +git -C "${srctree}" diff HEAD > "${diff_patch}" + +if [ ! -s "${diff_patch}" ]; then + rm -f "${diff_patch}" + exit +fi + +git -C ${srctree} status --porcelain --untracked-files=all | +while read stat path +do + if [ "${stat}" = '??' ]; then + + if ! diff -u /dev/null "${srctree}/${path}" > .tmp_diff && + ! head -n1 .tmp_diff | grep -q "Binary files"; then + { + echo "--- /dev/null" + echo "+++ linux/$path" + cat .tmp_diff | tail -n +3 + } >> ${untracked_patch} + fi + fi +done + +rm -f .tmp_diff + +if [ ! -s "${diff_patch}" ]; then + rm -f "${diff_patch}" + exit +fi diff --git a/scripts/package/mkdebian b/scripts/package/mkdebian index e80a661a79ee..e20a2b5be9eb 100755 --- a/scripts/package/mkdebian +++ b/scripts/package/mkdebian @@ -91,7 +91,7 @@ version=$KERNELRELEASE if [ -n "$KDEB_PKGVERSION" ]; then packageversion=$KDEB_PKGVERSION else - packageversion=$version-$($srctree/init/build-version) + packageversion=$(${srctree}/scripts/setlocalversion --no-local ${srctree})-$($srctree/init/build-version) fi sourcename=${KDEB_SOURCENAME:-linux-upstream} @@ -152,6 +152,14 @@ mkdir -p debian/patches } > debian/patches/config echo config > debian/patches/series +$(dirname $0)/gen-diff-patch debian/patches/diff.patch debian/patches/untracked.patch +if [ -f debian/patches/diff.patch ]; then + echo diff.patch >> debian/patches/series +fi +if [ -f debian/patches/untracked.patch ]; then + echo untracked.patch >> debian/patches/series +fi + echo $debarch > debian/arch extra_build_depends=", $(if_enabled_echo CONFIG_UNWINDER_ORC libelf-dev:native)" extra_build_depends="$extra_build_depends, $(if_enabled_echo CONFIG_SYSTEM_TRUSTED_KEYRING libssl-dev:native)" diff --git a/scripts/package/mkspec b/scripts/package/mkspec index 5f007137f5a0..b7d1dc28a5d6 100755 --- a/scripts/package/mkspec +++ b/scripts/package/mkspec @@ -19,6 +19,8 @@ else mkdir -p rpmbuild/SOURCES cp linux.tar.gz rpmbuild/SOURCES cp "${KCONFIG_CONFIG}" rpmbuild/SOURCES/config + $(dirname $0)/gen-diff-patch rpmbuild/SOURCES/diff.patch rpmbuild/SOURCES/untracked.patch + touch rpmbuild/SOURCES/diff.patch rpmbuild/SOURCES/untracked.patch fi if grep -q CONFIG_MODULES=y include/config/auto.conf; then @@ -53,6 +55,8 @@ sed -e '/^DEL/d' -e 's/^\t*//' <&2 + echo "Usage: $0 [--no-local] [srctree]" >&2 exit 1 } +no_local=false +if test "$1" = "--no-local"; then + no_local=true + shift +fi + srctree=. if test $# -gt 0; then srctree=$1 @@ -26,14 +32,22 @@ fi scm_version() { - local short + local short=false + local no_dirty=false local tag - short=false + + while [ $# -gt 0 ]; + do + case "$1" in + --short) + short=true;; + --no-dirty) + no_dirty=true;; + esac + shift + done cd "$srctree" - if test "$1" = "--short"; then - short=true - fi if test -n "$(git rev-parse --show-cdup 2>/dev/null)"; then return @@ -75,6 +89,10 @@ scm_version() printf '%s%s' -g "$(echo $head | cut -c1-12)" fi + if ${no_dirty}; then + return + fi + # Check for uncommitted changes. # This script must avoid any write attempt to the source tree, which # might be read-only. @@ -110,11 +128,6 @@ collect_files() echo "$res" } -if ! test -e include/config/auto.conf; then - echo "Error: kernelrelease not valid - run 'make prepare' to update it" >&2 - exit 1 -fi - if [ -z "${KERNELVERSION}" ]; then echo "KERNELVERSION is not set" >&2 exit 1 @@ -126,6 +139,16 @@ if test ! "$srctree" -ef .; then file_localversion="${file_localversion}$(collect_files "$srctree"/localversion*)" fi +if ${no_local}; then + echo "${KERNELVERSION}$(scm_version --no-dirty)" + exit 0 +fi + +if ! test -e include/config/auto.conf; then + echo "Error: kernelrelease not valid - run 'make prepare' to update it" >&2 + exit 1 +fi + # version string from CONFIG_LOCALVERSION config_localversion=$(sed -n 's/^CONFIG_LOCALVERSION=\(.*\)$/\1/p' include/config/auto.conf) -- cgit From c7df4813b149362248d6ef7be41a311e27bf75fe Mon Sep 17 00:00:00 2001 From: Kal Conley Date: Wed, 8 Mar 2023 18:40:13 +0100 Subject: xsk: Add missing overflow check in xdp_umem_reg The number of chunks can overflow u32. Make sure to return -EINVAL on overflow. Also remove a redundant u32 cast assigning umem->npgs. Fixes: bbff2f321a86 ("xsk: new descriptor addressing scheme") Signed-off-by: Kal Conley Signed-off-by: Daniel Borkmann Acked-by: Magnus Karlsson Link: https://lore.kernel.org/bpf/20230308174013.1114745-1-kal.conley@dectris.com --- net/xdp/xdp_umem.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/net/xdp/xdp_umem.c b/net/xdp/xdp_umem.c index 4681e8e8ad94..02207e852d79 100644 --- a/net/xdp/xdp_umem.c +++ b/net/xdp/xdp_umem.c @@ -150,10 +150,11 @@ static int xdp_umem_account_pages(struct xdp_umem *umem) static int xdp_umem_reg(struct xdp_umem *umem, struct xdp_umem_reg *mr) { - u32 npgs_rem, chunk_size = mr->chunk_size, headroom = mr->headroom; bool unaligned_chunks = mr->flags & XDP_UMEM_UNALIGNED_CHUNK_FLAG; - u64 npgs, addr = mr->addr, size = mr->len; - unsigned int chunks, chunks_rem; + u32 chunk_size = mr->chunk_size, headroom = mr->headroom; + u64 addr = mr->addr, size = mr->len; + u32 chunks_rem, npgs_rem; + u64 chunks, npgs; int err; if (chunk_size < XDP_UMEM_MIN_CHUNK_SIZE || chunk_size > PAGE_SIZE) { @@ -188,8 +189,8 @@ static int xdp_umem_reg(struct xdp_umem *umem, struct xdp_umem_reg *mr) if (npgs > U32_MAX) return -EINVAL; - chunks = (unsigned int)div_u64_rem(size, chunk_size, &chunks_rem); - if (chunks == 0) + chunks = div_u64_rem(size, chunk_size, &chunks_rem); + if (!chunks || chunks > U32_MAX) return -EINVAL; if (!unaligned_chunks && chunks_rem) @@ -202,7 +203,7 @@ static int xdp_umem_reg(struct xdp_umem *umem, struct xdp_umem_reg *mr) umem->headroom = headroom; umem->chunk_size = chunk_size; umem->chunks = chunks; - umem->npgs = (u32)npgs; + umem->npgs = npgs; umem->pgs = NULL; umem->user = NULL; umem->flags = mr->flags; -- cgit From 203873a535d627c668f293be0cb73e26c30f9cc7 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Thu, 16 Mar 2023 11:38:19 +0100 Subject: fbdev: stifb: Provide valid pixelclock and add fb_check_var() checks Find a valid modeline depending on the machine graphic card configuration and add the fb_check_var() function to validate Xorg provided graphics settings. Signed-off-by: Helge Deller Cc: stable@vger.kernel.org --- drivers/video/fbdev/stifb.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/drivers/video/fbdev/stifb.c b/drivers/video/fbdev/stifb.c index 3feb6e40d56d..ef8a4c5fc687 100644 --- a/drivers/video/fbdev/stifb.c +++ b/drivers/video/fbdev/stifb.c @@ -921,6 +921,28 @@ SETUP_HCRX(struct stifb_info *fb) /* ------------------- driver specific functions --------------------------- */ +static int +stifb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) +{ + struct stifb_info *fb = container_of(info, struct stifb_info, info); + + if (var->xres != fb->info.var.xres || + var->yres != fb->info.var.yres || + var->bits_per_pixel != fb->info.var.bits_per_pixel) + return -EINVAL; + + var->xres_virtual = var->xres; + var->yres_virtual = var->yres; + var->xoffset = 0; + var->yoffset = 0; + var->grayscale = fb->info.var.grayscale; + var->red.length = fb->info.var.red.length; + var->green.length = fb->info.var.green.length; + var->blue.length = fb->info.var.blue.length; + + return 0; +} + static int stifb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, u_int transp, struct fb_info *info) @@ -1145,6 +1167,7 @@ stifb_init_display(struct stifb_info *fb) static const struct fb_ops stifb_ops = { .owner = THIS_MODULE, + .fb_check_var = stifb_check_var, .fb_setcolreg = stifb_setcolreg, .fb_blank = stifb_blank, .fb_fillrect = stifb_fillrect, @@ -1164,6 +1187,7 @@ static int __init stifb_init_fb(struct sti_struct *sti, int bpp_pref) struct stifb_info *fb; struct fb_info *info; unsigned long sti_rom_address; + char modestr[32]; char *dev_name; int bpp, xres, yres; @@ -1342,6 +1366,9 @@ static int __init stifb_init_fb(struct sti_struct *sti, int bpp_pref) info->flags = FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT; info->pseudo_palette = &fb->pseudo_palette; + scnprintf(modestr, sizeof(modestr), "%dx%d-%d", xres, yres, bpp); + fb_find_mode(&info->var, info, modestr, NULL, 0, NULL, bpp); + /* This has to be done !!! */ if (fb_alloc_cmap(&info->cmap, NR_PALETTE, 0)) goto out_err1; -- cgit From 92e2a00f2987483e1f9253625828622edd442e61 Mon Sep 17 00:00:00 2001 From: Wei Chen Date: Wed, 15 Mar 2023 07:18:31 +0000 Subject: fbdev: nvidia: Fix potential divide by zero variable var->pixclock can be set by user. In case it equals to zero, divide by zero would occur in nvidiafb_set_par. Similar crashes have happened in other fbdev drivers. There is no check and modification on var->pixclock along the call chain to nvidia_check_var and nvidiafb_set_par. We believe it could also be triggered in driver nvidia from user site. Signed-off-by: Wei Chen Signed-off-by: Helge Deller --- drivers/video/fbdev/nvidia/nvidia.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/video/fbdev/nvidia/nvidia.c b/drivers/video/fbdev/nvidia/nvidia.c index e60a276b4855..ea4ba3dfb96b 100644 --- a/drivers/video/fbdev/nvidia/nvidia.c +++ b/drivers/video/fbdev/nvidia/nvidia.c @@ -764,6 +764,8 @@ static int nvidiafb_check_var(struct fb_var_screeninfo *var, int pitch, err = 0; NVTRACE_ENTER(); + if (!var->pixclock) + return -EINVAL; var->transp.offset = 0; var->transp.length = 0; -- cgit From d823685486a3446d061fed7c7d2f80af984f119a Mon Sep 17 00:00:00 2001 From: Wei Chen Date: Wed, 15 Mar 2023 08:33:47 +0000 Subject: fbdev: intelfb: Fix potential divide by zero Variable var->pixclock is controlled by user and can be assigned to zero. Without proper check, divide by zero would occur in intelfbhw_validate_mode and intelfbhw_mode_to_hw. Error out if var->pixclock is zero. Signed-off-by: Wei Chen Signed-off-by: Helge Deller --- drivers/video/fbdev/intelfb/intelfbdrv.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/video/fbdev/intelfb/intelfbdrv.c b/drivers/video/fbdev/intelfb/intelfbdrv.c index 0a9e5067b201..a81095b2b1ea 100644 --- a/drivers/video/fbdev/intelfb/intelfbdrv.c +++ b/drivers/video/fbdev/intelfb/intelfbdrv.c @@ -1222,6 +1222,9 @@ static int intelfb_check_var(struct fb_var_screeninfo *var, dinfo = GET_DINFO(info); + if (!var->pixclock) + return -EINVAL; + /* update the pitch */ if (intelfbhw_validate_mode(dinfo, var) != 0) return -EINVAL; -- cgit From 61ac4b86a4c047c20d5cb423ddd87496f14d9868 Mon Sep 17 00:00:00 2001 From: Wei Chen Date: Wed, 15 Mar 2023 09:05:18 +0000 Subject: fbdev: lxfb: Fix potential divide by zero var->pixclock can be assigned to zero by user. Without proper check, divide by zero would occur in lx_set_clock. Error out if var->pixclock is zero. Signed-off-by: Wei Chen Signed-off-by: Helge Deller --- drivers/video/fbdev/geode/lxfb_core.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/video/fbdev/geode/lxfb_core.c b/drivers/video/fbdev/geode/lxfb_core.c index 8130e9eee2b4..556d8b1a9e06 100644 --- a/drivers/video/fbdev/geode/lxfb_core.c +++ b/drivers/video/fbdev/geode/lxfb_core.c @@ -235,6 +235,9 @@ static void get_modedb(struct fb_videomode **modedb, unsigned int *size) static int lxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) { + if (!var->pixclock) + return -EINVAL; + if (var->xres > 1920 || var->yres > 1440) return -EINVAL; -- cgit From 44a3b36b42acfc433aaaf526191dd12fbb919fdb Mon Sep 17 00:00:00 2001 From: Wei Chen Date: Wed, 15 Mar 2023 09:22:54 +0000 Subject: fbdev: au1200fb: Fix potential divide by zero var->pixclock can be assigned to zero by user. Without proper check, divide by zero would occur when invoking macro PICOS2KHZ in au1200fb_fb_check_var. Error out if var->pixclock is zero. Signed-off-by: Wei Chen Signed-off-by: Helge Deller --- drivers/video/fbdev/au1200fb.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/video/fbdev/au1200fb.c b/drivers/video/fbdev/au1200fb.c index 81c315454428..b6b22fa4a8a0 100644 --- a/drivers/video/fbdev/au1200fb.c +++ b/drivers/video/fbdev/au1200fb.c @@ -1040,6 +1040,9 @@ static int au1200fb_fb_check_var(struct fb_var_screeninfo *var, u32 pixclock; int screen_size, plane; + if (!var->pixclock) + return -EINVAL; + plane = fbdev->plane; /* Make sure that the mode respect all LCD controller and -- cgit From 29413f05fe34e8824551b91f660fde781249417d Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Fri, 10 Mar 2023 08:47:29 -0600 Subject: fbdev: Use of_property_present() for testing DT property presence It is preferred to use typed property access functions (i.e. of_property_read_ functions) rather than low-level of_get_property/of_find_property functions for reading properties. As part of this, convert of_get_property/of_find_property calls to the recently added of_property_present() helper when we just want to test for presence of a property and nothing more. Signed-off-by: Rob Herring Signed-off-by: Helge Deller --- drivers/video/fbdev/amba-clcd.c | 2 +- drivers/video/fbdev/bw2.c | 2 +- drivers/video/fbdev/cg3.c | 2 +- drivers/video/fbdev/omap2/omapfb/dss/omapdss-boot-init.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/video/fbdev/amba-clcd.c b/drivers/video/fbdev/amba-clcd.c index f65c96d1394d..e45338227be6 100644 --- a/drivers/video/fbdev/amba-clcd.c +++ b/drivers/video/fbdev/amba-clcd.c @@ -854,7 +854,7 @@ static struct clcd_board *clcdfb_of_get_board(struct amba_device *dev) board->caps = CLCD_CAP_ALL; board->check = clcdfb_check; board->decode = clcdfb_decode; - if (of_find_property(node, "memory-region", NULL)) { + if (of_property_present(node, "memory-region")) { board->setup = clcdfb_of_vram_setup; board->mmap = clcdfb_of_vram_mmap; board->remove = clcdfb_of_vram_remove; diff --git a/drivers/video/fbdev/bw2.c b/drivers/video/fbdev/bw2.c index 6403ae07970d..9cbadcd18b25 100644 --- a/drivers/video/fbdev/bw2.c +++ b/drivers/video/fbdev/bw2.c @@ -306,7 +306,7 @@ static int bw2_probe(struct platform_device *op) if (!par->regs) goto out_release_fb; - if (!of_find_property(dp, "width", NULL)) { + if (!of_property_present(dp, "width")) { err = bw2_do_default_mode(par, info, &linebytes); if (err) goto out_unmap_regs; diff --git a/drivers/video/fbdev/cg3.c b/drivers/video/fbdev/cg3.c index bdcc3f6ab666..3a37fff4df36 100644 --- a/drivers/video/fbdev/cg3.c +++ b/drivers/video/fbdev/cg3.c @@ -393,7 +393,7 @@ static int cg3_probe(struct platform_device *op) cg3_blank(FB_BLANK_UNBLANK, info); - if (!of_find_property(dp, "width", NULL)) { + if (!of_property_present(dp, "width")) { err = cg3_do_default_mode(par); if (err) goto out_unmap_screen; diff --git a/drivers/video/fbdev/omap2/omapfb/dss/omapdss-boot-init.c b/drivers/video/fbdev/omap2/omapfb/dss/omapdss-boot-init.c index 0ae0cab252d3..09f719af0d0c 100644 --- a/drivers/video/fbdev/omap2/omapfb/dss/omapdss-boot-init.c +++ b/drivers/video/fbdev/omap2/omapfb/dss/omapdss-boot-init.c @@ -192,7 +192,7 @@ static int __init omapdss_boot_init(void) omapdss_walk_device(dss, true); for_each_available_child_of_node(dss, child) { - if (!of_find_property(child, "compatible", NULL)) + if (!of_property_present(child, "compatible")) continue; omapdss_walk_device(child, true); -- cgit From 32d57f667f871bc5a8babbe27ea4c5e668ee0ea8 Mon Sep 17 00:00:00 2001 From: Alexander Lobakin Date: Wed, 1 Mar 2023 12:59:07 +0100 Subject: iavf: fix inverted Rx hash condition leading to disabled hash Condition, which checks whether the netdev has hashing enabled is inverted. Basically, the tagged commit effectively disabled passing flow hash from descriptor to skb, unless user *disables* it via Ethtool. Commit a876c3ba59a6 ("i40e/i40evf: properly report Rx packet hash") fixed this problem, but only for i40e. Invert the condition now in iavf and unblock passing hash to skbs again. Fixes: 857942fd1aa1 ("i40e: Fix Rx hash reported to the stack by our driver") Reviewed-by: Larysa Zaremba Reviewed-by: Michal Kubiak Signed-off-by: Alexander Lobakin Tested-by: Rafal Romanowski Reviewed-by: Leon Romanovsky Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/iavf/iavf_txrx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/iavf/iavf_txrx.c b/drivers/net/ethernet/intel/iavf/iavf_txrx.c index 18b6a702a1d6..e989feda133c 100644 --- a/drivers/net/ethernet/intel/iavf/iavf_txrx.c +++ b/drivers/net/ethernet/intel/iavf/iavf_txrx.c @@ -1096,7 +1096,7 @@ static inline void iavf_rx_hash(struct iavf_ring *ring, cpu_to_le64((u64)IAVF_RX_DESC_FLTSTAT_RSS_HASH << IAVF_RX_DESC_STATUS_FLTSTAT_SHIFT); - if (ring->netdev->features & NETIF_F_RXHASH) + if (!(ring->netdev->features & NETIF_F_RXHASH)) return; if ((rx_desc->wb.qword1.status_error_len & rss_mask) == rss_mask) { -- cgit From de58647b4301fe181f9c38e8b46f7021584ae427 Mon Sep 17 00:00:00 2001 From: Alexander Lobakin Date: Wed, 1 Mar 2023 12:59:08 +0100 Subject: iavf: fix non-tunneled IPv6 UDP packet type and hashing Currently, IAVF's decode_rx_desc_ptype() correctly reports payload type of L4 for IPv4 UDP packets and IPv{4,6} TCP, but only L3 for IPv6 UDP. Originally, i40e, ice and iavf were affected. Commit 73df8c9e3e3d ("i40e: Correct UDP packet header for non_tunnel-ipv6") fixed that in i40e, then commit 638a0c8c8861 ("ice: fix incorrect payload indicator on PTYPE") fixed that for ice. IPv6 UDP is L4 obviously. Fix it and make iavf report correct L4 hash type for such packets, so that the stack won't calculate it on CPU when needs it. Fixes: 206812b5fccb ("i40e/i40evf: i40e implementation for skb_set_hash") Reviewed-by: Larysa Zaremba Reviewed-by: Michal Kubiak Signed-off-by: Alexander Lobakin Tested-by: Rafal Romanowski Reviewed-by: Leon Romanovsky Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/iavf/iavf_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/iavf/iavf_common.c b/drivers/net/ethernet/intel/iavf/iavf_common.c index 16c490965b61..dd11dbbd5551 100644 --- a/drivers/net/ethernet/intel/iavf/iavf_common.c +++ b/drivers/net/ethernet/intel/iavf/iavf_common.c @@ -661,7 +661,7 @@ struct iavf_rx_ptype_decoded iavf_ptype_lookup[BIT(8)] = { /* Non Tunneled IPv6 */ IAVF_PTT(88, IP, IPV6, FRG, NONE, NONE, NOF, NONE, PAY3), IAVF_PTT(89, IP, IPV6, NOF, NONE, NONE, NOF, NONE, PAY3), - IAVF_PTT(90, IP, IPV6, NOF, NONE, NONE, NOF, UDP, PAY3), + IAVF_PTT(90, IP, IPV6, NOF, NONE, NONE, NOF, UDP, PAY4), IAVF_PTT_UNUSED_ENTRY(91), IAVF_PTT(92, IP, IPV6, NOF, NONE, NONE, NOF, TCP, PAY4), IAVF_PTT(93, IP, IPV6, NOF, NONE, NONE, NOF, SCTP, PAY4), -- cgit From 964290ff32d132bf971d45b29f7de39756dab7c8 Mon Sep 17 00:00:00 2001 From: Ahmed Zaki Date: Wed, 15 Mar 2023 13:59:25 -0600 Subject: iavf: do not track VLAN 0 filters When an interface with the maximum number of VLAN filters is brought up, a spurious error is logged: [257.483082] 8021q: adding VLAN 0 to HW filter on device enp0s3 [257.483094] iavf 0000:00:03.0 enp0s3: Max allowed VLAN filters 8. Remove existing VLANs or disable filtering via Ethtool if supported. The VF driver complains that it cannot add the VLAN 0 filter. On the other hand, the PF driver always adds VLAN 0 filter on VF initialization. The VF does not need to ask the PF for that filter at all. Fix the error by not tracking VLAN 0 filters altogether. With that, the check added by commit 0e710a3ffd0c ("iavf: Fix VF driver counting VLAN 0 filters") in iavf_virtchnl.c is useless and might be confusing if left as it suggests that we track VLAN 0. Fixes: 0e710a3ffd0c ("iavf: Fix VF driver counting VLAN 0 filters") Signed-off-by: Ahmed Zaki Reviewed-by: Michal Kubiak Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/iavf/iavf_main.c | 8 ++++++++ drivers/net/ethernet/intel/iavf/iavf_virtchnl.c | 2 -- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c index 3273aeb8fa67..327cd9b1af2c 100644 --- a/drivers/net/ethernet/intel/iavf/iavf_main.c +++ b/drivers/net/ethernet/intel/iavf/iavf_main.c @@ -893,6 +893,10 @@ static int iavf_vlan_rx_add_vid(struct net_device *netdev, { struct iavf_adapter *adapter = netdev_priv(netdev); + /* Do not track VLAN 0 filter, always added by the PF on VF init */ + if (!vid) + return 0; + if (!VLAN_FILTERING_ALLOWED(adapter)) return -EIO; @@ -919,6 +923,10 @@ static int iavf_vlan_rx_kill_vid(struct net_device *netdev, { struct iavf_adapter *adapter = netdev_priv(netdev); + /* We do not track VLAN 0 filter */ + if (!vid) + return 0; + iavf_del_vlan(adapter, IAVF_VLAN(vid, be16_to_cpu(proto))); if (proto == cpu_to_be16(ETH_P_8021Q)) clear_bit(vid, adapter->vsi.active_cvlans); diff --git a/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c b/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c index 6d23338604bb..4e17d006c52d 100644 --- a/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c +++ b/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c @@ -2446,8 +2446,6 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter, list_for_each_entry(f, &adapter->vlan_filter_list, list) { if (f->is_new_vlan) { f->is_new_vlan = false; - if (!f->vlan.vid) - continue; if (f->vlan.tpid == ETH_P_8021Q) set_bit(f->vlan.vid, adapter->vsi.active_cvlans); -- cgit From 65f69851e44d71248b952a687e44759a7abb5016 Mon Sep 17 00:00:00 2001 From: Lin Ma Date: Tue, 7 Mar 2023 23:29:17 +0800 Subject: igb: revert rtnl_lock() that causes deadlock The commit 6faee3d4ee8b ("igb: Add lock to avoid data race") adds rtnl_lock to eliminate a false data race shown below (FREE from device detaching) | (USE from netdev core) igb_remove | igb_ndo_get_vf_config igb_disable_sriov | vf >= adapter->vfs_allocated_count? kfree(adapter->vf_data) | adapter->vfs_allocated_count = 0 | | memcpy(... adapter->vf_data[vf] The above race will never happen and the extra rtnl_lock causes deadlock below [ 141.420169] [ 141.420672] __schedule+0x2dd/0x840 [ 141.421427] schedule+0x50/0xc0 [ 141.422041] schedule_preempt_disabled+0x11/0x20 [ 141.422678] __mutex_lock.isra.13+0x431/0x6b0 [ 141.423324] unregister_netdev+0xe/0x20 [ 141.423578] igbvf_remove+0x45/0xe0 [igbvf] [ 141.423791] pci_device_remove+0x36/0xb0 [ 141.423990] device_release_driver_internal+0xc1/0x160 [ 141.424270] pci_stop_bus_device+0x6d/0x90 [ 141.424507] pci_stop_and_remove_bus_device+0xe/0x20 [ 141.424789] pci_iov_remove_virtfn+0xba/0x120 [ 141.425452] sriov_disable+0x2f/0xf0 [ 141.425679] igb_disable_sriov+0x4e/0x100 [igb] [ 141.426353] igb_remove+0xa0/0x130 [igb] [ 141.426599] pci_device_remove+0x36/0xb0 [ 141.426796] device_release_driver_internal+0xc1/0x160 [ 141.427060] driver_detach+0x44/0x90 [ 141.427253] bus_remove_driver+0x55/0xe0 [ 141.427477] pci_unregister_driver+0x2a/0xa0 [ 141.428296] __x64_sys_delete_module+0x141/0x2b0 [ 141.429126] ? mntput_no_expire+0x4a/0x240 [ 141.429363] ? syscall_trace_enter.isra.19+0x126/0x1a0 [ 141.429653] do_syscall_64+0x5b/0x80 [ 141.429847] ? exit_to_user_mode_prepare+0x14d/0x1c0 [ 141.430109] ? syscall_exit_to_user_mode+0x12/0x30 [ 141.430849] ? do_syscall_64+0x67/0x80 [ 141.431083] ? syscall_exit_to_user_mode_prepare+0x183/0x1b0 [ 141.431770] ? syscall_exit_to_user_mode+0x12/0x30 [ 141.432482] ? do_syscall_64+0x67/0x80 [ 141.432714] ? exc_page_fault+0x64/0x140 [ 141.432911] entry_SYSCALL_64_after_hwframe+0x72/0xdc Since the igb_disable_sriov() will call pci_disable_sriov() before releasing any resources, the netdev core will synchronize the cleanup to avoid any races. This patch removes the useless rtnl_(un)lock to guarantee correctness. CC: stable@vger.kernel.org Fixes: 6faee3d4ee8b ("igb: Add lock to avoid data race") Reported-by: Corinna Vinschen Link: https://lore.kernel.org/intel-wired-lan/ZAcJvkEPqWeJHO2r@calimero.vinschen.de/ Signed-off-by: Lin Ma Tested-by: Corinna Vinschen Reviewed-by: Jacob Keller Reviewed-by: Simon Horman Tested-by: Rafal Romanowski Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/igb/igb_main.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index 03bc1e8af575..5532361b0e94 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -3863,9 +3863,7 @@ static void igb_remove(struct pci_dev *pdev) igb_release_hw_control(adapter); #ifdef CONFIG_PCI_IOV - rtnl_lock(); igb_disable_sriov(pdev); - rtnl_unlock(); #endif unregister_netdev(netdev); -- cgit From 50f303496d92e25b79bdfb73e3707ad0684ad67f Mon Sep 17 00:00:00 2001 From: Akihiko Odaki Date: Tue, 22 Nov 2022 18:28:03 +0900 Subject: igb: Enable SR-IOV after reinit Enabling SR-IOV causes the virtual functions to make requests to the PF via the mailbox. Notably, E1000_VF_RESET request will happen during the initialization of the VF. However, unless the reinit is done, the VMMB interrupt, which delivers mailbox interrupt from VF to PF will be kept masked and such requests will be silently ignored. Enable SR-IOV at the very end of the procedure to configure the device for SR-IOV so that the PF is configured properly for SR-IOV when a VF is activated. Fixes: fa44f2f185f7 ("igb: Enable SR-IOV configuration via PCI sysfs interface") Signed-off-by: Akihiko Odaki Tested-by: Marek Szlosek Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/igb/igb_main.c | 135 +++++++++++++----------------- 1 file changed, 58 insertions(+), 77 deletions(-) diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index 5532361b0e94..274c781b5547 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -109,6 +109,7 @@ static void igb_free_all_rx_resources(struct igb_adapter *); static void igb_setup_mrqc(struct igb_adapter *); static int igb_probe(struct pci_dev *, const struct pci_device_id *); static void igb_remove(struct pci_dev *pdev); +static void igb_init_queue_configuration(struct igb_adapter *adapter); static int igb_sw_init(struct igb_adapter *); int igb_open(struct net_device *); int igb_close(struct net_device *); @@ -175,9 +176,7 @@ static void igb_nfc_filter_restore(struct igb_adapter *adapter); #ifdef CONFIG_PCI_IOV static int igb_vf_configure(struct igb_adapter *adapter, int vf); -static int igb_pci_enable_sriov(struct pci_dev *dev, int num_vfs); -static int igb_disable_sriov(struct pci_dev *dev); -static int igb_pci_disable_sriov(struct pci_dev *dev); +static int igb_disable_sriov(struct pci_dev *dev, bool reinit); #endif static int igb_suspend(struct device *); @@ -3665,7 +3664,7 @@ err_sw_init: kfree(adapter->shadow_vfta); igb_clear_interrupt_scheme(adapter); #ifdef CONFIG_PCI_IOV - igb_disable_sriov(pdev); + igb_disable_sriov(pdev, false); #endif pci_iounmap(pdev, adapter->io_addr); err_ioremap: @@ -3679,7 +3678,38 @@ err_dma: } #ifdef CONFIG_PCI_IOV -static int igb_disable_sriov(struct pci_dev *pdev) +static int igb_sriov_reinit(struct pci_dev *dev) +{ + struct net_device *netdev = pci_get_drvdata(dev); + struct igb_adapter *adapter = netdev_priv(netdev); + struct pci_dev *pdev = adapter->pdev; + + rtnl_lock(); + + if (netif_running(netdev)) + igb_close(netdev); + else + igb_reset(adapter); + + igb_clear_interrupt_scheme(adapter); + + igb_init_queue_configuration(adapter); + + if (igb_init_interrupt_scheme(adapter, true)) { + rtnl_unlock(); + dev_err(&pdev->dev, "Unable to allocate memory for queues\n"); + return -ENOMEM; + } + + if (netif_running(netdev)) + igb_open(netdev); + + rtnl_unlock(); + + return 0; +} + +static int igb_disable_sriov(struct pci_dev *pdev, bool reinit) { struct net_device *netdev = pci_get_drvdata(pdev); struct igb_adapter *adapter = netdev_priv(netdev); @@ -3713,10 +3743,10 @@ static int igb_disable_sriov(struct pci_dev *pdev) adapter->flags |= IGB_FLAG_DMAC; } - return 0; + return reinit ? igb_sriov_reinit(pdev) : 0; } -static int igb_enable_sriov(struct pci_dev *pdev, int num_vfs) +static int igb_enable_sriov(struct pci_dev *pdev, int num_vfs, bool reinit) { struct net_device *netdev = pci_get_drvdata(pdev); struct igb_adapter *adapter = netdev_priv(netdev); @@ -3781,12 +3811,6 @@ static int igb_enable_sriov(struct pci_dev *pdev, int num_vfs) "Unable to allocate memory for VF MAC filter list\n"); } - /* only call pci_enable_sriov() if no VFs are allocated already */ - if (!old_vfs) { - err = pci_enable_sriov(pdev, adapter->vfs_allocated_count); - if (err) - goto err_out; - } dev_info(&pdev->dev, "%d VFs allocated\n", adapter->vfs_allocated_count); for (i = 0; i < adapter->vfs_allocated_count; i++) @@ -3794,6 +3818,17 @@ static int igb_enable_sriov(struct pci_dev *pdev, int num_vfs) /* DMA Coalescing is not supported in IOV mode. */ adapter->flags &= ~IGB_FLAG_DMAC; + + if (reinit) { + err = igb_sriov_reinit(pdev); + if (err) + goto err_out; + } + + /* only call pci_enable_sriov() if no VFs are allocated already */ + if (!old_vfs) + err = pci_enable_sriov(pdev, adapter->vfs_allocated_count); + goto out; err_out: @@ -3863,7 +3898,7 @@ static void igb_remove(struct pci_dev *pdev) igb_release_hw_control(adapter); #ifdef CONFIG_PCI_IOV - igb_disable_sriov(pdev); + igb_disable_sriov(pdev, false); #endif unregister_netdev(netdev); @@ -3909,7 +3944,7 @@ static void igb_probe_vfs(struct igb_adapter *adapter) igb_reset_interrupt_capability(adapter); pci_sriov_set_totalvfs(pdev, 7); - igb_enable_sriov(pdev, max_vfs); + igb_enable_sriov(pdev, max_vfs, false); #endif /* CONFIG_PCI_IOV */ } @@ -9518,71 +9553,17 @@ static void igb_shutdown(struct pci_dev *pdev) } } -#ifdef CONFIG_PCI_IOV -static int igb_sriov_reinit(struct pci_dev *dev) -{ - struct net_device *netdev = pci_get_drvdata(dev); - struct igb_adapter *adapter = netdev_priv(netdev); - struct pci_dev *pdev = adapter->pdev; - - rtnl_lock(); - - if (netif_running(netdev)) - igb_close(netdev); - else - igb_reset(adapter); - - igb_clear_interrupt_scheme(adapter); - - igb_init_queue_configuration(adapter); - - if (igb_init_interrupt_scheme(adapter, true)) { - rtnl_unlock(); - dev_err(&pdev->dev, "Unable to allocate memory for queues\n"); - return -ENOMEM; - } - - if (netif_running(netdev)) - igb_open(netdev); - - rtnl_unlock(); - - return 0; -} - -static int igb_pci_disable_sriov(struct pci_dev *dev) -{ - int err = igb_disable_sriov(dev); - - if (!err) - err = igb_sriov_reinit(dev); - - return err; -} - -static int igb_pci_enable_sriov(struct pci_dev *dev, int num_vfs) -{ - int err = igb_enable_sriov(dev, num_vfs); - - if (err) - goto out; - - err = igb_sriov_reinit(dev); - if (!err) - return num_vfs; - -out: - return err; -} - -#endif static int igb_pci_sriov_configure(struct pci_dev *dev, int num_vfs) { #ifdef CONFIG_PCI_IOV - if (num_vfs == 0) - return igb_pci_disable_sriov(dev); - else - return igb_pci_enable_sriov(dev, num_vfs); + int err; + + if (num_vfs == 0) { + return igb_disable_sriov(dev, true); + } else { + err = igb_enable_sriov(dev, num_vfs, true); + return err ? err : num_vfs; + } #endif return 0; } -- cgit From 85eb39bb39cbb5c086df1e19ba67cc1366693a77 Mon Sep 17 00:00:00 2001 From: Gaosheng Cui Date: Tue, 22 Nov 2022 10:28:52 +0800 Subject: intel/igbvf: free irq on the error path in igbvf_request_msix() In igbvf_request_msix(), irqs have not been freed on the err path, we need to free it. Fix it. Fixes: d4e0fe01a38a ("igbvf: add new driver to support 82576 virtual functions") Signed-off-by: Gaosheng Cui Reviewed-by: Maciej Fijalkowski Tested-by: Marek Szlosek Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/igbvf/netdev.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/igbvf/netdev.c b/drivers/net/ethernet/intel/igbvf/netdev.c index 3a32809510fc..72cb1b56e9f2 100644 --- a/drivers/net/ethernet/intel/igbvf/netdev.c +++ b/drivers/net/ethernet/intel/igbvf/netdev.c @@ -1074,7 +1074,7 @@ static int igbvf_request_msix(struct igbvf_adapter *adapter) igbvf_intr_msix_rx, 0, adapter->rx_ring->name, netdev); if (err) - goto out; + goto free_irq_tx; adapter->rx_ring->itr_register = E1000_EITR(vector); adapter->rx_ring->itr_val = adapter->current_itr; @@ -1083,10 +1083,14 @@ static int igbvf_request_msix(struct igbvf_adapter *adapter) err = request_irq(adapter->msix_entries[vector].vector, igbvf_msix_other, 0, netdev->name, netdev); if (err) - goto out; + goto free_irq_rx; igbvf_configure_msix(adapter); return 0; +free_irq_rx: + free_irq(adapter->msix_entries[--vector].vector, netdev); +free_irq_tx: + free_irq(adapter->msix_entries[--vector].vector, netdev); out: return err; } -- cgit From 02c83791ef969c6a8a150b4927193d0d0e50fb23 Mon Sep 17 00:00:00 2001 From: Akihiko Odaki Date: Thu, 1 Dec 2022 19:20:03 +0900 Subject: igbvf: Regard vf reset nack as success vf reset nack actually represents the reset operation itself is performed but no address is assigned. Therefore, e1000_reset_hw_vf should fill the "perm_addr" with the zero address and return success on such an occasion. This prevents its callers in netdev.c from saying PF still resetting, and instead allows them to correctly report that no address is assigned. Fixes: 6ddbc4cf1f4d ("igb: Indicate failure on vf reset for empty mac address") Signed-off-by: Akihiko Odaki Reviewed-by: Leon Romanovsky Tested-by: Marek Szlosek Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/igbvf/vf.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/intel/igbvf/vf.c b/drivers/net/ethernet/intel/igbvf/vf.c index b8ba3f94c363..a47a2e3e548c 100644 --- a/drivers/net/ethernet/intel/igbvf/vf.c +++ b/drivers/net/ethernet/intel/igbvf/vf.c @@ -1,6 +1,8 @@ // SPDX-License-Identifier: GPL-2.0 /* Copyright(c) 2009 - 2018 Intel Corporation. */ +#include + #include "vf.h" static s32 e1000_check_for_link_vf(struct e1000_hw *hw); @@ -131,11 +133,16 @@ static s32 e1000_reset_hw_vf(struct e1000_hw *hw) /* set our "perm_addr" based on info provided by PF */ ret_val = mbx->ops.read_posted(hw, msgbuf, 3); if (!ret_val) { - if (msgbuf[0] == (E1000_VF_RESET | - E1000_VT_MSGTYPE_ACK)) + switch (msgbuf[0]) { + case E1000_VF_RESET | E1000_VT_MSGTYPE_ACK: memcpy(hw->mac.perm_addr, addr, ETH_ALEN); - else + break; + case E1000_VF_RESET | E1000_VT_MSGTYPE_NACK: + eth_zero_addr(hw->mac.perm_addr); + break; + default: ret_val = -E1000_ERR_MAC_INIT; + } } } -- cgit From 2b4cc3d3f4d8ec42961e98568a0afeee96a943ab Mon Sep 17 00:00:00 2001 From: AKASHI Takahiro Date: Tue, 7 Mar 2023 15:45:31 +0900 Subject: igc: fix the validation logic for taprio's gate list The check introduced in the commit a5fd39464a40 ("igc: Lift TAPRIO schedule restriction") can detect a false positive error in some corner case. For instance, tc qdisc replace ... taprio num_tc 4 ... sched-entry S 0x01 100000 # slot#1 sched-entry S 0x03 100000 # slot#2 sched-entry S 0x04 100000 # slot#3 sched-entry S 0x08 200000 # slot#4 flags 0x02 # hardware offload Here the queue#0 (the first queue) is on at the slot#1 and #2, and off at the slot#3 and #4. Under the current logic, when the slot#4 is examined, validate_schedule() returns *false* since the enablement count for the queue#0 is two and it is already off at the previous slot (i.e. #3). But this definition is truely correct. Let's fix the logic to enforce a strict validation for consecutively-opened slots. Fixes: a5fd39464a40 ("igc: Lift TAPRIO schedule restriction") Signed-off-by: AKASHI Takahiro Reviewed-by: Kurt Kanzenbach Acked-by: Vinicius Costa Gomes Tested-by: Naama Meir Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/igc/igc_main.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c index 2928a6c73692..25fc6c65209b 100644 --- a/drivers/net/ethernet/intel/igc/igc_main.c +++ b/drivers/net/ethernet/intel/igc/igc_main.c @@ -6010,18 +6010,18 @@ static bool validate_schedule(struct igc_adapter *adapter, if (e->command != TC_TAPRIO_CMD_SET_GATES) return false; - for (i = 0; i < adapter->num_tx_queues; i++) { - if (e->gate_mask & BIT(i)) + for (i = 0; i < adapter->num_tx_queues; i++) + if (e->gate_mask & BIT(i)) { queue_uses[i]++; - /* There are limitations: A single queue cannot be - * opened and closed multiple times per cycle unless the - * gate stays open. Check for it. - */ - if (queue_uses[i] > 1 && - !(prev->gate_mask & BIT(i))) - return false; - } + /* There are limitations: A single queue cannot + * be opened and closed multiple times per cycle + * unless the gate stays open. Check for it. + */ + if (queue_uses[i] > 1 && + !(prev->gate_mask & BIT(i))) + return false; + } } return true; -- cgit From a204b490595de71016b2360a1886ec8c12d0afac Mon Sep 17 00:00:00 2001 From: Joel Selvaraj Date: Sun, 12 Mar 2023 23:14:02 -0500 Subject: scsi: core: Add BLIST_SKIP_VPD_PAGES for SKhynix H28U74301AMR Xiaomi Poco F1 (qcom/sdm845-xiaomi-beryllium*.dts) comes with a SKhynix H28U74301AMR UFS. The sd_read_cpr() operation leads to a 120 second timeout, making the device bootup very slow: [ 121.457736] sd 0:0:0:1: [sdb] tag#23 timing out command, waited 120s Setting the BLIST_SKIP_VPD_PAGES allows the device to skip the failing sd_read_cpr operation and boot normally. Signed-off-by: Joel Selvaraj Link: https://lore.kernel.org/r/20230313041402.39330-1-joelselvaraj.oss@gmail.com Cc: stable@vger.kernel.org Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_devinfo.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c index bc9d280417f6..3fcaf10a9dfe 100644 --- a/drivers/scsi/scsi_devinfo.c +++ b/drivers/scsi/scsi_devinfo.c @@ -234,6 +234,7 @@ static struct { {"SGI", "RAID5", "*", BLIST_SPARSELUN}, {"SGI", "TP9100", "*", BLIST_REPORTLUN2}, {"SGI", "Universal Xport", "*", BLIST_NO_ULD_ATTACH}, + {"SKhynix", "H28U74301AMR", NULL, BLIST_SKIP_VPD_PAGES}, {"IBM", "Universal Xport", "*", BLIST_NO_ULD_ATTACH}, {"SUN", "Universal Xport", "*", BLIST_NO_ULD_ATTACH}, {"DELL", "Universal Xport", "*", BLIST_NO_ULD_ATTACH}, -- cgit From 0367076b0817d5c75dfb83001ce7ce5c64d803a9 Mon Sep 17 00:00:00 2001 From: Nilesh Javali Date: Sun, 12 Mar 2023 21:37:10 -0700 Subject: scsi: qla2xxx: Perform lockless command completion in abort path While adding and removing the controller, the following call trace was observed: WARNING: CPU: 3 PID: 623596 at kernel/dma/mapping.c:532 dma_free_attrs+0x33/0x50 CPU: 3 PID: 623596 Comm: sh Kdump: loaded Not tainted 5.14.0-96.el9.x86_64 #1 RIP: 0010:dma_free_attrs+0x33/0x50 Call Trace: qla2x00_async_sns_sp_done+0x107/0x1b0 [qla2xxx] qla2x00_abort_srb+0x8e/0x250 [qla2xxx] ? ql_dbg+0x70/0x100 [qla2xxx] __qla2x00_abort_all_cmds+0x108/0x190 [qla2xxx] qla2x00_abort_all_cmds+0x24/0x70 [qla2xxx] qla2x00_abort_isp_cleanup+0x305/0x3e0 [qla2xxx] qla2x00_remove_one+0x364/0x400 [qla2xxx] pci_device_remove+0x36/0xa0 __device_release_driver+0x17a/0x230 device_release_driver+0x24/0x30 pci_stop_bus_device+0x68/0x90 pci_stop_and_remove_bus_device_locked+0x16/0x30 remove_store+0x75/0x90 kernfs_fop_write_iter+0x11c/0x1b0 new_sync_write+0x11f/0x1b0 vfs_write+0x1eb/0x280 ksys_write+0x5f/0xe0 do_syscall_64+0x5c/0x80 ? do_user_addr_fault+0x1d8/0x680 ? do_syscall_64+0x69/0x80 ? exc_page_fault+0x62/0x140 ? asm_exc_page_fault+0x8/0x30 entry_SYSCALL_64_after_hwframe+0x44/0xae The command was completed in the abort path during driver unload with a lock held, causing the warning in abort path. Hence complete the command without any lock held. Reported-by: Lin Li Tested-by: Lin Li Cc: stable@vger.kernel.org Signed-off-by: Nilesh Javali Link: https://lore.kernel.org/r/20230313043711.13500-2-njavali@marvell.com Reviewed-by: Himanshu Madhani Reviewed-by: John Meneghini Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_os.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 80c4ee9df2a4..bee1b8a82020 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -1865,6 +1865,17 @@ __qla2x00_abort_all_cmds(struct qla_qpair *qp, int res) for (cnt = 1; cnt < req->num_outstanding_cmds; cnt++) { sp = req->outstanding_cmds[cnt]; if (sp) { + /* + * perform lockless completion during driver unload + */ + if (qla2x00_chip_is_down(vha)) { + req->outstanding_cmds[cnt] = NULL; + spin_unlock_irqrestore(qp->qp_lock_ptr, flags); + sp->done(sp, res); + spin_lock_irqsave(qp->qp_lock_ptr, flags); + continue; + } + switch (sp->cmd_type) { case TYPE_SRB: qla2x00_abort_srb(qp, sp, res, &flags); -- cgit From d3affdeb400f3adc925bd996f3839481f5291839 Mon Sep 17 00:00:00 2001 From: Quinn Tran Date: Sun, 12 Mar 2023 21:37:11 -0700 Subject: scsi: qla2xxx: Synchronize the IOCB count to be in order A system hang was observed with the following call trace: BUG: kernel NULL pointer dereference, address: 0000000000000000 PGD 0 P4D 0 Oops: 0000 [#1] PREEMPT SMP NOPTI CPU: 15 PID: 86747 Comm: nvme Kdump: loaded Not tainted 6.2.0+ #1 Hardware name: Dell Inc. PowerEdge R6515/04F3CJ, BIOS 2.7.3 03/31/2022 RIP: 0010:__wake_up_common+0x55/0x190 Code: 41 f6 01 04 0f 85 b2 00 00 00 48 8b 43 08 4c 8d 40 e8 48 8d 43 08 48 89 04 24 48 89 c6\ 49 8d 40 18 48 39 c6 0f 84 e9 00 00 00 <49> 8b 40 18 89 6c 24 14 31 ed 4c 8d 60 e8 41 8b 18 f6 c3 04 75 5d RSP: 0018:ffffb05a82afbba0 EFLAGS: 00010082 RAX: 0000000000000000 RBX: ffff8f9b83a00018 RCX: 0000000000000000 RDX: 0000000000000001 RSI: ffff8f9b83a00020 RDI: ffff8f9b83a00018 RBP: 0000000000000001 R08: ffffffffffffffe8 R09: ffffb05a82afbbf8 R10: 70735f7472617473 R11: 5f30307832616c71 R12: 0000000000000001 R13: 0000000000000003 R14: 0000000000000000 R15: 0000000000000000 FS: 00007f815cf4c740(0000) GS:ffff8f9eeed80000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000000000000000 CR3: 000000010633a000 CR4: 0000000000350ee0 Call Trace: __wake_up_common_lock+0x83/0xd0 qla_nvme_ls_req+0x21b/0x2b0 [qla2xxx] __nvme_fc_send_ls_req+0x1b5/0x350 [nvme_fc] nvme_fc_xmt_disconnect_assoc+0xca/0x110 [nvme_fc] nvme_fc_delete_association+0x1bf/0x220 [nvme_fc] ? nvme_remove_namespaces+0x9f/0x140 [nvme_core] nvme_do_delete_ctrl+0x5b/0xa0 [nvme_core] nvme_sysfs_delete+0x5f/0x70 [nvme_core] kernfs_fop_write_iter+0x12b/0x1c0 vfs_write+0x2a3/0x3b0 ksys_write+0x5f/0xe0 do_syscall_64+0x5c/0x90 ? syscall_exit_work+0x103/0x130 ? syscall_exit_to_user_mode+0x12/0x30 ? do_syscall_64+0x69/0x90 ? exit_to_user_mode_loop+0xd0/0x130 ? exit_to_user_mode_prepare+0xec/0x100 ? syscall_exit_to_user_mode+0x12/0x30 ? do_syscall_64+0x69/0x90 ? syscall_exit_to_user_mode+0x12/0x30 ? do_syscall_64+0x69/0x90 entry_SYSCALL_64_after_hwframe+0x72/0xdc RIP: 0033:0x7f815cd3eb97 The IOCB counts are out of order and that would block any commands from going out and subsequently hang the system. Synchronize the IOCB count to be in correct order. Fixes: 5f63a163ed2f ("scsi: qla2xxx: Fix exchange oversubscription for management commands") Cc: stable@vger.kernel.org Signed-off-by: Quinn Tran Signed-off-by: Nilesh Javali Link: https://lore.kernel.org/r/20230313043711.13500-3-njavali@marvell.com Reviewed-by: Himanshu Madhani Reviewed-by: John Meneghini Tested-by: Lin Li Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_isr.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 030625ebb4e6..71feda2cdb63 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -1900,6 +1900,8 @@ qla2x00_get_sp_from_handle(scsi_qla_host_t *vha, const char *func, } req->outstanding_cmds[index] = NULL; + + qla_put_fw_resources(sp->qpair, &sp->iores); return sp; } @@ -3112,7 +3114,6 @@ qla25xx_process_bidir_status_iocb(scsi_qla_host_t *vha, void *pkt, } bsg_reply->reply_payload_rcv_len = 0; - qla_put_fw_resources(sp->qpair, &sp->iores); done: /* Return the vendor specific reply to API */ bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = rval; -- cgit From a13faca032acbf2699293587085293bdfaafc8ae Mon Sep 17 00:00:00 2001 From: Yu Kuai Date: Wed, 15 Mar 2023 14:21:54 +0800 Subject: scsi: scsi_dh_alua: Fix memleak for 'qdata' in alua_activate() If alua_rtpg_queue() failed from alua_activate(), then 'qdata' is not freed, which will cause following memleak: unreferenced object 0xffff88810b2c6980 (size 32): comm "kworker/u16:2", pid 635322, jiffies 4355801099 (age 1216426.076s) hex dump (first 32 bytes): 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 40 39 24 c1 ff ff ff ff 00 f8 ea 0a 81 88 ff ff @9$............. backtrace: [<0000000098f3a26d>] alua_activate+0xb0/0x320 [<000000003b529641>] scsi_dh_activate+0xb2/0x140 [<000000007b296db3>] activate_path_work+0xc6/0xe0 [dm_multipath] [<000000007adc9ace>] process_one_work+0x3c5/0x730 [<00000000c457a985>] worker_thread+0x93/0x650 [<00000000cb80e628>] kthread+0x1ba/0x210 [<00000000a1e61077>] ret_from_fork+0x22/0x30 Fix the problem by freeing 'qdata' in error path. Fixes: 625fe857e4fa ("scsi: scsi_dh_alua: Check scsi_device_get() return value") Signed-off-by: Yu Kuai Link: https://lore.kernel.org/r/20230315062154.668812-1-yukuai1@huaweicloud.com Reviewed-by: Benjamin Block Reviewed-by: Bart Van Assche Signed-off-by: Martin K. Petersen --- drivers/scsi/device_handler/scsi_dh_alua.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c index 362fa631f39b..a226dc1b65d7 100644 --- a/drivers/scsi/device_handler/scsi_dh_alua.c +++ b/drivers/scsi/device_handler/scsi_dh_alua.c @@ -1145,10 +1145,12 @@ static int alua_activate(struct scsi_device *sdev, rcu_read_unlock(); mutex_unlock(&h->init_mutex); - if (alua_rtpg_queue(pg, sdev, qdata, true)) + if (alua_rtpg_queue(pg, sdev, qdata, true)) { fn = NULL; - else + } else { + kfree(qdata); err = SCSI_DH_DEV_OFFLINED; + } kref_put(&pg->kref, release_port_group); out: if (fn) -- cgit From 27c934dd8832dd40fd34776f916dc201e18b319b Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Fri, 17 Mar 2023 13:13:08 -0400 Subject: nfsd: don't replace page in rq_pages if it's a continuation of last page The splice read calls nfsd_splice_actor to put the pages containing file data into the svc_rqst->rq_pages array. It's possible however to get a splice result that only has a partial page at the end, if (e.g.) the filesystem hands back a short read that doesn't cover the whole page. nfsd_splice_actor will plop the partial page into its rq_pages array and return. Then later, when nfsd_splice_actor is called again, the remainder of the page may end up being filled out. At this point, nfsd_splice_actor will put the page into the array _again_ corrupting the reply. If this is done enough times, rq_next_page will overrun the array and corrupt the trailing fields -- the rq_respages and rq_next_page pointers themselves. If we've already added the page to the array in the last pass, don't add it to the array a second time when dealing with a splice continuation. This was originally handled properly in nfsd_splice_actor, but commit 91e23b1c3982 ("NFSD: Clean up nfsd_splice_actor()") removed the check for it. Fixes: 91e23b1c3982 ("NFSD: Clean up nfsd_splice_actor()") Cc: Al Viro Reported-by: Dario Lesca Tested-by: David Critch Link: https://bugzilla.redhat.com/show_bug.cgi?id=2150630 Signed-off-by: Jeff Layton Signed-off-by: Chuck Lever --- fs/nfsd/vfs.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index ba34a31a7c70..cd0dbea335d9 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -941,8 +941,15 @@ nfsd_splice_actor(struct pipe_inode_info *pipe, struct pipe_buffer *buf, struct page *last_page; last_page = page + (offset + sd->len - 1) / PAGE_SIZE; - for (page += offset / PAGE_SIZE; page <= last_page; page++) + for (page += offset / PAGE_SIZE; page <= last_page; page++) { + /* + * Skip page replacement when extending the contents + * of the current page. + */ + if (page == *(rqstp->rq_next_page - 1)) + continue; svc_rqst_replace_page(rqstp, page); + } if (rqstp->rq_res.page_len == 0) // first call rqstp->rq_res.page_base = offset % PAGE_SIZE; rqstp->rq_res.page_len += sd->len; -- cgit From 70e42feab2e20618ddd0cbfc4ab4b08628236ecd Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Fri, 17 Mar 2023 21:53:52 -0400 Subject: ext4: fix possible double unlock when moving a directory Fixes: 0813299c586b ("ext4: Fix possible corruption when moving a directory") Link: https://lore.kernel.org/r/5efbe1b9-ad8b-4a4f-b422-24824d2b775c@kili.mountain Reported-by: Dan Carpenter Reported-by: syzbot+0c73d1d8b952c5f3d714@syzkaller.appspotmail.com Signed-off-by: Theodore Ts'o --- fs/ext4/namei.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index 31e21de56432..a5010b5b8a8c 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c @@ -3884,10 +3884,8 @@ static int ext4_rename(struct mnt_idmap *idmap, struct inode *old_dir, goto end_rename; } retval = ext4_rename_dir_prepare(handle, &old); - if (retval) { - inode_unlock(old.inode); + if (retval) goto end_rename; - } } /* * If we're renaming a file within an inline_data dir and adding or -- cgit From 30796d0dcb6e41c6558a07950f2ce60c209da867 Mon Sep 17 00:00:00 2001 From: Álvaro Fernández Rojas Date: Thu, 16 Mar 2023 18:28:07 +0100 Subject: net: dsa: b53: mmap: fix device tree support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CPU port should also be enabled in order to get a working switch. Fixes: a5538a777b73 ("net: dsa: b53: mmap: Add device tree support") Signed-off-by: Álvaro Fernández Rojas Acked-by: Florian Fainelli Link: https://lore.kernel.org/r/20230316172807.460146-1-noltari@gmail.com Signed-off-by: Jakub Kicinski --- drivers/net/dsa/b53/b53_mmap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/dsa/b53/b53_mmap.c b/drivers/net/dsa/b53/b53_mmap.c index e968322dfbf0..70887e0aece3 100644 --- a/drivers/net/dsa/b53/b53_mmap.c +++ b/drivers/net/dsa/b53/b53_mmap.c @@ -263,7 +263,7 @@ static int b53_mmap_probe_of(struct platform_device *pdev, if (of_property_read_u32(of_port, "reg", ®)) continue; - if (reg < B53_CPU_PORT) + if (reg < B53_N_PORTS) pdata->enabled_ports |= BIT(reg); } -- cgit From ff821092cf02a70c2bccd2d19269f01e29aa52cf Mon Sep 17 00:00:00 2001 From: Szymon Heidrich Date: Thu, 16 Mar 2023 11:19:54 +0100 Subject: net: usb: smsc95xx: Limit packet length to skb->len Packet length retrieved from descriptor may be larger than the actual socket buffer length. In such case the cloned skb passed up the network stack will leak kernel memory contents. Fixes: 2f7ca802bdae ("net: Add SMSC LAN9500 USB2.0 10/100 ethernet adapter driver") Signed-off-by: Szymon Heidrich Reviewed-by: Jakub Kicinski Link: https://lore.kernel.org/r/20230316101954.75836-1-szymon.heidrich@gmail.com Signed-off-by: Jakub Kicinski --- drivers/net/usb/smsc95xx.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c index 32d2c60d334d..563ecd27b93e 100644 --- a/drivers/net/usb/smsc95xx.c +++ b/drivers/net/usb/smsc95xx.c @@ -1833,6 +1833,12 @@ static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb) size = (u16)((header & RX_STS_FL_) >> 16); align_count = (4 - ((size + NET_IP_ALIGN) % 4)) % 4; + if (unlikely(size > skb->len)) { + netif_dbg(dev, rx_err, dev->net, + "size err header=0x%08x\n", header); + return 0; + } + if (unlikely(header & RX_STS_ES_)) { netif_dbg(dev, rx_err, dev->net, "Error header=0x%08x\n", header); -- cgit From 3dacc5bb81472905a7f4f9879cb95477c22dc359 Mon Sep 17 00:00:00 2001 From: Grygorii Strashko Date: Thu, 16 Mar 2023 15:22:32 +0530 Subject: net: ethernet: ti: am65-cpts: reset pps genf adj settings on enable The CPTS PPS GENf adjustment settings are invalid after it has been disabled for a while, so reset them. Fixes: eb9233ce6751 ("net: ethernet: ti: am65-cpts: adjust pps following ptp changes") Signed-off-by: Grygorii Strashko Signed-off-by: Siddharth Vadapalli Reviewed-by: Roger Quadros Reviewed-by: Michal Swiatkowski Link: https://lore.kernel.org/r/20230316095232.2002680-1-s-vadapalli@ti.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/ti/am65-cpts.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/ethernet/ti/am65-cpts.c b/drivers/net/ethernet/ti/am65-cpts.c index 16ee9c29cb35..8caf85acbb6a 100644 --- a/drivers/net/ethernet/ti/am65-cpts.c +++ b/drivers/net/ethernet/ti/am65-cpts.c @@ -636,6 +636,10 @@ static void am65_cpts_perout_enable_hw(struct am65_cpts *cpts, val = lower_32_bits(cycles); am65_cpts_write32(cpts, val, genf[req->index].length); + am65_cpts_write32(cpts, 0, genf[req->index].control); + am65_cpts_write32(cpts, 0, genf[req->index].ppm_hi); + am65_cpts_write32(cpts, 0, genf[req->index].ppm_low); + cpts->genf_enable |= BIT(req->index); } else { am65_cpts_write32(cpts, 0, genf[req->index].length); -- cgit From efbcbb12ee99f750c9f25c873b55ad774871de2a Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 17 Mar 2023 13:51:17 -0700 Subject: media: m5mols: fix off-by-one loop termination error The __find_restype() function loops over the m5mols_default_ffmt[] array, and the termination condition ends up being wrong: instead of stopping when the iterator becomes the size of the array it traverses, it stops after it has already overshot the array. Now, in practice this doesn't likely matter, because the code will always find the entry it looks for, and will thus return early and never hit that last extra iteration. But it turns out that clang will unroll the loop fully, because it has only two iterations (well, three due to the off-by-one bug), and then clang will end up just giving up in the middle of the loop unrolling when it notices that the code walks past the end of the array. And that made 'objtool' very unhappy indeed, because the generated code just falls off the edge of the universe, and ends up falling through to the next function, causing this warning: drivers/media/i2c/m5mols/m5mols.o: warning: objtool: m5mols_set_fmt() falls through to next function m5mols_get_frame_desc() Fix the loop ending condition. Reported-by: Jens Axboe Analyzed-by: Miguel Ojeda Analyzed-by: Nick Desaulniers Link: https://lore.kernel.org/linux-block/CAHk-=wgTSdKYbmB1JYM5vmHMcD9J9UZr0mn7BOYM_LudrP+Xvw@mail.gmail.com/ Fixes: bc125106f8af ("[media] Add support for M-5MOLS 8 Mega Pixel camera ISP") Cc: HeungJun, Kim Cc: Sylwester Nawrocki Cc: Kyungmin Park Cc: Mauro Carvalho Chehab Signed-off-by: Linus Torvalds --- drivers/media/i2c/m5mols/m5mols_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/i2c/m5mols/m5mols_core.c b/drivers/media/i2c/m5mols/m5mols_core.c index 2b01873ba0db..5c2336f318d9 100644 --- a/drivers/media/i2c/m5mols/m5mols_core.c +++ b/drivers/media/i2c/m5mols/m5mols_core.c @@ -488,7 +488,7 @@ static enum m5mols_restype __find_restype(u32 code) do { if (code == m5mols_default_ffmt[type].code) return type; - } while (type++ != SIZE_DEFAULT_FFMT); + } while (++type != SIZE_DEFAULT_FFMT); return 0; } -- cgit From 43e5f1d5921128373743585e3275ed9044ef8b8f Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 13 Mar 2023 15:12:30 -0700 Subject: fscrypt: improve fscrypt_destroy_keyring() documentation Document that fscrypt_destroy_keyring() must be called after all potentially-encrypted inodes have been evicted. Link: https://lore.kernel.org/r/20230313221231.272498-3-ebiggers@kernel.org Signed-off-by: Eric Biggers --- fs/crypto/keyring.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/fs/crypto/keyring.c b/fs/crypto/keyring.c index 78086f8dbda5..bb15709ac9a4 100644 --- a/fs/crypto/keyring.c +++ b/fs/crypto/keyring.c @@ -207,10 +207,11 @@ static int allocate_filesystem_keyring(struct super_block *sb) * Release all encryption keys that have been added to the filesystem, along * with the keyring that contains them. * - * This is called at unmount time. The filesystem's underlying block device(s) - * are still available at this time; this is important because after user file - * accesses have been allowed, this function may need to evict keys from the - * keyslots of an inline crypto engine, which requires the block device(s). + * This is called at unmount time, after all potentially-encrypted inodes have + * been evicted. The filesystem's underlying block device(s) are still + * available at this time; this is important because after user file accesses + * have been allowed, this function may need to evict keys from the keyslots of + * an inline crypto engine, which requires the block device(s). */ void fscrypt_destroy_keyring(struct super_block *sb) { @@ -227,12 +228,12 @@ void fscrypt_destroy_keyring(struct super_block *sb) hlist_for_each_entry_safe(mk, tmp, bucket, mk_node) { /* - * Since all inodes were already evicted, every key - * remaining in the keyring should have an empty inode - * list, and should only still be in the keyring due to - * the single active ref associated with ->mk_secret. - * There should be no structural refs beyond the one - * associated with the active ref. + * Since all potentially-encrypted inodes were already + * evicted, every key remaining in the keyring should + * have an empty inode list, and should only still be in + * the keyring due to the single active ref associated + * with ->mk_secret. There should be no structural refs + * beyond the one associated with the active ref. */ WARN_ON(refcount_read(&mk->mk_active_refs) != 1); WARN_ON(refcount_read(&mk->mk_struct_refs) != 1); -- cgit From 4bcf6f827a79c59806c695dc280e763c5b6a6813 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 13 Mar 2023 15:12:31 -0700 Subject: fscrypt: check for NULL keyring in fscrypt_put_master_key_activeref() It is a bug for fscrypt_put_master_key_activeref() to see a NULL keyring. But it used to be possible due to the bug, now fixed, where fscrypt_destroy_keyring() was called before security_sb_delete(). To be consistent with how fscrypt_destroy_keyring() uses WARN_ON for the same issue, WARN and leak the fscrypt_master_key if the keyring is NULL instead of dereferencing the NULL pointer. This is a robustness improvement, not a fix. Link: https://lore.kernel.org/r/20230313221231.272498-4-ebiggers@kernel.org Signed-off-by: Eric Biggers --- fs/crypto/keyring.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/crypto/keyring.c b/fs/crypto/keyring.c index bb15709ac9a4..13d336a6cc5d 100644 --- a/fs/crypto/keyring.c +++ b/fs/crypto/keyring.c @@ -92,6 +92,8 @@ void fscrypt_put_master_key_activeref(struct super_block *sb, * destroying any subkeys embedded in it. */ + if (WARN_ON(!sb->s_master_keys)) + return; spin_lock(&sb->s_master_keys->lock); hlist_del_rcu(&mk->mk_node); spin_unlock(&sb->s_master_keys->lock); -- cgit From 25143b6a01d0cc5319edd3de22ffa2578b045550 Mon Sep 17 00:00:00 2001 From: Daniil Tatianin Date: Thu, 16 Mar 2023 13:29:21 +0300 Subject: qed/qed_sriov: guard against NULL derefs from qed_iov_get_vf_info We have to make sure that the info returned by the helper is valid before using it. Found by Linux Verification Center (linuxtesting.org) with the SVACE static analysis tool. Fixes: f990c82c385b ("qed*: Add support for ndo_set_vf_trust") Fixes: 733def6a04bf ("qed*: IOV link control") Signed-off-by: Daniil Tatianin Reviewed-by: Michal Swiatkowski Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qed/qed_sriov.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/qlogic/qed/qed_sriov.c b/drivers/net/ethernet/qlogic/qed/qed_sriov.c index 2bf18748581d..fa167b1aa019 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_sriov.c +++ b/drivers/net/ethernet/qlogic/qed/qed_sriov.c @@ -4404,6 +4404,9 @@ qed_iov_configure_min_tx_rate(struct qed_dev *cdev, int vfid, u32 rate) } vf = qed_iov_get_vf_info(QED_LEADING_HWFN(cdev), (u16)vfid, true); + if (!vf) + return -EINVAL; + vport_id = vf->vport_id; return qed_configure_vport_wfq(cdev, vport_id, rate); @@ -5152,7 +5155,7 @@ static void qed_iov_handle_trust_change(struct qed_hwfn *hwfn) /* Validate that the VF has a configured vport */ vf = qed_iov_get_vf_info(hwfn, i, true); - if (!vf->vport_instance) + if (!vf || !vf->vport_instance) continue; memset(¶ms, 0, sizeof(params)); -- cgit From e8d20c3ded59a092532513c9bd030d1ea66f5f44 Mon Sep 17 00:00:00 2001 From: Zheng Wang Date: Fri, 17 Mar 2023 00:15:26 +0800 Subject: xirc2ps_cs: Fix use after free bug in xirc2ps_detach In xirc2ps_probe, the local->tx_timeout_task was bounded with xirc2ps_tx_timeout_task. When timeout occurs, it will call xirc_tx_timeout->schedule_work to start the work. When we call xirc2ps_detach to remove the driver, there may be a sequence as follows: Stop responding to timeout tasks and complete scheduled tasks before cleanup in xirc2ps_detach, which will fix the problem. CPU0 CPU1 |xirc2ps_tx_timeout_task xirc2ps_detach | free_netdev | kfree(dev); | | | do_reset | //use dev Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Signed-off-by: Zheng Wang Signed-off-by: David S. Miller --- drivers/net/ethernet/xircom/xirc2ps_cs.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/ethernet/xircom/xirc2ps_cs.c b/drivers/net/ethernet/xircom/xirc2ps_cs.c index 894e92ef415b..9f505cf02d96 100644 --- a/drivers/net/ethernet/xircom/xirc2ps_cs.c +++ b/drivers/net/ethernet/xircom/xirc2ps_cs.c @@ -503,6 +503,11 @@ static void xirc2ps_detach(struct pcmcia_device *link) { struct net_device *dev = link->priv; + struct local_info *local = netdev_priv(dev); + + netif_carrier_off(dev); + netif_tx_disable(dev); + cancel_work_sync(&local->tx_timeout_task); dev_dbg(&link->dev, "detach\n"); -- cgit From 4203d84032e28f893594a453bd8bc9c3b15c7334 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Thu, 16 Mar 2023 13:33:24 -0700 Subject: net: phy: Ensure state transitions are processed from phy_stop() In the phy_disconnect() -> phy_stop() path, we will be forcibly setting the PHY state machine to PHY_HALTED. This invalidates the old_state != phydev->state condition in phy_state_machine() such that we will neither display the state change for debugging, nor will we invoke the link_change_notify() callback. Factor the code by introducing phy_process_state_change(), and ensure that we process the state change from phy_stop() as well. Fixes: 5c5f626bcace ("net: phy: improve handling link_change_notify callback") Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/phy/phy.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index b33e55a7364e..99a07eb54c44 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -57,6 +57,18 @@ static const char *phy_state_to_str(enum phy_state st) return NULL; } +static void phy_process_state_change(struct phy_device *phydev, + enum phy_state old_state) +{ + if (old_state != phydev->state) { + phydev_dbg(phydev, "PHY state change %s -> %s\n", + phy_state_to_str(old_state), + phy_state_to_str(phydev->state)); + if (phydev->drv && phydev->drv->link_change_notify) + phydev->drv->link_change_notify(phydev); + } +} + static void phy_link_up(struct phy_device *phydev) { phydev->phy_link_change(phydev, true); @@ -1301,6 +1313,7 @@ EXPORT_SYMBOL(phy_free_interrupt); void phy_stop(struct phy_device *phydev) { struct net_device *dev = phydev->attached_dev; + enum phy_state old_state; if (!phy_is_started(phydev) && phydev->state != PHY_DOWN) { WARN(1, "called from state %s\n", @@ -1309,6 +1322,7 @@ void phy_stop(struct phy_device *phydev) } mutex_lock(&phydev->lock); + old_state = phydev->state; if (phydev->state == PHY_CABLETEST) { phy_abort_cable_test(phydev); @@ -1319,6 +1333,7 @@ void phy_stop(struct phy_device *phydev) sfp_upstream_stop(phydev->sfp_bus); phydev->state = PHY_HALTED; + phy_process_state_change(phydev, old_state); mutex_unlock(&phydev->lock); @@ -1436,13 +1451,7 @@ void phy_state_machine(struct work_struct *work) if (err < 0) phy_error(phydev); - if (old_state != phydev->state) { - phydev_dbg(phydev, "PHY state change %s -> %s\n", - phy_state_to_str(old_state), - phy_state_to_str(phydev->state)); - if (phydev->drv && phydev->drv->link_change_notify) - phydev->drv->link_change_notify(phydev); - } + phy_process_state_change(phydev, old_state); /* Only re-schedule a PHY state machine change if we are polling the * PHY, if PHY_MAC_INTERRUPT is set, then we will be moving -- cgit From 99669259f3361d759219811e670b7e0742668556 Mon Sep 17 00:00:00 2001 From: Maxime Bizon Date: Thu, 16 Mar 2023 16:33:16 -0700 Subject: net: mdio: fix owner field for mdio buses registered using device-tree Bus ownership is wrong when using of_mdiobus_register() to register an mdio bus. That function is not inline, so when it calls mdiobus_register() the wrong THIS_MODULE value is captured. Signed-off-by: Maxime Bizon Fixes: 90eff9096c01 ("net: phy: Allow splitting MDIO bus/device support from PHYs") [florian: fix kdoc, added Fixes tag] Signed-off-by: Florian Fainelli Reviewed-by: Simon Horman Signed-off-by: David S. Miller --- drivers/net/mdio/of_mdio.c | 12 +++++++----- drivers/net/phy/mdio_devres.c | 11 ++++++----- include/linux/of_mdio.h | 22 +++++++++++++++++++--- 3 files changed, 32 insertions(+), 13 deletions(-) diff --git a/drivers/net/mdio/of_mdio.c b/drivers/net/mdio/of_mdio.c index 510822d6d0d9..1e46e39f5f46 100644 --- a/drivers/net/mdio/of_mdio.c +++ b/drivers/net/mdio/of_mdio.c @@ -139,21 +139,23 @@ bool of_mdiobus_child_is_phy(struct device_node *child) EXPORT_SYMBOL(of_mdiobus_child_is_phy); /** - * of_mdiobus_register - Register mii_bus and create PHYs from the device tree + * __of_mdiobus_register - Register mii_bus and create PHYs from the device tree * @mdio: pointer to mii_bus structure * @np: pointer to device_node of MDIO bus. + * @owner: module owning the @mdio object. * * This function registers the mii_bus structure and registers a phy_device * for each child node of @np. */ -int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np) +int __of_mdiobus_register(struct mii_bus *mdio, struct device_node *np, + struct module *owner) { struct device_node *child; bool scanphys = false; int addr, rc; if (!np) - return mdiobus_register(mdio); + return __mdiobus_register(mdio, owner); /* Do not continue if the node is disabled */ if (!of_device_is_available(np)) @@ -172,7 +174,7 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np) of_property_read_u32(np, "reset-post-delay-us", &mdio->reset_post_delay_us); /* Register the MDIO bus */ - rc = mdiobus_register(mdio); + rc = __mdiobus_register(mdio, owner); if (rc) return rc; @@ -236,7 +238,7 @@ unregister: mdiobus_unregister(mdio); return rc; } -EXPORT_SYMBOL(of_mdiobus_register); +EXPORT_SYMBOL(__of_mdiobus_register); /** * of_mdio_find_device - Given a device tree node, find the mdio_device diff --git a/drivers/net/phy/mdio_devres.c b/drivers/net/phy/mdio_devres.c index b560e99695df..69b829e6ab35 100644 --- a/drivers/net/phy/mdio_devres.c +++ b/drivers/net/phy/mdio_devres.c @@ -98,13 +98,14 @@ EXPORT_SYMBOL(__devm_mdiobus_register); #if IS_ENABLED(CONFIG_OF_MDIO) /** - * devm_of_mdiobus_register - Resource managed variant of of_mdiobus_register() + * __devm_of_mdiobus_register - Resource managed variant of of_mdiobus_register() * @dev: Device to register mii_bus for * @mdio: MII bus structure to register * @np: Device node to parse + * @owner: Owning module */ -int devm_of_mdiobus_register(struct device *dev, struct mii_bus *mdio, - struct device_node *np) +int __devm_of_mdiobus_register(struct device *dev, struct mii_bus *mdio, + struct device_node *np, struct module *owner) { struct mdiobus_devres *dr; int ret; @@ -117,7 +118,7 @@ int devm_of_mdiobus_register(struct device *dev, struct mii_bus *mdio, if (!dr) return -ENOMEM; - ret = of_mdiobus_register(mdio, np); + ret = __of_mdiobus_register(mdio, np, owner); if (ret) { devres_free(dr); return ret; @@ -127,7 +128,7 @@ int devm_of_mdiobus_register(struct device *dev, struct mii_bus *mdio, devres_add(dev, dr); return 0; } -EXPORT_SYMBOL(devm_of_mdiobus_register); +EXPORT_SYMBOL(__devm_of_mdiobus_register); #endif /* CONFIG_OF_MDIO */ MODULE_LICENSE("GPL"); diff --git a/include/linux/of_mdio.h b/include/linux/of_mdio.h index da633d34ab86..8a52ef2e6fa6 100644 --- a/include/linux/of_mdio.h +++ b/include/linux/of_mdio.h @@ -14,9 +14,25 @@ #if IS_ENABLED(CONFIG_OF_MDIO) bool of_mdiobus_child_is_phy(struct device_node *child); -int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np); -int devm_of_mdiobus_register(struct device *dev, struct mii_bus *mdio, - struct device_node *np); +int __of_mdiobus_register(struct mii_bus *mdio, struct device_node *np, + struct module *owner); + +static inline int of_mdiobus_register(struct mii_bus *mdio, + struct device_node *np) +{ + return __of_mdiobus_register(mdio, np, THIS_MODULE); +} + +int __devm_of_mdiobus_register(struct device *dev, struct mii_bus *mdio, + struct device_node *np, struct module *owner); + +static inline int devm_of_mdiobus_register(struct device *dev, + struct mii_bus *mdio, + struct device_node *np) +{ + return __devm_of_mdiobus_register(dev, mdio, np, THIS_MODULE); +} + struct mdio_device *of_mdio_find_device(struct device_node *np); struct phy_device *of_phy_find_device(struct device_node *phy_np); struct phy_device * -- cgit From 30b605b8501e321f79e19c3238aa6ca31da6087c Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Thu, 16 Mar 2023 16:33:17 -0700 Subject: net: mdio: fix owner field for mdio buses registered using ACPI Bus ownership is wrong when using acpi_mdiobus_register() to register an mdio bus. That function is not inline, so when it calls mdiobus_register() the wrong THIS_MODULE value is captured. CC: Maxime Bizon Fixes: 803ca24d2f92 ("net: mdio: Add ACPI support code for mdio") Signed-off-by: Florian Fainelli Reviewed-by: Simon Horman Signed-off-by: David S. Miller --- drivers/net/mdio/acpi_mdio.c | 10 ++++++---- include/linux/acpi_mdio.h | 9 ++++++++- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/drivers/net/mdio/acpi_mdio.c b/drivers/net/mdio/acpi_mdio.c index d77c987fda9c..4630dde01974 100644 --- a/drivers/net/mdio/acpi_mdio.c +++ b/drivers/net/mdio/acpi_mdio.c @@ -18,16 +18,18 @@ MODULE_AUTHOR("Calvin Johnson "); MODULE_LICENSE("GPL"); /** - * acpi_mdiobus_register - Register mii_bus and create PHYs from the ACPI ASL. + * __acpi_mdiobus_register - Register mii_bus and create PHYs from the ACPI ASL. * @mdio: pointer to mii_bus structure * @fwnode: pointer to fwnode of MDIO bus. This fwnode is expected to represent + * @owner: module owning this @mdio object. * an ACPI device object corresponding to the MDIO bus and its children are * expected to correspond to the PHY devices on that bus. * * This function registers the mii_bus structure and registers a phy_device * for each child node of @fwnode. */ -int acpi_mdiobus_register(struct mii_bus *mdio, struct fwnode_handle *fwnode) +int __acpi_mdiobus_register(struct mii_bus *mdio, struct fwnode_handle *fwnode, + struct module *owner) { struct fwnode_handle *child; u32 addr; @@ -35,7 +37,7 @@ int acpi_mdiobus_register(struct mii_bus *mdio, struct fwnode_handle *fwnode) /* Mask out all PHYs from auto probing. */ mdio->phy_mask = GENMASK(31, 0); - ret = mdiobus_register(mdio); + ret = __mdiobus_register(mdio, owner); if (ret) return ret; @@ -55,4 +57,4 @@ int acpi_mdiobus_register(struct mii_bus *mdio, struct fwnode_handle *fwnode) } return 0; } -EXPORT_SYMBOL(acpi_mdiobus_register); +EXPORT_SYMBOL(__acpi_mdiobus_register); diff --git a/include/linux/acpi_mdio.h b/include/linux/acpi_mdio.h index 0a24ab7cb66f..8e2eefa9fbc0 100644 --- a/include/linux/acpi_mdio.h +++ b/include/linux/acpi_mdio.h @@ -9,7 +9,14 @@ #include #if IS_ENABLED(CONFIG_ACPI_MDIO) -int acpi_mdiobus_register(struct mii_bus *mdio, struct fwnode_handle *fwnode); +int __acpi_mdiobus_register(struct mii_bus *mdio, struct fwnode_handle *fwnode, + struct module *owner); + +static inline int +acpi_mdiobus_register(struct mii_bus *mdio, struct fwnode_handle *handle) +{ + return __acpi_mdiobus_register(mdio, handle, THIS_MODULE); +} #else /* CONFIG_ACPI_MDIO */ static inline int acpi_mdiobus_register(struct mii_bus *mdio, struct fwnode_handle *fwnode) -- cgit From 070246e4674b125860d311c18ce2623e73e2bd51 Mon Sep 17 00:00:00 2001 From: Jochen Henneberg Date: Fri, 17 Mar 2023 09:08:17 +0100 Subject: net: stmmac: Fix for mismatched host/device DMA address width Currently DMA address width is either read from a RO device register or force set from the platform data. This breaks DMA when the host DMA address width is <=32it but the device is >32bit. Right now the driver may decide to use a 2nd DMA descriptor for another buffer (happens in case of TSO xmit) assuming that 32bit addressing is used due to platform configuration but the device will still use both descriptor addresses as one address. This can be observed with the Intel EHL platform driver that sets 32bit for addr64 but the MAC reports 40bit. The TX queue gets stuck in case of TCP with iptables NAT configuration on TSO packets. The logic should be like this: Whatever we do on the host side (memory allocation GFP flags) should happen with the host DMA width, whenever we decide how to set addresses on the device registers we must use the device DMA address width. This patch renames the platform address width field from addr64 (term used in device datasheet) to host_addr and uses this value exclusively for host side operations while all chip operations consider the device DMA width as read from the device register. Fixes: 7cfc4486e7ea ("stmmac: intel: Configure EHL PSE0 GbE and PSE1 GbE to 32 bits DMA addressing") Signed-off-by: Jochen Henneberg Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/common.h | 1 + drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c | 2 +- drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c | 4 +-- .../net/ethernet/stmicro/stmmac/dwmac-mediatek.c | 2 +- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 30 ++++++++++++---------- include/linux/stmmac.h | 2 +- 6 files changed, 22 insertions(+), 19 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h index 6b5d96bced47..ec9c130276d8 100644 --- a/drivers/net/ethernet/stmicro/stmmac/common.h +++ b/drivers/net/ethernet/stmicro/stmmac/common.h @@ -418,6 +418,7 @@ struct dma_features { unsigned int frpbs; unsigned int frpes; unsigned int addr64; + unsigned int host_dma_width; unsigned int rssen; unsigned int vlhash; unsigned int sphen; diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c index ac550d1ac015..2a2be65d65a0 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c @@ -288,7 +288,7 @@ static int imx_dwmac_probe(struct platform_device *pdev) goto err_parse_dt; } - plat_dat->addr64 = dwmac->ops->addr_width; + plat_dat->host_dma_width = dwmac->ops->addr_width; plat_dat->init = imx_dwmac_init; plat_dat->exit = imx_dwmac_exit; plat_dat->clks_config = imx_dwmac_clks_config; diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c index 7deb1f817dac..13aa919633b4 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c @@ -684,7 +684,7 @@ static int ehl_pse0_common_data(struct pci_dev *pdev, intel_priv->is_pse = true; plat->bus_id = 2; - plat->addr64 = 32; + plat->host_dma_width = 32; plat->clk_ptp_rate = 200000000; @@ -725,7 +725,7 @@ static int ehl_pse1_common_data(struct pci_dev *pdev, intel_priv->is_pse = true; plat->bus_id = 3; - plat->addr64 = 32; + plat->host_dma_width = 32; plat->clk_ptp_rate = 200000000; diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c index 2f7d8e4561d9..9ae31e3dc821 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c @@ -591,7 +591,7 @@ static int mediatek_dwmac_common_data(struct platform_device *pdev, plat->use_phy_wol = priv_plat->mac_wol ? 0 : 1; plat->riwt_off = 1; plat->maxmtu = ETH_DATA_LEN; - plat->addr64 = priv_plat->variant->dma_bit_mask; + plat->host_dma_width = priv_plat->variant->dma_bit_mask; plat->bsp_priv = priv_plat; plat->init = mediatek_dwmac_init; plat->clks_config = mediatek_dwmac_clks_config; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 8f543c3ab5c5..17310ade88dd 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -1431,7 +1431,7 @@ static int stmmac_init_rx_buffers(struct stmmac_priv *priv, struct stmmac_rx_buffer *buf = &rx_q->buf_pool[i]; gfp_t gfp = (GFP_ATOMIC | __GFP_NOWARN); - if (priv->dma_cap.addr64 <= 32) + if (priv->dma_cap.host_dma_width <= 32) gfp |= GFP_DMA32; if (!buf->page) { @@ -4587,7 +4587,7 @@ static inline void stmmac_rx_refill(struct stmmac_priv *priv, u32 queue) unsigned int entry = rx_q->dirty_rx; gfp_t gfp = (GFP_ATOMIC | __GFP_NOWARN); - if (priv->dma_cap.addr64 <= 32) + if (priv->dma_cap.host_dma_width <= 32) gfp |= GFP_DMA32; while (dirty-- > 0) { @@ -6205,7 +6205,7 @@ static int stmmac_dma_cap_show(struct seq_file *seq, void *v) seq_printf(seq, "\tFlexible RX Parser: %s\n", priv->dma_cap.frpsel ? "Y" : "N"); seq_printf(seq, "\tEnhanced Addressing: %d\n", - priv->dma_cap.addr64); + priv->dma_cap.host_dma_width); seq_printf(seq, "\tReceive Side Scaling: %s\n", priv->dma_cap.rssen ? "Y" : "N"); seq_printf(seq, "\tVLAN Hash Filtering: %s\n", @@ -7178,20 +7178,22 @@ int stmmac_dvr_probe(struct device *device, dev_info(priv->device, "SPH feature enabled\n"); } - /* The current IP register MAC_HW_Feature1[ADDR64] only define - * 32/40/64 bit width, but some SOC support others like i.MX8MP - * support 34 bits but it map to 40 bits width in MAC_HW_Feature1[ADDR64]. - * So overwrite dma_cap.addr64 according to HW real design. + /* Ideally our host DMA address width is the same as for the + * device. However, it may differ and then we have to use our + * host DMA width for allocation and the device DMA width for + * register handling. */ - if (priv->plat->addr64) - priv->dma_cap.addr64 = priv->plat->addr64; + if (priv->plat->host_dma_width) + priv->dma_cap.host_dma_width = priv->plat->host_dma_width; + else + priv->dma_cap.host_dma_width = priv->dma_cap.addr64; - if (priv->dma_cap.addr64) { + if (priv->dma_cap.host_dma_width) { ret = dma_set_mask_and_coherent(device, - DMA_BIT_MASK(priv->dma_cap.addr64)); + DMA_BIT_MASK(priv->dma_cap.host_dma_width)); if (!ret) { - dev_info(priv->device, "Using %d bits DMA width\n", - priv->dma_cap.addr64); + dev_info(priv->device, "Using %d/%d bits DMA host/device width\n", + priv->dma_cap.host_dma_width, priv->dma_cap.addr64); /* * If more than 32 bits can be addressed, make sure to @@ -7206,7 +7208,7 @@ int stmmac_dvr_probe(struct device *device, goto error_hw_init; } - priv->dma_cap.addr64 = 32; + priv->dma_cap.host_dma_width = 32; } } diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h index a152678b82b7..a2414c187483 100644 --- a/include/linux/stmmac.h +++ b/include/linux/stmmac.h @@ -215,7 +215,7 @@ struct plat_stmmacenet_data { int unicast_filter_entries; int tx_fifo_size; int rx_fifo_size; - u32 addr64; + u32 host_dma_width; u32 rx_queues_to_use; u32 tx_queues_to_use; u8 rx_sched_algorithm; -- cgit From 04361b8bb81819efb68bf39c276025e2250ac537 Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Fri, 17 Mar 2023 07:28:00 +0000 Subject: net: sfp: fix state loss when updating state_hw_mask Andrew reports that the SFF modules on one of the ZII platforms do not indicate link up due to the SFP code believing that LOS indicating that there is no signal being received from the remote end, but in fact the LOS signal is showing that there is signal. What makes SFF modules different from SFPs is they typically have an inverted LOS, which uncovered this issue. When we read the hardware state, we mask it with state_hw_mask so we ignore anything we're not interested in. However, we don't re-read when state_hw_mask changes, leading to sfp->state being stale. Arrange for a software poll of the module state after we have parsed the EEPROM in sfp_sm_mod_probe() and updated state_*_mask. This will generate any necessary events for signal changes for the state machine as well as updating sfp->state. Reported-by: Andrew Lunn Tested-by: Andrew Lunn Fixes: 8475c4b70b04 ("net: sfp: re-implement soft state polling setup") Signed-off-by: Russell King (Oracle) Signed-off-by: David S. Miller --- drivers/net/phy/sfp.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/phy/sfp.c b/drivers/net/phy/sfp.c index c02cad6478a8..fb98db61e06c 100644 --- a/drivers/net/phy/sfp.c +++ b/drivers/net/phy/sfp.c @@ -2190,6 +2190,11 @@ static void sfp_sm_module(struct sfp *sfp, unsigned int event) break; } + /* Force a poll to re-read the hardware signal state after + * sfp_sm_mod_probe() changed state_hw_mask. + */ + mod_delayed_work(system_wq, &sfp->poll, 1); + err = sfp_hwmon_insert(sfp); if (err) dev_warn(sfp->dev, "hwmon probe failed: %pe\n", -- cgit From 6d206b1ea9f48433a96edec7028586db1d947911 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Fri, 17 Mar 2023 16:32:59 +0100 Subject: mlxsw: core_thermal: Fix fan speed in maximum cooling state The cooling levels array is supposed to prevent the system fans from being configured below a 20% duty cycle as otherwise some of them get stuck at 0 RPM. Due to an off-by-one error, the last element in the array was not initialized, causing it to be set to zero, which in turn lead to fans being configured with a 0% duty cycle in maximum cooling state. Since commit 332fdf951df8 ("mlxsw: thermal: Fix out-of-bounds memory accesses") the contents of the array are static. Therefore, instead of fixing the initialization of the array, simply remove it and adjust thermal_cooling_device_ops::set_cur_state() so that the configured duty cycle is never set below 20%. Before: # cat /sys/class/thermal/thermal_zone0/cdev0/type mlxsw_fan # echo 10 > /sys/class/thermal/thermal_zone0/cdev0/cur_state # cat /sys/class/hwmon/hwmon0/name mlxsw # cat /sys/class/hwmon/hwmon0/pwm1 0 After: # cat /sys/class/thermal/thermal_zone0/cdev0/type mlxsw_fan # echo 10 > /sys/class/thermal/thermal_zone0/cdev0/cur_state # cat /sys/class/hwmon/hwmon0/name mlxsw # cat /sys/class/hwmon/hwmon0/pwm1 255 This bug was uncovered when the thermal subsystem repeatedly tried to configure the cooling devices to their maximum state due to another issue [1]. This resulted in the fans being stuck at 0 RPM, which eventually lead to the system undergoing thermal shutdown. [1] https://lore.kernel.org/netdev/ZA3CFNhU4AbtsP4G@shredder/ Fixes: a421ce088ac8 ("mlxsw: core: Extend cooling device with cooling levels") Signed-off-by: Ido Schimmel Reviewed-by: Vadim Pasternak Signed-off-by: Petr Machata Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/core_thermal.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c index c5240d38c9db..09ed6e5fa6c3 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c @@ -105,7 +105,6 @@ struct mlxsw_thermal { struct thermal_zone_device *tzdev; int polling_delay; struct thermal_cooling_device *cdevs[MLXSW_MFCR_PWMS_MAX]; - u8 cooling_levels[MLXSW_THERMAL_MAX_STATE + 1]; struct thermal_trip trips[MLXSW_THERMAL_NUM_TRIPS]; struct mlxsw_cooling_states cooling_states[MLXSW_THERMAL_NUM_TRIPS]; struct mlxsw_thermal_area line_cards[]; @@ -468,7 +467,7 @@ static int mlxsw_thermal_set_cur_state(struct thermal_cooling_device *cdev, return idx; /* Normalize the state to the valid speed range. */ - state = thermal->cooling_levels[state]; + state = max_t(unsigned long, MLXSW_THERMAL_MIN_STATE, state); mlxsw_reg_mfsc_pack(mfsc_pl, idx, mlxsw_state_to_duty(state)); err = mlxsw_reg_write(thermal->core, MLXSW_REG(mfsc), mfsc_pl); if (err) { @@ -859,10 +858,6 @@ int mlxsw_thermal_init(struct mlxsw_core *core, } } - /* Initialize cooling levels per PWM state. */ - for (i = 0; i < MLXSW_THERMAL_MAX_STATE; i++) - thermal->cooling_levels[i] = max(MLXSW_THERMAL_MIN_STATE, i); - thermal->polling_delay = bus_info->low_frequency ? MLXSW_THERMAL_SLOW_POLL_INT : MLXSW_THERMAL_POLL_INT; -- cgit From bc4f359b3b607daac0290d0038561237a86b38cb Mon Sep 17 00:00:00 2001 From: Anton Gusev Date: Tue, 31 Jan 2023 10:58:18 +0300 Subject: tracing: Fix wrong return in kprobe_event_gen_test.c Overwriting the error code with the deletion result may cause the function to return 0 despite encountering an error. Commit b111545d26c0 ("tracing: Remove the useless value assignment in test_create_synth_event()") solves a similar issue by returning the original error code, so this patch does the same. Found by Linux Verification Center (linuxtesting.org) with SVACE. Link: https://lore.kernel.org/linux-trace-kernel/20230131075818.5322-1-aagusev@ispras.ru Signed-off-by: Anton Gusev Reviewed-by: Steven Rostedt (Google) Acked-by: Masami Hiramatsu (Google) Signed-off-by: Steven Rostedt (Google) --- kernel/trace/kprobe_event_gen_test.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/trace/kprobe_event_gen_test.c b/kernel/trace/kprobe_event_gen_test.c index 4850fdfe27f1..5a4b722b5045 100644 --- a/kernel/trace/kprobe_event_gen_test.c +++ b/kernel/trace/kprobe_event_gen_test.c @@ -146,7 +146,7 @@ static int __init test_gen_kprobe_cmd(void) if (trace_event_file_is_valid(gen_kprobe_test)) gen_kprobe_test = NULL; /* We got an error after creating the event, delete it */ - ret = kprobe_event_delete("gen_kprobe_test"); + kprobe_event_delete("gen_kprobe_test"); goto out; } @@ -211,7 +211,7 @@ static int __init test_gen_kretprobe_cmd(void) if (trace_event_file_is_valid(gen_kretprobe_test)) gen_kretprobe_test = NULL; /* We got an error after creating the event, delete it */ - ret = kprobe_event_delete("gen_kretprobe_test"); + kprobe_event_delete("gen_kretprobe_test"); goto out; } -- cgit From 7a025e066e0f0afd39cc88a089929ccb945ce9e8 Mon Sep 17 00:00:00 2001 From: Tom Rix Date: Thu, 9 Mar 2023 10:04:14 -0500 Subject: tracing/osnoise: set several trace_osnoise.c variables storage-class-specifier to static smatch reports several similar warnings kernel/trace/trace_osnoise.c:220:1: warning: symbol '__pcpu_scope_per_cpu_osnoise_var' was not declared. Should it be static? kernel/trace/trace_osnoise.c:243:1: warning: symbol '__pcpu_scope_per_cpu_timerlat_var' was not declared. Should it be static? kernel/trace/trace_osnoise.c:335:14: warning: symbol 'interface_lock' was not declared. Should it be static? kernel/trace/trace_osnoise.c:2242:5: warning: symbol 'timerlat_min_period' was not declared. Should it be static? kernel/trace/trace_osnoise.c:2243:5: warning: symbol 'timerlat_max_period' was not declared. Should it be static? These variables are only used in trace_osnoise.c, so it should be static Link: https://lore.kernel.org/linux-trace-kernel/20230309150414.4036764-1-trix@redhat.com Signed-off-by: Tom Rix Acked-by: Masami Hiramatsu (Google) Acked-by: Daniel Bristot de Oliveira Signed-off-by: Steven Rostedt (Google) --- kernel/trace/trace_osnoise.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/kernel/trace/trace_osnoise.c b/kernel/trace/trace_osnoise.c index 04f0fdae19a1..9176bb7a9bb4 100644 --- a/kernel/trace/trace_osnoise.c +++ b/kernel/trace/trace_osnoise.c @@ -217,7 +217,7 @@ struct osnoise_variables { /* * Per-cpu runtime information. */ -DEFINE_PER_CPU(struct osnoise_variables, per_cpu_osnoise_var); +static DEFINE_PER_CPU(struct osnoise_variables, per_cpu_osnoise_var); /* * this_cpu_osn_var - Return the per-cpu osnoise_variables on its relative CPU @@ -240,7 +240,7 @@ struct timerlat_variables { u64 count; }; -DEFINE_PER_CPU(struct timerlat_variables, per_cpu_timerlat_var); +static DEFINE_PER_CPU(struct timerlat_variables, per_cpu_timerlat_var); /* * this_cpu_tmr_var - Return the per-cpu timerlat_variables on its relative CPU @@ -332,7 +332,7 @@ struct timerlat_sample { /* * Protect the interface. */ -struct mutex interface_lock; +static struct mutex interface_lock; /* * Tracer data. @@ -2239,8 +2239,8 @@ static struct trace_min_max_param osnoise_print_stack = { /* * osnoise/timerlat_period: min 100 us, max 1 s */ -u64 timerlat_min_period = 100; -u64 timerlat_max_period = 1000000; +static u64 timerlat_min_period = 100; +static u64 timerlat_max_period = 1000000; static struct trace_min_max_param timerlat_period = { .lock = &interface_lock, .val = &osnoise_data.timerlat_period, -- cgit From 4c42f5f0d1dd20bddd9f940beb1e6ccad60c4498 Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Fri, 10 Mar 2023 12:04:50 +0200 Subject: trace/hwlat: Do not wipe the contents of per-cpu thread data Do not wipe the contents of the per-cpu kthread data when starting the tracer, as this will completely forget about already running instances and can later start new additional per-cpu threads. Link: https://lore.kernel.org/all/20230302113654.2984709-1-tero.kristo@linux.intel.com/ Link: https://lkml.kernel.org/r/20230310100451.3948583-2-tero.kristo@linux.intel.com Cc: stable@vger.kernel.org Fixes: f46b16520a087 ("trace/hwlat: Implement the per-cpu mode") Signed-off-by: Tero Kristo Acked-by: Daniel Bristot de Oliveira Signed-off-by: Steven Rostedt (Google) --- kernel/trace/trace_hwlat.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/kernel/trace/trace_hwlat.c b/kernel/trace/trace_hwlat.c index d440ddd5fd8b..edc26dc22c3f 100644 --- a/kernel/trace/trace_hwlat.c +++ b/kernel/trace/trace_hwlat.c @@ -584,9 +584,6 @@ static int start_per_cpu_kthreads(struct trace_array *tr) */ cpumask_and(current_mask, cpu_online_mask, tr->tracing_cpumask); - for_each_online_cpu(cpu) - per_cpu(hwlat_per_cpu_data, cpu).kthread = NULL; - for_each_cpu(cpu, current_mask) { retval = start_cpu_kthread(cpu); if (retval) -- cgit From 08697bca9bbba15f2058fdbd9f970bd5f6a8a2e8 Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Fri, 10 Mar 2023 12:04:51 +0200 Subject: trace/hwlat: Do not start per-cpu thread if it is already running The hwlatd tracer will end up starting multiple per-cpu threads with the following script: #!/bin/sh cd /sys/kernel/debug/tracing echo 0 > tracing_on echo hwlat > current_tracer echo per-cpu > hwlat_detector/mode echo 100000 > hwlat_detector/width echo 200000 > hwlat_detector/window echo 1 > tracing_on To fix the issue, check if the hwlatd thread for the cpu is already running, before starting a new one. Along with the previous patch, this avoids running multiple instances of the same CPU thread on the system. Link: https://lore.kernel.org/all/20230302113654.2984709-1-tero.kristo@linux.intel.com/ Link: https://lkml.kernel.org/r/20230310100451.3948583-3-tero.kristo@linux.intel.com Cc: stable@vger.kernel.org Fixes: f46b16520a087 ("trace/hwlat: Implement the per-cpu mode") Signed-off-by: Tero Kristo Acked-by: Daniel Bristot de Oliveira Signed-off-by: Steven Rostedt (Google) --- kernel/trace/trace_hwlat.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/kernel/trace/trace_hwlat.c b/kernel/trace/trace_hwlat.c index edc26dc22c3f..c4945f8adc11 100644 --- a/kernel/trace/trace_hwlat.c +++ b/kernel/trace/trace_hwlat.c @@ -492,6 +492,10 @@ static int start_cpu_kthread(unsigned int cpu) { struct task_struct *kthread; + /* Do not start a new hwlatd thread if it is already running */ + if (per_cpu(hwlat_per_cpu_data, cpu).kthread) + return 0; + kthread = kthread_run_on_cpu(kthread_fn, NULL, cpu, "hwlatd/%u"); if (IS_ERR(kthread)) { pr_err(BANNER "could not start sampling thread\n"); -- cgit From 8732565549011cabbea08329a1aefd78a68d96c7 Mon Sep 17 00:00:00 2001 From: Tom Rix Date: Sat, 11 Mar 2023 08:51:13 -0500 Subject: ftrace: Set direct_ops storage-class-specifier to static smatch reports this warning kernel/trace/ftrace.c:2594:19: warning: symbol 'direct_ops' was not declared. Should it be static? The variable direct_ops is only used in ftrace.c, so it should be static Link: https://lore.kernel.org/linux-trace-kernel/20230311135113.711824-1-trix@redhat.com Signed-off-by: Tom Rix Acked-by: Masami Hiramatsu (Google) Signed-off-by: Steven Rostedt (Google) --- kernel/trace/ftrace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index a47f7d93e32d..ec2897a76004 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -2503,7 +2503,7 @@ static void call_direct_funcs(unsigned long ip, unsigned long pip, arch_ftrace_set_direct_caller(fregs, addr); } -struct ftrace_ops direct_ops = { +static struct ftrace_ops direct_ops = { .func = call_direct_funcs, .flags = FTRACE_OPS_FL_DIRECT | FTRACE_OPS_FL_SAVE_REGS | FTRACE_OPS_FL_PERMANENT, -- cgit From e400be674a1a40e9dcb2e95f84d6c1fd2d88f31d Mon Sep 17 00:00:00 2001 From: Sung-hun Kim Date: Tue, 14 Mar 2023 10:37:07 +0900 Subject: tracing: Make splice_read available again Since the commit 36e2c7421f02 ("fs: don't allow splice read/write without explicit ops") is applied to the kernel, splice() and sendfile() calls on the trace file (/sys/kernel/debug/tracing /trace) return EINVAL. This patch restores these system calls by initializing splice_read in file_operations of the trace file. This patch only enables such functionalities for the read case. Link: https://lore.kernel.org/linux-trace-kernel/20230314013707.28814-1-sfoon.kim@samsung.com Cc: stable@vger.kernel.org Fixes: 36e2c7421f02 ("fs: don't allow splice read/write without explicit ops") Signed-off-by: Sung-hun Kim Signed-off-by: Steven Rostedt (Google) --- kernel/trace/trace.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index fbb602a8b64b..4e9a7a952025 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -5164,6 +5164,8 @@ loff_t tracing_lseek(struct file *file, loff_t offset, int whence) static const struct file_operations tracing_fops = { .open = tracing_open, .read = seq_read, + .read_iter = seq_read_iter, + .splice_read = generic_file_splice_read, .write = tracing_write_stub, .llseek = tracing_lseek, .release = tracing_release, -- cgit From a98151ad53b53f010ee364ec2fd06445b328578b Mon Sep 17 00:00:00 2001 From: Vlastimil Babka Date: Wed, 15 Mar 2023 15:24:46 +0100 Subject: ring-buffer: remove obsolete comment for free_buffer_page() The comment refers to mm/slob.c which is being removed. It comes from commit ed56829cb319 ("ring_buffer: reset buffer page when freeing") and according to Steven the borrowed code was a page mapcount and mapping reset, which was later removed by commit e4c2ce82ca27 ("ring_buffer: allocate buffer page pointer"). Thus the comment is not accurate anyway, remove it. Link: https://lore.kernel.org/linux-trace-kernel/20230315142446.27040-1-vbabka@suse.cz Cc: Masami Hiramatsu Cc: Ingo Molnar Reported-by: Mike Rapoport Suggested-by: Steven Rostedt (Google) Fixes: e4c2ce82ca27 ("ring_buffer: allocate buffer page pointer") Signed-off-by: Vlastimil Babka Reviewed-by: Mukesh Ojha Signed-off-by: Steven Rostedt (Google) --- kernel/trace/ring_buffer.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index 071184324d18..3c7cd135333f 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c @@ -354,10 +354,6 @@ static void rb_init_page(struct buffer_data_page *bpage) local_set(&bpage->commit, 0); } -/* - * Also stolen from mm/slob.c. Thanks to Mathieu Desnoyers for pointing - * this issue out. - */ static void free_buffer_page(struct buffer_page *bpage) { free_page((unsigned long)bpage->page); -- cgit From 71c7a30442b724717a30d5e7d1662ba4904eb3d4 Mon Sep 17 00:00:00 2001 From: Costa Shulyupin Date: Thu, 16 Mar 2023 16:45:35 +0200 Subject: tracing/hwlat: Replace sched_setaffinity with set_cpus_allowed_ptr There is a problem with the behavior of hwlat in a container, resulting in incorrect output. A warning message is generated: "cpumask changed while in round-robin mode, switching to mode none", and the tracing_cpumask is ignored. This issue arises because the kernel thread, hwlatd, is not a part of the container, and the function sched_setaffinity is unable to locate it using its PID. Additionally, the task_struct of hwlatd is already known. Ultimately, the function set_cpus_allowed_ptr achieves the same outcome as sched_setaffinity, but employs task_struct instead of PID. Test case: # cd /sys/kernel/tracing # echo 0 > tracing_on # echo round-robin > hwlat_detector/mode # echo hwlat > current_tracer # unshare --fork --pid bash -c 'echo 1 > tracing_on' # dmesg -c Actual behavior: [573502.809060] hwlat_detector: cpumask changed while in round-robin mode, switching to mode none Link: https://lore.kernel.org/linux-trace-kernel/20230316144535.1004952-1-costa.shul@redhat.com Cc: Masami Hiramatsu Fixes: 0330f7aa8ee63 ("tracing: Have hwlat trace migrate across tracing_cpumask CPUs") Signed-off-by: Costa Shulyupin Acked-by: Daniel Bristot de Oliveira Signed-off-by: Steven Rostedt (Google) --- kernel/trace/trace_hwlat.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/trace/trace_hwlat.c b/kernel/trace/trace_hwlat.c index c4945f8adc11..2f37a6e68aa9 100644 --- a/kernel/trace/trace_hwlat.c +++ b/kernel/trace/trace_hwlat.c @@ -339,7 +339,7 @@ static void move_to_next_cpu(void) cpumask_clear(current_mask); cpumask_set_cpu(next_cpu, current_mask); - sched_setaffinity(0, current_mask); + set_cpus_allowed_ptr(current, current_mask); return; change_mode: @@ -446,7 +446,7 @@ static int start_single_kthread(struct trace_array *tr) } - sched_setaffinity(kthread->pid, current_mask); + set_cpus_allowed_ptr(kthread, current_mask); kdata->kthread = kthread; wake_up_process(kthread); -- cgit From e8d018dd0257f744ca50a729e3d042cf2ec9da65 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 19 Mar 2023 13:27:55 -0700 Subject: Linux 6.3-rc3 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index b1506df8b8d8..a2c310df2145 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ VERSION = 6 PATCHLEVEL = 3 SUBLEVEL = 0 -EXTRAVERSION = -rc2 +EXTRAVERSION = -rc3 NAME = Hurr durr I'ma ninja sloth # *DOCUMENTATION* -- cgit From a8eff03545d4cef12ae66a1905627c1818a0f81a Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Sat, 18 Mar 2023 01:19:00 +0200 Subject: net: dsa: report rx_bytes unadjusted for ETH_HLEN We collect the software statistics counters for RX bytes (reported to /proc/net/dev and to ethtool -S $dev | grep 'rx_bytes: ") at a time when skb->len has already been adjusted by the eth_type_trans() -> skb_pull_inline(skb, ETH_HLEN) call to exclude the L2 header. This means that when connecting 2 DSA interfaces back to back and sending 1 packet with length 100, the sending interface will report tx_bytes as incrementing by 100, and the receiving interface will report rx_bytes as incrementing by 86. Since accounting for that in scripts is quirky and is something that would be DSA-specific behavior (requiring users to know that they are running on a DSA interface in the first place), the proposal is that we treat it as a bug and fix it. This design bug has always existed in DSA, according to my analysis: commit 91da11f870f0 ("net: Distributed Switch Architecture protocol support") also updates skb->dev->stats.rx_bytes += skb->len after the eth_type_trans() call. Technically, prior to Florian's commit a86d8becc3f0 ("net: dsa: Factor bottom tag receive functions"), each and every vendor-specific tagging protocol driver open-coded the same bug, until the buggy code was consolidated into something resembling what can be seen now. So each and every driver should have its own Fixes: tag, because of their different histories until the convergence point. I'm not going to do that, for the sake of simplicity, but just blame the oldest appearance of buggy code. There are 2 ways to fix the problem. One is the obvious way, and the other is how I ended up doing it. Obvious would have been to move dev_sw_netstats_rx_add() one line above eth_type_trans(), and below skb_push(skb, ETH_HLEN). But DSA processing is not as simple as that. We count the bytes after removing everything DSA-related from the packet, to emulate what the packet's length was, on the wire, when the user port received it. When eth_type_trans() executes, dsa_untag_bridge_pvid() has not run yet, so in case the switch driver requests this behavior - commit 412a1526d067 ("net: dsa: untag the bridge pvid from rx skbs") has the details - the obvious variant of the fix wouldn't have worked, because the positioning there would have also counted the not-yet-stripped VLAN header length, something which is absent from the packet as seen on the wire (there it may be untagged, whereas software will see it as PVID-tagged). Fixes: f613ed665bb3 ("net: dsa: Add support for 64-bit statistics") Signed-off-by: Vladimir Oltean Signed-off-by: David S. Miller --- net/dsa/tag.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/dsa/tag.c b/net/dsa/tag.c index b2fba1a003ce..5105a5ff58fa 100644 --- a/net/dsa/tag.c +++ b/net/dsa/tag.c @@ -114,7 +114,7 @@ static int dsa_switch_rcv(struct sk_buff *skb, struct net_device *dev, skb = nskb; } - dev_sw_netstats_rx_add(skb->dev, skb->len); + dev_sw_netstats_rx_add(skb->dev, skb->len + ETH_HLEN); if (dsa_skb_defer_rx_timestamp(p, skb)) return 0; -- cgit From 6b6bc5b8bd2d4ca9e1efa9ae0f98a0b0687ace75 Mon Sep 17 00:00:00 2001 From: Zheng Wang Date: Sat, 18 Mar 2023 16:05:26 +0800 Subject: net: qcom/emac: Fix use after free bug in emac_remove due to race condition In emac_probe, &adpt->work_thread is bound with emac_work_thread. Then it will be started by timeout handler emac_tx_timeout or a IRQ handler emac_isr. If we remove the driver which will call emac_remove to make cleanup, there may be a unfinished work. The possible sequence is as follows: Fix it by finishing the work before cleanup in the emac_remove and disable timeout response. CPU0 CPU1 |emac_work_thread emac_remove | free_netdev | kfree(netdev); | |emac_reinit_locked |emac_mac_down |//use netdev Fixes: b9b17debc69d ("net: emac: emac gigabit ethernet controller driver") Signed-off-by: Zheng Wang Signed-off-by: David S. Miller --- drivers/net/ethernet/qualcomm/emac/emac.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/net/ethernet/qualcomm/emac/emac.c b/drivers/net/ethernet/qualcomm/emac/emac.c index 3115b2c12898..eaa50050aa0b 100644 --- a/drivers/net/ethernet/qualcomm/emac/emac.c +++ b/drivers/net/ethernet/qualcomm/emac/emac.c @@ -724,9 +724,15 @@ static int emac_remove(struct platform_device *pdev) struct net_device *netdev = dev_get_drvdata(&pdev->dev); struct emac_adapter *adpt = netdev_priv(netdev); + netif_carrier_off(netdev); + netif_tx_disable(netdev); + unregister_netdev(netdev); netif_napi_del(&adpt->rx_q.napi); + free_irq(adpt->irq.irq, &adpt->irq); + cancel_work_sync(&adpt->work_thread); + emac_clks_teardown(adpt); put_device(&adpt->phydev->mdio.dev); -- cgit From 7f247f5a2c18b3f21206cdd51193df4f38e1b9f5 Mon Sep 17 00:00:00 2001 From: Szymon Heidrich Date: Sat, 18 Mar 2023 10:25:52 +0100 Subject: net: usb: lan78xx: Limit packet length to skb->len Packet length retrieved from descriptor may be larger than the actual socket buffer length. In such case the cloned skb passed up the network stack will leak kernel memory contents. Additionally prevent integer underflow when size is less than ETH_FCS_LEN. Fixes: 55d7de9de6c3 ("Microchip's LAN7800 family USB 2/3 to 10/100/1000 Ethernet device driver") Signed-off-by: Szymon Heidrich Signed-off-by: David S. Miller --- drivers/net/usb/lan78xx.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c index 068488890d57..c458c030fadf 100644 --- a/drivers/net/usb/lan78xx.c +++ b/drivers/net/usb/lan78xx.c @@ -3579,13 +3579,29 @@ static int lan78xx_rx(struct lan78xx_net *dev, struct sk_buff *skb, size = (rx_cmd_a & RX_CMD_A_LEN_MASK_); align_count = (4 - ((size + RXW_PADDING) % 4)) % 4; + if (unlikely(size > skb->len)) { + netif_dbg(dev, rx_err, dev->net, + "size err rx_cmd_a=0x%08x\n", + rx_cmd_a); + return 0; + } + if (unlikely(rx_cmd_a & RX_CMD_A_RED_)) { netif_dbg(dev, rx_err, dev->net, "Error rx_cmd_a=0x%08x", rx_cmd_a); } else { - u32 frame_len = size - ETH_FCS_LEN; + u32 frame_len; struct sk_buff *skb2; + if (unlikely(size < ETH_FCS_LEN)) { + netif_dbg(dev, rx_err, dev->net, + "size err rx_cmd_a=0x%08x\n", + rx_cmd_a); + return 0; + } + + frame_len = size - ETH_FCS_LEN; + skb2 = napi_alloc_skb(&dev->napi, frame_len); if (!skb2) return 0; -- cgit From 7d722c9802d4bd61a1f1614e07413b6a5fac382d Mon Sep 17 00:00:00 2001 From: Tom Rix Date: Sat, 18 Mar 2023 09:13:42 -0400 Subject: usb: plusb: remove unused pl_clear_QuickLink_features function clang with W=1 reports drivers/net/usb/plusb.c:65:1: error: unused function 'pl_clear_QuickLink_features' [-Werror,-Wunused-function] pl_clear_QuickLink_features(struct usbnet *dev, int val) ^ This static function is not used, so remove it. Signed-off-by: Tom Rix Signed-off-by: David S. Miller --- drivers/net/usb/plusb.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/net/usb/plusb.c b/drivers/net/usb/plusb.c index 7a2b0094de51..2894114858a2 100644 --- a/drivers/net/usb/plusb.c +++ b/drivers/net/usb/plusb.c @@ -61,12 +61,6 @@ pl_vendor_req(struct usbnet *dev, u8 req, u8 val, u8 index) val, index, NULL, 0); } -static inline int -pl_clear_QuickLink_features(struct usbnet *dev, int val) -{ - return pl_vendor_req(dev, 1, (u8) val, 0); -} - static inline int pl_set_QuickLink_features(struct usbnet *dev, int val) { -- cgit From 19b3bb51c3bc288b3f2c6f8c4450b0f548320625 Mon Sep 17 00:00:00 2001 From: Geoff Levand Date: Sat, 18 Mar 2023 17:39:16 +0000 Subject: net/ps3_gelic_net: Fix RX sk_buff length The Gelic Ethernet device needs to have the RX sk_buffs aligned to GELIC_NET_RXBUF_ALIGN, and also the length of the RX sk_buffs must be a multiple of GELIC_NET_RXBUF_ALIGN. The current Gelic Ethernet driver was not allocating sk_buffs large enough to allow for this alignment. Also, correct the maximum and minimum MTU sizes, and add a new preprocessor macro for the maximum frame size, GELIC_NET_MAX_FRAME. Fixes various randomly occurring runtime network errors. Fixes: 02c1889166b4 ("ps3: gigabit ethernet driver for PS3, take3") Signed-off-by: Geoff Levand Signed-off-by: David S. Miller --- drivers/net/ethernet/toshiba/ps3_gelic_net.c | 19 ++++++++++--------- drivers/net/ethernet/toshiba/ps3_gelic_net.h | 5 +++-- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/drivers/net/ethernet/toshiba/ps3_gelic_net.c b/drivers/net/ethernet/toshiba/ps3_gelic_net.c index cf8de8a7a8a1..dffd664e65f4 100644 --- a/drivers/net/ethernet/toshiba/ps3_gelic_net.c +++ b/drivers/net/ethernet/toshiba/ps3_gelic_net.c @@ -365,26 +365,27 @@ iommu_error: * * allocates a new rx skb, iommu-maps it and attaches it to the descriptor. * Activate the descriptor state-wise + * + * Gelic RX sk_buffs must be aligned to GELIC_NET_RXBUF_ALIGN and the length + * must be a multiple of GELIC_NET_RXBUF_ALIGN. */ static int gelic_descr_prepare_rx(struct gelic_card *card, struct gelic_descr *descr) { + static const unsigned int rx_skb_size = + ALIGN(GELIC_NET_MAX_FRAME, GELIC_NET_RXBUF_ALIGN) + + GELIC_NET_RXBUF_ALIGN - 1; int offset; - unsigned int bufsize; if (gelic_descr_get_status(descr) != GELIC_DESCR_DMA_NOT_IN_USE) dev_info(ctodev(card), "%s: ERROR status\n", __func__); - /* we need to round up the buffer size to a multiple of 128 */ - bufsize = ALIGN(GELIC_NET_MAX_MTU, GELIC_NET_RXBUF_ALIGN); - /* and we need to have it 128 byte aligned, therefore we allocate a - * bit more */ - descr->skb = dev_alloc_skb(bufsize + GELIC_NET_RXBUF_ALIGN - 1); + descr->skb = netdev_alloc_skb(*card->netdev, rx_skb_size); if (!descr->skb) { descr->buf_addr = 0; /* tell DMAC don't touch memory */ return -ENOMEM; } - descr->buf_size = cpu_to_be32(bufsize); + descr->buf_size = cpu_to_be32(rx_skb_size); descr->dmac_cmd_status = 0; descr->result_size = 0; descr->valid_size = 0; @@ -397,7 +398,7 @@ static int gelic_descr_prepare_rx(struct gelic_card *card, /* io-mmu-map the skb */ descr->buf_addr = cpu_to_be32(dma_map_single(ctodev(card), descr->skb->data, - GELIC_NET_MAX_MTU, + GELIC_NET_MAX_FRAME, DMA_FROM_DEVICE)); if (!descr->buf_addr) { dev_kfree_skb_any(descr->skb); @@ -915,7 +916,7 @@ static void gelic_net_pass_skb_up(struct gelic_descr *descr, data_error = be32_to_cpu(descr->data_error); /* unmap skb buffer */ dma_unmap_single(ctodev(card), be32_to_cpu(descr->buf_addr), - GELIC_NET_MAX_MTU, + GELIC_NET_MAX_FRAME, DMA_FROM_DEVICE); skb_put(skb, be32_to_cpu(descr->valid_size)? diff --git a/drivers/net/ethernet/toshiba/ps3_gelic_net.h b/drivers/net/ethernet/toshiba/ps3_gelic_net.h index 68f324ed4eaf..0d98defb011e 100644 --- a/drivers/net/ethernet/toshiba/ps3_gelic_net.h +++ b/drivers/net/ethernet/toshiba/ps3_gelic_net.h @@ -19,8 +19,9 @@ #define GELIC_NET_RX_DESCRIPTORS 128 /* num of descriptors */ #define GELIC_NET_TX_DESCRIPTORS 128 /* num of descriptors */ -#define GELIC_NET_MAX_MTU VLAN_ETH_FRAME_LEN -#define GELIC_NET_MIN_MTU VLAN_ETH_ZLEN +#define GELIC_NET_MAX_FRAME 2312 +#define GELIC_NET_MAX_MTU 2294 +#define GELIC_NET_MIN_MTU 64 #define GELIC_NET_RXBUF_ALIGN 128 #define GELIC_CARD_RX_CSUM_DEFAULT 1 /* hw chksum */ #define GELIC_NET_WATCHDOG_TIMEOUT 5*HZ -- cgit From bebe933d35a63d4f042fbf4dce4f22e689ba0fcd Mon Sep 17 00:00:00 2001 From: Geoff Levand Date: Sat, 18 Mar 2023 17:39:16 +0000 Subject: net/ps3_gelic_net: Use dma_mapping_error The current Gelic Etherenet driver was checking the return value of its dma_map_single call, and not using the dma_mapping_error() routine. Fixes runtime problems like these: DMA-API: ps3_gelic_driver sb_05: device driver failed to check map error WARNING: CPU: 0 PID: 0 at kernel/dma/debug.c:1027 .check_unmap+0x888/0x8dc Fixes: 02c1889166b4 ("ps3: gigabit ethernet driver for PS3, take3") Reviewed-by: Alexander Duyck Signed-off-by: Geoff Levand Signed-off-by: David S. Miller --- drivers/net/ethernet/toshiba/ps3_gelic_net.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/drivers/net/ethernet/toshiba/ps3_gelic_net.c b/drivers/net/ethernet/toshiba/ps3_gelic_net.c index dffd664e65f4..9d535ae59626 100644 --- a/drivers/net/ethernet/toshiba/ps3_gelic_net.c +++ b/drivers/net/ethernet/toshiba/ps3_gelic_net.c @@ -317,15 +317,17 @@ static int gelic_card_init_chain(struct gelic_card *card, /* set up the hardware pointers in each descriptor */ for (i = 0; i < no; i++, descr++) { + dma_addr_t cpu_addr; + gelic_descr_set_status(descr, GELIC_DESCR_DMA_NOT_IN_USE); - descr->bus_addr = - dma_map_single(ctodev(card), descr, - GELIC_DESCR_SIZE, - DMA_BIDIRECTIONAL); - if (!descr->bus_addr) + cpu_addr = dma_map_single(ctodev(card), descr, + GELIC_DESCR_SIZE, DMA_BIDIRECTIONAL); + + if (dma_mapping_error(ctodev(card), cpu_addr)) goto iommu_error; + descr->bus_addr = cpu_to_be32(cpu_addr); descr->next = descr + 1; descr->prev = descr - 1; } @@ -375,6 +377,7 @@ static int gelic_descr_prepare_rx(struct gelic_card *card, static const unsigned int rx_skb_size = ALIGN(GELIC_NET_MAX_FRAME, GELIC_NET_RXBUF_ALIGN) + GELIC_NET_RXBUF_ALIGN - 1; + dma_addr_t cpu_addr; int offset; if (gelic_descr_get_status(descr) != GELIC_DESCR_DMA_NOT_IN_USE) @@ -396,11 +399,10 @@ static int gelic_descr_prepare_rx(struct gelic_card *card, if (offset) skb_reserve(descr->skb, GELIC_NET_RXBUF_ALIGN - offset); /* io-mmu-map the skb */ - descr->buf_addr = cpu_to_be32(dma_map_single(ctodev(card), - descr->skb->data, - GELIC_NET_MAX_FRAME, - DMA_FROM_DEVICE)); - if (!descr->buf_addr) { + cpu_addr = dma_map_single(ctodev(card), descr->skb->data, + GELIC_NET_MAX_FRAME, DMA_FROM_DEVICE); + descr->buf_addr = cpu_to_be32(cpu_addr); + if (dma_mapping_error(ctodev(card), cpu_addr)) { dev_kfree_skb_any(descr->skb); descr->skb = NULL; dev_info(ctodev(card), @@ -780,7 +782,7 @@ static int gelic_descr_prepare_tx(struct gelic_card *card, buf = dma_map_single(ctodev(card), skb->data, skb->len, DMA_TO_DEVICE); - if (!buf) { + if (dma_mapping_error(ctodev(card), buf)) { dev_err(ctodev(card), "dma map 2 failed (%p, %i). Dropping packet\n", skb->data, skb->len); -- cgit From 7d31677bb7b1944ac89e9155110dc1b9acbb3895 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 27 Jan 2023 23:14:00 +0100 Subject: gpu: host1x: fix uninitialized variable use The error handling for platform_get_irq() failing no longer works after a recent change, clang now points this out with a warning: drivers/gpu/host1x/dev.c:520:6: error: variable 'syncpt_irq' is uninitialized when used here [-Werror,-Wuninitialized] if (syncpt_irq < 0) ^~~~~~~~~~ Fix this by removing the variable and checking the correct error status. Fixes: 625d4ffb438c ("gpu: host1x: Rewrite syncpoint interrupt handling") Signed-off-by: Arnd Bergmann Reviewed-by: Jon Hunter Reviewed-by: Nick Desaulniers Reviewed-by: Mikko Perttunen Reviewed-by: Nathan Chancellor Signed-off-by: Linus Torvalds --- drivers/gpu/host1x/dev.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/host1x/dev.c b/drivers/gpu/host1x/dev.c index 4872d183d860..aae2efeef503 100644 --- a/drivers/gpu/host1x/dev.c +++ b/drivers/gpu/host1x/dev.c @@ -487,7 +487,6 @@ static int host1x_get_resets(struct host1x *host) static int host1x_probe(struct platform_device *pdev) { struct host1x *host; - int syncpt_irq; int err; host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL); @@ -517,8 +516,8 @@ static int host1x_probe(struct platform_device *pdev) } host->syncpt_irq = platform_get_irq(pdev, 0); - if (syncpt_irq < 0) - return syncpt_irq; + if (host->syncpt_irq < 0) + return host->syncpt_irq; mutex_init(&host->devices_lock); INIT_LIST_HEAD(&host->devices); -- cgit From d7e673c2a900206bea3461a4b4ecc74ea930f80e Mon Sep 17 00:00:00 2001 From: Damien Le Moal Date: Mon, 20 Mar 2023 15:35:06 +0900 Subject: zonefs: Prevent uninitialized symbol 'size' warning In zonefs_file_dio_append(), initialize the variable size to 0 to prevent compilation and static code analizers warning such as: New smatch warnings: fs/zonefs/file.c:441 zonefs_file_dio_append() error: uninitialized symbol 'size'. The warning is a false positive as size is never actually used uninitialized. No functional change. Reported-by: kernel test robot Reported-by: Dan Carpenter Link: https://lore.kernel.org/r/202303191227.GL8Dprbi-lkp@intel.com/ Signed-off-by: Damien Le Moal Reviewed-by: Johannes Thumshirn Reviewed-by: Himanshu Madhani --- fs/zonefs/file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/zonefs/file.c b/fs/zonefs/file.c index 738b0e28d74b..a545a6d9a32e 100644 --- a/fs/zonefs/file.c +++ b/fs/zonefs/file.c @@ -383,7 +383,7 @@ static ssize_t zonefs_file_dio_append(struct kiocb *iocb, struct iov_iter *from) struct block_device *bdev = inode->i_sb->s_bdev; unsigned int max = bdev_max_zone_append_sectors(bdev); struct bio *bio; - ssize_t size; + ssize_t size = 0; int nr_pages; ssize_t ret; -- cgit From 88b170088ad2c3e27086fe35769aa49f8a512564 Mon Sep 17 00:00:00 2001 From: Damien Le Moal Date: Mon, 20 Mar 2023 22:49:15 +0900 Subject: zonefs: Fix error message in zonefs_file_dio_append() Since the expected write location in a sequential file is always at the end of the file (append write), when an invalid write append location is detected in zonefs_file_dio_append(), print the invalid written location instead of the expected write location. Fixes: a608da3bd730 ("zonefs: Detect append writes at invalid locations") Cc: stable@vger.kernel.org Signed-off-by: Damien Le Moal Reviewed-by: Christoph Hellwig Reviewed-by: Johannes Thumshirn Reviewed-by: Himanshu Madhani --- fs/zonefs/file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/zonefs/file.c b/fs/zonefs/file.c index a545a6d9a32e..617e4f9db42e 100644 --- a/fs/zonefs/file.c +++ b/fs/zonefs/file.c @@ -426,7 +426,7 @@ static ssize_t zonefs_file_dio_append(struct kiocb *iocb, struct iov_iter *from) if (bio->bi_iter.bi_sector != wpsector) { zonefs_warn(inode->i_sb, "Corrupted write pointer %llu for zone at %llu\n", - wpsector, z->z_sector); + bio->bi_iter.bi_sector, z->z_sector); ret = -EIO; } } -- cgit From f038f3917baf04835ba2b7bcf2a04ac93fbf8a9c Mon Sep 17 00:00:00 2001 From: Jiasheng Jiang Date: Fri, 17 Mar 2023 14:43:37 +0800 Subject: octeontx2-vf: Add missing free for alloc_percpu Add the free_percpu for the allocated "vf->hw.lmt_info" in order to avoid memory leak, same as the "pf->hw.lmt_info" in `drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c`. Fixes: 5c0512072f65 ("octeontx2-pf: cn10k: Use runtime allocated LMTLINE region") Signed-off-by: Jiasheng Jiang Reviewed-by: Michal Swiatkowski Acked-by: Geethasowjanya Akula Link: https://lore.kernel.org/r/20230317064337.18198-1-jiasheng@iscas.ac.cn Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c index 7f8ffbf79cf7..ab126f8706c7 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c @@ -709,6 +709,7 @@ err_unreg_netdev: err_ptp_destroy: otx2_ptp_destroy(vf); err_detach_rsrc: + free_percpu(vf->hw.lmt_info); if (test_bit(CN10K_LMTST, &vf->hw.cap_flag)) qmem_free(vf->dev, vf->dync_lmt); otx2_detach_resources(&vf->mbox); @@ -762,6 +763,7 @@ static void otx2vf_remove(struct pci_dev *pdev) otx2_shutdown_tc(vf); otx2vf_disable_mbox_intr(vf); otx2_detach_resources(&vf->mbox); + free_percpu(vf->hw.lmt_info); if (test_bit(CN10K_LMTST, &vf->hw.cap_flag)) qmem_free(vf->dev, vf->dync_lmt); otx2vf_vfaf_mbox_destroy(vf); -- cgit From b69245126a48e50882021180fa5d264dc7149ccc Mon Sep 17 00:00:00 2001 From: "Masami Hiramatsu (Google)" Date: Wed, 15 Mar 2023 22:54:08 +0900 Subject: bootconfig: Fix testcase to increase max node Since commit 6c40624930c5 ("bootconfig: Increase max nodes of bootconfig from 1024 to 8192 for DCC support") increased the max number of bootconfig node to 8192, the bootconfig testcase of the max number of nodes fails. To fix this issue, we can not simply increase the number in the test script because the test bootconfig file becomes too big (>32KB). To fix that, we can use a combination of three alphabets (26^3 = 17576). But with that, we can not express the 8193 (just one exceed from the limitation) because it also exceeds the max size of bootconfig. So, the first 26 nodes will just use one alphabet. With this fix, test-bootconfig.sh passes all tests. Link: https://lore.kernel.org/all/167888844790.791176.670805252426835131.stgit@devnote2/ Reported-by: Heinz Wiesinger Link: https://lore.kernel.org/all/2463802.XAFRqVoOGU@amaterasu.liwjatan.org Fixes: 6c40624930c5 ("bootconfig: Increase max nodes of bootconfig from 1024 to 8192 for DCC support") Signed-off-by: Masami Hiramatsu (Google) Reviewed-by: Steven Rostedt (Google) --- tools/bootconfig/test-bootconfig.sh | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/tools/bootconfig/test-bootconfig.sh b/tools/bootconfig/test-bootconfig.sh index f68e2e9eef8b..a2c484c243f5 100755 --- a/tools/bootconfig/test-bootconfig.sh +++ b/tools/bootconfig/test-bootconfig.sh @@ -87,10 +87,14 @@ xfail grep -i "error" $OUTFILE echo "Max node number check" -echo -n > $TEMPCONF -for i in `seq 1 1024` ; do - echo "node$i" >> $TEMPCONF -done +awk ' +BEGIN { + for (i = 0; i < 26; i += 1) + printf("%c\n", 65 + i % 26) + for (i = 26; i < 8192; i += 1) + printf("%c%c%c\n", 65 + i % 26, 65 + (i / 26) % 26, 65 + (i / 26 / 26)) +} +' > $TEMPCONF xpass $BOOTCONF -a $TEMPCONF $INITRD echo "badnode" >> $TEMPCONF -- cgit From 47f9e4c924025c5be87959d3335e66fcbb7f6b5c Mon Sep 17 00:00:00 2001 From: David Howells Date: Tue, 14 Mar 2023 15:15:18 +0000 Subject: keys: Do not cache key in task struct if key is requested from kernel thread The key which gets cached in task structure from a kernel thread does not get invalidated even after expiry. Due to which, a new key request from kernel thread will be served with the cached key if it's present in task struct irrespective of the key validity. The change is to not cache key in task_struct when key requested from kernel thread so that kernel thread gets a valid key on every key request. The problem has been seen with the cifs module doing DNS lookups from a kernel thread and the results getting pinned by being attached to that kernel thread's cache - and thus not something that can be easily got rid of. The cache would ordinarily be cleared by notify-resume, but kernel threads don't do that. This isn't seen with AFS because AFS is doing request_key() within the kernel half of a user thread - which will do notify-resume. Fixes: 7743c48e54ee ("keys: Cache result of request_key*() temporarily in task_struct") Signed-off-by: Bharath SM Signed-off-by: David Howells Reviewed-by: Jarkko Sakkinen cc: Shyam Prasad N cc: Steve French cc: keyrings@vger.kernel.org cc: linux-cifs@vger.kernel.org cc: linux-fsdevel@vger.kernel.org Link: https://lore.kernel.org/r/CAGypqWw951d=zYRbdgNR4snUDvJhWL=q3=WOyh7HhSJupjz2vA@mail.gmail.com/ --- security/keys/request_key.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/security/keys/request_key.c b/security/keys/request_key.c index 2da4404276f0..07a0ef2baacd 100644 --- a/security/keys/request_key.c +++ b/security/keys/request_key.c @@ -38,9 +38,12 @@ static void cache_requested_key(struct key *key) #ifdef CONFIG_KEYS_REQUEST_CACHE struct task_struct *t = current; - key_put(t->cached_requested_key); - t->cached_requested_key = key_get(key); - set_tsk_thread_flag(t, TIF_NOTIFY_RESUME); + /* Do not cache key if it is a kernel thread */ + if (!(t->flags & PF_KTHREAD)) { + key_put(t->cached_requested_key); + t->cached_requested_key = key_get(key); + set_tsk_thread_flag(t, TIF_NOTIFY_RESUME); + } #endif } -- cgit From 4fc5c74dde69a7eda172514aaeb5a7df3600adb3 Mon Sep 17 00:00:00 2001 From: Robbie Harwood Date: Mon, 20 Feb 2023 12:12:53 -0500 Subject: verify_pefile: relax wrapper length check The PE Format Specification (section "The Attribute Certificate Table (Image Only)") states that `dwLength` is to be rounded up to 8-byte alignment when used for traversal. Therefore, the field is not required to be an 8-byte multiple in the first place. Accordingly, pesign has not performed this alignment since version 0.110. This causes kexec failure on pesign'd binaries with "PEFILE: Signature wrapper len wrong". Update the comment and relax the check. Signed-off-by: Robbie Harwood Signed-off-by: David Howells cc: Jarkko Sakkinen cc: Eric Biederman cc: Herbert Xu cc: keyrings@vger.kernel.org cc: linux-crypto@vger.kernel.org cc: kexec@lists.infradead.org Link: https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#the-attribute-certificate-table-image-only Link: https://github.com/rhboot/pesign Link: https://lore.kernel.org/r/20230220171254.592347-2-rharwood@redhat.com/ # v2 --- crypto/asymmetric_keys/verify_pefile.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/crypto/asymmetric_keys/verify_pefile.c b/crypto/asymmetric_keys/verify_pefile.c index 7553ab18db89..fe1bb374239d 100644 --- a/crypto/asymmetric_keys/verify_pefile.c +++ b/crypto/asymmetric_keys/verify_pefile.c @@ -135,11 +135,15 @@ static int pefile_strip_sig_wrapper(const void *pebuf, pr_debug("sig wrapper = { %x, %x, %x }\n", wrapper.length, wrapper.revision, wrapper.cert_type); - /* Both pesign and sbsign round up the length of certificate table - * (in optional header data directories) to 8 byte alignment. + /* sbsign rounds up the length of certificate table (in optional + * header data directories) to 8 byte alignment. However, the PE + * specification states that while entries are 8-byte aligned, this is + * not included in their length, and as a result, pesign has not + * rounded up since 0.110. */ - if (round_up(wrapper.length, 8) != ctx->sig_len) { - pr_debug("Signature wrapper len wrong\n"); + if (wrapper.length > ctx->sig_len) { + pr_debug("Signature wrapper bigger than sig len (%x > %x)\n", + ctx->sig_len, wrapper.length); return -ELIBBAD; } if (wrapper.revision != WIN_CERT_REVISION_2_0) { -- cgit From 3584c1dbfffdabf8e3dc1dd25748bb38dd01cd43 Mon Sep 17 00:00:00 2001 From: Robbie Harwood Date: Mon, 20 Feb 2023 12:12:54 -0500 Subject: asymmetric_keys: log on fatal failures in PE/pkcs7 These particular errors can be encountered while trying to kexec when secureboot lockdown is in place. Without this change, even with a signed debug build, one still needs to reboot the machine to add the appropriate dyndbg parameters (since lockdown blocks debugfs). Accordingly, upgrade all pr_debug() before fatal error into pr_warn(). Signed-off-by: Robbie Harwood Signed-off-by: David Howells cc: Jarkko Sakkinen cc: Eric Biederman cc: Herbert Xu cc: keyrings@vger.kernel.org cc: linux-crypto@vger.kernel.org cc: kexec@lists.infradead.org Link: https://lore.kernel.org/r/20230220171254.592347-3-rharwood@redhat.com/ # v2 --- crypto/asymmetric_keys/pkcs7_verify.c | 10 +++++----- crypto/asymmetric_keys/verify_pefile.c | 24 ++++++++++++------------ 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/crypto/asymmetric_keys/pkcs7_verify.c b/crypto/asymmetric_keys/pkcs7_verify.c index 4fa769c4bcdb..f0d4ff3c20a8 100644 --- a/crypto/asymmetric_keys/pkcs7_verify.c +++ b/crypto/asymmetric_keys/pkcs7_verify.c @@ -79,16 +79,16 @@ static int pkcs7_digest(struct pkcs7_message *pkcs7, } if (sinfo->msgdigest_len != sig->digest_size) { - pr_debug("Sig %u: Invalid digest size (%u)\n", - sinfo->index, sinfo->msgdigest_len); + pr_warn("Sig %u: Invalid digest size (%u)\n", + sinfo->index, sinfo->msgdigest_len); ret = -EBADMSG; goto error; } if (memcmp(sig->digest, sinfo->msgdigest, sinfo->msgdigest_len) != 0) { - pr_debug("Sig %u: Message digest doesn't match\n", - sinfo->index); + pr_warn("Sig %u: Message digest doesn't match\n", + sinfo->index); ret = -EKEYREJECTED; goto error; } @@ -478,7 +478,7 @@ int pkcs7_supply_detached_data(struct pkcs7_message *pkcs7, const void *data, size_t datalen) { if (pkcs7->data) { - pr_debug("Data already supplied\n"); + pr_warn("Data already supplied\n"); return -EINVAL; } pkcs7->data = data; diff --git a/crypto/asymmetric_keys/verify_pefile.c b/crypto/asymmetric_keys/verify_pefile.c index fe1bb374239d..22beaf2213a2 100644 --- a/crypto/asymmetric_keys/verify_pefile.c +++ b/crypto/asymmetric_keys/verify_pefile.c @@ -74,7 +74,7 @@ static int pefile_parse_binary(const void *pebuf, unsigned int pelen, break; default: - pr_debug("Unknown PEOPT magic = %04hx\n", pe32->magic); + pr_warn("Unknown PEOPT magic = %04hx\n", pe32->magic); return -ELIBBAD; } @@ -95,7 +95,7 @@ static int pefile_parse_binary(const void *pebuf, unsigned int pelen, ctx->certs_size = ddir->certs.size; if (!ddir->certs.virtual_address || !ddir->certs.size) { - pr_debug("Unsigned PE binary\n"); + pr_warn("Unsigned PE binary\n"); return -ENODATA; } @@ -127,7 +127,7 @@ static int pefile_strip_sig_wrapper(const void *pebuf, unsigned len; if (ctx->sig_len < sizeof(wrapper)) { - pr_debug("Signature wrapper too short\n"); + pr_warn("Signature wrapper too short\n"); return -ELIBBAD; } @@ -142,16 +142,16 @@ static int pefile_strip_sig_wrapper(const void *pebuf, * rounded up since 0.110. */ if (wrapper.length > ctx->sig_len) { - pr_debug("Signature wrapper bigger than sig len (%x > %x)\n", - ctx->sig_len, wrapper.length); + pr_warn("Signature wrapper bigger than sig len (%x > %x)\n", + ctx->sig_len, wrapper.length); return -ELIBBAD; } if (wrapper.revision != WIN_CERT_REVISION_2_0) { - pr_debug("Signature is not revision 2.0\n"); + pr_warn("Signature is not revision 2.0\n"); return -ENOTSUPP; } if (wrapper.cert_type != WIN_CERT_TYPE_PKCS_SIGNED_DATA) { - pr_debug("Signature certificate type is not PKCS\n"); + pr_warn("Signature certificate type is not PKCS\n"); return -ENOTSUPP; } @@ -164,7 +164,7 @@ static int pefile_strip_sig_wrapper(const void *pebuf, ctx->sig_offset += sizeof(wrapper); ctx->sig_len -= sizeof(wrapper); if (ctx->sig_len < 4) { - pr_debug("Signature data missing\n"); + pr_warn("Signature data missing\n"); return -EKEYREJECTED; } @@ -198,7 +198,7 @@ check_len: return 0; } not_pkcs7: - pr_debug("Signature data not PKCS#7\n"); + pr_warn("Signature data not PKCS#7\n"); return -ELIBBAD; } @@ -341,8 +341,8 @@ static int pefile_digest_pe(const void *pebuf, unsigned int pelen, digest_size = crypto_shash_digestsize(tfm); if (digest_size != ctx->digest_len) { - pr_debug("Digest size mismatch (%zx != %x)\n", - digest_size, ctx->digest_len); + pr_warn("Digest size mismatch (%zx != %x)\n", + digest_size, ctx->digest_len); ret = -EBADMSG; goto error_no_desc; } @@ -373,7 +373,7 @@ static int pefile_digest_pe(const void *pebuf, unsigned int pelen, * PKCS#7 certificate. */ if (memcmp(digest, ctx->digest, ctx->digest_len) != 0) { - pr_debug("Digest mismatch\n"); + pr_warn("Digest mismatch\n"); ret = -EKEYREJECTED; } else { pr_debug("The digests match!\n"); -- cgit From 387d42ae6df76d2ae813432d05630535a5480038 Mon Sep 17 00:00:00 2001 From: Piotr Raczynski Date: Thu, 9 Mar 2023 13:38:56 -0800 Subject: ice: fix rx buffers handling for flow director packets Adding flow director filters stopped working correctly after commit 2fba7dc5157b ("ice: Add support for XDP multi-buffer on Rx side"). As a result, only first flow director filter can be added, adding next filter leads to NULL pointer dereference attached below. Rx buffer handling and reallocation logic has been optimized, however flow director specific traffic was not accounted for. As a result driver handled those packets incorrectly since new logic was based on ice_rx_ring::first_desc which was not set in this case. Fix this by setting struct ice_rx_ring::first_desc to next_to_clean for flow director received packets. [ 438.544867] BUG: kernel NULL pointer dereference, address: 0000000000000000 [ 438.551840] #PF: supervisor read access in kernel mode [ 438.556978] #PF: error_code(0x0000) - not-present page [ 438.562115] PGD 7c953b2067 P4D 0 [ 438.565436] Oops: 0000 [#1] PREEMPT SMP NOPTI [ 438.569794] CPU: 0 PID: 0 Comm: swapper/0 Kdump: loaded Not tainted 6.2.0-net-bug #1 [ 438.577531] Hardware name: Intel Corporation M50CYP2SBSTD/M50CYP2SBSTD, BIOS SE5C620.86B.01.01.0005.2202160810 02/16/2022 [ 438.588470] RIP: 0010:ice_clean_rx_irq+0x2b9/0xf20 [ice] [ 438.593860] Code: 45 89 f7 e9 ac 00 00 00 8b 4d 78 41 31 4e 10 41 09 d5 4d 85 f6 0f 84 82 00 00 00 49 8b 4e 08 41 8b 76 1c 65 8b 3d 47 36 4a 3f <48> 8b 11 48 c1 ea 36 39 d7 0f 85 a6 00 00 00 f6 41 08 02 0f 85 9c [ 438.612605] RSP: 0018:ff8c732640003ec8 EFLAGS: 00010082 [ 438.617831] RAX: 0000000000000800 RBX: 00000000000007ff RCX: 0000000000000000 [ 438.624957] RDX: 0000000000000800 RSI: 0000000000000000 RDI: 0000000000000000 [ 438.632089] RBP: ff4ed275a2158200 R08: 00000000ffffffff R09: 0000000000000020 [ 438.639222] R10: 0000000000000000 R11: 0000000000000020 R12: 0000000000001000 [ 438.646356] R13: 0000000000000000 R14: ff4ed275d0daffe0 R15: 0000000000000000 [ 438.653485] FS: 0000000000000000(0000) GS:ff4ed2738fa00000(0000) knlGS:0000000000000000 [ 438.661563] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 438.667310] CR2: 0000000000000000 CR3: 0000007c9f0d6006 CR4: 0000000000771ef0 [ 438.674444] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 438.681573] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 [ 438.688697] PKRU: 55555554 [ 438.691404] Call Trace: [ 438.693857] [ 438.695877] ? profile_tick+0x17/0x80 [ 438.699542] ice_msix_clean_ctrl_vsi+0x24/0x50 [ice] [ 438.702571] ice 0000:b1:00.0: VF 1: ctrl_vsi irq timeout [ 438.704542] __handle_irq_event_percpu+0x43/0x1a0 [ 438.704549] handle_irq_event+0x34/0x70 [ 438.704554] handle_edge_irq+0x9f/0x240 [ 438.709901] iavf 0000:b1:01.1: Failed to add Flow Director filter with status: 6 [ 438.714571] __common_interrupt+0x63/0x100 [ 438.714580] common_interrupt+0xb4/0xd0 [ 438.718424] iavf 0000:b1:01.1: Rule ID: 127 dst_ip: 0.0.0.0 src_ip 0.0.0.0 UDP: dst_port 4 src_port 0 [ 438.722255] [ 438.722257] [ 438.722257] asm_common_interrupt+0x22/0x40 [ 438.722262] RIP: 0010:cpuidle_enter_state+0xc8/0x430 [ 438.722267] Code: 6e e9 25 ff e8 f9 ef ff ff 8b 53 04 49 89 c5 0f 1f 44 00 00 31 ff e8 d7 f1 24 ff 45 84 ff 0f 85 57 02 00 00 fb 0f 1f 44 00 00 <45> 85 f6 0f 88 85 01 00 00 49 63 d6 48 8d 04 52 48 8d 04 82 49 8d [ 438.722269] RSP: 0018:ffffffff86003e50 EFLAGS: 00000246 [ 438.784108] RAX: ff4ed2738fa00000 RBX: ffbe72a64fc01020 RCX: 0000000000000000 [ 438.791234] RDX: 0000000000000000 RSI: ffffffff858d84de RDI: ffffffff85893641 [ 438.798365] RBP: 0000000000000002 R08: 0000000000000002 R09: 000000003158af9d [ 438.805490] R10: 0000000000000008 R11: 0000000000000354 R12: ffffffff862365a0 [ 438.812622] R13: 000000661b472a87 R14: 0000000000000002 R15: 0000000000000000 [ 438.819757] cpuidle_enter+0x29/0x40 [ 438.823333] do_idle+0x1b6/0x230 [ 438.826566] cpu_startup_entry+0x19/0x20 [ 438.830492] rest_init+0xcb/0xd0 [ 438.833717] arch_call_rest_init+0xa/0x30 [ 438.837731] start_kernel+0x776/0xb70 [ 438.841396] secondary_startup_64_no_verify+0xe5/0xeb [ 438.846449] Fixes: 2fba7dc5157b ("ice: Add support for XDP multi-buffer on Rx side") Signed-off-by: Piotr Raczynski Acked-by: Maciej Fijalkowski Reviewed-by: Simon Horman Tested-by: Arpana Arland (A Contingent worker at Intel) Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice_txrx.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ethernet/intel/ice/ice_txrx.c b/drivers/net/ethernet/intel/ice/ice_txrx.c index dfd22862e926..b61dd9f01540 100644 --- a/drivers/net/ethernet/intel/ice/ice_txrx.c +++ b/drivers/net/ethernet/intel/ice/ice_txrx.c @@ -1210,6 +1210,7 @@ int ice_clean_rx_irq(struct ice_rx_ring *rx_ring, int budget) ice_vc_fdir_irq_handler(ctrl_vsi, rx_desc); if (++ntc == cnt) ntc = 0; + rx_ring->first_desc = ntc; continue; } -- cgit From 83b49e7f63da88a1544cba2b2e40bfabb24bd203 Mon Sep 17 00:00:00 2001 From: Michal Swiatkowski Date: Fri, 10 Mar 2023 12:33:44 +0100 Subject: ice: check if VF exists before mode check Setting trust on VF should return EINVAL when there is no VF. Move checking for switchdev mode after checking if VF exists. Fixes: c54d209c78b8 ("ice: Wait for VF to be reset/ready before configuration") Signed-off-by: Michal Swiatkowski Signed-off-by: Kalyan Kodamagula Tested-by: Sujai Buvaneswaran Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice_sriov.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/intel/ice/ice_sriov.c b/drivers/net/ethernet/intel/ice/ice_sriov.c index 96a64c25e2ef..0cc05e54a781 100644 --- a/drivers/net/ethernet/intel/ice/ice_sriov.c +++ b/drivers/net/ethernet/intel/ice/ice_sriov.c @@ -1341,15 +1341,15 @@ int ice_set_vf_trust(struct net_device *netdev, int vf_id, bool trusted) struct ice_vf *vf; int ret; + vf = ice_get_vf_by_id(pf, vf_id); + if (!vf) + return -EINVAL; + if (ice_is_eswitch_mode_switchdev(pf)) { dev_info(ice_pf_to_dev(pf), "Trusted VF is forbidden in switchdev mode\n"); return -EOPNOTSUPP; } - vf = ice_get_vf_by_id(pf, vf_id); - if (!vf) - return -EINVAL; - ret = ice_check_vf_ready_for_cfg(vf); if (ret) goto out_put_vf; -- cgit From 7d46c0e670d5f646879b52bacc387bf48ff0e7f1 Mon Sep 17 00:00:00 2001 From: Michal Swiatkowski Date: Mon, 13 Mar 2023 13:09:15 +0100 Subject: ice: remove filters only if VSI is deleted Filters shouldn't be removed in VSI rebuild path. Removing them on PF VSI results in no rule for PF MAC after changing for example queues amount. Remove all filters only in the VSI remove flow. As unload should also cause the filter to be removed introduce, a new function ice_stop_eth(). It will unroll ice_start_eth(), so remove filters and close VSI. Fixes: 6624e780a577 ("ice: split ice_vsi_setup into smaller functions") Signed-off-by: Michal Swiatkowski Tested-by: Arpana Arland (A Contingent worker at Intel) Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice_lib.c | 2 +- drivers/net/ethernet/intel/ice/ice_main.c | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c index 0f52ea38b6f3..450317dfcca7 100644 --- a/drivers/net/ethernet/intel/ice/ice_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_lib.c @@ -291,6 +291,7 @@ static void ice_vsi_delete_from_hw(struct ice_vsi *vsi) struct ice_vsi_ctx *ctxt; int status; + ice_fltr_remove_all(vsi); ctxt = kzalloc(sizeof(*ctxt), GFP_KERNEL); if (!ctxt) return; @@ -2892,7 +2893,6 @@ void ice_vsi_decfg(struct ice_vsi *vsi) !test_bit(ICE_FLAG_FW_LLDP_AGENT, pf->flags)) ice_cfg_sw_lldp(vsi, false, false); - ice_fltr_remove_all(vsi); ice_rm_vsi_lan_cfg(vsi->port_info, vsi->idx); err = ice_rm_vsi_rdma_cfg(vsi->port_info, vsi->idx); if (err) diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index c233464b8f6b..0d8b8c6f9bd3 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -4641,6 +4641,12 @@ static int ice_start_eth(struct ice_vsi *vsi) return err; } +static void ice_stop_eth(struct ice_vsi *vsi) +{ + ice_fltr_remove_all(vsi); + ice_vsi_close(vsi); +} + static int ice_init_eth(struct ice_pf *pf) { struct ice_vsi *vsi = ice_get_main_vsi(pf); @@ -5129,7 +5135,7 @@ void ice_unload(struct ice_pf *pf) { ice_deinit_features(pf); ice_deinit_rdma(pf); - ice_vsi_close(ice_get_main_vsi(pf)); + ice_stop_eth(ice_get_main_vsi(pf)); ice_vsi_decfg(ice_get_main_vsi(pf)); ice_deinit_dev(pf); } -- cgit From 4e264be98b88a6d6f476c11087fe865696e8bef5 Mon Sep 17 00:00:00 2001 From: Stefan Assmann Date: Mon, 13 Mar 2023 17:06:45 +0100 Subject: iavf: fix hang on reboot with ice When a system with E810 with existing VFs gets rebooted the following hang may be observed. Pid 1 is hung in iavf_remove(), part of a network driver: PID: 1 TASK: ffff965400e5a340 CPU: 24 COMMAND: "systemd-shutdow" #0 [ffffaad04005fa50] __schedule at ffffffff8b3239cb #1 [ffffaad04005fae8] schedule at ffffffff8b323e2d #2 [ffffaad04005fb00] schedule_hrtimeout_range_clock at ffffffff8b32cebc #3 [ffffaad04005fb80] usleep_range_state at ffffffff8b32c930 #4 [ffffaad04005fbb0] iavf_remove at ffffffffc12b9b4c [iavf] #5 [ffffaad04005fbf0] pci_device_remove at ffffffff8add7513 #6 [ffffaad04005fc10] device_release_driver_internal at ffffffff8af08baa #7 [ffffaad04005fc40] pci_stop_bus_device at ffffffff8adcc5fc #8 [ffffaad04005fc60] pci_stop_and_remove_bus_device at ffffffff8adcc81e #9 [ffffaad04005fc70] pci_iov_remove_virtfn at ffffffff8adf9429 #10 [ffffaad04005fca8] sriov_disable at ffffffff8adf98e4 #11 [ffffaad04005fcc8] ice_free_vfs at ffffffffc04bb2c8 [ice] #12 [ffffaad04005fd10] ice_remove at ffffffffc04778fe [ice] #13 [ffffaad04005fd38] ice_shutdown at ffffffffc0477946 [ice] #14 [ffffaad04005fd50] pci_device_shutdown at ffffffff8add58f1 #15 [ffffaad04005fd70] device_shutdown at ffffffff8af05386 #16 [ffffaad04005fd98] kernel_restart at ffffffff8a92a870 #17 [ffffaad04005fda8] __do_sys_reboot at ffffffff8a92abd6 #18 [ffffaad04005fee0] do_syscall_64 at ffffffff8b317159 #19 [ffffaad04005ff08] __context_tracking_enter at ffffffff8b31b6fc #20 [ffffaad04005ff18] syscall_exit_to_user_mode at ffffffff8b31b50d #21 [ffffaad04005ff28] do_syscall_64 at ffffffff8b317169 #22 [ffffaad04005ff50] entry_SYSCALL_64_after_hwframe at ffffffff8b40009b RIP: 00007f1baa5c13d7 RSP: 00007fffbcc55a98 RFLAGS: 00000202 RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007f1baa5c13d7 RDX: 0000000001234567 RSI: 0000000028121969 RDI: 00000000fee1dead RBP: 00007fffbcc55ca0 R8: 0000000000000000 R9: 00007fffbcc54e90 R10: 00007fffbcc55050 R11: 0000000000000202 R12: 0000000000000005 R13: 0000000000000000 R14: 00007fffbcc55af0 R15: 0000000000000000 ORIG_RAX: 00000000000000a9 CS: 0033 SS: 002b During reboot all drivers PM shutdown callbacks are invoked. In iavf_shutdown() the adapter state is changed to __IAVF_REMOVE. In ice_shutdown() the call chain above is executed, which at some point calls iavf_remove(). However iavf_remove() expects the VF to be in one of the states __IAVF_RUNNING, __IAVF_DOWN or __IAVF_INIT_FAILED. If that's not the case it sleeps forever. So if iavf_shutdown() gets invoked before iavf_remove() the system will hang indefinitely because the adapter is already in state __IAVF_REMOVE. Fix this by returning from iavf_remove() if the state is __IAVF_REMOVE, as we already went through iavf_shutdown(). Fixes: 974578017fc1 ("iavf: Add waiting so the port is initialized in remove") Fixes: a8417330f8a5 ("iavf: Fix race condition between iavf_shutdown and iavf_remove") Reported-by: Marius Cornea Signed-off-by: Stefan Assmann Reviewed-by: Michal Kubiak Tested-by: Rafal Romanowski Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/iavf/iavf_main.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c index 327cd9b1af2c..095201e83c9d 100644 --- a/drivers/net/ethernet/intel/iavf/iavf_main.c +++ b/drivers/net/ethernet/intel/iavf/iavf_main.c @@ -5074,6 +5074,11 @@ static void iavf_remove(struct pci_dev *pdev) mutex_unlock(&adapter->crit_lock); break; } + /* Simply return if we already went through iavf_shutdown */ + if (adapter->state == __IAVF_REMOVE) { + mutex_unlock(&adapter->crit_lock); + return; + } mutex_unlock(&adapter->crit_lock); usleep_range(500, 1000); -- cgit From c672297bbc0e86dbf88396b8053e2fbb173f16ff Mon Sep 17 00:00:00 2001 From: Radoslaw Tyl Date: Mon, 13 Mar 2023 15:07:33 +0100 Subject: i40e: fix flow director packet filter programming Initialize to zero structures to build a valid Tx Packet used for the filter programming. Fixes: a9219b332f52 ("i40e: VLAN field for flow director") Signed-off-by: Radoslaw Tyl Reviewed-by: Michal Swiatkowski Tested-by: Arpana Arland (A Contingent worker at Intel) Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/i40e/i40e_txrx.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index 924f972b91fa..72b091f2509d 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -171,10 +171,10 @@ static char *i40e_create_dummy_packet(u8 *dummy_packet, bool ipv4, u8 l4proto, struct i40e_fdir_filter *data) { bool is_vlan = !!data->vlan_tag; - struct vlan_hdr vlan; - struct ipv6hdr ipv6; - struct ethhdr eth; - struct iphdr ip; + struct vlan_hdr vlan = {}; + struct ipv6hdr ipv6 = {}; + struct ethhdr eth = {}; + struct iphdr ip = {}; u8 *tmp; if (ipv4) { -- cgit From 10ec8ca8ec1a2f04c4ed90897225231c58c124a7 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Mon, 20 Mar 2023 15:37:25 +0100 Subject: bpf: Adjust insufficient default bpf_jit_limit We've seen recent AWS EKS (Kubernetes) user reports like the following: After upgrading EKS nodes from v20230203 to v20230217 on our 1.24 EKS clusters after a few days a number of the nodes have containers stuck in ContainerCreating state or liveness/readiness probes reporting the following error: Readiness probe errored: rpc error: code = Unknown desc = failed to exec in container: failed to start exec "4a11039f730203ffc003b7[...]": OCI runtime exec failed: exec failed: unable to start container process: unable to init seccomp: error loading seccomp filter into kernel: error loading seccomp filter: errno 524: unknown However, we had not been seeing this issue on previous AMIs and it only started to occur on v20230217 (following the upgrade from kernel 5.4 to 5.10) with no other changes to the underlying cluster or workloads. We tried the suggestions from that issue (sysctl net.core.bpf_jit_limit=452534528) which helped to immediately allow containers to be created and probes to execute but after approximately a day the issue returned and the value returned by cat /proc/vmallocinfo | grep bpf_jit | awk '{s+=$2} END {print s}' was steadily increasing. I tested bpf tree to observe bpf_jit_charge_modmem, bpf_jit_uncharge_modmem their sizes passed in as well as bpf_jit_current under tcpdump BPF filter, seccomp BPF and native (e)BPF programs, and the behavior all looks sane and expected, that is nothing "leaking" from an upstream perspective. The bpf_jit_limit knob was originally added in order to avoid a situation where unprivileged applications loading BPF programs (e.g. seccomp BPF policies) consuming all the module memory space via BPF JIT such that loading of kernel modules would be prevented. The default limit was defined back in 2018 and while good enough back then, we are generally seeing far more BPF consumers today. Adjust the limit for the BPF JIT pool from originally 1/4 to now 1/2 of the module memory space to better reflect today's needs and avoid more users running into potentially hard to debug issues. Fixes: fdadd04931c2 ("bpf: fix bpf_jit_limit knob for PAGE_SIZE >= 64K") Reported-by: Stephen Haynes Reported-by: Lefteris Alexakis Signed-off-by: Daniel Borkmann Link: https://github.com/awslabs/amazon-eks-ami/issues/1179 Link: https://github.com/awslabs/amazon-eks-ami/issues/1219 Reviewed-by: Kuniyuki Iwashima Link: https://lore.kernel.org/r/20230320143725.8394-1-daniel@iogearbox.net Signed-off-by: Alexei Starovoitov --- kernel/bpf/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c index b297e9f60ca1..e2d256c82072 100644 --- a/kernel/bpf/core.c +++ b/kernel/bpf/core.c @@ -972,7 +972,7 @@ static int __init bpf_jit_charge_init(void) { /* Only used as heuristic here to derive limit. */ bpf_jit_limit_max = bpf_jit_alloc_exec_limit(); - bpf_jit_limit = min_t(u64, round_up(bpf_jit_limit_max >> 2, + bpf_jit_limit = min_t(u64, round_up(bpf_jit_limit_max >> 1, PAGE_SIZE), LONG_MAX); return 0; } -- cgit From c83172b0639c8a005c0dd3b36252dc22ddd9f19c Mon Sep 17 00:00:00 2001 From: Gavin Li Date: Fri, 25 Nov 2022 04:15:40 +0200 Subject: net/mlx5e: Set uplink rep as NETNS_LOCAL Previously, NETNS_LOCAL was not set for uplink representors, inconsistent with VF representors, and allowed the uplink representor to be moved between net namespaces and separated from the VF representors it shares the core device with. Such usage would break the isolation model of namespaces, as devices in different namespaces would have access to shared memory. To solve this issue, set NETNS_LOCAL for uplink representors if eswitch is in switchdev mode. Fixes: 7a9fb35e8c3a ("net/mlx5e: Do not reload ethernet ports when changing eswitch mode") Signed-off-by: Gavin Li Reviewed-by: Gavi Teitz Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index a7f2ab22cc40..7ca7e9b57607 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -4150,8 +4150,12 @@ static netdev_features_t mlx5e_fix_features(struct net_device *netdev, } } - if (mlx5e_is_uplink_rep(priv)) + if (mlx5e_is_uplink_rep(priv)) { features = mlx5e_fix_uplink_rep_features(netdev, features); + features |= NETIF_F_NETNS_LOCAL; + } else { + features &= ~NETIF_F_NETNS_LOCAL; + } mutex_unlock(&priv->state_lock); -- cgit From 662404b24a4c4d839839ed25e3097571f5938b9b Mon Sep 17 00:00:00 2001 From: Gavin Li Date: Thu, 9 Feb 2023 12:48:52 +0200 Subject: net/mlx5e: Block entering switchdev mode with ns inconsistency Upon entering switchdev mode, VF/SF representors are spawned in the devlink instance's net namespace, whereas the PF net device transforms into the uplink representor, remaining in the net namespace the PF net device was in. Therefore, if a PF net device's namespace is different from its parent devlink net namespace, entering switchdev mode can create an illegal situation where all representors sharing the same core device are NOT in the same net namespace. To avoid this issue, block entering switchdev mode for devices whose child netdev net namespace has diverged from the parent devlink's. Fixes: 7768d1971de6 ("net/mlx5: E-Switch, Add control for encapsulation") Signed-off-by: Gavin Li Reviewed-by: Gavi Teitz Signed-off-by: Saeed Mahameed --- .../ethernet/mellanox/mlx5/core/eswitch_offloads.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c index 22075943bb58..25a8076a77bf 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c @@ -3405,6 +3405,18 @@ static int esw_inline_mode_to_devlink(u8 mlx5_mode, u8 *mode) return 0; } +static bool esw_offloads_devlink_ns_eq_netdev_ns(struct devlink *devlink) +{ + struct net *devl_net, *netdev_net; + struct mlx5_eswitch *esw; + + esw = mlx5_devlink_eswitch_get(devlink); + netdev_net = dev_net(esw->dev->mlx5e_res.uplink_netdev); + devl_net = devlink_net(devlink); + + return net_eq(devl_net, netdev_net); +} + int mlx5_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode, struct netlink_ext_ack *extack) { @@ -3419,6 +3431,13 @@ int mlx5_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode, if (esw_mode_from_devlink(mode, &mlx5_mode)) return -EINVAL; + if (mode == DEVLINK_ESWITCH_MODE_SWITCHDEV && + !esw_offloads_devlink_ns_eq_netdev_ns(devlink)) { + NL_SET_ERR_MSG_MOD(extack, + "Can't change E-Switch mode to switchdev when netdev net namespace has diverged from the devlink's."); + return -EPERM; + } + mlx5_lag_disable_change(esw->dev); err = mlx5_esw_try_lock(esw); if (err < 0) { -- cgit From 922f56e9a795d6f3dd72d3428ebdd7ee040fa855 Mon Sep 17 00:00:00 2001 From: Lama Kayal Date: Tue, 31 Jan 2023 14:07:03 +0200 Subject: net/mlx5: Fix steering rules cleanup vport's mc, uc and multicast rules are not deleted in teardown path when EEH happens. Since the vport's promisc settings(uc, mc and all) in firmware are reset after EEH, mlx5 driver will try to delete the above rules in the initialization path. This cause kernel crash because these software rules are no longer valid. Fix by nullifying these rules right after delete to avoid accessing any dangling pointers. Call Trace: __list_del_entry_valid+0xcc/0x100 (unreliable) tree_put_node+0xf4/0x1b0 [mlx5_core] tree_remove_node+0x30/0x70 [mlx5_core] mlx5_del_flow_rules+0x14c/0x1f0 [mlx5_core] esw_apply_vport_rx_mode+0x10c/0x200 [mlx5_core] esw_update_vport_rx_mode+0xb4/0x180 [mlx5_core] esw_vport_change_handle_locked+0x1ec/0x230 [mlx5_core] esw_enable_vport+0x130/0x260 [mlx5_core] mlx5_eswitch_enable_sriov+0x2a0/0x2f0 [mlx5_core] mlx5_device_enable_sriov+0x74/0x440 [mlx5_core] mlx5_load_one+0x114c/0x1550 [mlx5_core] mlx5_pci_resume+0x68/0xf0 [mlx5_core] eeh_report_resume+0x1a4/0x230 eeh_pe_dev_traverse+0x98/0x170 eeh_handle_normal_event+0x3e4/0x640 eeh_handle_event+0x4c/0x370 eeh_event_handler+0x14c/0x210 kthread+0x168/0x1b0 ret_from_kernel_thread+0x5c/0x84 Fixes: a35f71f27a61 ("net/mlx5: E-Switch, Implement promiscuous rx modes vf request handling") Signed-off-by: Huy Nguyen Signed-off-by: Lama Kayal Reviewed-by: Tariq Toukan Reviewed-by: Maor Dickman Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/eswitch.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c index 0f052513fefa..8bdf28762f41 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c @@ -959,6 +959,7 @@ void mlx5_esw_vport_disable(struct mlx5_eswitch *esw, u16 vport_num) */ esw_vport_change_handle_locked(vport); vport->enabled_events = 0; + esw_apply_vport_rx_mode(esw, vport, false, false); esw_vport_cleanup(esw, vport); esw->enabled_vports--; -- cgit From 6e9d51b1a5cb8d750c3daf89db4f4cdfd1051819 Mon Sep 17 00:00:00 2001 From: Roy Novich Date: Wed, 1 Mar 2023 15:47:11 +0200 Subject: net/mlx5e: Initialize link speed to zero mlx5e_port_max_linkspeed does not guarantee value assignment for speed. Avoid cases where link_speed might be used uninitialized. In case mlx5e_port_max_linkspeed fails, a default link speed of 50000 will be used for the calculations. Fixes: 3f6d08d196b2 ("net/mlx5e: Add RSS support for hairpin") Signed-off-by: Roy Novich Reviewed-by: Tariq Toukan Reviewed-by: Aya Levin Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index 6bfed633343a..87a2850b32d0 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -1103,8 +1103,8 @@ static void mlx5e_hairpin_params_init(struct mlx5e_hairpin_params *hairpin_params, struct mlx5_core_dev *mdev) { + u32 link_speed = 0; u64 link_speed64; - u32 link_speed; hairpin_params->mdev = mdev; /* set hairpin pair per each 50Gbs share of the link */ -- cgit From 7e3fce82d945cf6e7f99034b113ff2d250d7524d Mon Sep 17 00:00:00 2001 From: Emeel Hakim Date: Mon, 20 Mar 2023 13:13:55 +0200 Subject: net/mlx5e: Overcome slow response for first macsec ASO WQE MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit First ASO WQE poll causes a cache miss in hardware hence the resut is delayed. It causes to the situation where such WQE is polled earlier than it is needed. Add logic to retry ASO CQ polling operation. Fixes: 739cfa34518e ("net/mlx5: Make ASO poll CQ usable in atomic context")  Signed-off-by: Emeel Hakim Reviewed-by: Leon Romanovsky Reviewed-by: Raed Salem Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c index 8af53178e40d..33b3620ea45c 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c @@ -1412,6 +1412,7 @@ static int macsec_aso_query(struct mlx5_core_dev *mdev, struct mlx5e_macsec *mac struct mlx5e_macsec_aso *aso; struct mlx5_aso_wqe *aso_wqe; struct mlx5_aso *maso; + unsigned long expires; int err; aso = &macsec->aso; @@ -1425,7 +1426,13 @@ static int macsec_aso_query(struct mlx5_core_dev *mdev, struct mlx5e_macsec *mac macsec_aso_build_wqe_ctrl_seg(aso, &aso_wqe->aso_ctrl, NULL); mlx5_aso_post_wqe(maso, false, &aso_wqe->ctrl); - err = mlx5_aso_poll_cq(maso, false); + expires = jiffies + msecs_to_jiffies(10); + do { + err = mlx5_aso_poll_cq(maso, false); + if (err) + usleep_range(2, 10); + } while (err && time_is_after_jiffies(expires)); + if (err) goto err_out; -- cgit From 44d553188c38ac74b799dfdcebafef2f7bb70942 Mon Sep 17 00:00:00 2001 From: Maher Sanalla Date: Wed, 15 Mar 2023 11:04:38 +0200 Subject: net/mlx5: Read the TC mapping of all priorities on ETS query When ETS configurations are queried by the user to get the mapping assignment between packet priority and traffic class, only priorities up to maximum TCs are queried from QTCT register in FW to retrieve their assigned TC, leaving the rest of the priorities mapped to the default TC #0 which might be misleading. Fix by querying the TC mapping of all priorities on each ETS query, regardless of the maximum number of TCs configured in FW. Fixes: 820c2c5e773d ("net/mlx5e: Read ETS settings directly from firmware") Signed-off-by: Maher Sanalla Reviewed-by: Moshe Shemesh Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c index 2449731b7d79..89de92d06483 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c @@ -117,12 +117,14 @@ static int mlx5e_dcbnl_ieee_getets(struct net_device *netdev, if (!MLX5_CAP_GEN(priv->mdev, ets)) return -EOPNOTSUPP; - ets->ets_cap = mlx5_max_tc(priv->mdev) + 1; - for (i = 0; i < ets->ets_cap; i++) { + for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { err = mlx5_query_port_prio_tc(mdev, i, &ets->prio_tc[i]); if (err) return err; + } + ets->ets_cap = mlx5_max_tc(priv->mdev) + 1; + for (i = 0; i < ets->ets_cap; i++) { err = mlx5_query_port_tc_group(mdev, i, &tc_group[i]); if (err) return err; -- cgit From 640fcdbcf27fc62de9223f958ceb4e897a00e791 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 27 Feb 2023 14:16:10 +0300 Subject: net/mlx5: E-Switch, Fix an Oops in error handling code The error handling dereferences "vport". There is nothing we can do if it is an error pointer except returning the error code. Fixes: 133dcfc577ea ("net/mlx5: E-Switch, Alloc and free unique metadata for match") Signed-off-by: Dan Carpenter Reviewed-by: Roi Dayan Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/esw/acl/ingress_ofld.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/ingress_ofld.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/ingress_ofld.c index d55775627a47..50d2ea323979 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/ingress_ofld.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/ingress_ofld.c @@ -364,8 +364,7 @@ int mlx5_esw_acl_ingress_vport_metadata_update(struct mlx5_eswitch *esw, u16 vpo if (WARN_ON_ONCE(IS_ERR(vport))) { esw_warn(esw->dev, "vport(%d) invalid!\n", vport_num); - err = PTR_ERR(vport); - goto out; + return PTR_ERR(vport); } esw_acl_ingress_ofld_rules_destroy(esw, vport); -- cgit From 032a954061afd4b7426c3eb6bfd2952ef1e9a384 Mon Sep 17 00:00:00 2001 From: Álvaro Fernández Rojas Date: Sun, 19 Mar 2023 10:55:40 +0100 Subject: net: dsa: tag_brcm: legacy: fix daisy-chained switches MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When BCM63xx internal switches are connected to switches with a 4-byte Broadcom tag, it does not identify the packet as VLAN tagged, so it adds one based on its PVID (which is likely 0). Right now, the packet is received by the BCM63xx internal switch and the 6-byte tag is properly processed. The next step would to decode the corresponding 4-byte tag. However, the internal switch adds an invalid VLAN tag after the 6-byte tag and the 4-byte tag handling fails. In order to fix this we need to remove the invalid VLAN tag after the 6-byte tag before passing it to the 4-byte tag decoding. Fixes: 964dbf186eaa ("net: dsa: tag_brcm: add support for legacy tags") Signed-off-by: Álvaro Fernández Rojas Reviewed-by: Michal Swiatkowski Reviewed-by: Florian Fainelli Link: https://lore.kernel.org/r/20230319095540.239064-1-noltari@gmail.com Signed-off-by: Jakub Kicinski --- net/dsa/tag_brcm.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/net/dsa/tag_brcm.c b/net/dsa/tag_brcm.c index 10239daa5745..cacdafb41200 100644 --- a/net/dsa/tag_brcm.c +++ b/net/dsa/tag_brcm.c @@ -7,6 +7,7 @@ #include #include +#include #include #include @@ -252,6 +253,7 @@ static struct sk_buff *brcm_leg_tag_xmit(struct sk_buff *skb, static struct sk_buff *brcm_leg_tag_rcv(struct sk_buff *skb, struct net_device *dev) { + int len = BRCM_LEG_TAG_LEN; int source_port; u8 *brcm_tag; @@ -266,12 +268,16 @@ static struct sk_buff *brcm_leg_tag_rcv(struct sk_buff *skb, if (!skb->dev) return NULL; + /* VLAN tag is added by BCM63xx internal switch */ + if (netdev_uses_dsa(skb->dev)) + len += VLAN_HLEN; + /* Remove Broadcom tag and update checksum */ - skb_pull_rcsum(skb, BRCM_LEG_TAG_LEN); + skb_pull_rcsum(skb, len); dsa_default_offload_fwd_mark(skb); - dsa_strip_etype_header(skb, BRCM_LEG_TAG_LEN); + dsa_strip_etype_header(skb, len); return skb; } -- cgit From 4fe3c88552a3fbe1944426a4506a18cdeb457b5a Mon Sep 17 00:00:00 2001 From: Li Zetao Date: Mon, 20 Mar 2023 14:33:18 +0000 Subject: atm: idt77252: fix kmemleak when rmmod idt77252 There are memory leaks reported by kmemleak: unreferenced object 0xffff888106500800 (size 128): comm "modprobe", pid 1017, jiffies 4297787785 (age 67.152s) hex dump (first 32 bytes): 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ backtrace: [<00000000970ce626>] __kmem_cache_alloc_node+0x20c/0x380 [<00000000fb5f78d9>] kmalloc_trace+0x2f/0xb0 [<000000000e947e2a>] idt77252_init_one+0x2847/0x3c90 [idt77252] [<000000006efb048e>] local_pci_probe+0xeb/0x1a0 ... unreferenced object 0xffff888106500b00 (size 128): comm "modprobe", pid 1017, jiffies 4297787785 (age 67.152s) hex dump (first 32 bytes): 00 20 3d 01 80 88 ff ff 00 20 3d 01 80 88 ff ff . =...... =..... f0 23 3d 01 80 88 ff ff 00 20 3d 01 00 00 00 00 .#=...... =..... backtrace: [<00000000970ce626>] __kmem_cache_alloc_node+0x20c/0x380 [<00000000fb5f78d9>] kmalloc_trace+0x2f/0xb0 [<00000000f451c5be>] alloc_scq.constprop.0+0x4a/0x400 [idt77252] [<00000000e6313849>] idt77252_init_one+0x28cf/0x3c90 [idt77252] The root cause is traced to the vc_maps which alloced in open_card_oam() are not freed in close_card_oam(). The vc_maps are used to record open connections, so when close a vc_map in close_card_oam(), the memory should be freed. Moreover, the ubr0 is not closed when close a idt77252 device, leading to the memory leak of vc_map and scq_info. Fix them by adding kfree in close_card_oam() and implementing new close_card_ubr0() to close ubr0. Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Signed-off-by: Li Zetao Reviewed-by: Francois Romieu Link: https://lore.kernel.org/r/20230320143318.2644630-1-lizetao1@huawei.com Signed-off-by: Jakub Kicinski --- drivers/atm/idt77252.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/atm/idt77252.c b/drivers/atm/idt77252.c index eec0cc2144e0..e327a0229dc1 100644 --- a/drivers/atm/idt77252.c +++ b/drivers/atm/idt77252.c @@ -2909,6 +2909,7 @@ close_card_oam(struct idt77252_dev *card) recycle_rx_pool_skb(card, &vc->rcv.rx_pool); } + kfree(vc); } } } @@ -2952,6 +2953,15 @@ open_card_ubr0(struct idt77252_dev *card) return 0; } +static void +close_card_ubr0(struct idt77252_dev *card) +{ + struct vc_map *vc = card->vcs[0]; + + free_scq(card, vc->scq); + kfree(vc); +} + static int idt77252_dev_open(struct idt77252_dev *card) { @@ -3001,6 +3011,7 @@ static void idt77252_dev_close(struct atm_dev *dev) struct idt77252_dev *card = dev->dev_data; u32 conf; + close_card_ubr0(card); close_card_oam(card); conf = SAR_CFG_RXPTH | /* enable receive path */ -- cgit From 8e50ed774554f93d55426039b27b1e38d7fa64d8 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 20 Mar 2023 16:34:27 +0000 Subject: erspan: do not use skb_mac_header() in ndo_start_xmit() Drivers should not assume skb_mac_header(skb) == skb->data in their ndo_start_xmit(). Use skb_network_offset() and skb_transport_offset() which better describe what is needed in erspan_fb_xmit() and ip6erspan_tunnel_xmit() syzbot reported: WARNING: CPU: 0 PID: 5083 at include/linux/skbuff.h:2873 skb_mac_header include/linux/skbuff.h:2873 [inline] WARNING: CPU: 0 PID: 5083 at include/linux/skbuff.h:2873 ip6erspan_tunnel_xmit+0x1d9c/0x2d90 net/ipv6/ip6_gre.c:962 Modules linked in: CPU: 0 PID: 5083 Comm: syz-executor406 Not tainted 6.3.0-rc2-syzkaller-00866-gd4671cb96fa3 #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 03/02/2023 RIP: 0010:skb_mac_header include/linux/skbuff.h:2873 [inline] RIP: 0010:ip6erspan_tunnel_xmit+0x1d9c/0x2d90 net/ipv6/ip6_gre.c:962 Code: 04 02 41 01 de 84 c0 74 08 3c 03 0f 8e 1c 0a 00 00 45 89 b4 24 c8 00 00 00 c6 85 77 fe ff ff 01 e9 33 e7 ff ff e8 b4 27 a1 f8 <0f> 0b e9 b6 e7 ff ff e8 a8 27 a1 f8 49 8d bf f0 0c 00 00 48 b8 00 RSP: 0018:ffffc90003b2f830 EFLAGS: 00010293 RAX: 0000000000000000 RBX: 000000000000ffff RCX: 0000000000000000 RDX: ffff888021273a80 RSI: ffffffff88e1bd4c RDI: 0000000000000003 RBP: ffffc90003b2f9d8 R08: 0000000000000003 R09: 000000000000ffff R10: 000000000000ffff R11: 0000000000000000 R12: ffff88802b28da00 R13: 00000000000000d0 R14: ffff88807e25b6d0 R15: ffff888023408000 FS: 0000555556a61300(0000) GS:ffff8880b9800000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 000055e5b11eb6e8 CR3: 0000000027c1b000 CR4: 00000000003506f0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 Call Trace: __netdev_start_xmit include/linux/netdevice.h:4900 [inline] netdev_start_xmit include/linux/netdevice.h:4914 [inline] __dev_direct_xmit+0x504/0x730 net/core/dev.c:4300 dev_direct_xmit include/linux/netdevice.h:3088 [inline] packet_xmit+0x20a/0x390 net/packet/af_packet.c:285 packet_snd net/packet/af_packet.c:3075 [inline] packet_sendmsg+0x31a0/0x5150 net/packet/af_packet.c:3107 sock_sendmsg_nosec net/socket.c:724 [inline] sock_sendmsg+0xde/0x190 net/socket.c:747 __sys_sendto+0x23a/0x340 net/socket.c:2142 __do_sys_sendto net/socket.c:2154 [inline] __se_sys_sendto net/socket.c:2150 [inline] __x64_sys_sendto+0xe1/0x1b0 net/socket.c:2150 do_syscall_x64 arch/x86/entry/common.c:50 [inline] do_syscall_64+0x39/0xb0 arch/x86/entry/common.c:80 entry_SYSCALL_64_after_hwframe+0x63/0xcd RIP: 0033:0x7f123aaa1039 Code: 28 00 00 00 75 05 48 83 c4 28 c3 e8 b1 14 00 00 90 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 c0 ff ff ff f7 d8 64 89 01 48 RSP: 002b:00007ffc15d12058 EFLAGS: 00000246 ORIG_RAX: 000000000000002c RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007f123aaa1039 RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000003 RBP: 0000000000000000 R08: 0000000020000040 R09: 0000000000000014 R10: 0000000000000000 R11: 0000000000000246 R12: 00007f123aa648c0 R13: 431bde82d7b634db R14: 0000000000000000 R15: 0000000000000000 Fixes: 1baf5ebf8954 ("erspan: auto detect truncated packets.") Reported-by: syzbot Signed-off-by: Eric Dumazet Reviewed-by: Simon Horman Link: https://lore.kernel.org/r/20230320163427.8096-1-edumazet@google.com Signed-off-by: Jakub Kicinski --- net/ipv4/ip_gre.c | 4 ++-- net/ipv6/ip6_gre.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index ffff46cdcb58..e55a20264960 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -552,7 +552,7 @@ static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev) truncate = true; } - nhoff = skb_network_header(skb) - skb_mac_header(skb); + nhoff = skb_network_offset(skb); if (skb->protocol == htons(ETH_P_IP) && (ntohs(ip_hdr(skb)->tot_len) > skb->len - nhoff)) truncate = true; @@ -561,7 +561,7 @@ static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev) int thoff; if (skb_transport_header_was_set(skb)) - thoff = skb_transport_header(skb) - skb_mac_header(skb); + thoff = skb_transport_offset(skb); else thoff = nhoff + sizeof(struct ipv6hdr); if (ntohs(ipv6_hdr(skb)->payload_len) > skb->len - thoff) diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c index 89f5f0f3f5d6..a4ecfc9d2593 100644 --- a/net/ipv6/ip6_gre.c +++ b/net/ipv6/ip6_gre.c @@ -959,7 +959,7 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb, truncate = true; } - nhoff = skb_network_header(skb) - skb_mac_header(skb); + nhoff = skb_network_offset(skb); if (skb->protocol == htons(ETH_P_IP) && (ntohs(ip_hdr(skb)->tot_len) > skb->len - nhoff)) truncate = true; @@ -968,7 +968,7 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb, int thoff; if (skb_transport_header_was_set(skb)) - thoff = skb_transport_header(skb) - skb_mac_header(skb); + thoff = skb_transport_offset(skb); else thoff = nhoff + sizeof(struct ipv6hdr); if (ntohs(ipv6_hdr(skb)->payload_len) > skb->len - thoff) -- cgit From 6acc72a43eac78a309160d0a7512bbc59bcdd757 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Tue, 21 Mar 2023 03:03:23 +0200 Subject: net: mscc: ocelot: fix stats region batching The blamed commit changed struct ocelot_stat_layout :: "u32 offset" to "u32 reg". However, "u32 reg" is not quite a register address, but an enum ocelot_reg, which in itself encodes an enum ocelot_target target in the upper bits, and an index into the ocelot->map[target][] array in the lower bits. So, whereas the previous code comparison between stats_layout[i].offset and last + 1 was correct (because those "offsets" at the time were 32-bit relative addresses), the new code, comparing layout[i].reg to last + 4 is not correct, because the "reg" here is an enum/index, not an actual register address. What we want to compare are indeed register addresses, but to do that, we need to actually go through the same motions as __ocelot_bulk_read_ix() itself. With this bug, all statistics counters are deemed by ocelot_prepare_stats_regions() as constituting their own region. (Truncated) log on VSC9959 (Felix) below (prints added by me): Before: region of 1 contiguous counters starting with SYS:STAT:CNT[0x000] region of 1 contiguous counters starting with SYS:STAT:CNT[0x001] region of 1 contiguous counters starting with SYS:STAT:CNT[0x002] ... region of 1 contiguous counters starting with SYS:STAT:CNT[0x041] region of 1 contiguous counters starting with SYS:STAT:CNT[0x042] region of 1 contiguous counters starting with SYS:STAT:CNT[0x080] region of 1 contiguous counters starting with SYS:STAT:CNT[0x081] ... region of 1 contiguous counters starting with SYS:STAT:CNT[0x0ac] region of 1 contiguous counters starting with SYS:STAT:CNT[0x100] region of 1 contiguous counters starting with SYS:STAT:CNT[0x101] ... region of 1 contiguous counters starting with SYS:STAT:CNT[0x111] After: region of 67 contiguous counters starting with SYS:STAT:CNT[0x000] region of 45 contiguous counters starting with SYS:STAT:CNT[0x080] region of 18 contiguous counters starting with SYS:STAT:CNT[0x100] Since commit d87b1c08f38a ("net: mscc: ocelot: use bulk reads for stats") intended bulking as a performance improvement, and since now, with trivial-sized regions, performance is even worse than without bulking at all, this could easily qualify as a performance regression. Fixes: d4c367650704 ("net: mscc: ocelot: keep ocelot_stat_layout by reg address, not offset") Signed-off-by: Vladimir Oltean Acked-by: Colin Foster Tested-by: Colin Foster Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mscc/ocelot_stats.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mscc/ocelot_stats.c b/drivers/net/ethernet/mscc/ocelot_stats.c index bdb893476832..096c81ec9dd6 100644 --- a/drivers/net/ethernet/mscc/ocelot_stats.c +++ b/drivers/net/ethernet/mscc/ocelot_stats.c @@ -899,7 +899,8 @@ static int ocelot_prepare_stats_regions(struct ocelot *ocelot) if (!layout[i].reg) continue; - if (region && layout[i].reg == last + 4) { + if (region && ocelot->map[SYS][layout[i].reg & REG_MASK] == + ocelot->map[SYS][last & REG_MASK] + 4) { region->count++; } else { region = devm_kzalloc(ocelot->dev, sizeof(*region), -- cgit From 17dfd210459837b453c2a3c20406ee12082f151c Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Tue, 21 Mar 2023 03:03:24 +0200 Subject: net: mscc: ocelot: fix transfer from region->buf to ocelot->stats To understand the problem, we need some definitions. The driver is aware of multiple counters (enum ocelot_stat), yet not all switches supported by the driver implement all counters. There are 2 statistics layouts: ocelot_stats_layout and ocelot_mm_stats_layout, the latter having 36 counters more than the former. ocelot->stats[] is not a compact array, i.e. there are elements within it which are not going to be populated for ocelot_stats_layout. On the other hand, ocelot->stats[] is easily indexable, for example "tx_octets" for port 3 can be found at ocelot->stats[3 * OCELOT_NUM_STATS + OCELOT_STAT_TX_OCTETS], and that is why we keep it sparse. Regions, as created by ocelot_prepare_stats_regions(), are compact (every element from region->buf will correspond to a counter that is present in this switch's layout) but are not easily indexable. Let's define holes as the ranges of values of enum ocelot_stat for which ocelot_stats_layout doesn't have a "reg" defined. For example, there is a hole between OCELOT_STAT_RX_GREEN_PRIO_7 and OCELOT_STAT_TX_OCTETS which is of 23 elements that are only present on ocelot_mm_stats_layout, and as such, they are also present in enum ocelot_stat. Let's define the left extremity of the hole - the last enum ocelot_stat still defined - as A (in this case OCELOT_STAT_RX_GREEN_PRIO_7) and the right extremity - the first enum ocelot_stat that is defined after a series of undefined ones - as B (in this case OCELOT_STAT_TX_OCTETS). There is a bug in the procedure which transfers stats from region->buf[] to ocelot->stats[]. For each hole in the ocelot_stats_layout, the logic transfers the stats starting with enum ocelot_stat B to ocelot->stats[] index A + 1. So all stats after a hole are saved to a position which is off by B - A + 1 elements. This causes 2 kinds of issues: (a) counters which shouldn't increment increment (b) counters which should increment don't Holes in the ocelot_stat_layout automatically imply the end of a region and the beginning of a new one; however the reverse is not necessarily true. For example, for ocelot_mm_stat_layout, there could be multiple regions (which indicate discontinuities in register addresses) while there is no hole (which indicates discontinuities in enum ocelot_stat values). In the example above, the stats from the second region->buf[] are not transferred to ocelot->stats starting with index "port * OCELOT_NUM_STATS + OCELOT_STAT_TX_OCTETS" as they should, but rather, starting with element "port * OCELOT_NUM_STATS + OCELOT_STAT_RX_GREEN_PRIO_7 + 1". That stats[] array element is not reported to user space for switches that use ocelot_stat_layout, and that is how issue (b) occurs. However, if the length of the second region is larger than the hole, then some stats will start to be transferred to the ocelot->stats[] indices which *are* reported to user space, but those indices contain wrong values (corresponding to unexpected counters). This is how issue (a) occurs. The procedure, as it was introduced in commit d87b1c08f38a ("net: mscc: ocelot: use bulk reads for stats"), was not buggy, because there were no holes in the struct ocelot_stat_layout instances at that time. The problem is that when those holes were introduced, the function was not updated to take them into consideration. To update the procedure, we need to know, for each region, which enum ocelot_stat corresponds to its region->base. We have no way of deducing that based on the contents of struct ocelot_stats_region, so we need to add this information. Fixes: ab3f97a9610a ("net: mscc: ocelot: export ethtool MAC Merge stats for Felix VSC9959") Signed-off-by: Vladimir Oltean Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mscc/ocelot_stats.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/mscc/ocelot_stats.c b/drivers/net/ethernet/mscc/ocelot_stats.c index 096c81ec9dd6..f18371154475 100644 --- a/drivers/net/ethernet/mscc/ocelot_stats.c +++ b/drivers/net/ethernet/mscc/ocelot_stats.c @@ -258,6 +258,7 @@ struct ocelot_stat_layout { struct ocelot_stats_region { struct list_head node; u32 base; + enum ocelot_stat first_stat; int count; u32 *buf; }; @@ -341,11 +342,12 @@ static int ocelot_port_update_stats(struct ocelot *ocelot, int port) */ static void ocelot_port_transfer_stats(struct ocelot *ocelot, int port) { - unsigned int idx = port * OCELOT_NUM_STATS; struct ocelot_stats_region *region; int j; list_for_each_entry(region, &ocelot->stats_regions, node) { + unsigned int idx = port * OCELOT_NUM_STATS + region->first_stat; + for (j = 0; j < region->count; j++) { u64 *stat = &ocelot->stats[idx + j]; u64 val = region->buf[j]; @@ -355,8 +357,6 @@ static void ocelot_port_transfer_stats(struct ocelot *ocelot, int port) *stat = (*stat & ~(u64)U32_MAX) + val; } - - idx += region->count; } } @@ -915,6 +915,7 @@ static int ocelot_prepare_stats_regions(struct ocelot *ocelot) WARN_ON(last >= layout[i].reg); region->base = layout[i].reg; + region->first_stat = i; region->count = 1; list_add_tail(®ion->node, &ocelot->stats_regions); } -- cgit From 5291099e0f61a4a1f4d2e11ac2af8123ece17e0e Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Tue, 21 Mar 2023 03:03:25 +0200 Subject: net: mscc: ocelot: add TX_MM_HOLD to ocelot_mm_stats_layout The lack of a definition for this counter is what initially prompted me to investigate a problem which really manifested itself as the previous change, "net: mscc: ocelot: fix transfer from region->buf to ocelot->stats". When TX_MM_HOLD is defined in enum ocelot_stat but not in struct ocelot_stat_layout ocelot_mm_stats_layout, this creates a hole, which due to the aforementioned bug, makes all counters following TX_MM_HOLD be recorded off by one compared to their correct position. So for example, a non-zero TX_PMAC_OCTETS would be reported as TX_MERGE_FRAGMENTS, TX_PMAC_UNICAST would be reported as TX_PMAC_OCTETS, TX_PMAC_64 would be reported as TX_PMAC_PAUSE, etc etc. This is because the size of the hole (1) is much smaller than the size of the region, so the phenomenon where the stats are off-by-one, rather than lost, prevails. However, the phenomenon where stats are lost can be seen too, for example with DROP_LOCAL, which is at the beginning of its own region (offset 0x000400 vs the previous 0x0002b0 constitutes a discontinuity). This is also reported as off by one and saved to TX_PMAC_1527_MAX, but that counter is not reported to the unstructured "ethtool -S", as opposed to DROP_LOCAL which is (as "drop_local"). Fixes: ab3f97a9610a ("net: mscc: ocelot: export ethtool MAC Merge stats for Felix VSC9959") Signed-off-by: Vladimir Oltean Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mscc/ocelot_stats.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ethernet/mscc/ocelot_stats.c b/drivers/net/ethernet/mscc/ocelot_stats.c index f18371154475..d0e6cd8dbe5c 100644 --- a/drivers/net/ethernet/mscc/ocelot_stats.c +++ b/drivers/net/ethernet/mscc/ocelot_stats.c @@ -274,6 +274,7 @@ static const struct ocelot_stat_layout ocelot_mm_stats_layout[OCELOT_NUM_STATS] OCELOT_STAT(RX_ASSEMBLY_OK), OCELOT_STAT(RX_MERGE_FRAGMENTS), OCELOT_STAT(TX_MERGE_FRAGMENTS), + OCELOT_STAT(TX_MM_HOLD), OCELOT_STAT(RX_PMAC_OCTETS), OCELOT_STAT(RX_PMAC_UNICAST), OCELOT_STAT(RX_PMAC_MULTICAST), -- cgit From 4107b8746d93ace135b8c4da4f19bbae81db785f Mon Sep 17 00:00:00 2001 From: Zhang Changzhong Date: Tue, 21 Mar 2023 14:45:43 +1100 Subject: net/sonic: use dma_mapping_error() for error check The DMA address returned by dma_map_single() should be checked with dma_mapping_error(). Fix it accordingly. Fixes: efcce839360f ("[PATCH] macsonic/jazzsonic network drivers update") Signed-off-by: Zhang Changzhong Tested-by: Stan Johnson Signed-off-by: Finn Thain Reviewed-by: Leon Romanovsky Link: https://lore.kernel.org/r/6645a4b5c1e364312103f48b7b36783b94e197a2.1679370343.git.fthain@linux-m68k.org Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/natsemi/sonic.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/natsemi/sonic.c b/drivers/net/ethernet/natsemi/sonic.c index d17d1b4f2585..825356ee3492 100644 --- a/drivers/net/ethernet/natsemi/sonic.c +++ b/drivers/net/ethernet/natsemi/sonic.c @@ -292,7 +292,7 @@ static int sonic_send_packet(struct sk_buff *skb, struct net_device *dev) */ laddr = dma_map_single(lp->device, skb->data, length, DMA_TO_DEVICE); - if (!laddr) { + if (dma_mapping_error(lp->device, laddr)) { pr_err_ratelimited("%s: failed to map tx DMA buffer.\n", dev->name); dev_kfree_skb_any(skb); return NETDEV_TX_OK; @@ -509,7 +509,7 @@ static bool sonic_alloc_rb(struct net_device *dev, struct sonic_local *lp, *new_addr = dma_map_single(lp->device, skb_put(*new_skb, SONIC_RBSIZE), SONIC_RBSIZE, DMA_FROM_DEVICE); - if (!*new_addr) { + if (dma_mapping_error(lp->device, *new_addr)) { dev_kfree_skb(*new_skb); *new_skb = NULL; return false; -- cgit From b58e3d4311b54b6dd0e37165277965da0c9eb21d Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 17 Mar 2023 10:53:24 +0100 Subject: wifi: iwlwifi: mvm: fix mvmtxq->stopped handling This could race if the queue is redirected while full, then the flushing internally would start it while it's not yet usable again. Fix it by using two state bits instead of just one. Reviewed-by: Benjamin Berg Tested-by: Jose Ignacio Tornos Martinez Signed-off-by: Johannes Berg --- drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 5 ++++- drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 4 +++- drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 5 ++++- drivers/net/wireless/intel/iwlwifi/mvm/sta.c | 4 ++-- 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index 565522466eba..f81c609ecf58 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -732,7 +732,10 @@ void iwl_mvm_mac_itxq_xmit(struct ieee80211_hw *hw, struct ieee80211_txq *txq) rcu_read_lock(); do { - while (likely(!mvmtxq->stopped && + while (likely(!test_bit(IWL_MVM_TXQ_STATE_STOP_FULL, + &mvmtxq->state) && + !test_bit(IWL_MVM_TXQ_STATE_STOP_REDIRECT, + &mvmtxq->state) && !test_bit(IWL_MVM_STATUS_IN_D3, &mvm->status))) { skb = ieee80211_tx_dequeue(hw, txq); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index 90bc95d96a78..421d2649b0f0 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -729,7 +729,9 @@ struct iwl_mvm_txq { struct list_head list; u16 txq_id; atomic_t tx_request; - bool stopped; +#define IWL_MVM_TXQ_STATE_STOP_FULL 0 +#define IWL_MVM_TXQ_STATE_STOP_REDIRECT 1 + unsigned long state; }; static inline struct iwl_mvm_txq * diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c index f4e9446d9dc2..efad8f92d132 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c @@ -1691,7 +1691,10 @@ static void iwl_mvm_queue_state_change(struct iwl_op_mode *op_mode, txq = sta->txq[tid]; mvmtxq = iwl_mvm_txq_from_mac80211(txq); - mvmtxq->stopped = !start; + if (start) + clear_bit(IWL_MVM_TXQ_STATE_STOP_FULL, &mvmtxq->state); + else + set_bit(IWL_MVM_TXQ_STATE_STOP_FULL, &mvmtxq->state); if (start && mvmsta->sta_state != IEEE80211_STA_NOTEXIST) iwl_mvm_mac_itxq_xmit(mvm->hw, txq); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c index 69634fb82a9b..21ad7b85c434 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c @@ -693,7 +693,7 @@ static int iwl_mvm_redirect_queue(struct iwl_mvm *mvm, int queue, int tid, queue, iwl_mvm_ac_to_tx_fifo[ac]); /* Stop the queue and wait for it to empty */ - txq->stopped = true; + set_bit(IWL_MVM_TXQ_STATE_STOP_REDIRECT, &txq->state); ret = iwl_trans_wait_tx_queues_empty(mvm->trans, BIT(queue)); if (ret) { @@ -736,7 +736,7 @@ static int iwl_mvm_redirect_queue(struct iwl_mvm *mvm, int queue, int tid, out: /* Continue using the queue */ - txq->stopped = false; + clear_bit(IWL_MVM_TXQ_STATE_STOP_REDIRECT, &txq->state); return ret; } -- cgit From 923bf981eb6ecc027227716e30701bdcc1845fbf Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 17 Mar 2023 10:53:25 +0100 Subject: wifi: iwlwifi: mvm: protect TXQ list manipulation Some recent upstream debugging uncovered the fact that in iwlwifi, the TXQ list manipulation is racy. Introduce a new state bit for when the TXQ is completely ready and can be used without locking, and if that's not set yet acquire the lock to check everything correctly. Reviewed-by: Benjamin Berg Tested-by: Jose Ignacio Tornos Martinez Signed-off-by: Johannes Berg --- drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 45 +++++++---------------- drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 2 + drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 1 + drivers/net/wireless/intel/iwlwifi/mvm/sta.c | 25 +++++++++++-- 4 files changed, 39 insertions(+), 34 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index f81c609ecf58..b55b1b17f4d1 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -760,42 +760,25 @@ static void iwl_mvm_mac_wake_tx_queue(struct ieee80211_hw *hw, struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); struct iwl_mvm_txq *mvmtxq = iwl_mvm_txq_from_mac80211(txq); - /* - * Please note that racing is handled very carefully here: - * mvmtxq->txq_id is updated during allocation, and mvmtxq->list is - * deleted afterwards. - * This means that if: - * mvmtxq->txq_id != INVALID_QUEUE && list_empty(&mvmtxq->list): - * queue is allocated and we can TX. - * mvmtxq->txq_id != INVALID_QUEUE && !list_empty(&mvmtxq->list): - * a race, should defer the frame. - * mvmtxq->txq_id == INVALID_QUEUE && list_empty(&mvmtxq->list): - * need to allocate the queue and defer the frame. - * mvmtxq->txq_id == INVALID_QUEUE && !list_empty(&mvmtxq->list): - * queue is already scheduled for allocation, no need to allocate, - * should defer the frame. - */ - - /* If the queue is allocated TX and return. */ - if (!txq->sta || mvmtxq->txq_id != IWL_MVM_INVALID_QUEUE) { - /* - * Check that list is empty to avoid a race where txq_id is - * already updated, but the queue allocation work wasn't - * finished - */ - if (unlikely(txq->sta && !list_empty(&mvmtxq->list))) - return; - + if (likely(test_bit(IWL_MVM_TXQ_STATE_READY, &mvmtxq->state)) || + !txq->sta) { iwl_mvm_mac_itxq_xmit(hw, txq); return; } - /* The list is being deleted only after the queue is fully allocated. */ - if (!list_empty(&mvmtxq->list)) - return; + /* iwl_mvm_mac_itxq_xmit() will later be called by the worker + * to handle any packets we leave on the txq now + */ - list_add_tail(&mvmtxq->list, &mvm->add_stream_txqs); - schedule_work(&mvm->add_stream_wk); + spin_lock_bh(&mvm->add_stream_lock); + /* The list is being deleted only after the queue is fully allocated. */ + if (list_empty(&mvmtxq->list) && + /* recheck under lock */ + !test_bit(IWL_MVM_TXQ_STATE_READY, &mvmtxq->state)) { + list_add_tail(&mvmtxq->list, &mvm->add_stream_txqs); + schedule_work(&mvm->add_stream_wk); + } + spin_unlock_bh(&mvm->add_stream_lock); } #define CHECK_BA_TRIGGER(_mvm, _trig, _tid_bm, _tid, _fmt...) \ diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index 421d2649b0f0..f307c345dfa0 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -731,6 +731,7 @@ struct iwl_mvm_txq { atomic_t tx_request; #define IWL_MVM_TXQ_STATE_STOP_FULL 0 #define IWL_MVM_TXQ_STATE_STOP_REDIRECT 1 +#define IWL_MVM_TXQ_STATE_READY 2 unsigned long state; }; @@ -829,6 +830,7 @@ struct iwl_mvm { struct iwl_mvm_tvqm_txq_info tvqm_info[IWL_MAX_TVQM_QUEUES]; }; struct work_struct add_stream_wk; /* To add streams to queues */ + spinlock_t add_stream_lock; const char *nvm_file_name; struct iwl_nvm_data *nvm_data; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c index efad8f92d132..9711841bb456 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c @@ -1195,6 +1195,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, INIT_DELAYED_WORK(&mvm->scan_timeout_dwork, iwl_mvm_scan_timeout_wk); INIT_WORK(&mvm->add_stream_wk, iwl_mvm_add_new_dqa_stream_wk); INIT_LIST_HEAD(&mvm->add_stream_txqs); + spin_lock_init(&mvm->add_stream_lock); init_waitqueue_head(&mvm->rx_sync_waitq); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c index 21ad7b85c434..9caae77995ca 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c @@ -384,8 +384,11 @@ static int iwl_mvm_disable_txq(struct iwl_mvm *mvm, struct ieee80211_sta *sta, struct iwl_mvm_txq *mvmtxq = iwl_mvm_txq_from_tid(sta, tid); - mvmtxq->txq_id = IWL_MVM_INVALID_QUEUE; + spin_lock_bh(&mvm->add_stream_lock); list_del_init(&mvmtxq->list); + clear_bit(IWL_MVM_TXQ_STATE_READY, &mvmtxq->state); + mvmtxq->txq_id = IWL_MVM_INVALID_QUEUE; + spin_unlock_bh(&mvm->add_stream_lock); } /* Regardless if this is a reserved TXQ for a STA - mark it as false */ @@ -479,8 +482,11 @@ static int iwl_mvm_remove_sta_queue_marking(struct iwl_mvm *mvm, int queue) disable_agg_tids |= BIT(tid); mvmsta->tid_data[tid].txq_id = IWL_MVM_INVALID_QUEUE; - mvmtxq->txq_id = IWL_MVM_INVALID_QUEUE; + spin_lock_bh(&mvm->add_stream_lock); list_del_init(&mvmtxq->list); + clear_bit(IWL_MVM_TXQ_STATE_READY, &mvmtxq->state); + mvmtxq->txq_id = IWL_MVM_INVALID_QUEUE; + spin_unlock_bh(&mvm->add_stream_lock); } mvmsta->tfd_queue_msk &= ~BIT(queue); /* Don't use this queue anymore */ @@ -1444,12 +1450,22 @@ void iwl_mvm_add_new_dqa_stream_wk(struct work_struct *wk) * a queue in the function itself. */ if (iwl_mvm_sta_alloc_queue(mvm, txq->sta, txq->ac, tid)) { + spin_lock_bh(&mvm->add_stream_lock); list_del_init(&mvmtxq->list); + spin_unlock_bh(&mvm->add_stream_lock); continue; } - list_del_init(&mvmtxq->list); + /* now we're ready, any remaining races/concurrency will be + * handled in iwl_mvm_mac_itxq_xmit() + */ + set_bit(IWL_MVM_TXQ_STATE_READY, &mvmtxq->state); + local_bh_disable(); + spin_lock(&mvm->add_stream_lock); + list_del_init(&mvmtxq->list); + spin_unlock(&mvm->add_stream_lock); + iwl_mvm_mac_itxq_xmit(mvm->hw, txq); local_bh_enable(); } @@ -1864,8 +1880,11 @@ static void iwl_mvm_disable_sta_queues(struct iwl_mvm *mvm, struct iwl_mvm_txq *mvmtxq = iwl_mvm_txq_from_mac80211(sta->txq[i]); + spin_lock_bh(&mvm->add_stream_lock); mvmtxq->txq_id = IWL_MVM_INVALID_QUEUE; list_del_init(&mvmtxq->list); + clear_bit(IWL_MVM_TXQ_STATE_READY, &mvmtxq->state); + spin_unlock_bh(&mvm->add_stream_lock); } } -- cgit From 4e348c6c6e23491ae6eb5e077848a42d0562339c Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 14 Mar 2023 10:59:50 +0100 Subject: wifi: mac80211: fix qos on mesh interfaces When ieee80211_select_queue is called for mesh, the sta pointer is usually NULL, since the nexthop is looked up much later in the tx path. Explicitly check for unicast address in that case in order to make qos work again. Cc: stable@vger.kernel.org Fixes: 50e2ab392919 ("wifi: mac80211: fix queue selection for mesh/OCB interfaces") Signed-off-by: Felix Fietkau Link: https://lore.kernel.org/r/20230314095956.62085-1-nbd@nbd.name Signed-off-by: Johannes Berg --- net/mac80211/wme.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c index a12c63638680..1601be576414 100644 --- a/net/mac80211/wme.c +++ b/net/mac80211/wme.c @@ -147,6 +147,7 @@ u16 ieee80211_select_queue_80211(struct ieee80211_sub_if_data *sdata, u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata, struct sta_info *sta, struct sk_buff *skb) { + const struct ethhdr *eth = (void *)skb->data; struct mac80211_qos_map *qos_map; bool qos; @@ -154,8 +155,9 @@ u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata, skb_get_hash(skb); /* all mesh/ocb stations are required to support WME */ - if (sta && (sdata->vif.type == NL80211_IFTYPE_MESH_POINT || - sdata->vif.type == NL80211_IFTYPE_OCB)) + if ((sdata->vif.type == NL80211_IFTYPE_MESH_POINT && + !is_multicast_ether_addr(eth->h_dest)) || + (sdata->vif.type == NL80211_IFTYPE_OCB && sta)) qos = true; else if (sta) qos = sta->sta.wme; -- cgit From f355f70145744518ca1d9799b42f4a8da9aa0d36 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 14 Mar 2023 10:59:52 +0100 Subject: wifi: mac80211: fix mesh path discovery based on unicast packets If a packet has reached its intended destination, it was bumped to the code that accepts it, without first checking if a mesh_path needs to be created based on the discovered source. Fix this by moving the destination address check further down. Cc: stable@vger.kernel.org Fixes: 986e43b19ae9 ("wifi: mac80211: fix receiving A-MSDU frames on mesh interfaces") Signed-off-by: Felix Fietkau Link: https://lore.kernel.org/r/20230314095956.62085-3-nbd@nbd.name Signed-off-by: Johannes Berg --- net/mac80211/rx.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index f7fdfe710951..e8de500eb9f3 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -2765,17 +2765,6 @@ ieee80211_rx_mesh_data(struct ieee80211_sub_if_data *sdata, struct sta_info *sta mesh_rmc_check(sdata, eth->h_source, mesh_hdr)) return RX_DROP_MONITOR; - /* Frame has reached destination. Don't forward */ - if (ether_addr_equal(sdata->vif.addr, eth->h_dest)) - goto rx_accept; - - if (!ifmsh->mshcfg.dot11MeshForwarding) { - if (is_multicast_ether_addr(eth->h_dest)) - goto rx_accept; - - return RX_DROP_MONITOR; - } - /* forward packet */ if (sdata->crypto_tx_tailroom_needed_cnt) tailroom = IEEE80211_ENCRYPT_TAILROOM; @@ -2814,6 +2803,17 @@ ieee80211_rx_mesh_data(struct ieee80211_sub_if_data *sdata, struct sta_info *sta rcu_read_unlock(); } + /* Frame has reached destination. Don't forward */ + if (ether_addr_equal(sdata->vif.addr, eth->h_dest)) + goto rx_accept; + + if (!ifmsh->mshcfg.dot11MeshForwarding) { + if (is_multicast_ether_addr(eth->h_dest)) + goto rx_accept; + + return RX_DROP_MONITOR; + } + skb_set_queue_mapping(skb, ieee802_1d_to_ac[skb->priority]); ieee80211_fill_mesh_addresses(&hdr, &hdr.frame_control, -- cgit From caa0708a81d6a2217c942959ef40d515ec1d3108 Mon Sep 17 00:00:00 2001 From: "Masami Hiramatsu (Google)" Date: Tue, 28 Feb 2023 10:01:42 +0900 Subject: bootconfig: Change message if no bootconfig with CONFIG_BOOT_CONFIG_FORCE=y Change no bootconfig data error message if user do not specify 'bootconfig' option but CONFIG_BOOT_CONFIG_FORCE=y. With CONFIG_BOOT_CONFIG_FORCE=y, the kernel proceeds bootconfig check even if user does not specify 'bootconfig' option. So the current error message is confusing. Let's show just an information message to notice skipping the bootconfig in that case. Link: https://lore.kernel.org/all/167754610254.318944.16848412476667893329.stgit@devnote2/ Fixes: b743852ccc1d ("Allow forcing unconditional bootconfig processing") Reported-by: Geert Uytterhoeven Link: https://lore.kernel.org/all/CAMuHMdV9jJvE2y8gY5V_CxidUikCf5515QMZHzTA3rRGEOj6=w@mail.gmail.com/ Suggested-by: Paul E. McKenney Signed-off-by: Masami Hiramatsu (Google) Tested-by: Paul E. McKenney Acked-by: Mukesh Ojha --- init/main.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/init/main.c b/init/main.c index 4425d1783d5c..bb87b789c543 100644 --- a/init/main.c +++ b/init/main.c @@ -156,7 +156,7 @@ static char *extra_init_args; #ifdef CONFIG_BOOT_CONFIG /* Is bootconfig on command line? */ -static bool bootconfig_found = IS_ENABLED(CONFIG_BOOT_CONFIG_FORCE); +static bool bootconfig_found; static size_t initargs_offs; #else # define bootconfig_found false @@ -429,7 +429,7 @@ static void __init setup_boot_config(void) err = parse_args("bootconfig", tmp_cmdline, NULL, 0, 0, 0, NULL, bootconfig_params); - if (IS_ERR(err) || !bootconfig_found) + if (IS_ERR(err) || !(bootconfig_found || IS_ENABLED(CONFIG_BOOT_CONFIG_FORCE))) return; /* parse_args() stops at the next param of '--' and returns an address */ @@ -437,7 +437,11 @@ static void __init setup_boot_config(void) initargs_offs = err - tmp_cmdline; if (!data) { - pr_err("'bootconfig' found on command line, but no bootconfig found\n"); + /* If user intended to use bootconfig, show an error level message */ + if (bootconfig_found) + pr_err("'bootconfig' found on command line, but no bootconfig found\n"); + else + pr_info("No bootconfig data provided, so skipping bootconfig"); return; } -- cgit From bb765a743377d46d8da8e7f7e5128022504741b9 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Tue, 21 Mar 2023 12:42:00 +0100 Subject: mlxsw: spectrum_fid: Fix incorrect local port type Local port is a 10-bit number, but it was mistakenly stored in a u8, resulting in firmware errors when using a netdev corresponding to a local port higher than 255. Fix by storing the local port in u16, as is done in the rest of the code. Fixes: bf73904f5fba ("mlxsw: Add support for 802.1Q FID family") Signed-off-by: Ido Schimmel Reviewed-by: Danielle Ratson Signed-off-by: Petr Machata Reviewed-by: Simon Horman Link: https://lore.kernel.org/r/eace1f9d96545ab8a2775db857cb7e291a9b166b.1679398549.git.petrm@nvidia.com Signed-off-by: Paolo Abeni --- drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c index 045a24cacfa5..b6ee2d658b0c 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c @@ -1354,7 +1354,7 @@ static int mlxsw_sp_fid_8021q_port_vid_map(struct mlxsw_sp_fid *fid, u16 vid) { struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; - u8 local_port = mlxsw_sp_port->local_port; + u16 local_port = mlxsw_sp_port->local_port; int err; /* In case there are no {Port, VID} => FID mappings on the port, @@ -1391,7 +1391,7 @@ mlxsw_sp_fid_8021q_port_vid_unmap(struct mlxsw_sp_fid *fid, struct mlxsw_sp_port *mlxsw_sp_port, u16 vid) { struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; - u8 local_port = mlxsw_sp_port->local_port; + u16 local_port = mlxsw_sp_port->local_port; mlxsw_sp_fid_port_vid_list_del(fid, mlxsw_sp_port->local_port, vid); mlxsw_sp_fid_evid_map(fid, local_port, vid, false); -- cgit From 915efd8a446b74442039d31689d5d863caf82517 Mon Sep 17 00:00:00 2001 From: Jesper Dangaard Brouer Date: Tue, 21 Mar 2023 14:52:31 +0100 Subject: xdp: bpf_xdp_metadata use EOPNOTSUPP for no driver support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When driver doesn't implement a bpf_xdp_metadata kfunc the fallback implementation returns EOPNOTSUPP, which indicate device driver doesn't implement this kfunc. Currently many drivers also return EOPNOTSUPP when the hint isn't available, which is ambiguous from an API point of view. Instead change drivers to return ENODATA in these cases. There can be natural cases why a driver doesn't provide any hardware info for a specific hint, even on a frame to frame basis (e.g. PTP). Lets keep these cases as separate return codes. When describing the return values, adjust the function kernel-doc layout to get proper rendering for the return values. Fixes: ab46182d0dcb ("net/mlx4_en: Support RX XDP metadata") Fixes: bc8d405b1ba9 ("net/mlx5e: Support RX XDP metadata") Fixes: 306531f0249f ("veth: Support RX XDP metadata") Fixes: 3d76a4d3d4e5 ("bpf: XDP metadata RX kfuncs") Signed-off-by: Jesper Dangaard Brouer Acked-by: Stanislav Fomichev Acked-by: Toke Høiland-Jørgensen Acked-by: Tariq Toukan Link: https://lore.kernel.org/r/167940675120.2718408.8176058626864184420.stgit@firesoul Signed-off-by: Alexei Starovoitov --- Documentation/networking/xdp-rx-metadata.rst | 7 +++++-- drivers/net/ethernet/mellanox/mlx4/en_rx.c | 4 ++-- drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c | 4 ++-- drivers/net/veth.c | 4 ++-- net/core/xdp.c | 10 ++++++++-- 5 files changed, 19 insertions(+), 10 deletions(-) diff --git a/Documentation/networking/xdp-rx-metadata.rst b/Documentation/networking/xdp-rx-metadata.rst index aac63fc2d08b..25ce72af81c2 100644 --- a/Documentation/networking/xdp-rx-metadata.rst +++ b/Documentation/networking/xdp-rx-metadata.rst @@ -23,10 +23,13 @@ metadata is supported, this set will grow: An XDP program can use these kfuncs to read the metadata into stack variables for its own consumption. Or, to pass the metadata on to other consumers, an XDP program can store it into the metadata area carried -ahead of the packet. +ahead of the packet. Not all packets will necessary have the requested +metadata available in which case the driver returns ``-ENODATA``. Not all kfuncs have to be implemented by the device driver; when not -implemented, the default ones that return ``-EOPNOTSUPP`` will be used. +implemented, the default ones that return ``-EOPNOTSUPP`` will be used +to indicate the device driver have not implemented this kfunc. + Within an XDP frame, the metadata layout (accessed via ``xdp_buff``) is as follows:: diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ethernet/mellanox/mlx4/en_rx.c index 0869d4fff17b..4b5e459b6d49 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c @@ -674,7 +674,7 @@ int mlx4_en_xdp_rx_timestamp(const struct xdp_md *ctx, u64 *timestamp) struct mlx4_en_xdp_buff *_ctx = (void *)ctx; if (unlikely(_ctx->ring->hwtstamp_rx_filter != HWTSTAMP_FILTER_ALL)) - return -EOPNOTSUPP; + return -ENODATA; *timestamp = mlx4_en_get_hwtstamp(_ctx->mdev, mlx4_en_get_cqe_ts(_ctx->cqe)); @@ -686,7 +686,7 @@ int mlx4_en_xdp_rx_hash(const struct xdp_md *ctx, u32 *hash) struct mlx4_en_xdp_buff *_ctx = (void *)ctx; if (unlikely(!(_ctx->dev->features & NETIF_F_RXHASH))) - return -EOPNOTSUPP; + return -ENODATA; *hash = be32_to_cpu(_ctx->cqe->immed_rss_invalid); return 0; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c b/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c index bcd6370de440..c5dae48b7932 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c @@ -162,7 +162,7 @@ static int mlx5e_xdp_rx_timestamp(const struct xdp_md *ctx, u64 *timestamp) const struct mlx5e_xdp_buff *_ctx = (void *)ctx; if (unlikely(!mlx5e_rx_hw_stamp(_ctx->rq->tstamp))) - return -EOPNOTSUPP; + return -ENODATA; *timestamp = mlx5e_cqe_ts_to_ns(_ctx->rq->ptp_cyc2time, _ctx->rq->clock, get_cqe_ts(_ctx->cqe)); @@ -174,7 +174,7 @@ static int mlx5e_xdp_rx_hash(const struct xdp_md *ctx, u32 *hash) const struct mlx5e_xdp_buff *_ctx = (void *)ctx; if (unlikely(!(_ctx->xdp.rxq->dev->features & NETIF_F_RXHASH))) - return -EOPNOTSUPP; + return -ENODATA; *hash = be32_to_cpu(_ctx->cqe->rss_hash_result); return 0; diff --git a/drivers/net/veth.c b/drivers/net/veth.c index 1bb54de7124d..046461ee42ea 100644 --- a/drivers/net/veth.c +++ b/drivers/net/veth.c @@ -1610,7 +1610,7 @@ static int veth_xdp_rx_timestamp(const struct xdp_md *ctx, u64 *timestamp) struct veth_xdp_buff *_ctx = (void *)ctx; if (!_ctx->skb) - return -EOPNOTSUPP; + return -ENODATA; *timestamp = skb_hwtstamps(_ctx->skb)->hwtstamp; return 0; @@ -1621,7 +1621,7 @@ static int veth_xdp_rx_hash(const struct xdp_md *ctx, u32 *hash) struct veth_xdp_buff *_ctx = (void *)ctx; if (!_ctx->skb) - return -EOPNOTSUPP; + return -ENODATA; *hash = skb_get_hash(_ctx->skb); return 0; diff --git a/net/core/xdp.c b/net/core/xdp.c index 8c92fc553317..247797168579 100644 --- a/net/core/xdp.c +++ b/net/core/xdp.c @@ -720,7 +720,10 @@ __diag_ignore_all("-Wmissing-prototypes", * @ctx: XDP context pointer. * @timestamp: Return value pointer. * - * Returns 0 on success or ``-errno`` on error. + * Return: + * * Returns 0 on success or ``-errno`` on error. + * * ``-EOPNOTSUPP`` : means device driver does not implement kfunc + * * ``-ENODATA`` : means no RX-timestamp available for this frame */ __bpf_kfunc int bpf_xdp_metadata_rx_timestamp(const struct xdp_md *ctx, u64 *timestamp) { @@ -732,7 +735,10 @@ __bpf_kfunc int bpf_xdp_metadata_rx_timestamp(const struct xdp_md *ctx, u64 *tim * @ctx: XDP context pointer. * @hash: Return value pointer. * - * Returns 0 on success or ``-errno`` on error. + * Return: + * * Returns 0 on success or ``-errno`` on error. + * * ``-EOPNOTSUPP`` : means device driver doesn't implement kfunc + * * ``-ENODATA`` : means no RX-hash available for this frame */ __bpf_kfunc int bpf_xdp_metadata_rx_hash(const struct xdp_md *ctx, u32 *hash) { -- cgit From 3c44a431d62bf4a20d7b901f98266ae3f4676d48 Mon Sep 17 00:00:00 2001 From: Zhengping Jiang Date: Tue, 21 Feb 2023 16:17:56 -0800 Subject: Bluetooth: hci_sync: Resume adv with no RPA when active scan The address resolution should be disabled during the active scan, so all the advertisements can reach the host. The advertising has to be paused before disabling the address resolution, because the advertising will prevent any changes to the resolving list and the address resolution status. Skipping this will cause the hci error and the discovery failure. According to the bluetooth specification: "7.8.44 LE Set Address Resolution Enable command This command shall not be used when: - Advertising (other than periodic advertising) is enabled, - Scanning is enabled, or - an HCI_LE_Create_Connection, HCI_LE_Extended_Create_Connection, or HCI_LE_Periodic_Advertising_Create_Sync command is outstanding." If the host is using RPA, the controller needs to generate RPA for the advertising, so the advertising must remain paused during the active scan. If the host is not using RPA, the advertising can be resumed after disabling the address resolution. Fixes: 9afc675edeeb ("Bluetooth: hci_sync: allow advertise when scan without RPA") Signed-off-by: Zhengping Jiang Signed-off-by: Luiz Augusto von Dentz --- net/bluetooth/hci_sync.c | 64 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 44 insertions(+), 20 deletions(-) diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c index 117eedb6f709..7e152e912e8c 100644 --- a/net/bluetooth/hci_sync.c +++ b/net/bluetooth/hci_sync.c @@ -2367,6 +2367,45 @@ static int hci_resume_advertising_sync(struct hci_dev *hdev) return err; } +static int hci_pause_addr_resolution(struct hci_dev *hdev) +{ + int err; + + if (!use_ll_privacy(hdev)) + return 0; + + if (!hci_dev_test_flag(hdev, HCI_LL_RPA_RESOLUTION)) + return 0; + + /* Cannot disable addr resolution if scanning is enabled or + * when initiating an LE connection. + */ + if (hci_dev_test_flag(hdev, HCI_LE_SCAN) || + hci_lookup_le_connect(hdev)) { + bt_dev_err(hdev, "Command not allowed when scan/LE connect"); + return -EPERM; + } + + /* Cannot disable addr resolution if advertising is enabled. */ + err = hci_pause_advertising_sync(hdev); + if (err) { + bt_dev_err(hdev, "Pause advertising failed: %d", err); + return err; + } + + err = hci_le_set_addr_resolution_enable_sync(hdev, 0x00); + if (err) + bt_dev_err(hdev, "Unable to disable Address Resolution: %d", + err); + + /* Return if address resolution is disabled and RPA is not used. */ + if (!err && scan_use_rpa(hdev)) + return err; + + hci_resume_advertising_sync(hdev); + return err; +} + struct sk_buff *hci_read_local_oob_data_sync(struct hci_dev *hdev, bool extended, struct sock *sk) { @@ -2402,7 +2441,7 @@ static u8 hci_update_accept_list_sync(struct hci_dev *hdev) u8 filter_policy; int err; - /* Pause advertising if resolving list can be used as controllers are + /* Pause advertising if resolving list can be used as controllers * cannot accept resolving list modifications while advertising. */ if (use_ll_privacy(hdev)) { @@ -5394,27 +5433,12 @@ static int hci_active_scan_sync(struct hci_dev *hdev, uint16_t interval) cancel_interleave_scan(hdev); - /* Pause advertising since active scanning disables address resolution - * which advertising depend on in order to generate its RPAs. - */ - if (use_ll_privacy(hdev) && hci_dev_test_flag(hdev, HCI_PRIVACY)) { - err = hci_pause_advertising_sync(hdev); - if (err) { - bt_dev_err(hdev, "pause advertising failed: %d", err); - goto failed; - } - } - - /* Disable address resolution while doing active scanning since the - * accept list shall not be used and all reports shall reach the host - * anyway. + /* Pause address resolution for active scan and stop advertising if + * privacy is enabled. */ - err = hci_le_set_addr_resolution_enable_sync(hdev, 0x00); - if (err) { - bt_dev_err(hdev, "Unable to disable Address Resolution: %d", - err); + err = hci_pause_addr_resolution(hdev); + if (err) goto failed; - } /* All active scans will be done with either a resolvable private * address (when privacy feature has been enabled) or non-resolvable -- cgit From 876e78104f23ce9267822757a63562a609b126c3 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Fri, 24 Feb 2023 15:43:31 -0800 Subject: Bluetooth: hci_core: Detect if an ACL packet is in fact an ISO packet Because some transports don't have a dedicated type for ISO packets (see 14202eff214e1e941fefa0366d4c3bc4b1a0d500) they may use ACL type when in fact they are ISO packets. In the past this was left for the driver to detect such thing but it creates a problem when using the likes of btproxy when used by a VM as the host would not be aware of the connection the guest is doing it won't be able to detect such behavior, so this make bt_recv_frame detect when it happens as it is the common interface to all drivers including guest VMs. Fixes: 14202eff214e ("Bluetooth: btusb: Detect if an ACL packet is in fact an ISO packet") Signed-off-by: Luiz Augusto von Dentz --- net/bluetooth/hci_core.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index b65c3aabcd53..334e308451f5 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -2871,10 +2871,25 @@ int hci_recv_frame(struct hci_dev *hdev, struct sk_buff *skb) return -ENXIO; } - if (hci_skb_pkt_type(skb) != HCI_EVENT_PKT && - hci_skb_pkt_type(skb) != HCI_ACLDATA_PKT && - hci_skb_pkt_type(skb) != HCI_SCODATA_PKT && - hci_skb_pkt_type(skb) != HCI_ISODATA_PKT) { + switch (hci_skb_pkt_type(skb)) { + case HCI_EVENT_PKT: + break; + case HCI_ACLDATA_PKT: + /* Detect if ISO packet has been sent as ACL */ + if (hci_conn_num(hdev, ISO_LINK)) { + __u16 handle = __le16_to_cpu(hci_acl_hdr(skb)->handle); + __u8 type; + + type = hci_conn_lookup_type(hdev, hci_handle(handle)); + if (type == ISO_LINK) + hci_skb_pkt_type(skb) = HCI_ISODATA_PKT; + } + break; + case HCI_SCODATA_PKT: + break; + case HCI_ISODATA_PKT: + break; + default: kfree_skb(skb); return -EINVAL; } -- cgit From efe375b716c1c1c9b52a816f5b933a95421020a2 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Fri, 24 Feb 2023 15:54:31 -0800 Subject: Bluetooth: btusb: Remove detection of ISO packets over bulk This removes the code introduced by 14202eff214e1e941fefa0366d4c3bc4b1a0d500 as hci_recv_frame is now able to detect ACL packets that are in fact ISO packets. Fixes: 14202eff214e ("Bluetooth: btusb: Detect if an ACL packet is in fact an ISO packet") Signed-off-by: Luiz Augusto von Dentz --- drivers/bluetooth/btusb.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 18bc94718711..5c536151ef83 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -1050,21 +1050,11 @@ static int btusb_recv_bulk(struct btusb_data *data, void *buffer, int count) hci_skb_expect(skb) -= len; if (skb->len == HCI_ACL_HDR_SIZE) { - __u16 handle = __le16_to_cpu(hci_acl_hdr(skb)->handle); __le16 dlen = hci_acl_hdr(skb)->dlen; - __u8 type; /* Complete ACL header */ hci_skb_expect(skb) = __le16_to_cpu(dlen); - /* Detect if ISO packet has been sent over bulk */ - if (hci_conn_num(data->hdev, ISO_LINK)) { - type = hci_conn_lookup_type(data->hdev, - hci_handle(handle)); - if (type == ISO_LINK) - hci_skb_pkt_type(skb) = HCI_ISODATA_PKT; - } - if (skb_tailroom(skb) < hci_skb_expect(skb)) { kfree_skb(skb); skb = NULL; -- cgit From 2f10e40a948e8a2abe7f983df3959a333ca8955f Mon Sep 17 00:00:00 2001 From: Pauli Virtanen Date: Mon, 20 Feb 2023 19:38:24 +0000 Subject: Bluetooth: ISO: fix timestamped HCI ISO data packet parsing Use correct HCI ISO data packet header struct when the packet has timestamp. The timestamp, when present, goes before the other fields (Core v5.3 4E 5.4.5), so the structs are not compatible. Fixes: ccf74f2390d6 ("Bluetooth: Add BTPROTO_ISO socket type") Signed-off-by: Pauli Virtanen Signed-off-by: Luiz Augusto von Dentz --- net/bluetooth/iso.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/net/bluetooth/iso.c b/net/bluetooth/iso.c index 24444b502e58..8d136a730163 100644 --- a/net/bluetooth/iso.c +++ b/net/bluetooth/iso.c @@ -1620,7 +1620,6 @@ static void iso_disconn_cfm(struct hci_conn *hcon, __u8 reason) void iso_recv(struct hci_conn *hcon, struct sk_buff *skb, u16 flags) { struct iso_conn *conn = hcon->iso_data; - struct hci_iso_data_hdr *hdr; __u16 pb, ts, len; if (!conn) @@ -1642,6 +1641,8 @@ void iso_recv(struct hci_conn *hcon, struct sk_buff *skb, u16 flags) } if (ts) { + struct hci_iso_ts_data_hdr *hdr; + /* TODO: add timestamp to the packet? */ hdr = skb_pull_data(skb, HCI_ISO_TS_DATA_HDR_SIZE); if (!hdr) { @@ -1649,15 +1650,19 @@ void iso_recv(struct hci_conn *hcon, struct sk_buff *skb, u16 flags) goto drop; } + len = __le16_to_cpu(hdr->slen); } else { + struct hci_iso_data_hdr *hdr; + hdr = skb_pull_data(skb, HCI_ISO_DATA_HDR_SIZE); if (!hdr) { BT_ERR("Frame is too short (len %d)", skb->len); goto drop; } + + len = __le16_to_cpu(hdr->slen); } - len = __le16_to_cpu(hdr->slen); flags = hci_iso_data_flags(len); len = hci_iso_data_len(len); -- cgit From 294d749b5df5a22d17989833fb1a0a2cd1dfd243 Mon Sep 17 00:00:00 2001 From: Kiran K Date: Tue, 28 Feb 2023 16:31:54 +0530 Subject: Bluetooth: btintel: Iterate only bluetooth device ACPI entries Current flow interates over entire ACPI table entries looking for Bluetooth Per Platform Antenna Gain(PPAG) entry. This patch iterates over ACPI entries relvant to Bluetooth device only. Fixes: c585a92b2f9c ("Bluetooth: btintel: Set Per Platform Antenna Gain(PPAG)") Signed-off-by: Kiran K Signed-off-by: Luiz Augusto von Dentz --- drivers/bluetooth/btintel.c | 44 ++++++++++++++++++++++++---------------- drivers/bluetooth/btintel.h | 7 ------- include/net/bluetooth/hci_core.h | 1 + 3 files changed, 27 insertions(+), 25 deletions(-) diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c index bede8b005594..e8d4b59e89c5 100644 --- a/drivers/bluetooth/btintel.c +++ b/drivers/bluetooth/btintel.c @@ -26,7 +26,14 @@ #define ECDSA_HEADER_LEN 320 #define BTINTEL_PPAG_NAME "PPAG" -#define BTINTEL_PPAG_PREFIX "\\_SB_.PCI0.XHCI.RHUB" + +/* structure to store the PPAG data read from ACPI table */ +struct btintel_ppag { + u32 domain; + u32 mode; + acpi_status status; + struct hci_dev *hdev; +}; #define CMD_WRITE_BOOT_PARAMS 0xfc0e struct cmd_write_boot_params { @@ -1295,17 +1302,16 @@ static acpi_status btintel_ppag_callback(acpi_handle handle, u32 lvl, void *data status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &string); if (ACPI_FAILURE(status)) { - bt_dev_warn(hdev, "ACPI Failure: %s", acpi_format_exception(status)); + bt_dev_warn(hdev, "PPAG-BT: ACPI Failure: %s", acpi_format_exception(status)); return status; } - if (strncmp(BTINTEL_PPAG_PREFIX, string.pointer, - strlen(BTINTEL_PPAG_PREFIX))) { + len = strlen(string.pointer); + if (len < strlen(BTINTEL_PPAG_NAME)) { kfree(string.pointer); return AE_OK; } - len = strlen(string.pointer); if (strncmp((char *)string.pointer + len - 4, BTINTEL_PPAG_NAME, 4)) { kfree(string.pointer); return AE_OK; @@ -1314,7 +1320,8 @@ static acpi_status btintel_ppag_callback(acpi_handle handle, u32 lvl, void *data status = acpi_evaluate_object(handle, NULL, NULL, &buffer); if (ACPI_FAILURE(status)) { - bt_dev_warn(hdev, "ACPI Failure: %s", acpi_format_exception(status)); + ppag->status = status; + bt_dev_warn(hdev, "PPAG-BT: ACPI Failure: %s", acpi_format_exception(status)); return status; } @@ -1323,8 +1330,9 @@ static acpi_status btintel_ppag_callback(acpi_handle handle, u32 lvl, void *data if (p->type != ACPI_TYPE_PACKAGE || p->package.count != 2) { kfree(buffer.pointer); - bt_dev_warn(hdev, "Invalid object type: %d or package count: %d", + bt_dev_warn(hdev, "PPAG-BT: Invalid object type: %d or package count: %d", p->type, p->package.count); + ppag->status = AE_ERROR; return AE_ERROR; } @@ -1335,6 +1343,7 @@ static acpi_status btintel_ppag_callback(acpi_handle handle, u32 lvl, void *data ppag->domain = (u32)p->package.elements[0].integer.value; ppag->mode = (u32)p->package.elements[1].integer.value; + ppag->status = AE_OK; kfree(buffer.pointer); return AE_CTRL_TERMINATE; } @@ -2314,12 +2323,11 @@ error: static void btintel_set_ppag(struct hci_dev *hdev, struct intel_version_tlv *ver) { - acpi_status status; struct btintel_ppag ppag; struct sk_buff *skb; struct btintel_loc_aware_reg ppag_cmd; - /* PPAG is not supported if CRF is HrP2, Jfp2, JfP1 */ + /* PPAG is not supported if CRF is HrP2, Jfp2, JfP1 */ switch (ver->cnvr_top & 0xFFF) { case 0x504: /* Hrp2 */ case 0x202: /* Jfp2 */ @@ -2330,26 +2338,26 @@ static void btintel_set_ppag(struct hci_dev *hdev, struct intel_version_tlv *ver memset(&ppag, 0, sizeof(ppag)); ppag.hdev = hdev; - status = acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, - ACPI_UINT32_MAX, NULL, - btintel_ppag_callback, &ppag, NULL); + ppag.status = AE_NOT_FOUND; + acpi_walk_namespace(ACPI_TYPE_PACKAGE, ACPI_HANDLE(GET_HCIDEV_DEV(hdev)), + 1, NULL, btintel_ppag_callback, &ppag, NULL); - if (ACPI_FAILURE(status)) { - /* Do not log warning message if ACPI entry is not found */ - if (status == AE_NOT_FOUND) + if (ACPI_FAILURE(ppag.status)) { + if (ppag.status == AE_NOT_FOUND) { + bt_dev_dbg(hdev, "PPAG-BT: ACPI entry not found"); return; - bt_dev_warn(hdev, "PPAG: ACPI Failure: %s", acpi_format_exception(status)); + } return; } if (ppag.domain != 0x12) { - bt_dev_warn(hdev, "PPAG-BT Domain disabled"); + bt_dev_warn(hdev, "PPAG-BT: domain is not bluetooth"); return; } /* PPAG mode, BIT0 = 0 Disabled, BIT0 = 1 Enabled */ if (!(ppag.mode & BIT(0))) { - bt_dev_dbg(hdev, "PPAG disabled"); + bt_dev_dbg(hdev, "PPAG-BT: disabled"); return; } diff --git a/drivers/bluetooth/btintel.h b/drivers/bluetooth/btintel.h index 8e7da877efae..8fdb65b66315 100644 --- a/drivers/bluetooth/btintel.h +++ b/drivers/bluetooth/btintel.h @@ -137,13 +137,6 @@ struct intel_offload_use_cases { __u8 preset[8]; } __packed; -/* structure to store the PPAG data read from ACPI table */ -struct btintel_ppag { - u32 domain; - u32 mode; - struct hci_dev *hdev; -}; - struct btintel_loc_aware_reg { __le32 mcc; __le32 sel; diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 7254edfba4c9..6ed9b4d546a7 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -1613,6 +1613,7 @@ void hci_conn_add_sysfs(struct hci_conn *conn); void hci_conn_del_sysfs(struct hci_conn *conn); #define SET_HCIDEV_DEV(hdev, pdev) ((hdev)->dev.parent = (pdev)) +#define GET_HCIDEV_DEV(hdev) ((hdev)->dev.parent) /* ----- LMP capabilities ----- */ #define lmp_encrypt_capable(dev) ((dev)->features[0][0] & LMP_ENCRYPT) -- cgit From 1c66bee492a5fe00ae3fe890bb693bfc99f994c6 Mon Sep 17 00:00:00 2001 From: Min Li Date: Sat, 4 Mar 2023 21:50:35 +0800 Subject: Bluetooth: Fix race condition in hci_cmd_sync_clear There is a potential race condition in hci_cmd_sync_work and hci_cmd_sync_clear, and could lead to use-after-free. For instance, hci_cmd_sync_work is added to the 'req_workqueue' after cancel_work_sync The entry of 'cmd_sync_work_list' may be freed in hci_cmd_sync_clear, and causing kernel panic when it is used in 'hci_cmd_sync_work'. Here's the call trace: dump_stack_lvl+0x49/0x63 print_report.cold+0x5e/0x5d3 ? hci_cmd_sync_work+0x282/0x320 kasan_report+0xaa/0x120 ? hci_cmd_sync_work+0x282/0x320 __asan_report_load8_noabort+0x14/0x20 hci_cmd_sync_work+0x282/0x320 process_one_work+0x77b/0x11c0 ? _raw_spin_lock_irq+0x8e/0xf0 worker_thread+0x544/0x1180 ? poll_idle+0x1e0/0x1e0 kthread+0x285/0x320 ? process_one_work+0x11c0/0x11c0 ? kthread_complete_and_exit+0x30/0x30 ret_from_fork+0x22/0x30 Allocated by task 266: kasan_save_stack+0x26/0x50 __kasan_kmalloc+0xae/0xe0 kmem_cache_alloc_trace+0x191/0x350 hci_cmd_sync_queue+0x97/0x2b0 hci_update_passive_scan+0x176/0x1d0 le_conn_complete_evt+0x1b5/0x1a00 hci_le_conn_complete_evt+0x234/0x340 hci_le_meta_evt+0x231/0x4e0 hci_event_packet+0x4c5/0xf00 hci_rx_work+0x37d/0x880 process_one_work+0x77b/0x11c0 worker_thread+0x544/0x1180 kthread+0x285/0x320 ret_from_fork+0x22/0x30 Freed by task 269: kasan_save_stack+0x26/0x50 kasan_set_track+0x25/0x40 kasan_set_free_info+0x24/0x40 ____kasan_slab_free+0x176/0x1c0 __kasan_slab_free+0x12/0x20 slab_free_freelist_hook+0x95/0x1a0 kfree+0xba/0x2f0 hci_cmd_sync_clear+0x14c/0x210 hci_unregister_dev+0xff/0x440 vhci_release+0x7b/0xf0 __fput+0x1f3/0x970 ____fput+0xe/0x20 task_work_run+0xd4/0x160 do_exit+0x8b0/0x22a0 do_group_exit+0xba/0x2a0 get_signal+0x1e4a/0x25b0 arch_do_signal_or_restart+0x93/0x1f80 exit_to_user_mode_prepare+0xf5/0x1a0 syscall_exit_to_user_mode+0x26/0x50 ret_from_fork+0x15/0x30 Fixes: 6a98e3836fa2 ("Bluetooth: Add helper for serialized HCI command execution") Cc: stable@vger.kernel.org Signed-off-by: Min Li Signed-off-by: Luiz Augusto von Dentz --- net/bluetooth/hci_sync.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c index 7e152e912e8c..5b8dc8fb2e27 100644 --- a/net/bluetooth/hci_sync.c +++ b/net/bluetooth/hci_sync.c @@ -643,6 +643,7 @@ void hci_cmd_sync_clear(struct hci_dev *hdev) cancel_work_sync(&hdev->cmd_sync_work); cancel_work_sync(&hdev->reenable_adv_work); + mutex_lock(&hdev->cmd_sync_work_lock); list_for_each_entry_safe(entry, tmp, &hdev->cmd_sync_work_list, list) { if (entry->destroy) entry->destroy(hdev, entry->data, -ECANCELED); @@ -650,6 +651,7 @@ void hci_cmd_sync_clear(struct hci_dev *hdev) list_del(&entry->list); kfree(entry); } + mutex_unlock(&hdev->cmd_sync_work_lock); } void __hci_cmd_sync_cancel(struct hci_dev *hdev, int err) -- cgit From 52dd5e964a55c98c1b0bcf5fc737a5ddd00e7d4d Mon Sep 17 00:00:00 2001 From: Brian Gix Date: Mon, 6 Mar 2023 14:32:21 -0800 Subject: Bluetooth: Remove "Power-on" check from Mesh feature The Bluetooth mesh experimental feature enable was requiring the controller to be powered off in order for the Enable to work. Mesh is supposed to be enablable regardless of the controller state, and created an unintended requirement that the mesh daemon be started before the classic bluetoothd daemon. Fixes: af6bcc1921ff ("Bluetooth: Add experimental wrapper for MGMT based mesh") Signed-off-by: Brian Gix Signed-off-by: Luiz Augusto von Dentz --- net/bluetooth/mgmt.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 7add66f30e4d..39589f864ea7 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -4639,12 +4639,6 @@ static int set_mgmt_mesh_func(struct sock *sk, struct hci_dev *hdev, MGMT_OP_SET_EXP_FEATURE, MGMT_STATUS_INVALID_INDEX); - /* Changes can only be made when controller is powered down */ - if (hdev_is_powered(hdev)) - return mgmt_cmd_status(sk, hdev->id, - MGMT_OP_SET_EXP_FEATURE, - MGMT_STATUS_REJECTED); - /* Parameters are limited to a single octet */ if (data_len != MGMT_SET_EXP_FEATURE_SIZE + 1) return mgmt_cmd_status(sk, hdev->id, -- cgit From c79493c3ccf06a3aeb72017a96ca3dfd166bc16b Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Wed, 22 Mar 2023 01:28:31 +0200 Subject: net: enetc: fix aggregate RMON counters not showing the ranges When running "ethtool -S eno0 --groups rmon" without an explicit "--src emac|pmac" argument, the kernel will not report rx-rmon-etherStatsPkts64to64Octets, rx-rmon-etherStatsPkts65to127Octets, etc. This is because on ETHTOOL_MAC_STATS_SRC_AGGREGATE, we do not populate the "ranges" argument. ocelot_port_get_rmon_stats() does things differently and things work there. I had forgotten to make sure that the code is structured the same way in both drivers, so do that now. Fixes: cf52bd238b75 ("net: enetc: add support for MAC Merge statistics counters") Signed-off-by: Vladimir Oltean Reviewed-by: Simon Horman Link: https://lore.kernel.org/r/20230321232831.1200905-1-vladimir.oltean@nxp.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/freescale/enetc/enetc_ethtool.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c index bca68edfbe9c..da9d4b310fcd 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c +++ b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c @@ -370,8 +370,7 @@ static const struct ethtool_rmon_hist_range enetc_rmon_ranges[] = { }; static void enetc_rmon_stats(struct enetc_hw *hw, int mac, - struct ethtool_rmon_stats *s, - const struct ethtool_rmon_hist_range **ranges) + struct ethtool_rmon_stats *s) { s->undersize_pkts = enetc_port_rd(hw, ENETC_PM_RUND(mac)); s->oversize_pkts = enetc_port_rd(hw, ENETC_PM_ROVR(mac)); @@ -393,8 +392,6 @@ static void enetc_rmon_stats(struct enetc_hw *hw, int mac, s->hist_tx[4] = enetc_port_rd(hw, ENETC_PM_T1023(mac)); s->hist_tx[5] = enetc_port_rd(hw, ENETC_PM_T1522(mac)); s->hist_tx[6] = enetc_port_rd(hw, ENETC_PM_T1523X(mac)); - - *ranges = enetc_rmon_ranges; } static void enetc_get_eth_mac_stats(struct net_device *ndev, @@ -447,13 +444,15 @@ static void enetc_get_rmon_stats(struct net_device *ndev, struct enetc_hw *hw = &priv->si->hw; struct enetc_si *si = priv->si; + *ranges = enetc_rmon_ranges; + switch (rmon_stats->src) { case ETHTOOL_MAC_STATS_SRC_EMAC: - enetc_rmon_stats(hw, 0, rmon_stats, ranges); + enetc_rmon_stats(hw, 0, rmon_stats); break; case ETHTOOL_MAC_STATS_SRC_PMAC: if (si->hw_features & ENETC_SI_F_QBU) - enetc_rmon_stats(hw, 1, rmon_stats, ranges); + enetc_rmon_stats(hw, 1, rmon_stats); break; case ETHTOOL_MAC_STATS_SRC_AGGREGATE: ethtool_aggregate_rmon_stats(ndev, rmon_stats); -- cgit From 758d29fb3a8b3c756b4e4e0aa9b32ca8cfaf3feb Mon Sep 17 00:00:00 2001 From: Donald Hunter Date: Sun, 19 Mar 2023 19:37:58 +0000 Subject: tools: ynl: Fix genlmsg header encoding formats The pack strings use 'b' signed char for cmd and version but struct genlmsghdr defines them as unsigned char. Use 'B' instead. Fixes: 4e4480e89c47 ("tools: ynl: move the cli and netlink code around") Signed-off-by: Donald Hunter Link: https://lore.kernel.org/r/20230319193803.97453-1-donald.hunter@gmail.com Signed-off-by: Jakub Kicinski --- tools/net/ynl/lib/ynl.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/net/ynl/lib/ynl.py b/tools/net/ynl/lib/ynl.py index 90764a83c646..32536e1f9064 100644 --- a/tools/net/ynl/lib/ynl.py +++ b/tools/net/ynl/lib/ynl.py @@ -200,7 +200,7 @@ def _genl_msg(nl_type, nl_flags, genl_cmd, genl_version, seq=None): if seq is None: seq = random.randint(1, 1024) nlmsg = struct.pack("HHII", nl_type, nl_flags, seq, 0) - genlmsg = struct.pack("bbH", genl_cmd, genl_version, 0) + genlmsg = struct.pack("BBH", genl_cmd, genl_version, 0) return nlmsg + genlmsg @@ -264,7 +264,7 @@ class GenlMsg: self.hdr = nl_msg.raw[0:4] self.raw = nl_msg.raw[4:] - self.genl_cmd, self.genl_version, _ = struct.unpack("bbH", self.hdr) + self.genl_cmd, self.genl_version, _ = struct.unpack("BBH", self.hdr) self.raw_attrs = NlAttrs(self.raw) @@ -358,7 +358,7 @@ class YnlFamily(SpecFamily): raw >>= 1 i += 1 else: - value = enum['entries'][raw - i] + value = enum.entries_by_val[raw - i].name rsp[attr_spec['name']] = value def _decode(self, attrs, space): -- cgit From 68c3e4fc8628b1487c965aabb29207249657eb5f Mon Sep 17 00:00:00 2001 From: Joshua Washington Date: Tue, 21 Mar 2023 10:23:32 -0700 Subject: gve: Cache link_speed value from device The link speed is never changed for the uptime of a VM, and the current implementation sends an admin queue command for each call. Admin queue command invocations have nontrivial overhead (e.g., VM exits), which can be disruptive to users if triggered frequently. Our telemetry data shows that there are VMs that make frequent calls to this admin queue command. Caching the result of the original admin queue command would eliminate the need to send multiple admin queue commands on subsequent calls to retrieve link speed. Fixes: 7e074d5a76ca ("gve: Enable Link Speed Reporting in the driver.") Signed-off-by: Joshua Washington Reviewed-by: Simon Horman Link: https://lore.kernel.org/r/20230321172332.91678-1-joshwash@google.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/google/gve/gve_ethtool.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/google/gve/gve_ethtool.c b/drivers/net/ethernet/google/gve/gve_ethtool.c index ce574d097e28..5f81470843b4 100644 --- a/drivers/net/ethernet/google/gve/gve_ethtool.c +++ b/drivers/net/ethernet/google/gve/gve_ethtool.c @@ -537,7 +537,10 @@ static int gve_get_link_ksettings(struct net_device *netdev, struct ethtool_link_ksettings *cmd) { struct gve_priv *priv = netdev_priv(netdev); - int err = gve_adminq_report_link_speed(priv); + int err = 0; + + if (priv->link_speed == 0) + err = gve_adminq_report_link_speed(priv); cmd->base.speed = priv->link_speed; return err; -- cgit From 8eac0095de355ee31e1b014f79f83d2cd62a2d04 Mon Sep 17 00:00:00 2001 From: Grant Grundler Date: Tue, 21 Mar 2023 10:05:39 -0700 Subject: net: asix: fix modprobe "sysfs: cannot create duplicate filename" "modprobe asix ; rmmod asix ; modprobe asix" fails with: sysfs: cannot create duplicate filename \ '/devices/virtual/mdio_bus/usb-003:004' Issue was originally reported by Anton Lundin on 2022-06-22 (link below). Chrome OS team hit the same issue in Feb, 2023 when trying to find work arounds for other issues with AX88172 devices. The use of devm_mdiobus_register() with usbnet devices results in the MDIO data being associated with the USB device. When the asix driver is unloaded, the USB device continues to exist and the corresponding "mdiobus_unregister()" is NOT called until the USB device is unplugged or unauthorized. So the next "modprobe asix" will fail because the MDIO phy sysfs attributes still exist. The 'easy' (from a design PoV) fix is to use the non-devm variants of mdiobus_* functions and explicitly manage this use in the asix_bind and asix_unbind function calls. I've not explored trying to fix usbnet initialization so devm_* stuff will work. Fixes: e532a096be0e5 ("net: usb: asix: ax88772: add phylib support") Reported-by: Anton Lundin Link: https://lore.kernel.org/netdev/20220623063649.GD23685@pengutronix.de/T/ Tested-by: Eizan Miyamoto Signed-off-by: Grant Grundler Link: https://lore.kernel.org/r/20230321170539.732147-1-grundler@chromium.org Signed-off-by: Jakub Kicinski --- drivers/net/usb/asix_devices.c | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/drivers/net/usb/asix_devices.c b/drivers/net/usb/asix_devices.c index 743cbf5d662c..f7cff58fe044 100644 --- a/drivers/net/usb/asix_devices.c +++ b/drivers/net/usb/asix_devices.c @@ -666,8 +666,9 @@ static int asix_resume(struct usb_interface *intf) static int ax88772_init_mdio(struct usbnet *dev) { struct asix_common_private *priv = dev->driver_priv; + int ret; - priv->mdio = devm_mdiobus_alloc(&dev->udev->dev); + priv->mdio = mdiobus_alloc(); if (!priv->mdio) return -ENOMEM; @@ -679,7 +680,20 @@ static int ax88772_init_mdio(struct usbnet *dev) snprintf(priv->mdio->id, MII_BUS_ID_SIZE, "usb-%03d:%03d", dev->udev->bus->busnum, dev->udev->devnum); - return devm_mdiobus_register(&dev->udev->dev, priv->mdio); + ret = mdiobus_register(priv->mdio); + if (ret) { + netdev_err(dev->net, "Could not register MDIO bus (err %d)\n", ret); + mdiobus_free(priv->mdio); + priv->mdio = NULL; + } + + return ret; +} + +static void ax88772_mdio_unregister(struct asix_common_private *priv) +{ + mdiobus_unregister(priv->mdio); + mdiobus_free(priv->mdio); } static int ax88772_init_phy(struct usbnet *dev) @@ -896,16 +910,23 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf) ret = ax88772_init_mdio(dev); if (ret) - return ret; + goto mdio_err; ret = ax88772_phylink_setup(dev); if (ret) - return ret; + goto phylink_err; ret = ax88772_init_phy(dev); if (ret) - phylink_destroy(priv->phylink); + goto initphy_err; + return 0; + +initphy_err: + phylink_destroy(priv->phylink); +phylink_err: + ax88772_mdio_unregister(priv); +mdio_err: return ret; } @@ -926,6 +947,7 @@ static void ax88772_unbind(struct usbnet *dev, struct usb_interface *intf) phylink_disconnect_phy(priv->phylink); rtnl_unlock(); phylink_destroy(priv->phylink); + ax88772_mdio_unregister(priv); asix_rx_fixup_common_free(dev->driver_priv); } -- cgit From 8f058a6ef99f0b88a177b58cc46a44ff5112e40a Mon Sep 17 00:00:00 2001 From: Arınç ÜNAL Date: Mon, 20 Mar 2023 22:05:18 +0300 Subject: net: dsa: mt7530: move enabling disabling core clock to mt7530_pll_setup() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Split the code that enables and disables TRGMII clocks and core clock. Move enabling and disabling core clock to mt7530_pll_setup() as it's supposed to be run there. Add 20 ms delay before enabling the core clock as seen on the U-Boot MediaTek ethernet driver. Change the comment for enabling and disabling TRGMII clocks as the code seems to affect both TXC and RXC. Tested rgmii and trgmii modes of port 6 and rgmii mode of port 5 on MCM MT7530 on MT7621AT Unielec U7621-06 and standalone MT7530 on MT7623NI Bananapi BPI-R2. Fixes: b8f126a8d543 ("net-next: dsa: add dsa support for Mediatek MT7530 switch") Link: https://source.denx.de/u-boot/u-boot/-/blob/29a48bf9ccba45a5e560bb564bbe76e42629325f/drivers/net/mtk_eth.c#L589 Tested-by: Arınç ÜNAL Signed-off-by: Arınç ÜNAL Link: https://lore.kernel.org/r/20230320190520.124513-1-arinc.unal@arinc9.com Signed-off-by: Jakub Kicinski --- drivers/net/dsa/mt7530.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c index c2d81b7a429d..d4a559007973 100644 --- a/drivers/net/dsa/mt7530.c +++ b/drivers/net/dsa/mt7530.c @@ -396,6 +396,9 @@ mt7530_fdb_write(struct mt7530_priv *priv, u16 vid, /* Set up switch core clock for MT7530 */ static void mt7530_pll_setup(struct mt7530_priv *priv) { + /* Disable core clock */ + core_clear(priv, CORE_TRGMII_GSW_CLK_CG, REG_GSWCK_EN); + /* Disable PLL */ core_write(priv, CORE_GSWPLL_GRP1, 0); @@ -409,6 +412,11 @@ static void mt7530_pll_setup(struct mt7530_priv *priv) RG_GSWPLL_EN_PRE | RG_GSWPLL_POSDIV_200M(2) | RG_GSWPLL_FBKDIV_200M(32)); + + udelay(20); + + /* Enable core clock */ + core_set(priv, CORE_TRGMII_GSW_CLK_CG, REG_GSWCK_EN); } /* Setup TX circuit including relevant PAD and driving */ @@ -466,9 +474,8 @@ mt7530_pad_clk_setup(struct dsa_switch *ds, phy_interface_t interface) mt7530_write(priv, MT7530_TRGMII_TD_ODT(i), TD_DM_DRVP(8) | TD_DM_DRVN(8)); - /* Disable MT7530 core and TRGMII Tx clocks */ - core_clear(priv, CORE_TRGMII_GSW_CLK_CG, - REG_GSWCK_EN | REG_TRGMIICK_EN); + /* Disable the MT7530 TRGMII clocks */ + core_clear(priv, CORE_TRGMII_GSW_CLK_CG, REG_TRGMIICK_EN); /* Setup the MT7530 TRGMII Tx Clock */ core_write(priv, CORE_PLL_GROUP5, RG_LCDDS_PCW_NCPO1(ncpo1)); @@ -485,9 +492,8 @@ mt7530_pad_clk_setup(struct dsa_switch *ds, phy_interface_t interface) RG_LCDDS_PCW_NCPO_CHG | RG_LCCDS_C(3) | RG_LCDDS_PWDB | RG_LCDDS_ISO_EN); - /* Enable MT7530 core and TRGMII Tx clocks */ - core_set(priv, CORE_TRGMII_GSW_CLK_CG, - REG_GSWCK_EN | REG_TRGMIICK_EN); + /* Enable the MT7530 TRGMII clocks */ + core_set(priv, CORE_TRGMII_GSW_CLK_CG, REG_TRGMIICK_EN); } else { for (i = 0 ; i < NUM_TRGMII_CTRL; i++) mt7530_rmw(priv, MT7530_TRGMII_RD(i), -- cgit From fdcc8ccd823740c18e803b886cec461bc0e64201 Mon Sep 17 00:00:00 2001 From: Arınç ÜNAL Date: Mon, 20 Mar 2023 22:05:19 +0300 Subject: net: dsa: mt7530: move lowering TRGMII driving to mt7530_setup() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move lowering the TRGMII Tx clock driving to mt7530_setup(), after setting the core clock, as seen on the U-Boot MediaTek ethernet driver. Move the code which looks like it lowers the TRGMII Rx clock driving to after the TRGMII Tx clock driving is lowered. This is run after lowering the Tx clock driving on the U-Boot MediaTek ethernet driver as well. This way, the switch should consume less power regardless of port 6 being used. Update the comment explaining mt7530_pad_clk_setup(). Tested rgmii and trgmii modes of port 6 and rgmii mode of port 5 on MCM MT7530 on MT7621AT Unielec U7621-06 and standalone MT7530 on MT7623NI Bananapi BPI-R2. Fixes: b8f126a8d543 ("net-next: dsa: add dsa support for Mediatek MT7530 switch") Link: https://source.denx.de/u-boot/u-boot/-/blob/29a48bf9ccba45a5e560bb564bbe76e42629325f/drivers/net/mtk_eth.c#L682 Tested-by: Arınç ÜNAL Signed-off-by: Arınç ÜNAL Link: https://lore.kernel.org/r/20230320190520.124513-2-arinc.unal@arinc9.com Signed-off-by: Jakub Kicinski --- drivers/net/dsa/mt7530.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c index d4a559007973..8831bd409a40 100644 --- a/drivers/net/dsa/mt7530.c +++ b/drivers/net/dsa/mt7530.c @@ -419,12 +419,12 @@ static void mt7530_pll_setup(struct mt7530_priv *priv) core_set(priv, CORE_TRGMII_GSW_CLK_CG, REG_GSWCK_EN); } -/* Setup TX circuit including relevant PAD and driving */ +/* Setup port 6 interface mode and TRGMII TX circuit */ static int mt7530_pad_clk_setup(struct dsa_switch *ds, phy_interface_t interface) { struct mt7530_priv *priv = ds->priv; - u32 ncpo1, ssc_delta, trgint, i, xtal; + u32 ncpo1, ssc_delta, trgint, xtal; xtal = mt7530_read(priv, MT7530_MHWTRAP) & HWTRAP_XTAL_MASK; @@ -469,11 +469,6 @@ mt7530_pad_clk_setup(struct dsa_switch *ds, phy_interface_t interface) P6_INTF_MODE(trgint)); if (trgint) { - /* Lower Tx Driving for TRGMII path */ - for (i = 0 ; i < NUM_TRGMII_CTRL ; i++) - mt7530_write(priv, MT7530_TRGMII_TD_ODT(i), - TD_DM_DRVP(8) | TD_DM_DRVN(8)); - /* Disable the MT7530 TRGMII clocks */ core_clear(priv, CORE_TRGMII_GSW_CLK_CG, REG_TRGMIICK_EN); @@ -494,10 +489,6 @@ mt7530_pad_clk_setup(struct dsa_switch *ds, phy_interface_t interface) /* Enable the MT7530 TRGMII clocks */ core_set(priv, CORE_TRGMII_GSW_CLK_CG, REG_TRGMIICK_EN); - } else { - for (i = 0 ; i < NUM_TRGMII_CTRL; i++) - mt7530_rmw(priv, MT7530_TRGMII_RD(i), - RD_TAP_MASK, RD_TAP(16)); } return 0; @@ -2207,6 +2198,15 @@ mt7530_setup(struct dsa_switch *ds) mt7530_pll_setup(priv); + /* Lower Tx driving for TRGMII path */ + for (i = 0; i < NUM_TRGMII_CTRL; i++) + mt7530_write(priv, MT7530_TRGMII_TD_ODT(i), + TD_DM_DRVP(8) | TD_DM_DRVN(8)); + + for (i = 0; i < NUM_TRGMII_CTRL; i++) + mt7530_rmw(priv, MT7530_TRGMII_RD(i), + RD_TAP_MASK, RD_TAP(16)); + /* Enable port 6 */ val = mt7530_read(priv, MT7530_MHWTRAP); val &= ~MHWTRAP_P6_DIS & ~MHWTRAP_PHY_ACCESS; -- cgit From 407b508bdd70b6848993843d96ed49ac4108fb52 Mon Sep 17 00:00:00 2001 From: Arınç ÜNAL Date: Mon, 20 Mar 2023 22:05:20 +0300 Subject: net: dsa: mt7530: move setting ssc_delta to PHY_INTERFACE_MODE_TRGMII case MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move setting the ssc_delta variable to under the PHY_INTERFACE_MODE_TRGMII case as it's only needed when trgmii is used. Fixes: b8f126a8d543 ("net-next: dsa: add dsa support for Mediatek MT7530 switch") Signed-off-by: Arınç ÜNAL Link: https://lore.kernel.org/r/20230320190520.124513-3-arinc.unal@arinc9.com Signed-off-by: Jakub Kicinski --- drivers/net/dsa/mt7530.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c index 8831bd409a40..02410ac439b7 100644 --- a/drivers/net/dsa/mt7530.c +++ b/drivers/net/dsa/mt7530.c @@ -441,6 +441,10 @@ mt7530_pad_clk_setup(struct dsa_switch *ds, phy_interface_t interface) break; case PHY_INTERFACE_MODE_TRGMII: trgint = 1; + if (xtal == HWTRAP_XTAL_25MHZ) + ssc_delta = 0x57; + else + ssc_delta = 0x87; if (priv->id == ID_MT7621) { /* PLL frequency: 150MHz: 1.2GBit */ if (xtal == HWTRAP_XTAL_40MHZ) @@ -460,11 +464,6 @@ mt7530_pad_clk_setup(struct dsa_switch *ds, phy_interface_t interface) return -EINVAL; } - if (xtal == HWTRAP_XTAL_25MHZ) - ssc_delta = 0x57; - else - ssc_delta = 0x87; - mt7530_rmw(priv, MT7530_P6ECR, P6_INTF_MODE_MASK, P6_INTF_MODE(trgint)); -- cgit From b1de5c78ebe9858ccec9d49af2f76724f1d47e3e Mon Sep 17 00:00:00 2001 From: Liang He Date: Wed, 22 Mar 2023 14:20:57 +0800 Subject: net: mdio: thunder: Add missing fwnode_handle_put() In device_for_each_child_node(), we should add fwnode_handle_put() when break out of the iteration device_for_each_child_node() as it will automatically increase and decrease the refcounter. Fixes: 379d7ac7ca31 ("phy: mdio-thunder: Add driver for Cavium Thunder SoC MDIO buses.") Signed-off-by: Liang He Signed-off-by: David S. Miller --- drivers/net/mdio/mdio-thunder.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/mdio/mdio-thunder.c b/drivers/net/mdio/mdio-thunder.c index 3847ee92c109..6067d96b2b7b 100644 --- a/drivers/net/mdio/mdio-thunder.c +++ b/drivers/net/mdio/mdio-thunder.c @@ -106,6 +106,7 @@ static int thunder_mdiobus_pci_probe(struct pci_dev *pdev, if (i >= ARRAY_SIZE(nexus->buses)) break; } + fwnode_handle_put(fwn); return 0; err_release_regions: -- cgit From 260595b439776c473cc248f0de63fe78d964d849 Mon Sep 17 00:00:00 2001 From: Bob Peterson Date: Thu, 23 Mar 2023 12:26:02 -0400 Subject: Reinstate "GFS2: free disk inode which is deleted by remote node -V2" It turns out that reverting commit 970343cd4904 ("GFS2: free disk inode which is deleted by remote node -V2") causes a regression related to evicting inodes that were unlinked on a different cluster node. We could also have simply added a call to d_mark_dontcache() to function gfs2_try_evict(), but the original pre-revert code is better tested and proven. This reverts commit 445cb1277e10d7e19b631ef8a64aa3f055df377d. Signed-off-by: Bob Peterson Signed-off-by: Andreas Gruenbacher --- fs/gfs2/dentry.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/fs/gfs2/dentry.c b/fs/gfs2/dentry.c index 6fe9ca253b70..2e215e8c3c88 100644 --- a/fs/gfs2/dentry.c +++ b/fs/gfs2/dentry.c @@ -83,8 +83,26 @@ static int gfs2_dhash(const struct dentry *dentry, struct qstr *str) return 0; } +static int gfs2_dentry_delete(const struct dentry *dentry) +{ + struct gfs2_inode *ginode; + + if (d_really_is_negative(dentry)) + return 0; + + ginode = GFS2_I(d_inode(dentry)); + if (!gfs2_holder_initialized(&ginode->i_iopen_gh)) + return 0; + + if (test_bit(GLF_DEMOTE, &ginode->i_iopen_gh.gh_gl->gl_flags)) + return 1; + + return 0; +} + const struct dentry_operations gfs2_dops = { .d_revalidate = gfs2_drevalidate, .d_hash = gfs2_dhash, + .d_delete = gfs2_dentry_delete, }; -- cgit From 902160cdb2bf4d23cd75f43ed0597ddf0134bb89 Mon Sep 17 00:00:00 2001 From: Kiran K Date: Wed, 8 Mar 2023 13:28:37 +0530 Subject: Bluetooth: btinel: Check ACPI handle for NULL before accessing Older platforms and Virtual platforms which doesn't have support for bluetooth device in ACPI firmware will not have valid ACPI handle. Check for validity of handle before accessing. dmesg log from simics environment (virtual platform): BUG: unable to handle kernel NULL pointer dereference at 0000000000000018 IP: acpi_ns_walk_namespace+0x5c/0x278 PGD 0 P4D 0 Oops: 0000 [#1] SMP PTI Modules linked in: bnep intel_powerclamp coretemp kvm_intel kvm irqbypass intel_cstate input_leds joydev serio_raw mac_hid btusb(OE) btintel(OE) bluetooth(OE) lpc_ich compat(OE) ecdh_generic i7core_edac i5500_temp shpchp binfmt_misc sch_fq_codel parport_pc ppdev lp parport ip_tables x_tables autofs4 hid_generic usbhid hid e1000e psmouse ahci pata_acpi libahci ptp pps_core floppy CPU: 0 PID: 35 Comm: kworker/u3:0 Tainted: G OE 4.15.0-140-generic #144-Ubuntu Hardware name: Simics Simics, BIOS Simics 01/01/2011 Workqueue: hci0 hci_power_on [bluetooth] RIP: 0010:acpi_ns_walk_namespace+0x5c/0x278 RSP: 0000:ffffaa9c0049bba8 EFLAGS: 00010246 RAX: 0000000000000001 RBX: 0000000000001001 RCX: 0000000000000010 RDX: ffffffff92ea7e27 RSI: ffffffff92ea7e10 RDI: 00000000000000c8 RBP: ffffaa9c0049bbf8 R08: 0000000000000000 R09: ffffffffc05b39d0 R10: 0000000000000000 R11: 0000000000000001 R12: 0000000000000001 R13: 0000000000000000 R14: ffffffffc05b39d0 R15: ffffaa9c0049bc70 FS: 0000000000000000(0000) GS:ffff8be73fc00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000000000000018 CR3: 0000000075f0e000 CR4: 00000000000006f0 Fixes: 294d749b5df5 ("Bluetooth: btintel: Iterate only bluetooth device ACPI entries") Signed-off-by: Kiran K Signed-off-by: Luiz Augusto von Dentz --- drivers/bluetooth/btintel.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c index e8d4b59e89c5..af774688f1c0 100644 --- a/drivers/bluetooth/btintel.c +++ b/drivers/bluetooth/btintel.c @@ -2326,6 +2326,7 @@ static void btintel_set_ppag(struct hci_dev *hdev, struct intel_version_tlv *ver struct btintel_ppag ppag; struct sk_buff *skb; struct btintel_loc_aware_reg ppag_cmd; + acpi_handle handle; /* PPAG is not supported if CRF is HrP2, Jfp2, JfP1 */ switch (ver->cnvr_top & 0xFFF) { @@ -2335,12 +2336,18 @@ static void btintel_set_ppag(struct hci_dev *hdev, struct intel_version_tlv *ver return; } + handle = ACPI_HANDLE(GET_HCIDEV_DEV(hdev)); + if (!handle) { + bt_dev_info(hdev, "No support for BT device in ACPI firmware"); + return; + } + memset(&ppag, 0, sizeof(ppag)); ppag.hdev = hdev; ppag.status = AE_NOT_FOUND; - acpi_walk_namespace(ACPI_TYPE_PACKAGE, ACPI_HANDLE(GET_HCIDEV_DEV(hdev)), - 1, NULL, btintel_ppag_callback, &ppag, NULL); + acpi_walk_namespace(ACPI_TYPE_PACKAGE, handle, 1, NULL, + btintel_ppag_callback, &ppag, NULL); if (ACPI_FAILURE(ppag.status)) { if (ppag.status == AE_NOT_FOUND) { -- cgit From 5d44ab9e204200a78ad55cdf185aa2bb109b5950 Mon Sep 17 00:00:00 2001 From: Stephan Gerhold Date: Wed, 8 Mar 2023 14:31:55 +0100 Subject: Bluetooth: btqcomsmd: Fix command timeout after setting BD address On most devices using the btqcomsmd driver (e.g. the DragonBoard 410c and other devices based on the Qualcomm MSM8916/MSM8909/... SoCs) the Bluetooth firmware seems to become unresponsive for a while after setting the BD address. On recent kernel versions (at least 5.17+) this often causes timeouts for subsequent commands, e.g. the HCI reset sent by the Bluetooth core during initialization: Bluetooth: hci0: Opcode 0x c03 failed: -110 Unfortunately this behavior does not seem to be documented anywhere. Experimentation suggests that the minimum necessary delay to avoid the problem is ~150us. However, to be sure add a sleep for > 1ms in case it is a bit longer on other firmware versions. Older kernel versions are likely also affected, although perhaps with slightly different errors or less probability. Side effects can easily hide the issue in most cases, e.g. unrelated incoming interrupts that cause the necessary delay. Fixes: 1511cc750c3d ("Bluetooth: Introduce Qualcomm WCNSS SMD based HCI driver") Signed-off-by: Stephan Gerhold Signed-off-by: Luiz Augusto von Dentz --- drivers/bluetooth/btqcomsmd.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/drivers/bluetooth/btqcomsmd.c b/drivers/bluetooth/btqcomsmd.c index 2acb719e596f..11c7e04bf394 100644 --- a/drivers/bluetooth/btqcomsmd.c +++ b/drivers/bluetooth/btqcomsmd.c @@ -122,6 +122,21 @@ static int btqcomsmd_setup(struct hci_dev *hdev) return 0; } +static int btqcomsmd_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr) +{ + int ret; + + ret = qca_set_bdaddr_rome(hdev, bdaddr); + if (ret) + return ret; + + /* The firmware stops responding for a while after setting the bdaddr, + * causing timeouts for subsequent commands. Sleep a bit to avoid this. + */ + usleep_range(1000, 10000); + return 0; +} + static int btqcomsmd_probe(struct platform_device *pdev) { struct btqcomsmd *btq; @@ -162,7 +177,7 @@ static int btqcomsmd_probe(struct platform_device *pdev) hdev->close = btqcomsmd_close; hdev->send = btqcomsmd_send; hdev->setup = btqcomsmd_setup; - hdev->set_bdaddr = qca_set_bdaddr_rome; + hdev->set_bdaddr = btqcomsmd_set_bdaddr; ret = hci_register_dev(hdev); if (ret < 0) -- cgit From 9aa9d9473f1550d1936c31259720b3f1f4690576 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Wed, 8 Mar 2023 14:20:34 -0800 Subject: Bluetooth: L2CAP: Fix responding with wrong PDU type L2CAP_ECRED_CONN_REQ shall be responded with L2CAP_ECRED_CONN_RSP not L2CAP_LE_CONN_RSP: L2CAP LE EATT Server - Reject - run Listening for connections New client connection with handle 0x002a Sending L2CAP Request from client Client received response code 0x15 Unexpected L2CAP response code (expected 0x18) L2CAP LE EATT Server - Reject - test failed > ACL Data RX: Handle 42 flags 0x02 dlen 26 LE L2CAP: Enhanced Credit Connection Request (0x17) ident 1 len 18 PSM: 39 (0x0027) MTU: 64 MPS: 64 Credits: 5 Source CID: 65 Source CID: 66 Source CID: 67 Source CID: 68 Source CID: 69 < ACL Data TX: Handle 42 flags 0x00 dlen 16 LE L2CAP: LE Connection Response (0x15) ident 1 len 8 invalid size 00 00 00 00 00 00 06 00 L2CAP LE EATT Server - Reject - run Listening for connections New client connection with handle 0x002a Sending L2CAP Request from client Client received response code 0x18 L2CAP LE EATT Server - Reject - test passed Fixes: 15f02b910562 ("Bluetooth: L2CAP: Add initial code for Enhanced Credit Based Mode") Signed-off-by: Luiz Augusto von Dentz --- net/bluetooth/l2cap_core.c | 117 ++++++++++++++++++++++++++++++--------------- 1 file changed, 79 insertions(+), 38 deletions(-) diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index adfc3ea06d08..49926f59cc12 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -708,6 +708,17 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err) } EXPORT_SYMBOL_GPL(l2cap_chan_del); +static void __l2cap_chan_list_id(struct l2cap_conn *conn, u16 id, + l2cap_chan_func_t func, void *data) +{ + struct l2cap_chan *chan, *l; + + list_for_each_entry_safe(chan, l, &conn->chan_l, list) { + if (chan->ident == id) + func(chan, data); + } +} + static void __l2cap_chan_list(struct l2cap_conn *conn, l2cap_chan_func_t func, void *data) { @@ -775,23 +786,9 @@ static void l2cap_chan_le_connect_reject(struct l2cap_chan *chan) static void l2cap_chan_ecred_connect_reject(struct l2cap_chan *chan) { - struct l2cap_conn *conn = chan->conn; - struct l2cap_ecred_conn_rsp rsp; - u16 result; - - if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) - result = L2CAP_CR_LE_AUTHORIZATION; - else - result = L2CAP_CR_LE_BAD_PSM; - l2cap_state_change(chan, BT_DISCONN); - memset(&rsp, 0, sizeof(rsp)); - - rsp.result = cpu_to_le16(result); - - l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_RSP, sizeof(rsp), - &rsp); + __l2cap_ecred_conn_rsp_defer(chan); } static void l2cap_chan_connect_reject(struct l2cap_chan *chan) @@ -846,7 +843,7 @@ void l2cap_chan_close(struct l2cap_chan *chan, int reason) break; case L2CAP_MODE_EXT_FLOWCTL: l2cap_chan_ecred_connect_reject(chan); - break; + return; } } } @@ -3938,43 +3935,86 @@ void __l2cap_le_connect_rsp_defer(struct l2cap_chan *chan) &rsp); } -void __l2cap_ecred_conn_rsp_defer(struct l2cap_chan *chan) +static void l2cap_ecred_list_defer(struct l2cap_chan *chan, void *data) { + int *result = data; + + if (*result || test_bit(FLAG_ECRED_CONN_REQ_SENT, &chan->flags)) + return; + + switch (chan->state) { + case BT_CONNECT2: + /* If channel still pending accept add to result */ + (*result)++; + return; + case BT_CONNECTED: + return; + default: + /* If not connected or pending accept it has been refused */ + *result = -ECONNREFUSED; + return; + } +} + +struct l2cap_ecred_rsp_data { struct { struct l2cap_ecred_conn_rsp rsp; - __le16 dcid[5]; + __le16 scid[L2CAP_ECRED_MAX_CID]; } __packed pdu; + int count; +}; + +static void l2cap_ecred_rsp_defer(struct l2cap_chan *chan, void *data) +{ + struct l2cap_ecred_rsp_data *rsp = data; + + if (test_bit(FLAG_ECRED_CONN_REQ_SENT, &chan->flags)) + return; + + /* Reset ident so only one response is sent */ + chan->ident = 0; + + /* Include all channels pending with the same ident */ + if (!rsp->pdu.rsp.result) + rsp->pdu.rsp.dcid[rsp->count++] = cpu_to_le16(chan->scid); + else + l2cap_chan_del(chan, ECONNRESET); +} + +void __l2cap_ecred_conn_rsp_defer(struct l2cap_chan *chan) +{ struct l2cap_conn *conn = chan->conn; - u16 ident = chan->ident; - int i = 0; + struct l2cap_ecred_rsp_data data; + u16 id = chan->ident; + int result = 0; - if (!ident) + if (!id) return; - BT_DBG("chan %p ident %d", chan, ident); + BT_DBG("chan %p id %d", chan, id); - pdu.rsp.mtu = cpu_to_le16(chan->imtu); - pdu.rsp.mps = cpu_to_le16(chan->mps); - pdu.rsp.credits = cpu_to_le16(chan->rx_credits); - pdu.rsp.result = cpu_to_le16(L2CAP_CR_LE_SUCCESS); + memset(&data, 0, sizeof(data)); - mutex_lock(&conn->chan_lock); + data.pdu.rsp.mtu = cpu_to_le16(chan->imtu); + data.pdu.rsp.mps = cpu_to_le16(chan->mps); + data.pdu.rsp.credits = cpu_to_le16(chan->rx_credits); + data.pdu.rsp.result = cpu_to_le16(L2CAP_CR_LE_SUCCESS); - list_for_each_entry(chan, &conn->chan_l, list) { - if (chan->ident != ident) - continue; + /* Verify that all channels are ready */ + __l2cap_chan_list_id(conn, id, l2cap_ecred_list_defer, &result); - /* Reset ident so only one response is sent */ - chan->ident = 0; + if (result > 0) + return; - /* Include all channels pending with the same ident */ - pdu.dcid[i++] = cpu_to_le16(chan->scid); - } + if (result < 0) + data.pdu.rsp.result = cpu_to_le16(L2CAP_CR_LE_AUTHORIZATION); - mutex_unlock(&conn->chan_lock); + /* Build response */ + __l2cap_chan_list_id(conn, id, l2cap_ecred_rsp_defer, &data); - l2cap_send_cmd(conn, ident, L2CAP_ECRED_CONN_RSP, - sizeof(pdu.rsp) + i * sizeof(__le16), &pdu); + l2cap_send_cmd(conn, id, L2CAP_ECRED_CONN_RSP, + sizeof(data.pdu.rsp) + (data.count * sizeof(__le16)), + &data.pdu); } void __l2cap_connect_rsp_defer(struct l2cap_chan *chan) @@ -6078,6 +6118,7 @@ static inline int l2cap_ecred_conn_req(struct l2cap_conn *conn, __set_chan_timer(chan, chan->ops->get_sndtimeo(chan)); chan->ident = cmd->ident; + chan->mode = L2CAP_MODE_EXT_FLOWCTL; if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { l2cap_state_change(chan, BT_CONNECT2); -- cgit From 1e9ac114c4428fdb7ff4635b45d4f46017e8916f Mon Sep 17 00:00:00 2001 From: Zheng Wang Date: Thu, 9 Mar 2023 16:07:39 +0800 Subject: Bluetooth: btsdio: fix use after free bug in btsdio_remove due to unfinished work In btsdio_probe, &data->work was bound with btsdio_work.In btsdio_send_frame, it was started by schedule_work. If we call btsdio_remove with an unfinished job, there may be a race condition and cause UAF bug on hdev. Fixes: ddbaf13e3609 ("[Bluetooth] Add generic driver for Bluetooth SDIO devices") Signed-off-by: Zheng Wang Signed-off-by: Luiz Augusto von Dentz --- drivers/bluetooth/btsdio.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/bluetooth/btsdio.c b/drivers/bluetooth/btsdio.c index 795be33f2892..02893600db39 100644 --- a/drivers/bluetooth/btsdio.c +++ b/drivers/bluetooth/btsdio.c @@ -354,6 +354,7 @@ static void btsdio_remove(struct sdio_func *func) BT_DBG("func %p", func); + cancel_work_sync(&data->work); if (!data) return; -- cgit From 1a0291f81529e8044fb29845a0196ba47af894ce Mon Sep 17 00:00:00 2001 From: Howard Chung Date: Thu, 16 Mar 2023 18:11:38 +0800 Subject: Bluetooth: mgmt: Fix MGMT add advmon with RSSI command The MGMT command: MGMT_OP_ADD_ADV_PATTERNS_MONITOR_RSSI uses variable length argument. This causes host not able to register advmon with rssi. This patch has been locally tested by adding monitor with rssi via btmgmt on a kernel 6.1 machine. Reviewed-by: Archie Pusaka Fixes: b338d91703fa ("Bluetooth: Implement support for Mesh") Signed-off-by: Howard Chung Signed-off-by: Luiz Augusto von Dentz --- net/bluetooth/mgmt.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 39589f864ea7..249dc6777fb4 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -9357,7 +9357,8 @@ static const struct hci_mgmt_handler mgmt_handlers[] = { { add_ext_adv_data, MGMT_ADD_EXT_ADV_DATA_SIZE, HCI_MGMT_VAR_LEN }, { add_adv_patterns_monitor_rssi, - MGMT_ADD_ADV_PATTERNS_MONITOR_RSSI_SIZE }, + MGMT_ADD_ADV_PATTERNS_MONITOR_RSSI_SIZE, + HCI_MGMT_VAR_LEN }, { set_mesh, MGMT_SET_MESH_RECEIVER_SIZE, HCI_MGMT_VAR_LEN }, { mesh_features, MGMT_MESH_READ_FEATURES_SIZE }, -- cgit From bce56405201111807cc8e4f47c6de3e10b17c1ac Mon Sep 17 00:00:00 2001 From: Sungwoo Kim Date: Mon, 20 Mar 2023 21:50:18 -0400 Subject: Bluetooth: HCI: Fix global-out-of-bounds To loop a variable-length array, hci_init_stage_sync(stage) considers that stage[i] is valid as long as stage[i-1].func is valid. Thus, the last element of stage[].func should be intentionally invalid as hci_init0[], le_init2[], and others did. However, amp_init1[] and amp_init2[] have no invalid element, letting hci_init_stage_sync() keep accessing amp_init1[] over its valid range. This patch fixes this by adding {} in the last of amp_init1[] and amp_init2[]. ================================================================== BUG: KASAN: global-out-of-bounds in hci_dev_open_sync ( /v6.2-bzimage/net/bluetooth/hci_sync.c:3154 /v6.2-bzimage/net/bluetooth/hci_sync.c:3343 /v6.2-bzimage/net/bluetooth/hci_sync.c:4418 /v6.2-bzimage/net/bluetooth/hci_sync.c:4609 /v6.2-bzimage/net/bluetooth/hci_sync.c:4689) Read of size 8 at addr ffffffffaed1ab70 by task kworker/u5:0/1032 CPU: 0 PID: 1032 Comm: kworker/u5:0 Not tainted 6.2.0 #3 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04 Workqueue: hci1 hci_power_on Call Trace: dump_stack_lvl (/v6.2-bzimage/lib/dump_stack.c:107 (discriminator 1)) print_report (/v6.2-bzimage/mm/kasan/report.c:307 /v6.2-bzimage/mm/kasan/report.c:417) ? hci_dev_open_sync (/v6.2-bzimage/net/bluetooth/hci_sync.c:3154 /v6.2-bzimage/net/bluetooth/hci_sync.c:3343 /v6.2-bzimage/net/bluetooth/hci_sync.c:4418 /v6.2-bzimage/net/bluetooth/hci_sync.c:4609 /v6.2-bzimage/net/bluetooth/hci_sync.c:4689) kasan_report (/v6.2-bzimage/mm/kasan/report.c:184 /v6.2-bzimage/mm/kasan/report.c:519) ? hci_dev_open_sync (/v6.2-bzimage/net/bluetooth/hci_sync.c:3154 /v6.2-bzimage/net/bluetooth/hci_sync.c:3343 /v6.2-bzimage/net/bluetooth/hci_sync.c:4418 /v6.2-bzimage/net/bluetooth/hci_sync.c:4609 /v6.2-bzimage/net/bluetooth/hci_sync.c:4689) hci_dev_open_sync (/v6.2-bzimage/net/bluetooth/hci_sync.c:3154 /v6.2-bzimage/net/bluetooth/hci_sync.c:3343 /v6.2-bzimage/net/bluetooth/hci_sync.c:4418 /v6.2-bzimage/net/bluetooth/hci_sync.c:4609 /v6.2-bzimage/net/bluetooth/hci_sync.c:4689) ? __pfx_hci_dev_open_sync (/v6.2-bzimage/net/bluetooth/hci_sync.c:4635) ? mutex_lock (/v6.2-bzimage/./arch/x86/include/asm/atomic64_64.h:190 /v6.2-bzimage/./include/linux/atomic/atomic-long.h:443 /v6.2-bzimage/./include/linux/atomic/atomic-instrumented.h:1781 /v6.2-bzimage/kernel/locking/mutex.c:171 /v6.2-bzimage/kernel/locking/mutex.c:285) ? __pfx_mutex_lock (/v6.2-bzimage/kernel/locking/mutex.c:282) hci_power_on (/v6.2-bzimage/net/bluetooth/hci_core.c:485 /v6.2-bzimage/net/bluetooth/hci_core.c:984) ? __pfx_hci_power_on (/v6.2-bzimage/net/bluetooth/hci_core.c:969) ? read_word_at_a_time (/v6.2-bzimage/./include/asm-generic/rwonce.h:85) ? strscpy (/v6.2-bzimage/./arch/x86/include/asm/word-at-a-time.h:62 /v6.2-bzimage/lib/string.c:161) process_one_work (/v6.2-bzimage/kernel/workqueue.c:2294) worker_thread (/v6.2-bzimage/./include/linux/list.h:292 /v6.2-bzimage/kernel/workqueue.c:2437) ? __pfx_worker_thread (/v6.2-bzimage/kernel/workqueue.c:2379) kthread (/v6.2-bzimage/kernel/kthread.c:376) ? __pfx_kthread (/v6.2-bzimage/kernel/kthread.c:331) ret_from_fork (/v6.2-bzimage/arch/x86/entry/entry_64.S:314) The buggy address belongs to the variable: amp_init1+0x30/0x60 The buggy address belongs to the physical page: page:000000003a157ec6 refcount:1 mapcount:0 mapping:0000000000000000 ia flags: 0x200000000001000(reserved|node=0|zone=2) raw: 0200000000001000 ffffea0005054688 ffffea0005054688 000000000000000 raw: 0000000000000000 0000000000000000 00000001ffffffff 000000000000000 page dumped because: kasan: bad access detected Memory state around the buggy address: ffffffffaed1aa00: f9 f9 f9 f9 00 00 00 00 f9 f9 f9 f9 00 00 00 00 ffffffffaed1aa80: 00 00 00 00 f9 f9 f9 f9 00 00 00 00 00 00 00 00 >ffffffffaed1ab00: 00 f9 f9 f9 f9 f9 f9 f9 00 00 00 00 00 00 f9 f9 ^ ffffffffaed1ab80: f9 f9 f9 f9 00 00 00 00 f9 f9 f9 f9 00 00 00 f9 ffffffffaed1ac00: f9 f9 f9 f9 00 06 f9 f9 f9 f9 f9 f9 00 00 02 f9 This bug is found by FuzzBT, a modified version of Syzkaller. Other contributors for this bug are Ruoyu Wu and Peng Hui. Fixes: d0b137062b2d ("Bluetooth: hci_sync: Rework init stages") Signed-off-by: Sungwoo Kim Reviewed-by: Simon Horman Signed-off-by: Luiz Augusto von Dentz --- net/bluetooth/hci_sync.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c index 5b8dc8fb2e27..5a6aa1627791 100644 --- a/net/bluetooth/hci_sync.c +++ b/net/bluetooth/hci_sync.c @@ -3360,6 +3360,7 @@ static const struct hci_init_stage amp_init1[] = { HCI_INIT(hci_read_flow_control_mode_sync), /* HCI_OP_READ_LOCATION_DATA */ HCI_INIT(hci_read_location_data_sync), + {} }; static int hci_init1_sync(struct hci_dev *hdev) @@ -3394,6 +3395,7 @@ static int hci_init1_sync(struct hci_dev *hdev) static const struct hci_init_stage amp_init2[] = { /* HCI_OP_READ_LOCAL_FEATURES */ HCI_INIT(hci_read_local_features_sync), + {} }; /* Read Buffer Size (ACL mtu, max pkt, etc.) */ -- cgit