* Re: [PATCH v3 1/2] phy: qcom: edp: Add eDP/DP mode switch support
From: Yongxing Mou @ 2026-04-20 12:48 UTC (permalink / raw)
To: Konrad Dybcio, Vinod Koul, Neil Armstrong, Stephen Boyd,
Bjorn Andersson
Cc: linux-arm-msm, linux-phy, linux-kernel, stable
In-Reply-To: <245f4589-d7ca-4d6b-8162-a86972752bd8@oss.qualcomm.com>
On 4/16/2026 5:34 PM, Konrad Dybcio wrote:
> On 3/2/26 9:28 AM, Yongxing Mou wrote:
>> The eDP PHY supports both eDP&DP modes, each requires a different table.
>> The current driver doesn't fully support every combo PHY mode and use
>> either the eDP or DP table when enable the platform. In addition, some
>> platforms mismatch between the mode and the table where DP mode uses
>> the eDP table or eDP mode use the DP table.
>>
>> Clean up and correct the tables for currently supported platforms based on
>> the HPG specification.
>>
>> Here lists the tables can be reused across current platforms.
>> DP mode:
>> -sa8775p/sc7280/sc8280xp/x1e80100
>> -glymur
>> eDP mode(low vdiff):
>> -glymur/sa8775p/sc8280xp/x1e80100
>> -sc7280
>>
>> Cc: stable@vger.kernel.org
>> Fixes: f199223cb490 ("phy: qcom: Introduce new eDP PHY driver")
>> Signed-off-by: Yongxing Mou <yongxing.mou@oss.qualcomm.com>
>> ---
>
> I went through everything and all the sequences are OK.
>
> SC8180X will need changes, but it's already incorrect so this
> doesn't necessarily affect it
>
> Thanks!
>
> Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
>
> Konrad
Thanks here.. I didn’t notice before that SC8180X is different from
SC7280, and will correct it in the next version.
^ permalink raw reply
* Re: [PATCH v3 1/2] phy: qcom: edp: Add eDP/DP mode switch support
From: Yongxing Mou @ 2026-04-20 12:47 UTC (permalink / raw)
To: Dmitry Baryshkov
Cc: Vinod Koul, Neil Armstrong, Stephen Boyd, Bjorn Andersson,
linux-arm-msm, linux-phy, linux-kernel, stable
In-Reply-To: <islxoe4wbqx5pl54difetdcl5lrqvfd5ysbaicxz5lv235sfmd@6hwrq3rmqx7c>
On 3/20/2026 2:36 PM, Dmitry Baryshkov wrote:
> On Mon, Mar 02, 2026 at 04:28:29PM +0800, Yongxing Mou wrote:
>> The eDP PHY supports both eDP&DP modes, each requires a different table.
>> The current driver doesn't fully support every combo PHY mode and use
>> either the eDP or DP table when enable the platform. In addition, some
>> platforms mismatch between the mode and the table where DP mode uses
>> the eDP table or eDP mode use the DP table.
>>
>> Clean up and correct the tables for currently supported platforms based on
>> the HPG specification.
>>
>> Here lists the tables can be reused across current platforms.
>> DP mode:
>> -sa8775p/sc7280/sc8280xp/x1e80100
>> -glymur
>> eDP mode(low vdiff):
>
> Separate question: should we extend phy_configure_dp_opts with the
> low/high vdiff? Is there a point in providing the ability to toggle
> between low vdiff and high vdiff?
>
Emm ,i haven't found any platform using high vdiff so far, and I'm not
clear in which cases switching between low and high vdiff would be needed.
>> -glymur/sa8775p/sc8280xp/x1e80100
>> -sc7280
>
> I understand your wish to perform all the changes in a single patch, but
> there is one problem with that. Consider this patch regresses one of the
> platforms (I'm looking at Kodiak and SC8180X as they get the biggest set
> of changes). It would be almost impossible to separate, which particular
> change caused the regression. I'd suggest splitting this patch into a
> set of more atomic changes. E.g. the AUX_CFG8 is definitely a separate
> change. Writing swing / pre_emph tables on Kodiak and SC8180X is a
> separate change (or two). Switching each of the platforms to the
> corrected set of tables ideally also should come as a separate change,
> so that in case of a regression the issue would be easier to identify.
>
Thank for point this, will separate the change.
I mostly overlooked SC8180X here, since I assumed it shares the same PHY
as SC7280. However, they are using different PHY sub‑versions. Will add
proper support for it in the next version.
>>
>> Cc: stable@vger.kernel.org
>> Fixes: f199223cb490 ("phy: qcom: Introduce new eDP PHY driver")
>> Signed-off-by: Yongxing Mou <yongxing.mou@oss.qualcomm.com>
>> ---
>> drivers/phy/qualcomm/phy-qcom-edp.c | 90 ++++++++++++++++++++++---------------
>> 1 file changed, 53 insertions(+), 37 deletions(-)
>>
>> diff --git a/drivers/phy/qualcomm/phy-qcom-edp.c b/drivers/phy/qualcomm/phy-qcom-edp.c
>> index 7372de05a0b8..36998326bae6 100644
>> --- a/drivers/phy/qualcomm/phy-qcom-edp.c
>> +++ b/drivers/phy/qualcomm/phy-qcom-edp.c
>> @@ -87,7 +87,8 @@ struct qcom_edp_phy_cfg {
>> bool is_edp;
>> const u8 *aux_cfg;
>> const u8 *vco_div_cfg;
>> - const struct qcom_edp_swing_pre_emph_cfg *swing_pre_emph_cfg;
>> + const struct qcom_edp_swing_pre_emph_cfg *dp_swing_pre_emph_cfg;
>> + const struct qcom_edp_swing_pre_emph_cfg *edp_swing_pre_emph_cfg;
>> const struct phy_ver_ops *ver_ops;
>> };
>>
>> @@ -116,17 +117,17 @@ struct qcom_edp {
>> };
>>
>> static const u8 dp_swing_hbr_rbr[4][4] = {
>> - { 0x08, 0x0f, 0x16, 0x1f },
>> + { 0x07, 0x0f, 0x16, 0x1f },
>> { 0x11, 0x1e, 0x1f, 0xff },
>> { 0x16, 0x1f, 0xff, 0xff },
>> { 0x1f, 0xff, 0xff, 0xff }
>> };
>>
>> static const u8 dp_pre_emp_hbr_rbr[4][4] = {
>> - { 0x00, 0x0d, 0x14, 0x1a },
>> + { 0x00, 0x0e, 0x15, 0x1a },
>> { 0x00, 0x0e, 0x15, 0xff },
>> { 0x00, 0x0e, 0xff, 0xff },
>> - { 0x03, 0xff, 0xff, 0xff }
>> + { 0x04, 0xff, 0xff, 0xff }
>> };
>
> I've checked, at least this table doesn't match SC8180X configuration.
>
Got it.
>>
>> static const u8 dp_swing_hbr2_hbr3[4][4] = {
>> @@ -150,6 +151,20 @@ static const struct qcom_edp_swing_pre_emph_cfg dp_phy_swing_pre_emph_cfg = {
>> .pre_emphasis_hbr3_hbr2 = &dp_pre_emp_hbr2_hbr3,
>> };
>>
>> +static const u8 dp_pre_emp_hbr_rbr_v8[4][4] = {
>> + { 0x00, 0x0e, 0x15, 0x1a },
>> + { 0x00, 0x0e, 0x15, 0xff },
>> + { 0x00, 0x0e, 0xff, 0xff },
>> + { 0x00, 0xff, 0xff, 0xff }
>> +};
>> +
>> +static const struct qcom_edp_swing_pre_emph_cfg dp_phy_swing_pre_emph_cfg_v8 = {
>> + .swing_hbr_rbr = &dp_swing_hbr_rbr,
>> + .swing_hbr3_hbr2 = &dp_swing_hbr2_hbr3,
>> + .pre_emphasis_hbr_rbr = &dp_pre_emp_hbr_rbr_v8,
>> + .pre_emphasis_hbr3_hbr2 = &dp_pre_emp_hbr2_hbr3,
>> +};
>> +
>> static const u8 edp_swing_hbr_rbr[4][4] = {
>> { 0x07, 0x0f, 0x16, 0x1f },
>> { 0x0d, 0x16, 0x1e, 0xff },
>> @@ -158,7 +173,7 @@ static const u8 edp_swing_hbr_rbr[4][4] = {
>> };
>>
>> static const u8 edp_pre_emp_hbr_rbr[4][4] = {
>> - { 0x05, 0x12, 0x17, 0x1d },
>> + { 0x05, 0x11, 0x17, 0x1d },
>
> This was changed only for Kodiak. For SC8180X, I assume, we should be
> using the older table.
>
Emm, for SC8180X, eDP low VDIFF (High HBR) only S1 (250mV) P0-0dB
Emphasis Settings "0x08" different from other "generic" tables which is
"0x0B".
>> { 0x05, 0x11, 0x18, 0xff },
>> { 0x06, 0x11, 0xff, 0xff },
>> { 0x00, 0xff, 0xff, 0xff }
>> @@ -172,10 +187,10 @@ static const u8 edp_swing_hbr2_hbr3[4][4] = {
>> };
>>
>> static const u8 edp_pre_emp_hbr2_hbr3[4][4] = {
>
> I think it becomes worth adding version to the "generic" tables. They
> are not that generic anyway.
>
Got it. SC8180X here need a different table..
>> - { 0x08, 0x11, 0x17, 0x1b },
>> - { 0x00, 0x0c, 0x13, 0xff },
>> - { 0x05, 0x10, 0xff, 0xff },
>> - { 0x00, 0xff, 0xff, 0xff }
>> + { 0x0c, 0x15, 0x19, 0x1e },
>> + { 0x0b, 0x15, 0x19, 0xff },
>> + { 0x0e, 0x14, 0xff, 0xff },
>> + { 0x0d, 0xff, 0xff, 0xff }
>
> Current table indeed doesn't match the swing table. Please take care
> about the SC8180X differences (I think, it will need separate set of
> tables).
>
Got it.
>> };
>>
>> static const struct qcom_edp_swing_pre_emph_cfg edp_phy_swing_pre_emph_cfg = {
>> @@ -193,25 +208,25 @@ static const u8 edp_phy_vco_div_cfg_v4[4] = {
>> 0x01, 0x01, 0x02, 0x00,
>> };
>>
>> -static const u8 edp_pre_emp_hbr_rbr_v5[4][4] = {
>> - { 0x05, 0x11, 0x17, 0x1d },
>> - { 0x05, 0x11, 0x18, 0xff },
>> - { 0x06, 0x11, 0xff, 0xff },
>> - { 0x00, 0xff, 0xff, 0xff }
>> +static const u8 edp_swing_hbr2_hbr3_v3[4][4] = {
>> + { 0x06, 0x11, 0x16, 0x1b },
>> + { 0x0b, 0x19, 0x1f, 0xff },
>> + { 0x18, 0x1f, 0xff, 0xff },
>> + { 0x1f, 0xff, 0xff, 0xff }
>> };
>>
>> -static const u8 edp_pre_emp_hbr2_hbr3_v5[4][4] = {
>> +static const u8 edp_pre_emp_hbr2_hbr3_v3[4][4] = {
>> { 0x0c, 0x15, 0x19, 0x1e },
>> - { 0x0b, 0x15, 0x19, 0xff },
>> - { 0x0e, 0x14, 0xff, 0xff },
>> + { 0x09, 0x14, 0x19, 0xff },
>> + { 0x0f, 0x14, 0xff, 0xff },
>> { 0x0d, 0xff, 0xff, 0xff }
>> };
>>
>> -static const struct qcom_edp_swing_pre_emph_cfg edp_phy_swing_pre_emph_cfg_v5 = {
>> +static const struct qcom_edp_swing_pre_emph_cfg edp_phy_swing_pre_emph_cfg_v3 = {
>> .swing_hbr_rbr = &edp_swing_hbr_rbr,
>> - .swing_hbr3_hbr2 = &edp_swing_hbr2_hbr3,
>> - .pre_emphasis_hbr_rbr = &edp_pre_emp_hbr_rbr_v5,
>> - .pre_emphasis_hbr3_hbr2 = &edp_pre_emp_hbr2_hbr3_v5,
>> + .swing_hbr3_hbr2 = &edp_swing_hbr2_hbr3_v3,
>> + .pre_emphasis_hbr_rbr = &edp_pre_emp_hbr_rbr,
>> + .pre_emphasis_hbr3_hbr2 = &edp_pre_emp_hbr2_hbr3_v3,
>> };
>>
>> static const u8 edp_phy_aux_cfg_v5[DP_AUX_CFG_SIZE] = {
>> @@ -262,12 +277,7 @@ static int qcom_edp_phy_init(struct phy *phy)
>> DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN,
>> edp->edp + DP_PHY_PD_CTL);
>>
>> - /*
>> - * TODO: Re-work the conditions around setting the cfg8 value
>> - * when more information becomes available about why this is
>> - * even needed.
>> - */
>> - if (edp->cfg->swing_pre_emph_cfg && !edp->is_edp)
>> + if (!edp->is_edp)
>> aux_cfg[8] = 0xb7;
>
> This is a separate fix, as it changes the aux_cfg[8] value for Kodiak
> and SC8180X.
>
Got it.
>>
>> writel(0xfc, edp->edp + DP_PHY_MODE);
>> @@ -291,7 +301,7 @@ static int qcom_edp_phy_init(struct phy *phy)
>>
>> static int qcom_edp_set_voltages(struct qcom_edp *edp, const struct phy_configure_opts_dp *dp_opts)
>> {
>> - const struct qcom_edp_swing_pre_emph_cfg *cfg = edp->cfg->swing_pre_emph_cfg;
>> + const struct qcom_edp_swing_pre_emph_cfg *cfg;
>> unsigned int v_level = 0;
>> unsigned int p_level = 0;
>> u8 ldo_config;
>> @@ -299,11 +309,10 @@ static int qcom_edp_set_voltages(struct qcom_edp *edp, const struct phy_configur
>> u8 emph;
>> int i;
>>
>> - if (!cfg)
>> - return 0;
>> -
>> if (edp->is_edp)
>> - cfg = &edp_phy_swing_pre_emph_cfg;
>> + cfg = edp->cfg->edp_swing_pre_emph_cfg;
>> + else
>> + cfg = edp->cfg->dp_swing_pre_emph_cfg;
>>
>> for (i = 0; i < dp_opts->lanes; i++) {
>> v_level = max(v_level, dp_opts->voltage[i]);
>> @@ -564,20 +573,24 @@ static const struct qcom_edp_phy_cfg sa8775p_dp_phy_cfg = {
>> .is_edp = false,
>> .aux_cfg = edp_phy_aux_cfg_v5,
>> .vco_div_cfg = edp_phy_vco_div_cfg_v4,
>> - .swing_pre_emph_cfg = &edp_phy_swing_pre_emph_cfg_v5,
>> + .dp_swing_pre_emph_cfg = &dp_phy_swing_pre_emph_cfg,
>> + .edp_swing_pre_emph_cfg = &edp_phy_swing_pre_emph_cfg,
>> .ver_ops = &qcom_edp_phy_ops_v4,
>> };
>>
>> static const struct qcom_edp_phy_cfg sc7280_dp_phy_cfg = {
>> .aux_cfg = edp_phy_aux_cfg_v4,
>> .vco_div_cfg = edp_phy_vco_div_cfg_v4,
>> + .dp_swing_pre_emph_cfg = &dp_phy_swing_pre_emph_cfg,
>> + .edp_swing_pre_emph_cfg = &edp_phy_swing_pre_emph_cfg_v3,
>> .ver_ops = &qcom_edp_phy_ops_v4,
>> };
>>
>> static const struct qcom_edp_phy_cfg sc8280xp_dp_phy_cfg = {
>> .aux_cfg = edp_phy_aux_cfg_v4,
>> .vco_div_cfg = edp_phy_vco_div_cfg_v4,
>> - .swing_pre_emph_cfg = &dp_phy_swing_pre_emph_cfg,
>> + .dp_swing_pre_emph_cfg = &dp_phy_swing_pre_emph_cfg,
>> + .edp_swing_pre_emph_cfg = &edp_phy_swing_pre_emph_cfg,
>> .ver_ops = &qcom_edp_phy_ops_v4,
>> };
>>
>> @@ -585,7 +598,8 @@ static const struct qcom_edp_phy_cfg sc8280xp_edp_phy_cfg = {
>> .is_edp = true,
>> .aux_cfg = edp_phy_aux_cfg_v4,
>> .vco_div_cfg = edp_phy_vco_div_cfg_v4,
>> - .swing_pre_emph_cfg = &edp_phy_swing_pre_emph_cfg,
>> + .dp_swing_pre_emph_cfg = &dp_phy_swing_pre_emph_cfg,
>> + .edp_swing_pre_emph_cfg = &edp_phy_swing_pre_emph_cfg,
>
> Ok, we are going to continue using eDP table because of is_edp = true.
>
>> .ver_ops = &qcom_edp_phy_ops_v4,
>> };
>>
>> @@ -766,7 +780,8 @@ static const struct phy_ver_ops qcom_edp_phy_ops_v6 = {
>> static struct qcom_edp_phy_cfg x1e80100_phy_cfg = {
>> .aux_cfg = edp_phy_aux_cfg_v4,
>> .vco_div_cfg = edp_phy_vco_div_cfg_v4,
>> - .swing_pre_emph_cfg = &dp_phy_swing_pre_emph_cfg,
>> + .dp_swing_pre_emph_cfg = &dp_phy_swing_pre_emph_cfg,
>> + .edp_swing_pre_emph_cfg = &edp_phy_swing_pre_emph_cfg,
>> .ver_ops = &qcom_edp_phy_ops_v6,
>> };
>>
>> @@ -945,7 +960,8 @@ static const struct phy_ver_ops qcom_edp_phy_ops_v8 = {
>> static struct qcom_edp_phy_cfg glymur_phy_cfg = {
>> .aux_cfg = edp_phy_aux_cfg_v8,
>> .vco_div_cfg = edp_phy_vco_div_cfg_v8,
>> - .swing_pre_emph_cfg = &edp_phy_swing_pre_emph_cfg_v5,
>> + .dp_swing_pre_emph_cfg = &dp_phy_swing_pre_emph_cfg_v8,
>> + .edp_swing_pre_emph_cfg = &edp_phy_swing_pre_emph_cfg,
>> .ver_ops = &qcom_edp_phy_ops_v8,
>> };
>>
>>
>> --
>> 2.43.0
>>
>>
>> --
>> linux-phy mailing list
>> linux-phy@lists.infradead.org
>> https://lists.infradead.org/mailman/listinfo/linux-phy
>
^ permalink raw reply
* Re: [PATCH 6.6.y] iio: common: st_sensors: Fix use of uninitialize device structs
From: Jonathan Cameron @ 2026-04-20 12:41 UTC (permalink / raw)
To: Fang Wang
Cc: maudspierings, gregkh, stable, patches, linux-kernel, lars,
dimitri.fedrau, markus.koeniger, andy, linux-iio,
Jonathan.Cameron
In-Reply-To: <tencent_B4E5A4D17E67F7C7096F7BF8A4C701223008@qq.com>
On Tue, 14 Apr 2026 14:45:53 +0800
Fang Wang <32840572@qq.com> wrote:
> From: Maud Spierings <maudspierings@gocontroll.com>
>
> [ Upstream commit 9f92e93e257b33e73622640a9205f8642ec16ddd ]
>
> Throughout the various probe functions &indio_dev->dev is used before it
> is initialized.
Looking at this again, I'm not sure what exactly what meant by 'initialized'
given device_initialize() has definitely been called on indio_dev->dev
as that's part of the allocation functions.
What this is actually about is device private structure (dev->p) being initialized
which are only done on device_add.
Given the struct device in the iio_dev is always the wrong thing to use
for messages (as it's not very informative if nothing else) this is fine.
So if not picked up already
Acked-by: Jonathan Cameron <jic23@kernel.org>
>This caused a kernel panic in st_sensors_power_enable()
> when the call to devm_regulator_bulk_get_enable() fails and then calls
> dev_err_probe() with the uninitialized device.
>
> This seems to only cause a panic with dev_err_probe(), dev_err(),
> dev_warn() and dev_info() don't seem to cause a panic, but are fixed
> as well.
>
> The issue is reported and traced here: [1]
>
> Link: https://lore.kernel.org/all/AM7P189MB100986A83D2F28AF3FFAF976E39EA@AM7P189MB1009.EURP189.PROD.OUTLOOK.COM/ [1]
> Cc: stable@vger.kernel.org
> Signed-off-by: Maud Spierings <maudspierings@gocontroll.com>
> Reviewed-by: Andy Shevchenko <andy@kernel.org>
> Link: https://... [1]
> Link: https://patch.msgid.link/20250527-st_iio_fix-v4-1-12d89801c761@gocontroll.com
> Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> Signed-off-by: Fang Wang <32840572@qq.com>
> ---
> drivers/iio/accel/st_accel_core.c | 10 +++---
> .../iio/common/st_sensors/st_sensors_core.c | 36 +++++++++----------
> .../common/st_sensors/st_sensors_trigger.c | 20 +++++------
> 3 files changed, 31 insertions(+), 35 deletions(-)
>
> diff --git a/drivers/iio/accel/st_accel_core.c b/drivers/iio/accel/st_accel_core.c
> index 51d8de18e6d6..45d2268e042e 100644
> --- a/drivers/iio/accel/st_accel_core.c
> +++ b/drivers/iio/accel/st_accel_core.c
> @@ -1342,6 +1342,7 @@ static int apply_acpi_orientation(struct iio_dev *indio_dev)
> union acpi_object *ont;
> union acpi_object *elements;
> acpi_status status;
> + struct device *parent = indio_dev->dev.parent;
> int ret = -EINVAL;
> unsigned int val;
> int i, j;
> @@ -1360,7 +1361,7 @@ static int apply_acpi_orientation(struct iio_dev *indio_dev)
> };
>
>
> - adev = ACPI_COMPANION(indio_dev->dev.parent);
> + adev = ACPI_COMPANION(parent);
> if (!adev)
> return -ENXIO;
>
> @@ -1369,8 +1370,7 @@ static int apply_acpi_orientation(struct iio_dev *indio_dev)
> if (status == AE_NOT_FOUND) {
> return -ENXIO;
> } else if (ACPI_FAILURE(status)) {
> - dev_warn(&indio_dev->dev, "failed to execute _ONT: %d\n",
> - status);
> + dev_warn(parent, "failed to execute _ONT: %d\n", status);
> return status;
> }
>
> @@ -1446,12 +1446,12 @@ static int apply_acpi_orientation(struct iio_dev *indio_dev)
> }
>
> ret = 0;
> - dev_info(&indio_dev->dev, "computed mount matrix from ACPI\n");
> + dev_info(parent, "computed mount matrix from ACPI\n");
>
> out:
> kfree(buffer.pointer);
> if (ret)
> - dev_dbg(&indio_dev->dev,
> + dev_dbg(parent,
> "failed to apply ACPI orientation data: %d\n", ret);
>
> return ret;
> diff --git a/drivers/iio/common/st_sensors/st_sensors_core.c b/drivers/iio/common/st_sensors/st_sensors_core.c
> index c77d7bdcc121..78f5728417d5 100644
> --- a/drivers/iio/common/st_sensors/st_sensors_core.c
> +++ b/drivers/iio/common/st_sensors/st_sensors_core.c
> @@ -154,7 +154,7 @@ static int st_sensors_set_fullscale(struct iio_dev *indio_dev, unsigned int fs)
> return err;
>
> st_accel_set_fullscale_error:
> - dev_err(&indio_dev->dev, "failed to set new fullscale.\n");
> + dev_err(indio_dev->dev.parent, "failed to set new fullscale.\n");
> return err;
> }
>
> @@ -231,8 +231,7 @@ int st_sensors_power_enable(struct iio_dev *indio_dev)
> ARRAY_SIZE(regulator_names),
> regulator_names);
> if (err)
> - return dev_err_probe(&indio_dev->dev, err,
> - "unable to enable supplies\n");
> + return dev_err_probe(parent, err, "unable to enable supplies\n");
>
> return 0;
> }
> @@ -241,13 +240,14 @@ EXPORT_SYMBOL_NS(st_sensors_power_enable, IIO_ST_SENSORS);
> static int st_sensors_set_drdy_int_pin(struct iio_dev *indio_dev,
> struct st_sensors_platform_data *pdata)
> {
> + struct device *parent = indio_dev->dev.parent;
> struct st_sensor_data *sdata = iio_priv(indio_dev);
>
> /* Sensor does not support interrupts */
> if (!sdata->sensor_settings->drdy_irq.int1.addr &&
> !sdata->sensor_settings->drdy_irq.int2.addr) {
> if (pdata->drdy_int_pin)
> - dev_info(&indio_dev->dev,
> + dev_info(parent,
> "DRDY on pin INT%d specified, but sensor does not support interrupts\n",
> pdata->drdy_int_pin);
> return 0;
> @@ -256,29 +256,27 @@ static int st_sensors_set_drdy_int_pin(struct iio_dev *indio_dev,
> switch (pdata->drdy_int_pin) {
> case 1:
> if (!sdata->sensor_settings->drdy_irq.int1.mask) {
> - dev_err(&indio_dev->dev,
> - "DRDY on INT1 not available.\n");
> + dev_err(parent, "DRDY on INT1 not available.\n");
> return -EINVAL;
> }
> sdata->drdy_int_pin = 1;
> break;
> case 2:
> if (!sdata->sensor_settings->drdy_irq.int2.mask) {
> - dev_err(&indio_dev->dev,
> - "DRDY on INT2 not available.\n");
> + dev_err(parent, "DRDY on INT2 not available.\n");
> return -EINVAL;
> }
> sdata->drdy_int_pin = 2;
> break;
> default:
> - dev_err(&indio_dev->dev, "DRDY on pdata not valid.\n");
> + dev_err(parent, "DRDY on pdata not valid.\n");
> return -EINVAL;
> }
>
> if (pdata->open_drain) {
> if (!sdata->sensor_settings->drdy_irq.int1.addr_od &&
> !sdata->sensor_settings->drdy_irq.int2.addr_od)
> - dev_err(&indio_dev->dev,
> + dev_err(parent,
> "open drain requested but unsupported.\n");
> else
> sdata->int_pin_open_drain = true;
> @@ -336,6 +334,7 @@ EXPORT_SYMBOL_NS(st_sensors_dev_name_probe, IIO_ST_SENSORS);
> int st_sensors_init_sensor(struct iio_dev *indio_dev,
> struct st_sensors_platform_data *pdata)
> {
> + struct device *parent = indio_dev->dev.parent;
> struct st_sensor_data *sdata = iio_priv(indio_dev);
> struct st_sensors_platform_data *of_pdata;
> int err = 0;
> @@ -343,7 +342,7 @@ int st_sensors_init_sensor(struct iio_dev *indio_dev,
> mutex_init(&sdata->odr_lock);
>
> /* If OF/DT pdata exists, it will take precedence of anything else */
> - of_pdata = st_sensors_dev_probe(indio_dev->dev.parent, pdata);
> + of_pdata = st_sensors_dev_probe(parent, pdata);
> if (IS_ERR(of_pdata))
> return PTR_ERR(of_pdata);
> if (of_pdata)
> @@ -370,7 +369,7 @@ int st_sensors_init_sensor(struct iio_dev *indio_dev,
> if (err < 0)
> return err;
> } else
> - dev_info(&indio_dev->dev, "Full-scale not possible\n");
> + dev_info(parent, "Full-scale not possible\n");
>
> err = st_sensors_set_odr(indio_dev, sdata->odr);
> if (err < 0)
> @@ -405,7 +404,7 @@ int st_sensors_init_sensor(struct iio_dev *indio_dev,
> mask = sdata->sensor_settings->drdy_irq.int2.mask_od;
> }
>
> - dev_info(&indio_dev->dev,
> + dev_info(parent,
> "set interrupt line to open drain mode on pin %d\n",
> sdata->drdy_int_pin);
> err = st_sensors_write_data_with_mask(indio_dev, addr,
> @@ -594,21 +593,20 @@ EXPORT_SYMBOL_NS(st_sensors_get_settings_index, IIO_ST_SENSORS);
> int st_sensors_verify_id(struct iio_dev *indio_dev)
> {
> struct st_sensor_data *sdata = iio_priv(indio_dev);
> + struct device *parent = indio_dev->dev.parent;
> int wai, err;
>
> if (sdata->sensor_settings->wai_addr) {
> err = regmap_read(sdata->regmap,
> sdata->sensor_settings->wai_addr, &wai);
> if (err < 0) {
> - dev_err(&indio_dev->dev,
> - "failed to read Who-Am-I register.\n");
> - return err;
> + return dev_err_probe(parent, err,
> + "failed to read Who-Am-I register.\n");
> }
>
> if (sdata->sensor_settings->wai != wai) {
> - dev_err(&indio_dev->dev,
> - "%s: WhoAmI mismatch (0x%x).\n",
> - indio_dev->name, wai);
> + dev_warn(parent, "%s: WhoAmI mismatch (0x%x).\n",
> + indio_dev->name, wai);
> return -EINVAL;
> }
> }
> diff --git a/drivers/iio/common/st_sensors/st_sensors_trigger.c b/drivers/iio/common/st_sensors/st_sensors_trigger.c
> index a0df9250a69f..b900acd471bd 100644
> --- a/drivers/iio/common/st_sensors/st_sensors_trigger.c
> +++ b/drivers/iio/common/st_sensors/st_sensors_trigger.c
> @@ -127,7 +127,7 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev,
> sdata->trig = devm_iio_trigger_alloc(parent, "%s-trigger",
> indio_dev->name);
> if (sdata->trig == NULL) {
> - dev_err(&indio_dev->dev, "failed to allocate iio trigger.\n");
> + dev_err(parent, "failed to allocate iio trigger.\n");
> return -ENOMEM;
> }
>
> @@ -143,7 +143,7 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev,
> case IRQF_TRIGGER_FALLING:
> case IRQF_TRIGGER_LOW:
> if (!sdata->sensor_settings->drdy_irq.addr_ihl) {
> - dev_err(&indio_dev->dev,
> + dev_err(parent,
> "falling/low specified for IRQ but hardware supports only rising/high: will request rising/high\n");
> if (irq_trig == IRQF_TRIGGER_FALLING)
> irq_trig = IRQF_TRIGGER_RISING;
> @@ -156,21 +156,19 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev,
> sdata->sensor_settings->drdy_irq.mask_ihl, 1);
> if (err < 0)
> return err;
> - dev_info(&indio_dev->dev,
> + dev_info(parent,
> "interrupts on the falling edge or active low level\n");
> }
> break;
> case IRQF_TRIGGER_RISING:
> - dev_info(&indio_dev->dev,
> - "interrupts on the rising edge\n");
> + dev_info(parent, "interrupts on the rising edge\n");
> break;
> case IRQF_TRIGGER_HIGH:
> - dev_info(&indio_dev->dev,
> - "interrupts active high level\n");
> + dev_info(parent, "interrupts active high level\n");
> break;
> default:
> /* This is the most preferred mode, if possible */
> - dev_err(&indio_dev->dev,
> + dev_err(parent,
> "unsupported IRQ trigger specified (%lx), enforce rising edge\n", irq_trig);
> irq_trig = IRQF_TRIGGER_RISING;
> }
> @@ -179,7 +177,7 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev,
> if (irq_trig == IRQF_TRIGGER_FALLING ||
> irq_trig == IRQF_TRIGGER_RISING) {
> if (!sdata->sensor_settings->drdy_irq.stat_drdy.addr) {
> - dev_err(&indio_dev->dev,
> + dev_err(parent,
> "edge IRQ not supported w/o stat register.\n");
> return -EOPNOTSUPP;
> }
> @@ -214,13 +212,13 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev,
> sdata->trig->name,
> sdata->trig);
> if (err) {
> - dev_err(&indio_dev->dev, "failed to request trigger IRQ.\n");
> + dev_err(parent, "failed to request trigger IRQ.\n");
> return err;
> }
>
> err = devm_iio_trigger_register(parent, sdata->trig);
> if (err < 0) {
> - dev_err(&indio_dev->dev, "failed to register iio trigger.\n");
> + dev_err(parent, "failed to register iio trigger.\n");
> return err;
> }
> indio_dev->trig = iio_trigger_get(sdata->trig);
^ permalink raw reply
* sashiko.dev review (Re: [PATCH v4 01/17] dmaengine: sh: rz-dmac: Move interrupt request after everything is set up)
From: Claudiu Beznea @ 2026-04-20 12:33 UTC (permalink / raw)
To: vkoul, Frank.Li, lgirdwood, broonie, perex, tiwai, biju.das.jz,
prabhakar.mahadev-lad.rj, p.zabel, geert+renesas,
fabrizio.castro.jz, long.luu.ur
Cc: dmaengine, linux-kernel, linux-sound, linux-renesas-soc,
Claudiu Beznea, stable
In-Reply-To: <20260411114303.2814115-2-claudiu.beznea.uj@bp.renesas.com>
> commit b3dfdd5fbd2463db407b1396ee1ae79801cb96bf
> Author: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> dmaengine: sh: rz-dmac: Move interrupt request after everything is set up
> This patch moves the channel interrupt request to the end of the channel
> probe function to prevent the IRQ handler from accessing uninitialized
> data. It also replaces dma_alloc_coherent() with dmam_alloc_coherent()
> to simplify the error path.
> > diff --git a/drivers/dma/sh/rz-dmac.c b/drivers/dma/sh/rz-dmac.c
> > index 625ff29024de0..9f206a33dcc6b 100644
> > --- a/drivers/dma/sh/rz-dmac.c
> > +++ b/drivers/dma/sh/rz-dmac.c
> [ ... ]
> > @@ -1210,16 +1207,6 @@ static int rz_dmac_probe(struct platform_device *pdev)
> > dma_register_err:
> > of_dma_controller_free(pdev->dev.of_node);
> > err:
> > - channel_num = i ? i - 1 : 0;
> > - for (i = 0; i < channel_num; i++) {
> > - struct rz_dmac_chan *channel = &dmac->channels[i];
> > -
> > - dma_free_coherent(&pdev->dev,
> > - sizeof(struct rz_lmdesc) * DMAC_NR_LMDESC,
> > - channel->lmdesc.base,
> > - channel->lmdesc.base_dma);
> > - }
> > -
> > reset_control_assert(dmac->rstc);
> > err_pm_runtime_put:
> > pm_runtime_put(&pdev->dev);
> > @@ -1232,18 +1219,9 @@ static int rz_dmac_probe(struct platform_device *pdev)
> > static void rz_dmac_remove(struct platform_device *pdev)
> > {
> > struct rz_dmac *dmac = platform_get_drvdata(pdev);
> > - unsigned int i;
> >
> > dma_async_device_unregister(&dmac->engine);
> > of_dma_controller_free(pdev->dev.of_node);
> > - for (i = 0; i < dmac->n_channels; i++) {
> > - struct rz_dmac_chan *channel = &dmac->channels[i];
> > -
> > - dma_free_coherent(&pdev->dev,
> > - sizeof(struct rz_lmdesc) * DMAC_NR_LMDESC,
> > - channel->lmdesc.base,
> > - channel->lmdesc.base_dma);
> > - }
> > reset_control_assert(dmac->rstc);
> > pm_runtime_put(&pdev->dev);
> > pm_runtime_disable(&pdev->dev);
> > }
> While this patch fixes the initialization races, does it leave a similar
> vulnerability exposed during teardown?
> Since devm_request_threaded_irq() is used to allocate the interrupts, they
> will remain active until after rz_dmac_remove() and the rz_dmac_probe() error
> paths complete.
> If an interrupt fires during or just after rz_dmac_remove(), could the handler
> attempt to access hardware registers while the device is in reset or powered
> down by pm_runtime_put()?
> Would it be safer to explicitly free or disable the IRQs before asserting the
> hardware reset and disabling runtime PM, or perhaps manage the reset and PM
> states via devm actions to guarantee correct teardown ordering?
On either failure or remove path the device is with runtime PM put (clocks being
disabled) and in reset state. The controller cannot generate interrupts from
this state.
However, to keep this series simple, I'll add this in a cleanup patch after the
current series will be merged.
^ permalink raw reply
* Re: [PATCH 5.15.y] PCI/ACPI: Restrict program_hpx_type2() to AER bits
From: Greg KH @ 2026-04-20 12:32 UTC (permalink / raw)
To: Haakon Bugge; +Cc: stable@vger.kernel.org, Bjorn Helgaas
In-Reply-To: <7226713B-8871-40FA-BAA1-6AC5E516AF46@oracle.com>
On Mon, Apr 20, 2026 at 12:20:05PM +0000, Haakon Bugge wrote:
> > commit 9abf79c8d7b40db0e5a34aa8c744ea60ff9a3fcf upstream.
> >
> > Previously program_hpx_type2() applied PCIe settings unconditionally,
> > which could incorrectly change bits like Extended Tag Field Enable and
> > Enable Relaxed Ordering.
> >
> > When _HPX was added to ACPI r3.0, the intent of the PCIe Setting
> > Record (Type 2) in sec 6.2.7.3 was to configure AER registers when the
> > OS does not own the AER Capability:
> >
> > The PCI Express setting record contains ... [the AER] Uncorrectable
> > Error Mask, Uncorrectable Error Severity, Correctable Error Mask
> > ... to be used when configuring registers in the Advanced Error
> > Reporting Extended Capability Structure ...
> >
> > OSPM [1] will only evaluate _HPX with Setting Record – Type 2 if
> > OSPM is not controlling the PCI Express Advanced Error Reporting
> > capability.
> >
> > ACPI r3.0b, sec 6.2.7.3, added more AER registers, including registers
> > in the PCIe Capability with AER-related bits, and the restriction that
> > the OS use this only when it owns PCIe native hotplug:
> >
> > ... when configuring PCI Express registers in the Advanced Error
> > Reporting Extended Capability Structure *or PCI Express Capability
> > Structure* ...
> >
> > An OS that has assumed ownership of native hot plug but does not
> > ... have ownership of the AER register set must use ... the Type 2
> > record to program the AER registers ...
> >
> > However, since the Type 2 record also includes register bits that
> > have functions other than AER, the OS must ignore values ... that
> > are not applicable.
> >
> > Restrict program_hpx_type2() to only the intended purpose:
> >
> > - Apply settings only when OS owns PCIe native hotplug but not AER,
> >
> > - Only touch the AER-related bits (Error Reporting Enables) in Device
> > Control
> >
> > - Don't touch Link Control at all, since nothing there seems AER-related,
> > but log _HPX settings for debugging purposes
> >
> > Note that Read Completion Boundary is now configured elsewhere, since it is
> > unrelated to _HPX.
> >
> > [1] Operating System-directed configuration and Power Management
> >
> > Fixes: 40abb96c51bb ("[PATCH] pciehp: Fix programming hotplug parameters")
> > Signed-off-by: Håkon Bugge <haakon.bugge@oracle.com>
> > Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
> > Link: https://patch.msgid.link/20260129175237.727059-3-haakon.bugge@oracle.com
> > [ Conflict in drivers/pci.h because the context has changed. ]
> > Signed-off-by: Håkon Bugge <haakon.bugge@oracle.com>
>
> I see this was not added to 5.15.203, hence a gentle ping on it.
The backlog for manually backported 5.15.y patches right now is over 100
patches long. You are in good company :)
thanks,
greg k-h
^ permalink raw reply
* Re: [PATCH] vmalloc: fix buffer overflow in vrealloc_node_align()
From: Vlastimil Babka (SUSE) @ 2026-04-20 12:21 UTC (permalink / raw)
To: Marco Elver, Andrew Morton
Cc: Uladzislau Rezki, linux-mm, linux-kernel, kasan-dev, Vitaly Wool,
stable, Harry Yoo (Oracle)
In-Reply-To: <20260420114805.3572606-2-elver@google.com>
On 4/20/26 13:47, Marco Elver wrote:
> Commit 4c5d3365882d ("mm/vmalloc: allow to set node and align in
> vrealloc") added the ability to force a new allocation if the current
> pointer is on the wrong NUMA node, or if an alignment constraint is not
> met, even if the user is shrinking the allocation.
>
> On this path (need_realloc), the code allocates a new object of 'size'
> bytes and then memcpy()s 'old_size' bytes into it. If the request is to
> shrink the object (size < old_size), this results in an out-of-bounds
> write on the new buffer.
>
> Fix this by bounding the copy length by the new allocation size.
>
> Fixes: 4c5d3365882d ("mm/vmalloc: allow to set node and align in vrealloc")
> Cc: <stable@vger.kernel.org>
> Reported-by: Harry Yoo (Oracle) <harry@kernel.org>
> Signed-off-by: Marco Elver <elver@google.com>
Acked-by: Vlastimil Babka (SUSE) <vbabka@kernel.org>
> ---
> mm/vmalloc.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/mm/vmalloc.c b/mm/vmalloc.c
> index 61caa55a4402..8b1124158f54 100644
> --- a/mm/vmalloc.c
> +++ b/mm/vmalloc.c
> @@ -4361,7 +4361,7 @@ void *vrealloc_node_align_noprof(const void *p, size_t size, unsigned long align
> return NULL;
>
> if (p) {
> - memcpy(n, p, old_size);
> + memcpy(n, p, min(size, old_size));
> vfree(p);
> }
>
^ permalink raw reply
* Re: [PATCH 5.15.y] PCI/ACPI: Restrict program_hpx_type2() to AER bits
From: Haakon Bugge @ 2026-04-20 12:20 UTC (permalink / raw)
To: stable@vger.kernel.org; +Cc: Bjorn Helgaas
In-Reply-To: <20260311171736.343422-1-haakon.bugge@oracle.com>
> commit 9abf79c8d7b40db0e5a34aa8c744ea60ff9a3fcf upstream.
>
> Previously program_hpx_type2() applied PCIe settings unconditionally,
> which could incorrectly change bits like Extended Tag Field Enable and
> Enable Relaxed Ordering.
>
> When _HPX was added to ACPI r3.0, the intent of the PCIe Setting
> Record (Type 2) in sec 6.2.7.3 was to configure AER registers when the
> OS does not own the AER Capability:
>
> The PCI Express setting record contains ... [the AER] Uncorrectable
> Error Mask, Uncorrectable Error Severity, Correctable Error Mask
> ... to be used when configuring registers in the Advanced Error
> Reporting Extended Capability Structure ...
>
> OSPM [1] will only evaluate _HPX with Setting Record – Type 2 if
> OSPM is not controlling the PCI Express Advanced Error Reporting
> capability.
>
> ACPI r3.0b, sec 6.2.7.3, added more AER registers, including registers
> in the PCIe Capability with AER-related bits, and the restriction that
> the OS use this only when it owns PCIe native hotplug:
>
> ... when configuring PCI Express registers in the Advanced Error
> Reporting Extended Capability Structure *or PCI Express Capability
> Structure* ...
>
> An OS that has assumed ownership of native hot plug but does not
> ... have ownership of the AER register set must use ... the Type 2
> record to program the AER registers ...
>
> However, since the Type 2 record also includes register bits that
> have functions other than AER, the OS must ignore values ... that
> are not applicable.
>
> Restrict program_hpx_type2() to only the intended purpose:
>
> - Apply settings only when OS owns PCIe native hotplug but not AER,
>
> - Only touch the AER-related bits (Error Reporting Enables) in Device
> Control
>
> - Don't touch Link Control at all, since nothing there seems AER-related,
> but log _HPX settings for debugging purposes
>
> Note that Read Completion Boundary is now configured elsewhere, since it is
> unrelated to _HPX.
>
> [1] Operating System-directed configuration and Power Management
>
> Fixes: 40abb96c51bb ("[PATCH] pciehp: Fix programming hotplug parameters")
> Signed-off-by: Håkon Bugge <haakon.bugge@oracle.com>
> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
> Link: https://patch.msgid.link/20260129175237.727059-3-haakon.bugge@oracle.com
> [ Conflict in drivers/pci.h because the context has changed. ]
> Signed-off-by: Håkon Bugge <haakon.bugge@oracle.com>
I see this was not added to 5.15.203, hence a gentle ping on it.
Thxs, Håkon
> ---
> drivers/pci/pci-acpi.c | 59 +++++++++++++++++-------------------------
> drivers/pci/pci.h | 3 +++
> drivers/pci/pcie/aer.c | 3 ---
> 3 files changed, 27 insertions(+), 38 deletions(-)
>
> diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
> index 268ca998443af..5e86038f2ea5f 100644
> --- a/drivers/pci/pci-acpi.c
> +++ b/drivers/pci/pci-acpi.c
> @@ -245,21 +245,6 @@ static acpi_status decode_type1_hpx_record(union acpi_object *record,
> return AE_OK;
> }
>
> -static bool pcie_root_rcb_set(struct pci_dev *dev)
> -{
> - struct pci_dev *rp = pcie_find_root_port(dev);
> - u16 lnkctl;
> -
> - if (!rp)
> - return false;
> -
> - pcie_capability_read_word(rp, PCI_EXP_LNKCTL, &lnkctl);
> - if (lnkctl & PCI_EXP_LNKCTL_RCB)
> - return true;
> -
> - return false;
> -}
> -
> /* _HPX PCI Express Setting Record (Type 2) */
> struct hpx_type2 {
> u32 revision;
> @@ -285,6 +270,7 @@ static void program_hpx_type2(struct pci_dev *dev, struct hpx_type2 *hpx)
> {
> int pos;
> u32 reg32;
> + const struct pci_host_bridge *host;
>
> if (!hpx)
> return;
> @@ -292,6 +278,15 @@ static void program_hpx_type2(struct pci_dev *dev, struct hpx_type2 *hpx)
> if (!pci_is_pcie(dev))
> return;
>
> + host = pci_find_host_bridge(dev->bus);
> +
> + /*
> + * Only do the _HPX Type 2 programming if OS owns PCIe native
> + * hotplug but not AER.
> + */
> + if (!host->native_pcie_hotplug || host->native_aer)
> + return;
> +
> if (hpx->revision > 1) {
> pci_warn(dev, "PCIe settings rev %d not supported\n",
> hpx->revision);
> @@ -299,33 +294,27 @@ static void program_hpx_type2(struct pci_dev *dev, struct hpx_type2 *hpx)
> }
>
> /*
> - * Don't allow _HPX to change MPS or MRRS settings. We manage
> - * those to make sure they're consistent with the rest of the
> - * platform.
> + * We only allow _HPX to program DEVCTL bits related to AER, namely
> + * PCI_EXP_DEVCTL_CERE, PCI_EXP_DEVCTL_NFERE, PCI_EXP_DEVCTL_FERE,
> + * and PCI_EXP_DEVCTL_URRE.
> + *
> + * The rest of DEVCTL is managed by the OS to make sure it's
> + * consistent with the rest of the platform.
> */
> - hpx->pci_exp_devctl_and |= PCI_EXP_DEVCTL_PAYLOAD |
> - PCI_EXP_DEVCTL_READRQ;
> - hpx->pci_exp_devctl_or &= ~(PCI_EXP_DEVCTL_PAYLOAD |
> - PCI_EXP_DEVCTL_READRQ);
> + hpx->pci_exp_devctl_and |= ~PCI_EXP_AER_FLAGS;
> + hpx->pci_exp_devctl_or &= PCI_EXP_AER_FLAGS;
>
> /* Initialize Device Control Register */
> pcie_capability_clear_and_set_word(dev, PCI_EXP_DEVCTL,
> ~hpx->pci_exp_devctl_and, hpx->pci_exp_devctl_or);
>
> - /* Initialize Link Control Register */
> + /* Log if _HPX attempts to modify Link Control Register */
> if (pcie_cap_has_lnkctl(dev)) {
> -
> - /*
> - * If the Root Port supports Read Completion Boundary of
> - * 128, set RCB to 128. Otherwise, clear it.
> - */
> - hpx->pci_exp_lnkctl_and |= PCI_EXP_LNKCTL_RCB;
> - hpx->pci_exp_lnkctl_or &= ~PCI_EXP_LNKCTL_RCB;
> - if (pcie_root_rcb_set(dev))
> - hpx->pci_exp_lnkctl_or |= PCI_EXP_LNKCTL_RCB;
> -
> - pcie_capability_clear_and_set_word(dev, PCI_EXP_LNKCTL,
> - ~hpx->pci_exp_lnkctl_and, hpx->pci_exp_lnkctl_or);
> + if (hpx->pci_exp_lnkctl_and != 0xffff ||
> + hpx->pci_exp_lnkctl_or != 0)
> + pci_info(dev, "_HPX attempts Link Control setting (AND %#06x OR %#06x)\n",
> + hpx->pci_exp_lnkctl_and,
> + hpx->pci_exp_lnkctl_or);
> }
>
> /* Find Advanced Error Reporting Enhanced Capability */
> diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
> index d9d7a79e3563e..e1614c8dc04bb 100644
> --- a/drivers/pci/pci.h
> +++ b/drivers/pci/pci.h
> @@ -11,6 +11,9 @@
>
> #define PCI_VSEC_ID_INTEL_TBT 0x1234 /* Thunderbolt */
>
> +#define PCI_EXP_AER_FLAGS (PCI_EXP_DEVCTL_CERE | PCI_EXP_DEVCTL_NFERE | \
> + PCI_EXP_DEVCTL_FERE | PCI_EXP_DEVCTL_URRE)
> +
> extern const unsigned char pcie_link_speed[];
> extern bool pci_early_dump;
>
> diff --git a/drivers/pci/pcie/aer.c b/drivers/pci/pcie/aer.c
> index a8bec1c3c769a..9b86df5b82359 100644
> --- a/drivers/pci/pcie/aer.c
> +++ b/drivers/pci/pcie/aer.c
> @@ -214,9 +214,6 @@ void pcie_ecrc_get_policy(char *str)
> }
> #endif /* CONFIG_PCIE_ECRC */
>
> -#define PCI_EXP_AER_FLAGS (PCI_EXP_DEVCTL_CERE | PCI_EXP_DEVCTL_NFERE | \
> - PCI_EXP_DEVCTL_FERE | PCI_EXP_DEVCTL_URRE)
> -
> int pcie_aer_is_native(struct pci_dev *dev)
> {
> struct pci_host_bridge *host = pci_find_host_bridge(dev->bus);
> --
> 2.43.5
^ permalink raw reply
* Re: [PATCH] vmalloc: fix buffer overflow in vrealloc_node_align()
From: Uladzislau Rezki @ 2026-04-20 12:17 UTC (permalink / raw)
To: Marco Elver
Cc: Vlastimil Babka, Andrew Morton, Uladzislau Rezki, linux-mm,
linux-kernel, kasan-dev, Vitaly Wool, stable, Harry Yoo (Oracle)
In-Reply-To: <20260420114805.3572606-2-elver@google.com>
On Mon, Apr 20, 2026 at 01:47:26PM +0200, Marco Elver wrote:
> Commit 4c5d3365882d ("mm/vmalloc: allow to set node and align in
> vrealloc") added the ability to force a new allocation if the current
> pointer is on the wrong NUMA node, or if an alignment constraint is not
> met, even if the user is shrinking the allocation.
>
> On this path (need_realloc), the code allocates a new object of 'size'
> bytes and then memcpy()s 'old_size' bytes into it. If the request is to
> shrink the object (size < old_size), this results in an out-of-bounds
> write on the new buffer.
>
> Fix this by bounding the copy length by the new allocation size.
>
> Fixes: 4c5d3365882d ("mm/vmalloc: allow to set node and align in vrealloc")
> Cc: <stable@vger.kernel.org>
> Reported-by: Harry Yoo (Oracle) <harry@kernel.org>
> Signed-off-by: Marco Elver <elver@google.com>
> ---
> mm/vmalloc.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/mm/vmalloc.c b/mm/vmalloc.c
> index 61caa55a4402..8b1124158f54 100644
> --- a/mm/vmalloc.c
> +++ b/mm/vmalloc.c
> @@ -4361,7 +4361,7 @@ void *vrealloc_node_align_noprof(const void *p, size_t size, unsigned long align
> return NULL;
>
> if (p) {
> - memcpy(n, p, old_size);
> + memcpy(n, p, min(size, old_size));
> vfree(p);
> }
>
> --
> 2.54.0.rc1.513.gad8abe7a5a-goog
>
Agree with a problem described in commit message:
Reviewed-by: Uladzislau Rezki (Sony) <urezki@gmail.com>
Thank you for fixing it!
--
Uladzislau Rezki
^ permalink raw reply
* [PATCH v2 2/4] drm/hibmc: Fix list of formats on the primary plane
From: Thomas Zimmermann @ 2026-04-20 12:09 UTC (permalink / raw)
To: xinliang.liu, tiantao6, kong.kongxinwei, sumit.semwal,
yongqin.liu, jstultz, maarten.lankhorst, mripard, airlied, simona
Cc: dri-devel, Thomas Zimmermann, Yongbang Shi, Rongrong Zou,
Sean Paul, Dmitry Baryshkov, Baihan Li, stable
In-Reply-To: <20260420121130.200133-1-tzimmermann@suse.de>
Remove all formats from the primary plane that are unsupported for
various reasons.
* Formats with alpha channel: planes should not announce alpha channels
unless they support transparency. There's no transparency support in
the primary plane's implementation.
* Formats with BGR order. The common format is in RGB channel order.
There's no BGR support in the primary plane's implementation.
* RGB888: atomic_update programs the format from cpp[0] * 8 / 16. For
RGB888's cpp value of 3 this returns 1.5; rounded to 1. Programming
the value of 1 to HIBMC_CRT_DISP_CTL_FORMAT sets up RGB565. Hence, the
output is distorted. This can be tested by booting with video=1024x768-24.
Removing all unsupported formats leaves XRGB8888 and RGB565. Both of
which are supported and work correctly.
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Fixes: da52605eea8f ("drm/hisilicon/hibmc: Add support for display engine")
Reviewed-by: Yongbang Shi <shiyongbang@huawei.com>
Cc: Rongrong Zou <zourongrong@gmail.com>
Cc: Sean Paul <seanpaul@chromium.org>
Cc: Xinliang Liu <xinliang.liu@linaro.org>
Cc: Dmitry Baryshkov <lumag@kernel.org>
Cc: Yongbang Shi <shiyongbang@huawei.com>
Cc: Baihan Li <libaihan@huawei.com>
Cc: <stable@vger.kernel.org> # v4.10+
---
drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c
index 8fa2a95bcdd1..c4f9ebd9250d 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c
@@ -118,10 +118,8 @@ static void hibmc_plane_atomic_update(struct drm_plane *plane,
}
static const u32 channel_formats1[] = {
- DRM_FORMAT_RGB565, DRM_FORMAT_BGR565, DRM_FORMAT_RGB888,
- DRM_FORMAT_BGR888, DRM_FORMAT_XRGB8888, DRM_FORMAT_XBGR8888,
- DRM_FORMAT_RGBA8888, DRM_FORMAT_BGRA8888, DRM_FORMAT_ARGB8888,
- DRM_FORMAT_ABGR8888
+ DRM_FORMAT_XRGB8888,
+ DRM_FORMAT_RGB565,
};
static const struct drm_plane_funcs hibmc_plane_funcs = {
--
2.53.0
^ permalink raw reply related
* [PATCH v2 1/4] drm/hibmc: Use drm_atomic_helper_check_plane_state()
From: Thomas Zimmermann @ 2026-04-20 12:09 UTC (permalink / raw)
To: xinliang.liu, tiantao6, kong.kongxinwei, sumit.semwal,
yongqin.liu, jstultz, maarten.lankhorst, mripard, airlied, simona
Cc: dri-devel, Thomas Zimmermann, Rongrong Zou, Sean Paul,
Dmitry Baryshkov, Baihan Li, Yongbang Shi, stable
In-Reply-To: <20260420121130.200133-1-tzimmermann@suse.de>
Call drm_atomic_helper_check_plane_state() from the primary plane's
atomic-check helper and replace the custom implementation.
All plane's implementations of atomic_check should call the shared
_check_plane_state() helper first. It adjusts the plane state for
correct positioning, rotation and scaling of the plane. Do this
even if the plane's CRTC has been disabled by setting the parameter
can_update_disabled. The original code returned early in this case,
but it's safe to so and cleaner to have all plane state initialized.
As we don't set can_position, drm_atomic_helper_check_plane_state()'s
visibility check tests if the plane covers all of the CRTC. This is
a small change from the original code, which tested if the plane is
exactly the size of the CRTC. With the new test, the plane still has
to cover all of the CRTC, but can be larger than the CRTC's size. A
later patch can fully implement this feature in hibmc.
If the plane is disabled, the helper clears the visibility flag in the
plane state. On errors or if the plane is not visible, the atomic-check
helper can return early. Implement all this in hibmc and drop the custom
code that does some of it.
v2:
- extend the commit description (Yongbang)
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Fixes: da52605eea8f ("drm/hisilicon/hibmc: Add support for display engine")
Cc: Rongrong Zou <zourongrong@gmail.com>
Cc: Sean Paul <seanpaul@chromium.org>
Cc: Xinliang Liu <xinliang.liu@linaro.org>
Cc: Dmitry Baryshkov <lumag@kernel.org>
Cc: Baihan Li <libaihan@huawei.com>
Cc: Yongbang Shi <shiyongbang@huawei.com>
Cc: <stable@vger.kernel.org> # v4.10+
---
.../gpu/drm/hisilicon/hibmc/hibmc_drm_de.c | 46 ++++++-------------
1 file changed, 14 insertions(+), 32 deletions(-)
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c
index 89bed78f1466..8fa2a95bcdd1 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c
@@ -55,46 +55,28 @@ static const struct hibmc_dislay_pll_config hibmc_pll_table[] = {
static int hibmc_plane_atomic_check(struct drm_plane *plane,
struct drm_atomic_state *state)
{
- struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state,
- plane);
- struct drm_framebuffer *fb = new_plane_state->fb;
- struct drm_crtc *crtc = new_plane_state->crtc;
- struct drm_crtc_state *crtc_state;
- u32 src_w = new_plane_state->src_w >> 16;
- u32 src_h = new_plane_state->src_h >> 16;
-
- if (!crtc || !fb)
- return 0;
+ struct drm_plane_state *new_plane_state =
+ drm_atomic_get_new_plane_state(state, plane);
+ struct drm_crtc_state *new_crtc_state = NULL;
+ int ret;
- crtc_state = drm_atomic_get_crtc_state(state, crtc);
- if (IS_ERR(crtc_state))
- return PTR_ERR(crtc_state);
+ if (new_plane_state->crtc)
+ new_crtc_state = drm_atomic_get_new_crtc_state(state, new_plane_state->crtc);
- if (src_w != new_plane_state->crtc_w || src_h != new_plane_state->crtc_h) {
- drm_dbg_atomic(plane->dev, "scale not support\n");
- return -EINVAL;
- }
-
- if (new_plane_state->crtc_x < 0 || new_plane_state->crtc_y < 0) {
- drm_dbg_atomic(plane->dev, "crtc_x/y of drm_plane state is invalid\n");
- return -EINVAL;
- }
-
- if (!crtc_state->enable)
+ ret = drm_atomic_helper_check_plane_state(new_plane_state, new_crtc_state,
+ DRM_PLANE_NO_SCALING,
+ DRM_PLANE_NO_SCALING,
+ false, true);
+ if (ret)
+ return ret;
+ else if (!new_plane_state->visible)
return 0;
- if (new_plane_state->crtc_x + new_plane_state->crtc_w >
- crtc_state->adjusted_mode.hdisplay ||
- new_plane_state->crtc_y + new_plane_state->crtc_h >
- crtc_state->adjusted_mode.vdisplay) {
- drm_dbg_atomic(plane->dev, "visible portion of plane is invalid\n");
- return -EINVAL;
- }
-
if (new_plane_state->fb->pitches[0] % 128 != 0) {
drm_dbg_atomic(plane->dev, "wrong stride with 128-byte aligned\n");
return -EINVAL;
}
+
return 0;
}
--
2.53.0
^ permalink raw reply related
* [PATCH 6.1.y] ublk: fix deadlock when reading partition table
From: Ruohan Lan @ 2026-04-20 12:01 UTC (permalink / raw)
To: gregkh, sashal, stable
Cc: linux-block, Ming Lei, Caleb Sander Mateos, Jens Axboe,
Ruohan Lan
From: Ming Lei <ming.lei@redhat.com>
[ Upstream commit c258f5c4502c9667bccf5d76fa731ab9c96687c1 ]
When one process(such as udev) opens ublk block device (e.g., to read
the partition table via bdev_open()), a deadlock[1] can occur:
1. bdev_open() grabs disk->open_mutex
2. The process issues read I/O to ublk backend to read partition table
3. In __ublk_complete_rq(), blk_update_request() or blk_mq_end_request()
runs bio->bi_end_io() callbacks
4. If this triggers fput() on file descriptor of ublk block device, the
work may be deferred to current task's task work (see fput() implementation)
5. This eventually calls blkdev_release() from the same context
6. blkdev_release() tries to grab disk->open_mutex again
7. Deadlock: same task waiting for a mutex it already holds
The fix is to run blk_update_request() and blk_mq_end_request() with bottom
halves disabled. This forces blkdev_release() to run in kernel work-queue
context instead of current task work context, and allows ublk server to make
forward progress, and avoids the deadlock.
Fixes: 71f28f3136af ("ublk_drv: add io_uring based userspace block driver")
Link: https://github.com/ublk-org/ublksrv/issues/170 [1]
Signed-off-by: Ming Lei <ming.lei@redhat.com>
Reviewed-by: Caleb Sander Mateos <csander@purestorage.com>
[axboe: rewrite comment in ublk]
Signed-off-by: Jens Axboe <axboe@kernel.dk>
[ The fix omits the change in __ublk_do_auto_buf_reg() since this function
doesn't exist in 6.1. ]
Signed-off-by: Ruohan Lan <ruohanlan@aliyun.com>
---
drivers/block/ublk_drv.c | 28 ++++++++++++++++++++++++++--
1 file changed, 26 insertions(+), 2 deletions(-)
diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c
index 121b62f8bb0a..00d29a3c3d28 100644
--- a/drivers/block/ublk_drv.c
+++ b/drivers/block/ublk_drv.c
@@ -603,12 +603,20 @@ static inline bool ubq_daemon_is_dying(struct ublk_queue *ubq)
return ubq->ubq_daemon->flags & PF_EXITING;
}
+static void ublk_end_request(struct request *req, blk_status_t error)
+{
+ local_bh_disable();
+ blk_mq_end_request(req, error);
+ local_bh_enable();
+}
+
/* todo: handle partial completion */
static void ublk_complete_rq(struct request *req)
{
struct ublk_queue *ubq = req->mq_hctx->driver_data;
struct ublk_io *io = &ubq->ios[req->tag];
unsigned int unmapped_bytes;
+ bool requeue;
/* failed read IO if nothing is read */
if (!io->res && req_op(req) == REQ_OP_READ)
@@ -641,7 +649,23 @@ static void ublk_complete_rq(struct request *req)
if (unlikely(unmapped_bytes < io->res))
io->res = unmapped_bytes;
- if (blk_update_request(req, BLK_STS_OK, io->res))
+ /*
+ * Run bio->bi_end_io() with softirqs disabled. If the final fput
+ * happens off this path, then that will prevent ublk's blkdev_release()
+ * from being called on current's task work, see fput() implementation.
+ *
+ * Otherwise, ublk server may not provide forward progress in case of
+ * reading the partition table from bdev_open() with disk->open_mutex
+ * held, and causes dead lock as we could already be holding
+ * disk->open_mutex here.
+ *
+ * Preferably we would not be doing IO with a mutex held that is also
+ * used for release, but this work-around will suffice for now.
+ */
+ local_bh_disable();
+ requeue = blk_update_request(req, BLK_STS_OK, io->res);
+ local_bh_enable();
+ if (requeue)
blk_mq_requeue_request(req, true);
else
__blk_mq_end_request(req, BLK_STS_OK);
@@ -694,7 +718,7 @@ static inline void __ublk_abort_rq(struct ublk_queue *ubq,
if (ublk_queue_can_use_recovery(ubq))
blk_mq_requeue_request(rq, false);
else
- blk_mq_end_request(rq, BLK_STS_IOERR);
+ ublk_end_request(rq, BLK_STS_IOERR);
mod_delayed_work(system_wq, &ubq->dev->monitor_work, 0);
}
--
2.43.0
^ permalink raw reply related
* [PATCH v2] btrfs: check and set EXTENT_DELALLOC_NEW before clearing EXTENT_DELALLOC
From: Qu Wenruo @ 2026-04-20 11:50 UTC (permalink / raw)
To: linux-btrfs; +Cc: stable
[WARNING]
When running test cases with injected errors or shutdown, e.g.
generic/388 or generic/475, there is a chance that the following kernel
warning is triggered:
BTRFS info (device dm-2): first mount of filesystem d8a19a28-3232-4809-b0df-38df83e71bff
BTRFS info (device dm-2): using crc32c checksum algorithm
BTRFS info (device dm-2): checking UUID tree
BTRFS info (device dm-2): turning on async discard
BTRFS info (device dm-2): enabling free space tree
BTRFS critical (device dm-2 state E): emergency shutdown
------------[ cut here ]------------
WARNING: extent_io.c:1742 at extent_writepage_io+0x437/0x520 [btrfs], CPU#2: kworker/u43:2/651591
CPU: 2 UID: 0 PID: 651591 Comm: kworker/u43:2 Tainted: G W OE 7.0.0-rc6-custom+ #365 PREEMPT(full) 5804053f02137e627472d94b5128cc9fcb110e88
RIP: 0010:extent_writepage_io+0x437/0x520 [btrfs]
Call Trace:
<TASK>
extent_write_cache_pages+0x2a5/0x820 [btrfs 70299925d0856939e93b17d480651713b3cbba58]
btrfs_writepages+0x74/0x130 [btrfs 70299925d0856939e93b17d480651713b3cbba58]
do_writepages+0xd0/0x160
__writeback_single_inode+0x42/0x340
writeback_sb_inodes+0x22d/0x580
wb_writeback+0xc6/0x360
wb_workfn+0xbd/0x470
process_one_work+0x198/0x3b0
worker_thread+0x1c8/0x330
kthread+0xee/0x120
ret_from_fork+0x2a6/0x330
ret_from_fork_asm+0x11/0x20
</TASK>
---[ end trace 0000000000000000 ]---
BTRFS error (device dm-2 state E): root 5 ino 259 folio 1323008 is marked dirty without notifying the fs
BTRFS error (device dm-2 state E): failed to submit blocks, root=5 inode=259 folio=1323008 submit_bitmap=0: -117
BTRFS info (device dm-2 state E): last unmount of filesystem d8a19a28-3232-4809-b0df-38df83e71bff
[CAUSE]
Inside btrfs we have the following pattern in several locations, for
example inside btrfs_dirty_folio():
btrfs_clear_extent_bit(&inode->io_tree, start_pos, end_of_last_block,
EXTENT_DELALLOC | EXTENT_DO_ACCOUNTING | EXTENT_DEFRAG,
cached);
ret = btrfs_set_extent_delalloc(inode, start_pos, end_of_last_block,
extra_bits, cached);
if (ret)
return ret;
However btrfs_set_extent_delalloc() can return IO errors other than -ENOMEM
through the following callchain:
btrfs_set_extent_delalloc()
\- btrfs_find_new_delalloc_bytes()
\- btrfs_get_extent()
\- btrfs_lookup_file_extent()
\- btrfs_search_slot()
When such IO error happened, the previous btrfs_clear_extent_bit() has
cleared the EXTENT_DELALLOC for the range, and we're expecting
btrfs_set_extent_delalloc() to re-set EXTENT_DELALLOC.
But since btrfs_set_extent_delalloc() failed before
btrfs_set_extent_bit(), EXTENT_DELALLOC flag is no longere present.
And if the folio range is dirty before entering
btrfs_set_extent_delalloc(), we got a dirty folio but no EXTENT_DELALLOC
flag now.
Then we hit the folio writeback:
extent_writepage()
|- writepage_delalloc()
| No ordered extent is created, as there is no EXTENT_DELALLOC set
| for the folio range.
| This also means the folio has no ordered flag set.
|
|- extent_writepage_io()
\- if (unlikely(!folio_test_ordered(folio))
Now we hit the warning.
[FIX]
Introduce a new helper, btrfs_reset_extent_delalloc() to replace the
currently open-coded btrfs_clear_extent_bit() +
btrfs_set_extent_delalloc() combination.
Instead of calling btrfs_clear_extent_bit() first, update
EXTENT_DELALLOC_NEW first, as that part can fail due to metadata IO,
meanwhile btrfs_clear_extent_bit() and btrfs_set_extent_bit() can really
only fail with -ENOMEM.
This allows us to fail early without clearing EXTENT_DELALLOC bit, so
even if that new btrfs_reset_extent_delalloc() failed before touching
EXTENT_DELALLOC, the existing dirty range will still have their old
EXTENT_DELALLOC flag present, thus avoid the warning.
Cc: stable@vger.kernel.org # 6.1+
Signed-off-by: Qu Wenruo <wqu@suse.com>
---
Changelog:
v2:
- Use NULL as @cached_extent for btrfs_find_new_delalloc_bytes()
Unlike later btrfs_clear_extent_bit(), btrfs_find_new_delalloc_bytes()
can hit several different extent maps and update @cached_state.
This makes later btrfs_set/clear_extent_bit() to discard the cache,
making the original optimization less useful.
---
fs/btrfs/btrfs_inode.h | 3 +++
fs/btrfs/file.c | 25 +++---------------
fs/btrfs/inode.c | 58 +++++++++++++++++++++++++++++++++++++-----
fs/btrfs/reflink.c | 4 +--
4 files changed, 58 insertions(+), 32 deletions(-)
diff --git a/fs/btrfs/btrfs_inode.h b/fs/btrfs/btrfs_inode.h
index 6e696b350dc5..ad523549d8b4 100644
--- a/fs/btrfs/btrfs_inode.h
+++ b/fs/btrfs/btrfs_inode.h
@@ -569,6 +569,9 @@ int btrfs_start_delalloc_roots(struct btrfs_fs_info *fs_info, long nr,
int btrfs_set_extent_delalloc(struct btrfs_inode *inode, u64 start, u64 end,
unsigned int extra_bits,
struct extent_state **cached_state);
+int btrfs_reset_extent_delalloc(struct btrfs_inode *inode, u64 start, u64 end,
+ unsigned int extra_bits,
+ struct extent_state **cached_state);
struct btrfs_new_inode_args {
/* Input */
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index a6f641a41d99..ab536a304500 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -85,16 +85,8 @@ int btrfs_dirty_folio(struct btrfs_inode *inode, struct folio *folio, loff_t pos
end_of_last_block = start_pos + num_bytes - 1;
- /*
- * The pages may have already been dirty, clear out old accounting so
- * we can set things up properly
- */
- btrfs_clear_extent_bit(&inode->io_tree, start_pos, end_of_last_block,
- EXTENT_DELALLOC | EXTENT_DO_ACCOUNTING | EXTENT_DEFRAG,
- cached);
-
- ret = btrfs_set_extent_delalloc(inode, start_pos, end_of_last_block,
- extra_bits, cached);
+ ret = btrfs_reset_extent_delalloc(inode, start_pos, end_of_last_block,
+ extra_bits, cached);
if (ret)
return ret;
@@ -1952,18 +1944,7 @@ static vm_fault_t btrfs_page_mkwrite(struct vm_fault *vmf)
}
}
- /*
- * page_mkwrite gets called when the page is firstly dirtied after it's
- * faulted in, but write(2) could also dirty a page and set delalloc
- * bits, thus in this case for space account reason, we still need to
- * clear any delalloc bits within this page range since we have to
- * reserve data&meta space before lock_page() (see above comments).
- */
- btrfs_clear_extent_bit(io_tree, page_start, end,
- EXTENT_DELALLOC | EXTENT_DO_ACCOUNTING |
- EXTENT_DEFRAG, &cached_state);
-
- ret = btrfs_set_extent_delalloc(inode, page_start, end, 0, &cached_state);
+ ret = btrfs_reset_extent_delalloc(inode, page_start, end, 0, &cached_state);
if (ret < 0) {
btrfs_unlock_extent(io_tree, page_start, page_end, &cached_state);
goto out_unlock;
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 71129502333a..ec2300698a6a 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -2810,7 +2810,10 @@ int btrfs_set_extent_delalloc(struct btrfs_inode *inode, u64 start, u64 end,
unsigned int extra_bits,
struct extent_state **cached_state)
{
- WARN_ON(PAGE_ALIGNED(end));
+ const u32 blocksize = inode->root->fs_info->sectorsize;
+
+ ASSERT(IS_ALIGNED(start, blocksize), "start=%llu", start);
+ ASSERT(IS_ALIGNED(end + 1, blocksize), "end=%llu", end);
if (start >= i_size_read(&inode->vfs_inode) &&
!(inode->flags & BTRFS_INODE_PREALLOC)) {
@@ -2833,6 +2836,52 @@ int btrfs_set_extent_delalloc(struct btrfs_inode *inode, u64 start, u64 end,
EXTENT_DELALLOC | extra_bits, cached_state);
}
+/*
+ * Clear the old accounting flags and set EXTENT_DELALLOC for the range.
+ *
+ * Return <0 for error, in that case no range has EXTENT_DELALLOC bit cleared or set.
+ */
+int btrfs_reset_extent_delalloc(struct btrfs_inode *inode, u64 start, u64 end,
+ unsigned int extra_bits,
+ struct extent_state **cached_state)
+{
+ const u32 blocksize = inode->root->fs_info->sectorsize;
+
+ /* The @extra_bits can only be EXTENT_NORESERVE for now. */
+ ASSERT(!(extra_bits & ~EXTENT_NORESERVE));
+
+ /* Basic alignment check. */
+ ASSERT(IS_ALIGNED(start, blocksize), "start=%llu", start);
+ ASSERT(IS_ALIGNED(end + 1, blocksize), "end=%llu", end);
+
+ /*
+ * Check and set DELALLOC_NEW flags, this needs to search tree thus
+ * can fail early.
+ * Thus we want to do this before clearing DELALLOC_EXTENT.
+ */
+ if (start >= i_size_read(&inode->vfs_inode) &&
+ !(inode->flags & BTRFS_INODE_PREALLOC)) {
+ /*
+ * There can't be any extents following eof in this case so just
+ * set the delalloc new bit for the range directly.
+ */
+ extra_bits |= EXTENT_DELALLOC_NEW;
+ } else {
+ int ret;
+
+ ret = btrfs_find_new_delalloc_bytes(inode, start, end + 1 - start,
+ NULL);
+ if (unlikely(ret))
+ return ret;
+ }
+ /* Clear the old accounting as the range may already be dirty. */
+ btrfs_clear_extent_bit(&inode->io_tree, start, end,
+ EXTENT_DELALLOC | EXTENT_DO_ACCOUNTING |
+ EXTENT_DEFRAG, cached_state);
+ return btrfs_set_extent_bit(&inode->io_tree, start, end,
+ EXTENT_DELALLOC | extra_bits, cached_state);
+}
+
static int insert_reserved_file_extent(struct btrfs_trans_handle *trans,
struct btrfs_inode *inode, u64 file_pos,
struct btrfs_file_extent_item *stack_fi,
@@ -4973,12 +5022,7 @@ int btrfs_truncate_block(struct btrfs_inode *inode, u64 offset, u64 start, u64 e
goto again;
}
- btrfs_clear_extent_bit(&inode->io_tree, block_start, block_end,
- EXTENT_DELALLOC | EXTENT_DO_ACCOUNTING | EXTENT_DEFRAG,
- &cached_state);
-
- ret = btrfs_set_extent_delalloc(inode, block_start, block_end, 0,
- &cached_state);
+ ret = btrfs_reset_extent_delalloc(inode, block_start, block_end, 0, &cached_state);
if (ret) {
btrfs_unlock_extent(io_tree, block_start, block_end, &cached_state);
goto out_unlock;
diff --git a/fs/btrfs/reflink.c b/fs/btrfs/reflink.c
index 14742abe0f92..fb34598a77ff 100644
--- a/fs/btrfs/reflink.c
+++ b/fs/btrfs/reflink.c
@@ -94,9 +94,7 @@ static int copy_inline_to_page(struct btrfs_inode *inode,
if (ret < 0)
goto out_unlock;
- btrfs_clear_extent_bit(&inode->io_tree, file_offset, range_end,
- EXTENT_DELALLOC | EXTENT_DO_ACCOUNTING | EXTENT_DEFRAG, NULL);
- ret = btrfs_set_extent_delalloc(inode, file_offset, range_end, 0, NULL);
+ ret = btrfs_reset_extent_delalloc(inode, file_offset, range_end, 0, NULL);
if (ret)
goto out_unlock;
--
2.53.0
^ permalink raw reply related
* [PATCH] vmalloc: fix buffer overflow in vrealloc_node_align()
From: Marco Elver @ 2026-04-20 11:47 UTC (permalink / raw)
To: elver, Vlastimil Babka, Andrew Morton
Cc: Uladzislau Rezki, linux-mm, linux-kernel, kasan-dev, Vitaly Wool,
stable, Harry Yoo (Oracle)
Commit 4c5d3365882d ("mm/vmalloc: allow to set node and align in
vrealloc") added the ability to force a new allocation if the current
pointer is on the wrong NUMA node, or if an alignment constraint is not
met, even if the user is shrinking the allocation.
On this path (need_realloc), the code allocates a new object of 'size'
bytes and then memcpy()s 'old_size' bytes into it. If the request is to
shrink the object (size < old_size), this results in an out-of-bounds
write on the new buffer.
Fix this by bounding the copy length by the new allocation size.
Fixes: 4c5d3365882d ("mm/vmalloc: allow to set node and align in vrealloc")
Cc: <stable@vger.kernel.org>
Reported-by: Harry Yoo (Oracle) <harry@kernel.org>
Signed-off-by: Marco Elver <elver@google.com>
---
mm/vmalloc.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index 61caa55a4402..8b1124158f54 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -4361,7 +4361,7 @@ void *vrealloc_node_align_noprof(const void *p, size_t size, unsigned long align
return NULL;
if (p) {
- memcpy(n, p, old_size);
+ memcpy(n, p, min(size, old_size));
vfree(p);
}
--
2.54.0.rc1.513.gad8abe7a5a-goog
^ permalink raw reply related
* Re: [PATCH] phy: qcom-qmp-ufs: Fix kaanapali PHY PLL lock failure after SM8650 G4 fix
From: Abel Vesa @ 2026-04-20 11:30 UTC (permalink / raw)
To: Nitin Rawat
Cc: vkoul, neil.armstrong, konrad.dybcio, dmitry.baryshkov, mani,
linux-arm-msm, linux-phy, linux-kernel, stable
In-Reply-To: <20260415104851.2763238-1-nitin.rawat@oss.qualcomm.com>
On 26-04-15 16:18:51, Nitin Rawat wrote:
> Commit 81af9e40e2e4 ("phy: qcom: qmp-ufs: Fix SM8650 PCS table for Gear 4")
> moved QPHY_V6_PCS_UFS_PLL_CNTL register configuration from the shared
> sm8650_ufsphy_g5_pcs table to the SM8650-specific sm8650_ufsphy_pcs base
> table to fix Gear 4 operation on SM8650.
>
> However, this change inadvertently broke kaanapali and SM8750 SoCs
> which also rely on the shared sm8650_ufsphy_g5_pcs table for Gear 5
> configuration but use their own sm8750_ufsphy_pcs base table. After the
> change, kaanapali PHYs are left without the required PLL_CNTL = 0x33
> setting, causing the PHY PLL to remain at its hardware reset default
> value, preventing PLL lock and resulting in DME_LINKSTARTUP timeouts.
>
> Fix this by adding the missing QPHY_V6_PCS_UFS_PLL_CNTL = 0x33 entry
> to the sm8750_ufsphy_pcs table, mirroring what the original commit
> already did for sm8650_ufsphy_pcs.
>
> Cc: stable@vger.kernel.org # v6.19.12
> Fixes: 81af9e40e2e4 ("phy: qcom: qmp-ufs: Fix SM8650 PCS table for Gear 4")
> Signed-off-by: Nitin Rawat <nitin.rawat@oss.qualcomm.com>
Reviewed-by: Abel Vesa <abel.vesa@oss.qualcomm.com>
^ permalink raw reply
* Re: [PATCH v1 2/2] drm/panfrost: Fix wait_bo ioctl leaking positive return from dma_resv_wait_timeout()
From: Steven Price @ 2026-04-20 11:18 UTC (permalink / raw)
To: Gyeyoung Baek, Tomeu Vizoso, Boris Brezillon, Rob Herring,
Adrián Larumbe
Cc: Oded Gabbay, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
David Airlie, Simona Vetter, dri-devel, linux-kernel, stable
In-Reply-To: <fe33f82fded7be1c18e2e0eb2db451d5a738cf39.1776581974.git.gye976@gmail.com>
On 19/04/2026 08:17, Gyeyoung Baek wrote:
> dma_resv_wait_timeout() returns a positive 'remaining jiffies' value
> on success, 0 on timeout, and -errno on failure.
>
> panfrost_ioctl_wait_bo() returns this 'long' result from an int-typed
> ioctl handler, so positive values reach userspace as bogus errors.
> Explicitly set ret to 0 on the success path.
>
> Fixes: f3ba91228e8e ("drm/panfrost: Add initial panfrost driver")
> Cc: stable@vger.kernel.org
> Signed-off-by: Gyeyoung Baek <gye976@gmail.com>
Reviewed-by: Steven Price <steven.price@arm.com>
> ---
> drivers/gpu/drm/panfrost/panfrost_drv.c | 2 ++
> 1 file changed, 2 insertions(+)
>
> diff --git a/drivers/gpu/drm/panfrost/panfrost_drv.c b/drivers/gpu/drm/panfrost/panfrost_drv.c
> index 3d0bdba2a..784e36d72 100644
> --- a/drivers/gpu/drm/panfrost/panfrost_drv.c
> +++ b/drivers/gpu/drm/panfrost/panfrost_drv.c
> @@ -390,6 +390,8 @@ panfrost_ioctl_wait_bo(struct drm_device *dev, void *data,
> true, timeout);
> if (!ret)
> ret = timeout ? -ETIMEDOUT : -EBUSY;
> + else if (ret > 0)
> + ret = 0;
>
> drm_gem_object_put(gem_obj);
>
^ permalink raw reply
* [PATCH] wifi: ath11k: fix warning when unbinding
From: Jose Ignacio Tornos Martinez @ 2026-04-20 11:01 UTC (permalink / raw)
To: jjohnson
Cc: linux-wireless, ath11k, linux-kernel,
Jose Ignacio Tornos Martinez, stable
If there is an error during some initialization related to firmware,
the buffers dp->tx_ring[i].tx_status are released.
However this is released again when the device is unbinded (ath11k_pci),
and we get:
WARNING: CPU: 0 PID: 6231 at mm/slub.c:4368 free_large_kmalloc+0x57/0x90
Call Trace:
free_large_kmalloc
ath11k_dp_free
ath11k_core_deinit
ath11k_pci_remove
...
The issue is always reproducible from a VM because the MSI addressing
initialization is failing.
In order to fix the issue, just set the buffers to NULL after releasing in
order to avoid the double free.
Fixes: d5c65159f289 ("ath11k: driver for Qualcomm IEEE 802.11ax devices")
Cc: stable@vger.kernel.org
Signed-off-by: Jose Ignacio Tornos Martinez <jtornosm@redhat.com>
---
drivers/net/wireless/ath/ath11k/dp.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/net/wireless/ath/ath11k/dp.c b/drivers/net/wireless/ath/ath11k/dp.c
index bbb86f165141..5a50b623bd07 100644
--- a/drivers/net/wireless/ath/ath11k/dp.c
+++ b/drivers/net/wireless/ath/ath11k/dp.c
@@ -1040,6 +1040,7 @@ void ath11k_dp_free(struct ath11k_base *ab)
idr_destroy(&dp->tx_ring[i].txbuf_idr);
spin_unlock_bh(&dp->tx_ring[i].tx_idr_lock);
kfree(dp->tx_ring[i].tx_status);
+ dp->tx_ring[i].tx_status = NULL;
}
/* Deinit any SOC level resource */
--
2.53.0
^ permalink raw reply related
* [PATCH net] netconsole: avoid out-of-bounds access on empty string in trim_newline()
From: Breno Leitao @ 2026-04-20 10:18 UTC (permalink / raw)
To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Matthew Wood
Cc: netdev, linux-kernel, kernel-team, stable, Breno Leitao
trim_newline() unconditionally dereferences s[len - 1] after computing
len = strnlen(s, maxlen). When the string is empty, len is 0 and the
expression underflows to s[(size_t)-1], reading (and potentially
writing) one byte before the buffer.
The two callers feed trim_newline() with the result of strscpy() from
configfs store callbacks (dev_name_store, userdatum_value_store).
configfs guarantees count >= 1 reaches the callback, but the byte
itself can be NUL: a userspace write(fd, "\0", 1) leaves the
destination empty after strscpy() and triggers the underflow. The OOB
write only fires if the adjacent byte happens to be '\n', so this is
not a security issue, but the access is undefined behaviour either way.
This pattern is commonly flagged by LLM-based code reviewers. While it
is not a security fix, the underlying access is undefined behaviour and
the change is small and self-contained, so it is a reasonable candidate
for the stable trees.
Guard the dereference on a non-zero length.
Fixes: ae001dc67907 ("net: netconsole: move newline trimming to function")
Cc: stable@vger.kernel.org
Signed-off-by: Breno Leitao <leitao@debian.org>
---
drivers/net/netconsole.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c
index 3c9acd6e49e86..205384dab89a6 100644
--- a/drivers/net/netconsole.c
+++ b/drivers/net/netconsole.c
@@ -497,6 +497,8 @@ static void trim_newline(char *s, size_t maxlen)
size_t len;
len = strnlen(s, maxlen);
+ if (!len)
+ return;
if (s[len - 1] == '\n')
s[len - 1] = '\0';
}
---
base-commit: c7275b05bc428c7373d97aa2da02d3a7fa6b9f66
change-id: 20260420-netcons_trim_newline-36f6ec3b9820
Best regards,
--
Breno Leitao <leitao@debian.org>
^ permalink raw reply related
* Re: [PATCH] phy: qcom-qmp-ufs: Fix kaanapali PHY PLL lock failure after SM8650 G4 fix
From: Manivannan Sadhasivam @ 2026-04-20 9:44 UTC (permalink / raw)
To: Nitin Rawat
Cc: vkoul, neil.armstrong, konrad.dybcio, dmitry.baryshkov, abel.vesa,
linux-arm-msm, linux-phy, linux-kernel, stable
In-Reply-To: <20260415104851.2763238-1-nitin.rawat@oss.qualcomm.com>
On Wed, Apr 15, 2026 at 04:18:51PM +0530, Nitin Rawat wrote:
> Commit 81af9e40e2e4 ("phy: qcom: qmp-ufs: Fix SM8650 PCS table for Gear 4")
> moved QPHY_V6_PCS_UFS_PLL_CNTL register configuration from the shared
> sm8650_ufsphy_g5_pcs table to the SM8650-specific sm8650_ufsphy_pcs base
> table to fix Gear 4 operation on SM8650.
>
> However, this change inadvertently broke kaanapali and SM8750 SoCs
> which also rely on the shared sm8650_ufsphy_g5_pcs table for Gear 5
> configuration but use their own sm8750_ufsphy_pcs base table. After the
> change, kaanapali PHYs are left without the required PLL_CNTL = 0x33
> setting, causing the PHY PLL to remain at its hardware reset default
> value, preventing PLL lock and resulting in DME_LINKSTARTUP timeouts.
>
> Fix this by adding the missing QPHY_V6_PCS_UFS_PLL_CNTL = 0x33 entry
> to the sm8750_ufsphy_pcs table, mirroring what the original commit
> already did for sm8650_ufsphy_pcs.
>
> Cc: stable@vger.kernel.org # v6.19.12
> Fixes: 81af9e40e2e4 ("phy: qcom: qmp-ufs: Fix SM8650 PCS table for Gear 4")
> Signed-off-by: Nitin Rawat <nitin.rawat@oss.qualcomm.com>
Reviewed-by: Manivannan Sadhasivam <mani@kernel.org>
- Mani
> ---
> drivers/phy/qualcomm/phy-qcom-qmp-ufs.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c b/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c
> index 771bc7c2ab50..b87314c8379d 100644
> --- a/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c
> +++ b/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c
> @@ -1112,6 +1112,7 @@ static const struct qmp_phy_init_tbl sm8750_ufsphy_pcs[] = {
> QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_MULTI_LANE_CTRL1, 0x02),
> QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_TX_MID_TERM_CTRL1, 0x43),
> QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_PCS_CTRL1, 0x40),
> + QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_PLL_CNTL, 0x33),
> QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_TX_LARGE_AMP_DRV_LVL, 0x0f),
> QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_RX_SIGDET_CTRL2, 0x68),
> QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_TX_POST_EMP_LVL_S4, 0x0e),
> --
> 2.34.1
>
--
மணிவண்ணன் சதாசிவம்
^ permalink raw reply
* Re: [PATCH] powerpc/pseries/papr-hvpipe: fix NULL dereference in handle creation
From: Greg KH @ 2026-04-20 9:44 UTC (permalink / raw)
To: Guangshuo Li
Cc: Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
Christophe Leroy (CS GROUP), Mahesh Salgaonkar, Tyrel Datwyler,
Haren Myneni, Christian Brauner, Kees Cook, linuxppc-dev,
linux-kernel, stable
In-Reply-To: <20260420093856.123681-1-lgs201920130244@gmail.com>
On Mon, Apr 20, 2026 at 05:38:56PM +0800, Guangshuo Li wrote:
> papr_hvpipe_dev_create_handle() transfers ownership of src_info with
> retain_and_null_ptr(src_info) after anon_inode_getfile() succeeds.
> However, retain_and_null_ptr() clears src_info immediately, and the
> function then still dereferences src_info in the subsequent list_add().
>
> Store the transferred pointer in a separate variable and use that for
> the list insertion.
>
> Manually identified during code review.
>
> Fixes: 6d3789d347a7af5c4b0b2da3af47b8d9da607ab2 ("papr-hvpipe: convert papr_hvpipe_dev_create_handle() to FD_PREPARE()")
Please use the proper notation here, as the documentation asks you to.
thanks,
greg k-h
^ permalink raw reply
* [PATCH] powerpc/pseries/papr-hvpipe: fix NULL dereference in handle creation
From: Guangshuo Li @ 2026-04-20 9:38 UTC (permalink / raw)
To: Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
Christophe Leroy (CS GROUP), Mahesh Salgaonkar, Tyrel Datwyler,
Haren Myneni, Guangshuo Li, Christian Brauner, Kees Cook,
linuxppc-dev, linux-kernel
Cc: stable
papr_hvpipe_dev_create_handle() transfers ownership of src_info with
retain_and_null_ptr(src_info) after anon_inode_getfile() succeeds.
However, retain_and_null_ptr() clears src_info immediately, and the
function then still dereferences src_info in the subsequent list_add().
Store the transferred pointer in a separate variable and use that for
the list insertion.
Manually identified during code review.
Fixes: 6d3789d347a7af5c4b0b2da3af47b8d9da607ab2 ("papr-hvpipe: convert papr_hvpipe_dev_create_handle() to FD_PREPARE()")
Cc: stable@vger.kernel.org
Signed-off-by: Guangshuo Li <lgs201920130244@gmail.com>
---
arch/powerpc/platforms/pseries/papr-hvpipe.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/platforms/pseries/papr-hvpipe.c b/arch/powerpc/platforms/pseries/papr-hvpipe.c
index 14ae480d060a..497eb967611b 100644
--- a/arch/powerpc/platforms/pseries/papr-hvpipe.c
+++ b/arch/powerpc/platforms/pseries/papr-hvpipe.c
@@ -480,6 +480,7 @@ static const struct file_operations papr_hvpipe_handle_ops = {
static int papr_hvpipe_dev_create_handle(u32 srcID)
{
struct hvpipe_source_info *src_info __free(kfree) = NULL;
+ struct hvpipe_source_info *owned_src_info;
spin_lock(&hvpipe_src_list_lock);
/*
@@ -509,7 +510,7 @@ static int papr_hvpipe_dev_create_handle(u32 srcID)
if (fdf.err)
return fdf.err;
- retain_and_null_ptr(src_info);
+ owned_src_info = retain_and_null_ptr(src_info);
spin_lock(&hvpipe_src_list_lock);
/*
* If two processes are executing ioctl() for the same
@@ -520,7 +521,7 @@ static int papr_hvpipe_dev_create_handle(u32 srcID)
spin_unlock(&hvpipe_src_list_lock);
return -EALREADY;
}
- list_add(&src_info->list, &hvpipe_src_list);
+ list_add(&owned_src_info->list, &hvpipe_src_list);
spin_unlock(&hvpipe_src_list_lock);
return fd_publish(fdf);
}
--
2.43.0
^ permalink raw reply related
* [PATCH] btrfs: check and set EXTENT_DELALLOC_NEW before clearing EXTENT_DELALLOC
From: Qu Wenruo @ 2026-04-20 9:31 UTC (permalink / raw)
To: linux-btrfs; +Cc: stable
[WARNING]
When running test cases with injected errors or shutdown, e.g.
generic/388 or generic/475, there is a chance that the following kernel
warning is triggered:
BTRFS info (device dm-2): first mount of filesystem d8a19a28-3232-4809-b0df-38df83e71bff
BTRFS info (device dm-2): using crc32c checksum algorithm
BTRFS info (device dm-2): checking UUID tree
BTRFS info (device dm-2): turning on async discard
BTRFS info (device dm-2): enabling free space tree
BTRFS critical (device dm-2 state E): emergency shutdown
------------[ cut here ]------------
WARNING: extent_io.c:1742 at extent_writepage_io+0x437/0x520 [btrfs], CPU#2: kworker/u43:2/651591
CPU: 2 UID: 0 PID: 651591 Comm: kworker/u43:2 Tainted: G W OE 7.0.0-rc6-custom+ #365 PREEMPT(full) 5804053f02137e627472d94b5128cc9fcb110e88
RIP: 0010:extent_writepage_io+0x437/0x520 [btrfs]
Call Trace:
<TASK>
extent_write_cache_pages+0x2a5/0x820 [btrfs 70299925d0856939e93b17d480651713b3cbba58]
btrfs_writepages+0x74/0x130 [btrfs 70299925d0856939e93b17d480651713b3cbba58]
do_writepages+0xd0/0x160
__writeback_single_inode+0x42/0x340
writeback_sb_inodes+0x22d/0x580
wb_writeback+0xc6/0x360
wb_workfn+0xbd/0x470
process_one_work+0x198/0x3b0
worker_thread+0x1c8/0x330
kthread+0xee/0x120
ret_from_fork+0x2a6/0x330
ret_from_fork_asm+0x11/0x20
</TASK>
---[ end trace 0000000000000000 ]---
BTRFS error (device dm-2 state E): root 5 ino 259 folio 1323008 is marked dirty without notifying the fs
BTRFS error (device dm-2 state E): failed to submit blocks, root=5 inode=259 folio=1323008 submit_bitmap=0: -117
BTRFS info (device dm-2 state E): last unmount of filesystem d8a19a28-3232-4809-b0df-38df83e71bff
[CAUSE]
Inside btrfs we have the following pattern in several locations, for
example inside btrfs_dirty_folio():
btrfs_clear_extent_bit(&inode->io_tree, start_pos, end_of_last_block,
EXTENT_DELALLOC | EXTENT_DO_ACCOUNTING | EXTENT_DEFRAG,
cached);
ret = btrfs_set_extent_delalloc(inode, start_pos, end_of_last_block,
extra_bits, cached);
if (ret)
return ret;
However btrfs_set_extent_delalloc() can return IO errors other than -ENOMEM
through the following callchain:
btrfs_set_extent_delalloc()
\- btrfs_find_new_delalloc_bytes()
\- btrfs_get_extent()
\- btrfs_lookup_file_extent()
\- btrfs_search_slot()
When such IO error happened, the previous btrfs_clear_extent_bit() has
cleared the EXTENT_DELALLOC for the range, and we're expecting
btrfs_set_extent_delalloc() to re-set EXTENT_DELALLOC.
But since btrfs_set_extent_delalloc() failed before
btrfs_set_extent_bit(), EXTENT_DELALLOC flag is no longere present.
And if the folio range is dirty before entering
btrfs_set_extent_delalloc(), we got a dirty folio but no EXTENT_DELALLOC
flag now.
Then we hit the folio writeback:
extent_writepage()
|- writepage_delalloc()
| No ordered extent is created, as there is no EXTENT_DELALLOC set
| for the folio range.
| This also means the folio has no ordered flag set.
|
|- extent_writepage_io()
\- if (unlikely(!folio_test_ordered(folio))
Now we hit the warning.
[FIX]
Introduce a new helper, btrfs_reset_extent_delalloc() to replace the
currently open-coded btrfs_clear_extent_bit() +
btrfs_set_extent_delalloc() combination.
Instead of calling btrfs_clear_extent_bit() first, update
EXTENT_DELALLOC_NEW first, as that part can fail due to metadata IO,
meanwhile btrfs_clear_extent_bit() and btrfs_set_extent_bit() can really
only fail with -ENOMEM.
This allows us to fail early without clearing EXTENT_DELALLOC bit, so
even if that new btrfs_reset_extent_delalloc() failed before touching
EXTENT_DELALLOC, the existing dirty range will still have their old
EXTENT_DELALLOC flag present, thus avoid the warning.
Cc: stable@vger.kernel.org # 6.1+
Signed-off-by: Qu Wenruo <wqu@suse.com>
---
fs/btrfs/btrfs_inode.h | 3 +++
fs/btrfs/file.c | 25 +++---------------
fs/btrfs/inode.c | 59 +++++++++++++++++++++++++++++++++++++-----
fs/btrfs/reflink.c | 4 +--
4 files changed, 59 insertions(+), 32 deletions(-)
diff --git a/fs/btrfs/btrfs_inode.h b/fs/btrfs/btrfs_inode.h
index 6e696b350dc5..ad523549d8b4 100644
--- a/fs/btrfs/btrfs_inode.h
+++ b/fs/btrfs/btrfs_inode.h
@@ -569,6 +569,9 @@ int btrfs_start_delalloc_roots(struct btrfs_fs_info *fs_info, long nr,
int btrfs_set_extent_delalloc(struct btrfs_inode *inode, u64 start, u64 end,
unsigned int extra_bits,
struct extent_state **cached_state);
+int btrfs_reset_extent_delalloc(struct btrfs_inode *inode, u64 start, u64 end,
+ unsigned int extra_bits,
+ struct extent_state **cached_state);
struct btrfs_new_inode_args {
/* Input */
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index a6f641a41d99..ab536a304500 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -85,16 +85,8 @@ int btrfs_dirty_folio(struct btrfs_inode *inode, struct folio *folio, loff_t pos
end_of_last_block = start_pos + num_bytes - 1;
- /*
- * The pages may have already been dirty, clear out old accounting so
- * we can set things up properly
- */
- btrfs_clear_extent_bit(&inode->io_tree, start_pos, end_of_last_block,
- EXTENT_DELALLOC | EXTENT_DO_ACCOUNTING | EXTENT_DEFRAG,
- cached);
-
- ret = btrfs_set_extent_delalloc(inode, start_pos, end_of_last_block,
- extra_bits, cached);
+ ret = btrfs_reset_extent_delalloc(inode, start_pos, end_of_last_block,
+ extra_bits, cached);
if (ret)
return ret;
@@ -1952,18 +1944,7 @@ static vm_fault_t btrfs_page_mkwrite(struct vm_fault *vmf)
}
}
- /*
- * page_mkwrite gets called when the page is firstly dirtied after it's
- * faulted in, but write(2) could also dirty a page and set delalloc
- * bits, thus in this case for space account reason, we still need to
- * clear any delalloc bits within this page range since we have to
- * reserve data&meta space before lock_page() (see above comments).
- */
- btrfs_clear_extent_bit(io_tree, page_start, end,
- EXTENT_DELALLOC | EXTENT_DO_ACCOUNTING |
- EXTENT_DEFRAG, &cached_state);
-
- ret = btrfs_set_extent_delalloc(inode, page_start, end, 0, &cached_state);
+ ret = btrfs_reset_extent_delalloc(inode, page_start, end, 0, &cached_state);
if (ret < 0) {
btrfs_unlock_extent(io_tree, page_start, page_end, &cached_state);
goto out_unlock;
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 71129502333a..0dc5fe7f7705 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -2810,7 +2810,10 @@ int btrfs_set_extent_delalloc(struct btrfs_inode *inode, u64 start, u64 end,
unsigned int extra_bits,
struct extent_state **cached_state)
{
- WARN_ON(PAGE_ALIGNED(end));
+ const u32 blocksize = inode->root->fs_info->sectorsize;
+
+ ASSERT(IS_ALIGNED(start, blocksize), "start=%llu", start);
+ ASSERT(IS_ALIGNED(end + 1, blocksize), "end=%llu", end);
if (start >= i_size_read(&inode->vfs_inode) &&
!(inode->flags & BTRFS_INODE_PREALLOC)) {
@@ -2833,6 +2836,53 @@ int btrfs_set_extent_delalloc(struct btrfs_inode *inode, u64 start, u64 end,
EXTENT_DELALLOC | extra_bits, cached_state);
}
+/*
+ * Clear the old accounting flags and set EXTENT_DELALLOC for the range.
+ *
+ * Return <0 for error, in that case no range has EXTENT_DELALLOC bit cleared or set.
+ */
+int btrfs_reset_extent_delalloc(struct btrfs_inode *inode, u64 start, u64 end,
+ unsigned int extra_bits,
+ struct extent_state **cached_state)
+{
+ const u32 blocksize = inode->root->fs_info->sectorsize;
+
+ /* The @extra_bits can only be EXTENT_NORESERVE for now. */
+ ASSERT(!(extra_bits & ~EXTENT_NORESERVE));
+
+ /* Basic alignment check. */
+ ASSERT(IS_ALIGNED(start, blocksize), "start=%llu", start);
+ ASSERT(IS_ALIGNED(end + 1, blocksize), "end=%llu", end);
+
+ /*
+ * Check and set DELALLOC_NEW flags, this needs to search tree thus
+ * can fail early.
+ * Thus we want to do this before clearing DELALLOC_EXTENT.
+ */
+ if (start >= i_size_read(&inode->vfs_inode) &&
+ !(inode->flags & BTRFS_INODE_PREALLOC)) {
+ /*
+ * There can't be any extents following eof in this case so just
+ * set the delalloc new bit for the range directly.
+ */
+ extra_bits |= EXTENT_DELALLOC_NEW;
+ } else {
+ int ret;
+
+ ret = btrfs_find_new_delalloc_bytes(inode, start,
+ end + 1 - start,
+ cached_state);
+ if (unlikely(ret))
+ return ret;
+ }
+ /* Clear the old accounting as the range may already be dirty. */
+ btrfs_clear_extent_bit(&inode->io_tree, start, end,
+ EXTENT_DELALLOC | EXTENT_DO_ACCOUNTING |
+ EXTENT_DEFRAG, cached_state);
+ return btrfs_set_extent_bit(&inode->io_tree, start, end,
+ EXTENT_DELALLOC | extra_bits, cached_state);
+}
+
static int insert_reserved_file_extent(struct btrfs_trans_handle *trans,
struct btrfs_inode *inode, u64 file_pos,
struct btrfs_file_extent_item *stack_fi,
@@ -4973,12 +5023,7 @@ int btrfs_truncate_block(struct btrfs_inode *inode, u64 offset, u64 start, u64 e
goto again;
}
- btrfs_clear_extent_bit(&inode->io_tree, block_start, block_end,
- EXTENT_DELALLOC | EXTENT_DO_ACCOUNTING | EXTENT_DEFRAG,
- &cached_state);
-
- ret = btrfs_set_extent_delalloc(inode, block_start, block_end, 0,
- &cached_state);
+ ret = btrfs_reset_extent_delalloc(inode, block_start, block_end, 0, &cached_state);
if (ret) {
btrfs_unlock_extent(io_tree, block_start, block_end, &cached_state);
goto out_unlock;
diff --git a/fs/btrfs/reflink.c b/fs/btrfs/reflink.c
index 14742abe0f92..fb34598a77ff 100644
--- a/fs/btrfs/reflink.c
+++ b/fs/btrfs/reflink.c
@@ -94,9 +94,7 @@ static int copy_inline_to_page(struct btrfs_inode *inode,
if (ret < 0)
goto out_unlock;
- btrfs_clear_extent_bit(&inode->io_tree, file_offset, range_end,
- EXTENT_DELALLOC | EXTENT_DO_ACCOUNTING | EXTENT_DEFRAG, NULL);
- ret = btrfs_set_extent_delalloc(inode, file_offset, range_end, 0, NULL);
+ ret = btrfs_reset_extent_delalloc(inode, file_offset, range_end, 0, NULL);
if (ret)
goto out_unlock;
--
2.53.0
^ permalink raw reply related
* [PATCH] ACPI: arm64: cpuidle: Tolerate platforms with no deep PSCI idle states
From: Breno Leitao @ 2026-04-20 9:27 UTC (permalink / raw)
To: Lorenzo Pieralisi, Hanjun Guo, Sudeep Holla, Catalin Marinas,
Will Deacon, Rafael J. Wysocki, Len Brown, Huisong Li
Cc: Rafael J. Wysocki, linux-acpi, linux-arm-kernel, linux-kernel,
pjaroszynski, rmikey, kernel-team, stable, Breno Leitao
Commit cac173bea57d ("ACPI: processor: idle: Rework the handling of
acpi_processor_ffh_lpi_probe()") moved the acpi_processor_ffh_lpi_probe()
call from acpi_processor_setup_cpuidle_dev(), where its return value was
ignored, to acpi_processor_get_power_info(), where it is now treated as
a hard failure. As a result, platforms where psci_acpi_cpu_init_idle()
returned -ENODEV stopped registering any cpuidle states, forcing CPUs to
busy-poll when idle.
On NVIDIA Grace (aarch64) systems with PSCIv1.1, pr->power.count is 1
(only WFI, no deep PSCI states beyond it), so the previous
"count = pr->power.count - 1; if (count <= 0) return -ENODEV;" check
returned -ENODEV for all 72 CPUs and disabled cpuidle entirely.
The lpi_states count is already validated in acpi_processor_get_lpi_info(),
so the check here is redundant. Simplify the loop to iterate over
lpi_states[1..power.count). When only WFI is present, the loop body
simply does not execute and the function returns 0, which is the correct
outcome: there is nothing to validate for FFH and no error to report.
Suggested-by: Huisong Li <lihuisong@huawei.com>
Cc: stable@vger.kernel.org
Fixes: cac173bea57d ("ACPI: processor: idle: Rework the handling of acpi_processor_ffh_lpi_probe()")
Signed-off-by: Breno Leitao <leitao@debian.org>
---
drivers/acpi/arm64/cpuidle.c | 10 +++-------
1 file changed, 3 insertions(+), 7 deletions(-)
diff --git a/drivers/acpi/arm64/cpuidle.c b/drivers/acpi/arm64/cpuidle.c
index 801f9c4501425..c68a5db8ebba8 100644
--- a/drivers/acpi/arm64/cpuidle.c
+++ b/drivers/acpi/arm64/cpuidle.c
@@ -16,7 +16,7 @@
static int psci_acpi_cpu_init_idle(unsigned int cpu)
{
- int i, count;
+ int i;
struct acpi_lpi_state *lpi;
struct acpi_processor *pr = per_cpu(processors, cpu);
@@ -30,14 +30,10 @@ static int psci_acpi_cpu_init_idle(unsigned int cpu)
if (!psci_ops.cpu_suspend)
return -EOPNOTSUPP;
- count = pr->power.count - 1;
- if (count <= 0)
- return -ENODEV;
-
- for (i = 0; i < count; i++) {
+ for (i = 1; i < pr->power.count; i++) {
u32 state;
- lpi = &pr->power.lpi_states[i + 1];
+ lpi = &pr->power.lpi_states[i];
/*
* Only bits[31:0] represent a PSCI power_state while
* bits[63:32] must be 0x0 as per ARM ACPI FFH Specification
---
base-commit: 1c7cc4904160c6fc6377564140062d68a3dc93a0
change-id: 20260413-ffh-93f68b2f46a3
Best regards,
--
Breno Leitao <leitao@debian.org>
^ permalink raw reply related
* Re: [PATCH 6.12.y 0/2] gpiolib: backport fa17f749ee5b and a7ac22d53d09
From: Bartosz Golaszewski @ 2026-04-20 9:26 UTC (permalink / raw)
To: Quentin Schulz
Cc: Heiko Stuebner, stable, linux-gpio, linux-kernel,
Bartosz Golaszewski, Quentin Schulz, Kent Gibson,
Paweł Narewski, Jakub Lewalski, Bartosz Golaszewski,
Linus Walleij, Bartosz Golaszewski, Andy Shevchenko
In-Reply-To: <20260415-6-12-gpiolib-cve-2026-22986-v1-0-3a7a6de332eb@cherry.de>
On Wed, 15 Apr 2026 13:15:39 +0200, Quentin Schulz <foss+kernel@0leil.net> said:
> Backport a7ac22d53d09 ("gpiolib: fix race condition for gdev->srcu") to
> 6.12.y. To make the git context difference between commit a7ac22d53d09
> and its backport in 6.12.y smaller, also backport fa17f749ee5b
> ("gpiolib: unify two loops initializing GPIO descriptors").
>
> a7ac22d53d09 fixes an issue reported as being present since 6.9. It's
> been fixed in 6.19 and backported to 6.18.y in fb674c8f1a5d8.
>
> The git context difference could be even smaller if we also backported
> d4f335b410dd ("gpiolib: rename GPIO chip printk macros") but its
> cherry-pick conflicts so I decided to not include it for now. It was
> backported to 6.18.y though (because it applied cleanly and helped
> a7ac22d53d09 being cleanly applied as well, see
> https://lore.kernel.org/stable/2026011530-owl-savage-9b8e@gregkh/).
>
> The changes between a7ac22d53d09 in v6.19 and the second patch of this
> series is (according to git range-diff):
>
> """
> ## drivers/gpio/gpiolib.c ##
> @@ drivers/gpio/gpiolib.c: int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
> gdev->ngpio = gc->ngpio;
> gdev->can_sleep = gc->can_sleep;
>
> -+ rwlock_init(&gdev->line_state_lock);
> -+ RAW_INIT_NOTIFIER_HEAD(&gdev->line_state_notifier);
> ++ BLOCKING_INIT_NOTIFIER_HEAD(&gdev->line_state_notifier);
> + BLOCKING_INIT_NOTIFIER_HEAD(&gdev->device_notifier);
> +
> + ret = init_srcu_struct(&gdev->srcu);
> @@ drivers/gpio/gpiolib.c: int gpiochip_add_data_with_key(struct gpio_chip *gc, voi
> @@ drivers/gpio/gpiolib.c: int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
> ret = gpiodev_add_to_list_unlocked(gdev);
> if (ret) {
> - gpiochip_err(gc, "GPIO integer space overlap, cannot add chip\n");
> + chip_err(gc, "GPIO integer space overlap, cannot add chip\n");
> - goto err_free_label;
> + goto err_cleanup_desc_srcu;
> }
> }
>
> -- rwlock_init(&gdev->line_state_lock);
> -- RAW_INIT_NOTIFIER_HEAD(&gdev->line_state_notifier);
> +- BLOCKING_INIT_NOTIFIER_HEAD(&gdev->line_state_notifier);
> - BLOCKING_INIT_NOTIFIER_HEAD(&gdev->device_notifier);
> -
> - ret = init_srcu_struct(&gdev->srcu);
> """
>
> s/gpiochip_err/chip_err/ aside, the rest of the diff comes from feature
> commits which do not fit the rules for backporting to stable.
>
> Signed-off-by: Quentin Schulz <quentin.schulz@cherry.de>
> ---
> Bartosz Golaszewski (1):
> gpiolib: unify two loops initializing GPIO descriptors
>
> Paweł Narewski (1):
> gpiolib: fix race condition for gdev->srcu
>
> drivers/gpio/gpiolib.c | 43 +++++++++++++++++++++----------------------
> 1 file changed, 21 insertions(+), 22 deletions(-)
> ---
> base-commit: e7a3953084a7050ca349010deb22546834c2e196
> change-id: 20260415-6-12-gpiolib-cve-2026-22986-f0b4331c0aa1
>
> Best regards,
> --
> Quentin Schulz <quentin.schulz@cherry.de>
>
>
Acked-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
^ permalink raw reply
* Re: [PATCH] drm/i915: skip __i915_request_skip() for already signaled requests
From: Krzysztof Karas @ 2026-04-20 9:18 UTC (permalink / raw)
To: Sebastian Brzezinka; +Cc: intel-gfx, andi.shyti, stable
In-Reply-To: <fe76921d35b6ae85aa651822726d0d9815aa5362.1776339012.git.sebastian.brzezinka@intel.com>
Hi Sebastian,
On 2026-04-16 at 13:31:18 +0200, Sebastian Brzezinka wrote:
> After a GPU reset the HWSP is zeroed, so previously completed
> requests appear incomplete. If such a request is picked up during
> reset_rewind() and marked guilty, i915_request_set_error_once()
> returns early (fence already signaled), leaving fence.error without
> a fatal error code. The subsequent __i915_request_skip() then hits:
> ```
> GEM_BUG_ON(!fatal_error(rq->fence.error))
> ```
>
> Fixes a kernel BUG observed on Sandy Bridge (Gen6) during
By "Fixes" do you mean this patch? Or are you referring to the
tag "Fixes:" below? If former would be the case, then imperative
form might be better: Fix.
In any case the patch looks sane:
Reviewed-by: Krzysztof Karas <krzysztof.karas@intel.com>
> heartbeat-triggered engine resets.
> ```
> kernel BUG at drivers/gpu/drm/i915/i915_request.c:556!
> RIP: __i915_request_skip+0x15e/0x1d0 [i915]
> ...
> __i915_request_reset+0x212/0xa70 [i915]
> reset_rewind+0xe4/0x280 [i915]
> intel_gt_reset+0x30d/0x5b0 [i915]
> heartbeat+0x516/0x530 [i915]
> ```
>
> Guard __i915_request_skip() with i915_request_signaled(), if the
> fence is already signaled, the ring content is committed and there
> is nothing left to skip.
>
> Cc: stable@vger.kernel.org
> Closes: https://gitlab.freedesktop.org/drm/i915/kernel/-/work_items/13729
> Fixes: 36e191f0644b ("drm/i915: Apply i915_request_skip() on submission")
> Signed-off-by: Sebastian Brzezinka <sebastian.brzezinka@intel.com>
> ---
> drivers/gpu/drm/i915/gt/intel_reset.c | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/i915/gt/intel_reset.c b/drivers/gpu/drm/i915/gt/intel_reset.c
> index 37272871b0f2..b728a5171e93 100644
> --- a/drivers/gpu/drm/i915/gt/intel_reset.c
> +++ b/drivers/gpu/drm/i915/gt/intel_reset.c
> @@ -133,7 +133,8 @@ void __i915_request_reset(struct i915_request *rq, bool guilty)
> rcu_read_lock(); /* protect the GEM context */
> if (guilty) {
> i915_request_set_error_once(rq, -EIO);
> - __i915_request_skip(rq);
> + if (!i915_request_signaled(rq))
> + __i915_request_skip(rq);
> banned = mark_guilty(rq);
> } else {
> i915_request_set_error_once(rq, -EAGAIN);
> --
> 2.53.0
>
--
Best Regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH v2] gpu: host1x: Fix device reference leak in device_add() error path
From: Guangshuo Li @ 2026-04-20 9:05 UTC (permalink / raw)
To: Mikko Perttunen
Cc: Thierry Reding, David Airlie, Simona Vetter,
Vamsee Vardhan Thummala, linux-kernel, dri-devel, linux-tegra,
stable
In-Reply-To: <q6Ni253ETr-zY8OZRWnm4g@nvidia.com>
Hi Mikko,
Thanks for reviewing.
On Mon, 20 Apr 2026 at 15:19, Mikko Perttunen <mperttunen@nvidia.com> wrote:
>
> Unrelated ..
>
Sorry about the unrelated change in drivers/firmware/edd.c. It was
included by mistake due to my carelessness when doing git add.
> This isn't a leak -- if device_add fails, the device is still on the
> device list, though in a "stuck" state, and will get cleaned up through
> host1x_device_del.
>
You're right. I misunderstood this path: if device_add() fails here,
the device remains on host1x->devices and can still be cleaned up
later via host1x_device_del(), so this is not a real leak.
I'll drop this host1x change.
Best regards,
Guangshuo
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox