From 083383aba01f278080938e3b71dbfa7256648ca4 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 6 Feb 2025 15:29:05 +0100 Subject: [PATCH 01/91] cpuidle: menu: Avoid discarding useful information [ Upstream commit 85975daeaa4d6ec560bfcd354fc9c08ad7f38888 ] When giving up on making a high-confidence prediction, get_typical_interval() always returns UINT_MAX which means that the next idle interval prediction will be based entirely on the time till the next timer. However, the information represented by the most recent intervals may not be completely useless in those cases. Namely, the largest recent idle interval is an upper bound on the recently observed idle duration, so it is reasonable to assume that the next idle duration is unlikely to exceed it. Moreover, this is still true after eliminating the suspected outliers if the sample set still under consideration is at least as large as 50% of the maximum sample set size. Accordingly, make get_typical_interval() return the current maximum recent interval value in that case instead of UINT_MAX. Signed-off-by: Rafael J. Wysocki Reported-by: Artem Bityutskiy Tested-by: Artem Bityutskiy Reviewed-by: Christian Loehle Tested-by: Christian Loehle Tested-by: Aboorva Devarajan Link: https://patch.msgid.link/7770672.EvYhyI6sBW@rjwysocki.net Signed-off-by: Sasha Levin --- drivers/cpuidle/governors/menu.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c index f3c9d49f0f2a..97ffadc7e57a 100644 --- a/drivers/cpuidle/governors/menu.c +++ b/drivers/cpuidle/governors/menu.c @@ -239,8 +239,19 @@ again: * This can deal with workloads that have long pauses interspersed * with sporadic activity with a bunch of short pauses. */ - if ((divisor * 4) <= INTERVALS * 3) + if (divisor * 4 <= INTERVALS * 3) { + /* + * If there are sufficiently many data points still under + * consideration after the outliers have been eliminated, + * returning without a prediction would be a mistake because it + * is likely that the next interval will not exceed the current + * maximum, so return the latter in that case. + */ + if (divisor >= INTERVALS / 2) + return max; + return UINT_MAX; + } thresh = max - 1; goto again; From bb8fb041cba26793200d006231fab765ee63ed64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20S=C3=B6derlund?= Date: Sat, 22 Feb 2025 00:09:07 +0100 Subject: [PATCH 02/91] media: adv7180: Disable test-pattern control on adv7180 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit a980bc5f56b0292336e408f657f79e574e8067c0 ] The register that enables selecting a test-pattern to be outputted in free-run mode (FREE_RUN_PAT_SEL[2:0]) is only available on adv7280 based devices, not the adv7180 based ones. Add a flag to mark devices that are capable of generating test-patterns, and those that are not. And only register the control on supported devices. Signed-off-by: Niklas Söderlund Signed-off-by: Hans Verkuil Signed-off-by: Sasha Levin --- drivers/media/i2c/adv7180.c | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/drivers/media/i2c/adv7180.c b/drivers/media/i2c/adv7180.c index 819ff9f7c90f..2a20a4fad796 100644 --- a/drivers/media/i2c/adv7180.c +++ b/drivers/media/i2c/adv7180.c @@ -195,6 +195,7 @@ struct adv7180_state; #define ADV7180_FLAG_V2 BIT(1) #define ADV7180_FLAG_MIPI_CSI2 BIT(2) #define ADV7180_FLAG_I2P BIT(3) +#define ADV7180_FLAG_TEST_PATTERN BIT(4) struct adv7180_chip_info { unsigned int flags; @@ -682,11 +683,15 @@ static int adv7180_init_controls(struct adv7180_state *state) ADV7180_HUE_MAX, 1, ADV7180_HUE_DEF); v4l2_ctrl_new_custom(&state->ctrl_hdl, &adv7180_ctrl_fast_switch, NULL); - v4l2_ctrl_new_std_menu_items(&state->ctrl_hdl, &adv7180_ctrl_ops, - V4L2_CID_TEST_PATTERN, - ARRAY_SIZE(test_pattern_menu) - 1, - 0, ARRAY_SIZE(test_pattern_menu) - 1, - test_pattern_menu); + if (state->chip_info->flags & ADV7180_FLAG_TEST_PATTERN) { + v4l2_ctrl_new_std_menu_items(&state->ctrl_hdl, + &adv7180_ctrl_ops, + V4L2_CID_TEST_PATTERN, + ARRAY_SIZE(test_pattern_menu) - 1, + 0, + ARRAY_SIZE(test_pattern_menu) - 1, + test_pattern_menu); + } state->sd.ctrl_handler = &state->ctrl_hdl; if (state->ctrl_hdl.error) { @@ -1221,7 +1226,7 @@ static const struct adv7180_chip_info adv7182_info = { }; static const struct adv7180_chip_info adv7280_info = { - .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_I2P, + .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_I2P | ADV7180_FLAG_TEST_PATTERN, .valid_input_mask = BIT(ADV7182_INPUT_CVBS_AIN1) | BIT(ADV7182_INPUT_CVBS_AIN2) | BIT(ADV7182_INPUT_CVBS_AIN3) | @@ -1235,7 +1240,8 @@ static const struct adv7180_chip_info adv7280_info = { }; static const struct adv7180_chip_info adv7280_m_info = { - .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_MIPI_CSI2 | ADV7180_FLAG_I2P, + .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_MIPI_CSI2 | ADV7180_FLAG_I2P | + ADV7180_FLAG_TEST_PATTERN, .valid_input_mask = BIT(ADV7182_INPUT_CVBS_AIN1) | BIT(ADV7182_INPUT_CVBS_AIN2) | BIT(ADV7182_INPUT_CVBS_AIN3) | @@ -1256,7 +1262,8 @@ static const struct adv7180_chip_info adv7280_m_info = { }; static const struct adv7180_chip_info adv7281_info = { - .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_MIPI_CSI2, + .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_MIPI_CSI2 | + ADV7180_FLAG_TEST_PATTERN, .valid_input_mask = BIT(ADV7182_INPUT_CVBS_AIN1) | BIT(ADV7182_INPUT_CVBS_AIN2) | BIT(ADV7182_INPUT_CVBS_AIN7) | @@ -1271,7 +1278,8 @@ static const struct adv7180_chip_info adv7281_info = { }; static const struct adv7180_chip_info adv7281_m_info = { - .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_MIPI_CSI2, + .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_MIPI_CSI2 | + ADV7180_FLAG_TEST_PATTERN, .valid_input_mask = BIT(ADV7182_INPUT_CVBS_AIN1) | BIT(ADV7182_INPUT_CVBS_AIN2) | BIT(ADV7182_INPUT_CVBS_AIN3) | @@ -1291,7 +1299,8 @@ static const struct adv7180_chip_info adv7281_m_info = { }; static const struct adv7180_chip_info adv7281_ma_info = { - .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_MIPI_CSI2, + .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_MIPI_CSI2 | + ADV7180_FLAG_TEST_PATTERN, .valid_input_mask = BIT(ADV7182_INPUT_CVBS_AIN1) | BIT(ADV7182_INPUT_CVBS_AIN2) | BIT(ADV7182_INPUT_CVBS_AIN3) | @@ -1316,7 +1325,7 @@ static const struct adv7180_chip_info adv7281_ma_info = { }; static const struct adv7180_chip_info adv7282_info = { - .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_I2P, + .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_I2P | ADV7180_FLAG_TEST_PATTERN, .valid_input_mask = BIT(ADV7182_INPUT_CVBS_AIN1) | BIT(ADV7182_INPUT_CVBS_AIN2) | BIT(ADV7182_INPUT_CVBS_AIN7) | @@ -1331,7 +1340,8 @@ static const struct adv7180_chip_info adv7282_info = { }; static const struct adv7180_chip_info adv7282_m_info = { - .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_MIPI_CSI2 | ADV7180_FLAG_I2P, + .flags = ADV7180_FLAG_V2 | ADV7180_FLAG_MIPI_CSI2 | ADV7180_FLAG_I2P | + ADV7180_FLAG_TEST_PATTERN, .valid_input_mask = BIT(ADV7182_INPUT_CVBS_AIN1) | BIT(ADV7182_INPUT_CVBS_AIN2) | BIT(ADV7182_INPUT_CVBS_AIN3) | From c2aa6567a6a486a61325eb222afbebf28768989f Mon Sep 17 00:00:00 2001 From: Matthias Fend Date: Tue, 7 Jan 2025 17:07:01 +0100 Subject: [PATCH 03/91] media: tc358746: improve calculation of the D-PHY timing registers [ Upstream commit 78d7265e2e1ce349e7f3c6a085f2b66d7b73f4ca ] When calculating D-PHY registers, using data rates that are not multiples of 16 can lead to precision loss in division operations. This can result in register values that produce timing violations against the MIPI standard. An example: cfg->hs_clk_rate = 294MHz hf_clk = 18 If the desired value in cfg->init is 100us, which is the minimum allowed value, then the LINEINITCNT register is calculated as 1799. But since the actual clock is 18.375MHz instead of 18MHz, this setting results in a time that is shorter than 100us and thus violates the standard. The correct value for LINEINITCNT would be 1837. Improve the precision of calculations by using Hz instead of MHz as unit. Signed-off-by: Matthias Fend Reviewed-by: Marco Felsch Signed-off-by: Hans Verkuil Signed-off-by: Sasha Levin --- drivers/media/i2c/tc358746.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/drivers/media/i2c/tc358746.c b/drivers/media/i2c/tc358746.c index 389582420ba7..048a1a381b33 100644 --- a/drivers/media/i2c/tc358746.c +++ b/drivers/media/i2c/tc358746.c @@ -460,24 +460,20 @@ out: return err; } -/* Use MHz as base so the div needs no u64 */ -static u32 tc358746_cfg_to_cnt(unsigned int cfg_val, - unsigned int clk_mhz, - unsigned int time_base) +static u32 tc358746_cfg_to_cnt(unsigned long cfg_val, unsigned long clk_hz, + unsigned long long time_base) { - return DIV_ROUND_UP(cfg_val * clk_mhz, time_base); + return div64_u64((u64)cfg_val * clk_hz + time_base - 1, time_base); } -static u32 tc358746_ps_to_cnt(unsigned int cfg_val, - unsigned int clk_mhz) +static u32 tc358746_ps_to_cnt(unsigned long cfg_val, unsigned long clk_hz) { - return tc358746_cfg_to_cnt(cfg_val, clk_mhz, USEC_PER_SEC); + return tc358746_cfg_to_cnt(cfg_val, clk_hz, PSEC_PER_SEC); } -static u32 tc358746_us_to_cnt(unsigned int cfg_val, - unsigned int clk_mhz) +static u32 tc358746_us_to_cnt(unsigned long cfg_val, unsigned long clk_hz) { - return tc358746_cfg_to_cnt(cfg_val, clk_mhz, 1); + return tc358746_cfg_to_cnt(cfg_val, clk_hz, USEC_PER_SEC); } static int tc358746_apply_dphy_config(struct tc358746 *tc358746) @@ -492,7 +488,6 @@ static int tc358746_apply_dphy_config(struct tc358746 *tc358746) /* The hs_byte_clk is also called SYSCLK in the excel sheet */ hs_byte_clk = cfg->hs_clk_rate / 8; - hs_byte_clk /= HZ_PER_MHZ; hf_clk = hs_byte_clk / 2; val = tc358746_us_to_cnt(cfg->init, hf_clk) - 1; From a68686c08b70bdad0b1a406bcfe7e07f3bdc5da2 Mon Sep 17 00:00:00 2001 From: Jianbo Liu Date: Thu, 20 Feb 2025 23:39:53 +0200 Subject: [PATCH 04/91] net/mlx5e: Add correct match to check IPSec syndromes for switchdev mode [ Upstream commit 85e4a808af2545fefaf18c8fe50071b06fcbdabc ] In commit dddb49b63d86 ("net/mlx5e: Add IPsec and ASO syndromes check in HW"), IPSec and ASO syndromes checks after decryption for the specified ASO object were added. But they are correct only for eswith in legacy mode. For switchdev mode, metadata register c1 is used to save the mapped id (not ASO object id). So, need to change the match accordingly for the check rules in status table. Signed-off-by: Jianbo Liu Reviewed-by: Leon Romanovsky Reviewed-by: Patrisious Haddad Signed-off-by: Tariq Toukan Link: https://patch.msgid.link/20250220213959.504304-4-tariqt@nvidia.com Signed-off-by: Jakub Kicinski Signed-off-by: Sasha Levin --- .../mellanox/mlx5/core/en_accel/ipsec_fs.c | 28 ++++++++++++++----- .../mellanox/mlx5/core/esw/ipsec_fs.c | 13 +++++++++ .../mellanox/mlx5/core/esw/ipsec_fs.h | 5 ++++ include/linux/mlx5/eswitch.h | 2 ++ 4 files changed, 41 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c index 57861d34d46f..59b9653f573c 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c @@ -165,6 +165,25 @@ static void ipsec_rx_status_pass_destroy(struct mlx5e_ipsec *ipsec, #endif } +static void ipsec_rx_rule_add_match_obj(struct mlx5e_ipsec_sa_entry *sa_entry, + struct mlx5e_ipsec_rx *rx, + struct mlx5_flow_spec *spec) +{ + struct mlx5e_ipsec *ipsec = sa_entry->ipsec; + + if (rx == ipsec->rx_esw) { + mlx5_esw_ipsec_rx_rule_add_match_obj(sa_entry, spec); + } else { + MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, + misc_parameters_2.metadata_reg_c_2); + MLX5_SET(fte_match_param, spec->match_value, + misc_parameters_2.metadata_reg_c_2, + sa_entry->ipsec_obj_id | BIT(31)); + + spec->match_criteria_enable |= MLX5_MATCH_MISC_PARAMETERS_2; + } +} + static int rx_add_rule_drop_auth_trailer(struct mlx5e_ipsec_sa_entry *sa_entry, struct mlx5e_ipsec_rx *rx) { @@ -200,11 +219,8 @@ static int rx_add_rule_drop_auth_trailer(struct mlx5e_ipsec_sa_entry *sa_entry, MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, misc_parameters_2.ipsec_syndrome); MLX5_SET(fte_match_param, spec->match_value, misc_parameters_2.ipsec_syndrome, 1); - MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, misc_parameters_2.metadata_reg_c_2); - MLX5_SET(fte_match_param, spec->match_value, - misc_parameters_2.metadata_reg_c_2, - sa_entry->ipsec_obj_id | BIT(31)); spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS_2; + ipsec_rx_rule_add_match_obj(sa_entry, rx, spec); rule = mlx5_add_flow_rules(ft, spec, &flow_act, &dest, 1); if (IS_ERR(rule)) { err = PTR_ERR(rule); @@ -281,10 +297,8 @@ static int rx_add_rule_drop_replay(struct mlx5e_ipsec_sa_entry *sa_entry, struct MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, misc_parameters_2.metadata_reg_c_4); MLX5_SET(fte_match_param, spec->match_value, misc_parameters_2.metadata_reg_c_4, 1); - MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, misc_parameters_2.metadata_reg_c_2); - MLX5_SET(fte_match_param, spec->match_value, misc_parameters_2.metadata_reg_c_2, - sa_entry->ipsec_obj_id | BIT(31)); spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS_2; + ipsec_rx_rule_add_match_obj(sa_entry, rx, spec); rule = mlx5_add_flow_rules(ft, spec, &flow_act, &dest, 1); if (IS_ERR(rule)) { err = PTR_ERR(rule); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.c index ed977ae75fab..4bba2884c1c0 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.c @@ -85,6 +85,19 @@ err_header_alloc: return err; } +void mlx5_esw_ipsec_rx_rule_add_match_obj(struct mlx5e_ipsec_sa_entry *sa_entry, + struct mlx5_flow_spec *spec) +{ + MLX5_SET(fte_match_param, spec->match_criteria, + misc_parameters_2.metadata_reg_c_1, + ESW_IPSEC_RX_MAPPED_ID_MATCH_MASK); + MLX5_SET(fte_match_param, spec->match_value, + misc_parameters_2.metadata_reg_c_1, + sa_entry->rx_mapped_id << ESW_ZONE_ID_BITS); + + spec->match_criteria_enable |= MLX5_MATCH_MISC_PARAMETERS_2; +} + void mlx5_esw_ipsec_rx_id_mapping_remove(struct mlx5e_ipsec_sa_entry *sa_entry) { struct mlx5e_ipsec *ipsec = sa_entry->ipsec; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.h b/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.h index ac9c65b89166..514c15258b1d 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.h @@ -20,6 +20,8 @@ int mlx5_esw_ipsec_rx_ipsec_obj_id_search(struct mlx5e_priv *priv, u32 id, void mlx5_esw_ipsec_tx_create_attr_set(struct mlx5e_ipsec *ipsec, struct mlx5e_ipsec_tx_create_attr *attr); void mlx5_esw_ipsec_restore_dest_uplink(struct mlx5_core_dev *mdev); +void mlx5_esw_ipsec_rx_rule_add_match_obj(struct mlx5e_ipsec_sa_entry *sa_entry, + struct mlx5_flow_spec *spec); #else static inline void mlx5_esw_ipsec_rx_create_attr_set(struct mlx5e_ipsec *ipsec, struct mlx5e_ipsec_rx_create_attr *attr) {} @@ -48,5 +50,8 @@ static inline void mlx5_esw_ipsec_tx_create_attr_set(struct mlx5e_ipsec *ipsec, struct mlx5e_ipsec_tx_create_attr *attr) {} static inline void mlx5_esw_ipsec_restore_dest_uplink(struct mlx5_core_dev *mdev) {} +static inline void +mlx5_esw_ipsec_rx_rule_add_match_obj(struct mlx5e_ipsec_sa_entry *sa_entry, + struct mlx5_flow_spec *spec) {} #endif /* CONFIG_MLX5_ESWITCH */ #endif /* __MLX5_ESW_IPSEC_FS_H__ */ diff --git a/include/linux/mlx5/eswitch.h b/include/linux/mlx5/eswitch.h index df73a2ccc9af..67256e776566 100644 --- a/include/linux/mlx5/eswitch.h +++ b/include/linux/mlx5/eswitch.h @@ -147,6 +147,8 @@ u32 mlx5_eswitch_get_vport_metadata_for_set(struct mlx5_eswitch *esw, /* reuse tun_opts for the mapped ipsec obj id when tun_id is 0 (invalid) */ #define ESW_IPSEC_RX_MAPPED_ID_MASK GENMASK(ESW_TUN_OPTS_BITS - 1, 0) +#define ESW_IPSEC_RX_MAPPED_ID_MATCH_MASK \ + GENMASK(31 - ESW_RESERVED_BITS, ESW_ZONE_ID_BITS) u8 mlx5_eswitch_mode(const struct mlx5_core_dev *dev); u16 mlx5_eswitch_get_total_vports(const struct mlx5_core_dev *dev); From 5b62f941eae80688aecbbbaed44b51cbb0fe1fa7 Mon Sep 17 00:00:00 2001 From: Ranjan Kumar Date: Thu, 20 Feb 2025 19:55:26 +0530 Subject: [PATCH 05/91] scsi: mpi3mr: Update timestamp only for supervisor IOCs [ Upstream commit 83a9d30d29f275571f6e8f879f04b2379be7eb6c ] The driver issues the time stamp update command periodically. Even if the command fails with supervisor only IOC Status. Instead check the Non-Supervisor capability bit reported by IOC as part of IOC Facts. Co-developed-by: Sumit Saxena Signed-off-by: Sumit Saxena Signed-off-by: Ranjan Kumar Link: https://lore.kernel.org/r/20250220142528.20837-3-ranjan.kumar@broadcom.com Signed-off-by: Martin K. Petersen Signed-off-by: Sasha Levin --- drivers/scsi/mpi3mr/mpi3mr_fw.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/mpi3mr/mpi3mr_fw.c b/drivers/scsi/mpi3mr/mpi3mr_fw.c index f6d3db3fd0d8..604f37e5c0c3 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_fw.c +++ b/drivers/scsi/mpi3mr/mpi3mr_fw.c @@ -2747,7 +2747,10 @@ static void mpi3mr_watchdog_work(struct work_struct *work) return; } - if (mrioc->ts_update_counter++ >= mrioc->ts_update_interval) { + if (!(mrioc->facts.ioc_capabilities & + MPI3_IOCFACTS_CAPABILITY_NON_SUPERVISOR_IOC) && + (mrioc->ts_update_counter++ >= mrioc->ts_update_interval)) { + mrioc->ts_update_counter = 0; mpi3mr_sync_timestamp(mrioc); } From 20a53c3689a20a5e34b88fc7705b7f0bf883eb1c Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 31 Jan 2025 13:00:40 +0100 Subject: [PATCH 06/91] loop: check in LO_FLAGS_DIRECT_IO in loop_default_blocksize [ Upstream commit f6f9e32fe1e454ae8ac0190b2c2bd6074914beec ] We can't go below the minimum direct I/O size no matter if direct I/O is enabled by passing in an O_DIRECT file descriptor or due to the explicit flag. Now that LO_FLAGS_DIRECT_IO is set earlier after assigning a backing file, loop_default_blocksize can check it instead of the O_DIRECT flag to handle both conditions. Signed-off-by: Christoph Hellwig Reviewed-by: Damien Le Moal Link: https://lore.kernel.org/r/20250131120120.1315125-4-hch@lst.de Signed-off-by: Jens Axboe Signed-off-by: Sasha Levin --- drivers/block/loop.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 6bd44ec2c9b1..fa9c77b8f4d2 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -916,7 +916,7 @@ static unsigned int loop_default_blocksize(struct loop_device *lo, struct block_device *backing_bdev) { /* In case of direct I/O, match underlying block size */ - if ((lo->lo_backing_file->f_flags & O_DIRECT) && backing_bdev) + if ((lo->lo_flags & LO_FLAGS_DIRECT_IO) && backing_bdev) return bdev_logical_block_size(backing_bdev); return SECTOR_SIZE; } From 2c600cbe33f2072b218037895b58753cc49e5e97 Mon Sep 17 00:00:00 2001 From: Nandakumar Edamana Date: Sat, 22 Feb 2025 02:31:11 +0530 Subject: [PATCH 07/91] libbpf: Fix out-of-bound read [ Upstream commit 236d3910117e9f97ebf75e511d8bcc950f1a4e5f ] In `set_kcfg_value_str`, an untrusted string is accessed with the assumption that it will be at least two characters long due to the presence of checks for opening and closing quotes. But the check for the closing quote (value[len - 1] != '"') misses the fact that it could be checking the opening quote itself in case of an invalid input that consists of just the opening quote. This commit adds an explicit check to make sure the string is at least two characters long. Signed-off-by: Nandakumar Edamana Signed-off-by: Andrii Nakryiko Link: https://lore.kernel.org/bpf/20250221210110.3182084-1-nandakumar@nandakumar.co.in Signed-off-by: Sasha Levin --- tools/lib/bpf/libbpf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index 5ff643e60d09..6e4d417604fa 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c @@ -2074,7 +2074,7 @@ static int set_kcfg_value_str(struct extern_desc *ext, char *ext_val, } len = strlen(value); - if (value[len - 1] != '"') { + if (len < 2 || value[len - 1] != '"') { pr_warn("extern (kcfg) '%s': invalid string config '%s'\n", ext->name, value); return -EINVAL; From b55a97d1bd4083729a60d19beffe85d4c96680de Mon Sep 17 00:00:00 2001 From: Jinliang Zheng Date: Thu, 20 Feb 2025 19:20:14 +0800 Subject: [PATCH 08/91] dm: fix unconditional IO throttle caused by REQ_PREFLUSH [ Upstream commit 88f7f56d16f568f19e1a695af34a7f4a6ce537a6 ] When a bio with REQ_PREFLUSH is submitted to dm, __send_empty_flush() generates a flush_bio with REQ_OP_WRITE | REQ_PREFLUSH | REQ_SYNC, which causes the flush_bio to be throttled by wbt_wait(). An example from v5.4, similar problem also exists in upstream: crash> bt 2091206 PID: 2091206 TASK: ffff2050df92a300 CPU: 109 COMMAND: "kworker/u260:0" #0 [ffff800084a2f7f0] __switch_to at ffff80004008aeb8 #1 [ffff800084a2f820] __schedule at ffff800040bfa0c4 #2 [ffff800084a2f880] schedule at ffff800040bfa4b4 #3 [ffff800084a2f8a0] io_schedule at ffff800040bfa9c4 #4 [ffff800084a2f8c0] rq_qos_wait at ffff8000405925bc #5 [ffff800084a2f940] wbt_wait at ffff8000405bb3a0 #6 [ffff800084a2f9a0] __rq_qos_throttle at ffff800040592254 #7 [ffff800084a2f9c0] blk_mq_make_request at ffff80004057cf38 #8 [ffff800084a2fa60] generic_make_request at ffff800040570138 #9 [ffff800084a2fae0] submit_bio at ffff8000405703b4 #10 [ffff800084a2fb50] xlog_write_iclog at ffff800001280834 [xfs] #11 [ffff800084a2fbb0] xlog_sync at ffff800001280c3c [xfs] #12 [ffff800084a2fbf0] xlog_state_release_iclog at ffff800001280df4 [xfs] #13 [ffff800084a2fc10] xlog_write at ffff80000128203c [xfs] #14 [ffff800084a2fcd0] xlog_cil_push at ffff8000012846dc [xfs] #15 [ffff800084a2fda0] xlog_cil_push_work at ffff800001284a2c [xfs] #16 [ffff800084a2fdb0] process_one_work at ffff800040111d08 #17 [ffff800084a2fe00] worker_thread at ffff8000401121cc #18 [ffff800084a2fe70] kthread at ffff800040118de4 After commit 2def2845cc33 ("xfs: don't allow log IO to be throttled"), the metadata submitted by xlog_write_iclog() should not be throttled. But due to the existence of the dm layer, throttling flush_bio indirectly causes the metadata bio to be throttled. Fix this by conditionally adding REQ_IDLE to flush_bio.bi_opf, which makes wbt_should_throttle() return false to avoid wbt_wait(). Signed-off-by: Jinliang Zheng Reviewed-by: Tianxiang Peng Reviewed-by: Hao Peng Signed-off-by: Mikulas Patocka Signed-off-by: Sasha Levin --- drivers/md/dm.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 19230404d8c2..d29125ee9e72 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -1541,14 +1541,18 @@ static void __send_empty_flush(struct clone_info *ci) { struct dm_table *t = ci->map; struct bio flush_bio; + blk_opf_t opf = REQ_OP_WRITE | REQ_PREFLUSH | REQ_SYNC; + + if ((ci->io->orig_bio->bi_opf & (REQ_IDLE | REQ_SYNC)) == + (REQ_IDLE | REQ_SYNC)) + opf |= REQ_IDLE; /* * Use an on-stack bio for this, it's safe since we don't * need to reference it after submit. It's just used as * the basis for the clone(s). */ - bio_init(&flush_bio, ci->io->md->disk->part0, NULL, 0, - REQ_OP_WRITE | REQ_PREFLUSH | REQ_SYNC); + bio_init(&flush_bio, ci->io->md->disk->part0, NULL, 0, opf); ci->bio = &flush_bio; ci->sector_count = 0; From d2d76fc02543a94fc126d8c8e490aa2f9a7ce5fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kai=20M=C3=A4kisara?= Date: Thu, 13 Feb 2025 11:26:30 +0200 Subject: [PATCH 09/91] scsi: scsi_debug: First fixes for tapes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit f69da85d5d5cc5b7dfb963a6c6c1ac0dd9002341 ] Patch includes the following: - Enable MODE SENSE/SELECT without actual page (to read/write only the Block Descriptor) - Store the density code and block size in the Block Descriptor (only short version for tapes) - Fix REWIND not to use the wrong page filling function Signed-off-by: Kai Mäkisara Link: https://lore.kernel.org/r/20250213092636.2510-2-Kai.Makisara@kolumbus.fi Reviewed-by: John Meneghini Tested-by: John Meneghini Signed-off-by: Martin K. Petersen Signed-off-by: Sasha Levin --- drivers/scsi/scsi_debug.c | 55 ++++++++++++++++++++++++++++++++++----- 1 file changed, 49 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index 680ba180a672..89a2aaccdcfc 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -173,6 +173,10 @@ static const char *sdebug_version_date = "20210520"; #define DEF_ZBC_MAX_OPEN_ZONES 8 #define DEF_ZBC_NR_CONV_ZONES 1 +/* Default parameters for tape drives */ +#define TAPE_DEF_DENSITY 0x0 +#define TAPE_DEF_BLKSIZE 0 + #define SDEBUG_LUN_0_VAL 0 /* bit mask values for sdebug_opts */ @@ -363,6 +367,10 @@ struct sdebug_dev_info { ktime_t create_ts; /* time since bootup that this device was created */ struct sdeb_zone_state *zstate; + /* For tapes */ + unsigned int tape_blksize; + unsigned int tape_density; + struct dentry *debugfs_entry; struct spinlock list_lock; struct list_head inject_err_list; @@ -773,7 +781,7 @@ static const struct opcode_info_t opcode_info_arr[SDEB_I_LAST_ELEM_P1 + 1] = { /* 20 */ {0, 0x1e, 0, 0, NULL, NULL, /* ALLOW REMOVAL */ {6, 0, 0, 0, 0x3, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, - {0, 0x1, 0, 0, resp_start_stop, NULL, /* REWIND ?? */ + {0, 0x1, 0, 0, NULL, NULL, /* REWIND ?? */ {6, 0x1, 0, 0, 0, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, {0, 0, 0, F_INV_OP | FF_RESPOND, NULL, NULL, /* ATA_PT */ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, @@ -2742,7 +2750,7 @@ static int resp_mode_sense(struct scsi_cmnd *scp, unsigned char *ap; unsigned char *arr __free(kfree); unsigned char *cmd = scp->cmnd; - bool dbd, llbaa, msense_6, is_disk, is_zbc; + bool dbd, llbaa, msense_6, is_disk, is_zbc, is_tape; arr = kzalloc(SDEBUG_MAX_MSENSE_SZ, GFP_ATOMIC); if (!arr) @@ -2755,7 +2763,8 @@ static int resp_mode_sense(struct scsi_cmnd *scp, llbaa = msense_6 ? false : !!(cmd[1] & 0x10); is_disk = (sdebug_ptype == TYPE_DISK); is_zbc = devip->zoned; - if ((is_disk || is_zbc) && !dbd) + is_tape = (sdebug_ptype == TYPE_TAPE); + if ((is_disk || is_zbc || is_tape) && !dbd) bd_len = llbaa ? 16 : 8; else bd_len = 0; @@ -2793,15 +2802,25 @@ static int resp_mode_sense(struct scsi_cmnd *scp, put_unaligned_be32(0xffffffff, ap + 0); else put_unaligned_be32(sdebug_capacity, ap + 0); - put_unaligned_be16(sdebug_sector_size, ap + 6); + if (is_tape) { + ap[0] = devip->tape_density; + put_unaligned_be16(devip->tape_blksize, ap + 6); + } else + put_unaligned_be16(sdebug_sector_size, ap + 6); offset += bd_len; ap = arr + offset; } else if (16 == bd_len) { + if (is_tape) { + mk_sense_invalid_fld(scp, SDEB_IN_DATA, 1, 4); + return check_condition_result; + } put_unaligned_be64((u64)sdebug_capacity, ap + 0); put_unaligned_be32(sdebug_sector_size, ap + 12); offset += bd_len; ap = arr + offset; } + if (cmd[2] == 0) + goto only_bd; /* Only block descriptor requested */ /* * N.B. If len>0 before resp_*_pg() call, then form of that call should be: @@ -2902,6 +2921,7 @@ static int resp_mode_sense(struct scsi_cmnd *scp, default: goto bad_pcode; } +only_bd: if (msense_6) arr[0] = offset - 1; else @@ -2945,8 +2965,27 @@ static int resp_mode_select(struct scsi_cmnd *scp, __func__, param_len, res); md_len = mselect6 ? (arr[0] + 1) : (get_unaligned_be16(arr + 0) + 2); bd_len = mselect6 ? arr[3] : get_unaligned_be16(arr + 6); - off = bd_len + (mselect6 ? 4 : 8); - if (md_len > 2 || off >= res) { + off = (mselect6 ? 4 : 8); + if (sdebug_ptype == TYPE_TAPE) { + int blksize; + + if (bd_len != 8) { + mk_sense_invalid_fld(scp, SDEB_IN_DATA, + mselect6 ? 3 : 6, -1); + return check_condition_result; + } + blksize = get_unaligned_be16(arr + off + 6); + if ((blksize % 4) != 0) { + mk_sense_invalid_fld(scp, SDEB_IN_DATA, off + 6, -1); + return check_condition_result; + } + devip->tape_density = arr[off]; + devip->tape_blksize = blksize; + } + off += bd_len; + if (off >= res) + return 0; /* No page written, just descriptors */ + if (md_len > 2) { mk_sense_invalid_fld(scp, SDEB_IN_DATA, 0, -1); return check_condition_result; } @@ -5835,6 +5874,10 @@ static struct sdebug_dev_info *sdebug_device_create( } else { devip->zoned = false; } + if (sdebug_ptype == TYPE_TAPE) { + devip->tape_density = TAPE_DEF_DENSITY; + devip->tape_blksize = TAPE_DEF_BLKSIZE; + } devip->create_ts = ktime_get_boottime(); atomic_set(&devip->stopped, (sdeb_tur_ms_to_ready > 0 ? 2 : 0)); spin_lock_init(&devip->list_lock); From 0bdaab17a2a177bbb8dfa96cf1413d183e8b6ea6 Mon Sep 17 00:00:00 2001 From: Patrisious Haddad Date: Wed, 19 Feb 2025 10:58:08 +0200 Subject: [PATCH 10/91] net/mlx5: Change POOL_NEXT_SIZE define value and make it global [ Upstream commit 80df31f384b4146a62a01b3d4beb376cc7b9a89e ] Change POOL_NEXT_SIZE define value from 0 to BIT(30), since this define is used to request the available maximum sized flow table, and zero doesn't make sense for it, whereas some places in the driver use zero explicitly expecting the smallest table size possible but instead due to this define they end up allocating the biggest table size unawarely. In addition move the definition to "include/linux/mlx5/fs.h" to expose the define to IB driver as well, while appropriately renaming it. Signed-off-by: Patrisious Haddad Reviewed-by: Maor Gottlieb Reviewed-by: Mark Bloch Signed-off-by: Tariq Toukan Link: https://patch.msgid.link/20250219085808.349923-3-tariqt@nvidia.com Signed-off-by: Leon Romanovsky Signed-off-by: Sasha Levin --- drivers/net/ethernet/mellanox/mlx5/core/esw/legacy.c | 2 +- drivers/net/ethernet/mellanox/mlx5/core/fs_ft_pool.c | 6 ++++-- drivers/net/ethernet/mellanox/mlx5/core/fs_ft_pool.h | 2 -- drivers/net/ethernet/mellanox/mlx5/core/lib/fs_chains.c | 3 ++- include/linux/mlx5/fs.h | 2 ++ 5 files changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/legacy.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/legacy.c index 8587cd572da5..bdb825aa8726 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/esw/legacy.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/legacy.c @@ -96,7 +96,7 @@ static int esw_create_legacy_fdb_table(struct mlx5_eswitch *esw) if (!flow_group_in) return -ENOMEM; - ft_attr.max_fte = POOL_NEXT_SIZE; + ft_attr.max_fte = MLX5_FS_MAX_POOL_SIZE; ft_attr.prio = LEGACY_FDB_PRIO; fdb = mlx5_create_flow_table(root_ns, &ft_attr); if (IS_ERR(fdb)) { diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_ft_pool.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_ft_pool.c index c14590acc772..f6abfd00d7e6 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_ft_pool.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_ft_pool.c @@ -50,10 +50,12 @@ mlx5_ft_pool_get_avail_sz(struct mlx5_core_dev *dev, enum fs_flow_table_type tab int i, found_i = -1; for (i = ARRAY_SIZE(FT_POOLS) - 1; i >= 0; i--) { - if (dev->priv.ft_pool->ft_left[i] && FT_POOLS[i] >= desired_size && + if (dev->priv.ft_pool->ft_left[i] && + (FT_POOLS[i] >= desired_size || + desired_size == MLX5_FS_MAX_POOL_SIZE) && FT_POOLS[i] <= max_ft_size) { found_i = i; - if (desired_size != POOL_NEXT_SIZE) + if (desired_size != MLX5_FS_MAX_POOL_SIZE) break; } } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_ft_pool.h b/drivers/net/ethernet/mellanox/mlx5/core/fs_ft_pool.h index 25f4274b372b..173e312db720 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_ft_pool.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_ft_pool.h @@ -7,8 +7,6 @@ #include #include "fs_core.h" -#define POOL_NEXT_SIZE 0 - int mlx5_ft_pool_init(struct mlx5_core_dev *dev); void mlx5_ft_pool_destroy(struct mlx5_core_dev *dev); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/fs_chains.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/fs_chains.c index 711d14dea248..d313cb7f0ed8 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lib/fs_chains.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/fs_chains.c @@ -161,7 +161,8 @@ mlx5_chains_create_table(struct mlx5_fs_chains *chains, ft_attr.flags |= (MLX5_FLOW_TABLE_TUNNEL_EN_REFORMAT | MLX5_FLOW_TABLE_TUNNEL_EN_DECAP); - sz = (chain == mlx5_chains_get_nf_ft_chain(chains)) ? FT_TBL_SZ : POOL_NEXT_SIZE; + sz = (chain == mlx5_chains_get_nf_ft_chain(chains)) ? + FT_TBL_SZ : MLX5_FS_MAX_POOL_SIZE; ft_attr.max_fte = sz; /* We use chains_default_ft(chains) as the table's next_ft till diff --git a/include/linux/mlx5/fs.h b/include/linux/mlx5/fs.h index b744e554f014..db5c9ddef170 100644 --- a/include/linux/mlx5/fs.h +++ b/include/linux/mlx5/fs.h @@ -40,6 +40,8 @@ #define MLX5_SET_CFG(p, f, v) MLX5_SET(create_flow_group_in, p, f, v) +#define MLX5_FS_MAX_POOL_SIZE BIT(30) + enum mlx5_flow_destination_type { MLX5_FLOW_DESTINATION_TYPE_NONE, MLX5_FLOW_DESTINATION_TYPE_VPORT, From 562e512f6bf999c9966baf64b4d9fded8071919e Mon Sep 17 00:00:00 2001 From: Balbir Singh Date: Fri, 7 Feb 2025 10:42:34 +1100 Subject: [PATCH 11/91] x86/kaslr: Reduce KASLR entropy on most x86 systems [ Upstream commit 7ffb791423c7c518269a9aad35039ef824a40adb ] When CONFIG_PCI_P2PDMA=y (which is basically enabled on all large x86 distros), it maps the PFN's via a ZONE_DEVICE mapping using devm_memremap_pages(). The mapped virtual address range corresponds to the pci_resource_start() of the BAR address and size corresponding to the BAR length. When KASLR is enabled, the direct map range of the kernel is reduced to the size of physical memory plus additional padding. If the BAR address is beyond this limit, PCI peer to peer DMA mappings fail. Fix this by not shrinking the size of the direct map when CONFIG_PCI_P2PDMA=y. This reduces the total available entropy, but it's better than the current work around of having to disable KASLR completely. [ mingo: Clarified the changelog to point out the broad impact ... ] Signed-off-by: Balbir Singh Signed-off-by: Ingo Molnar Reviewed-by: Kees Cook Acked-by: Bjorn Helgaas # drivers/pci/Kconfig Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Andy Lutomirski Link: https://lore.kernel.org/lkml/20250206023201.1481957-1-balbirs@nvidia.com/ Link: https://lore.kernel.org/r/20250206234234.1912585-1-balbirs@nvidia.com -- arch/x86/mm/kaslr.c | 10 ++++++++-- drivers/pci/Kconfig | 6 ++++++ 2 files changed, 14 insertions(+), 2 deletions(-) Signed-off-by: Sasha Levin --- arch/x86/mm/kaslr.c | 10 ++++++++-- drivers/pci/Kconfig | 6 ++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/arch/x86/mm/kaslr.c b/arch/x86/mm/kaslr.c index 230f1dee4f09..e0b0ec0f8245 100644 --- a/arch/x86/mm/kaslr.c +++ b/arch/x86/mm/kaslr.c @@ -109,8 +109,14 @@ void __init kernel_randomize_memory(void) memory_tb = DIV_ROUND_UP(max_pfn << PAGE_SHIFT, 1UL << TB_SHIFT) + CONFIG_RANDOMIZE_MEMORY_PHYSICAL_PADDING; - /* Adapt physical memory region size based on available memory */ - if (memory_tb < kaslr_regions[0].size_tb) + /* + * Adapt physical memory region size based on available memory, + * except when CONFIG_PCI_P2PDMA is enabled. P2PDMA exposes the + * device BAR space assuming the direct map space is large enough + * for creating a ZONE_DEVICE mapping in the direct map corresponding + * to the physical BAR address. + */ + if (!IS_ENABLED(CONFIG_PCI_P2PDMA) && (memory_tb < kaslr_regions[0].size_tb)) kaslr_regions[0].size_tb = memory_tb; /* diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig index 0d94e4a967d8..7cef00d9d7ab 100644 --- a/drivers/pci/Kconfig +++ b/drivers/pci/Kconfig @@ -194,6 +194,12 @@ config PCI_P2PDMA P2P DMA transactions must be between devices behind the same root port. + Enabling this option will reduce the entropy of x86 KASLR memory + regions. For example - on a 46 bit system, the entropy goes down + from 16 bits to 15 bits. The actual reduction in entropy depends + on the physical address bits, on processor features, kernel config + (5 level page table) and physical memory present on the system. + If unsure, say N. config PCI_LABEL From 9f27b38771b05067f5fadf4628296efb768e50d4 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sun, 16 Feb 2025 11:07:24 +0800 Subject: [PATCH 12/91] crypto: ahash - Set default reqsize from ahash_alg [ Upstream commit 9e01aaa1033d6e40f8d7cf4f20931a61ce9e3f04 ] Add a reqsize field to struct ahash_alg and use it to set the default reqsize so that algorithms with a static reqsize are not forced to create an init_tfm function. Signed-off-by: Herbert Xu Signed-off-by: Sasha Levin --- crypto/ahash.c | 4 ++++ include/crypto/hash.h | 3 +++ 2 files changed, 7 insertions(+) diff --git a/crypto/ahash.c b/crypto/ahash.c index bcd9de009a91..fe19bf7f15eb 100644 --- a/crypto/ahash.c +++ b/crypto/ahash.c @@ -473,6 +473,7 @@ static int crypto_ahash_init_tfm(struct crypto_tfm *tfm) struct ahash_alg *alg = crypto_ahash_alg(hash); crypto_ahash_set_statesize(hash, alg->halg.statesize); + crypto_ahash_set_reqsize(hash, alg->reqsize); if (tfm->__crt_alg->cra_type == &crypto_shash_type) return crypto_init_ahash_using_shash(tfm); @@ -638,6 +639,9 @@ static int ahash_prepare_alg(struct ahash_alg *alg) if (alg->halg.statesize == 0) return -EINVAL; + if (alg->reqsize && alg->reqsize < alg->halg.statesize) + return -EINVAL; + err = hash_prepare_alg(&alg->halg); if (err) return err; diff --git a/include/crypto/hash.h b/include/crypto/hash.h index 2d5ea9f9ff43..6692253f0b5b 100644 --- a/include/crypto/hash.h +++ b/include/crypto/hash.h @@ -132,6 +132,7 @@ struct ahash_request { * This is a counterpart to @init_tfm, used to remove * various changes set in @init_tfm. * @clone_tfm: Copy transform into new object, may allocate memory. + * @reqsize: Size of the request context. * @halg: see struct hash_alg_common */ struct ahash_alg { @@ -148,6 +149,8 @@ struct ahash_alg { void (*exit_tfm)(struct crypto_ahash *tfm); int (*clone_tfm)(struct crypto_ahash *dst, struct crypto_ahash *src); + unsigned int reqsize; + struct hash_alg_common halg; }; From 897c98fb328011461cc63ea1533688bdac035ad8 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sat, 15 Feb 2025 08:57:51 +0800 Subject: [PATCH 13/91] crypto: skcipher - Zap type in crypto_alloc_sync_skcipher [ Upstream commit ee509efc74ddbc59bb5d6fd6e050f9ef25f74bff ] The type needs to be zeroed as otherwise the user could use it to allocate an asynchronous sync skcipher. Signed-off-by: Herbert Xu Signed-off-by: Sasha Levin --- crypto/skcipher.c | 1 + 1 file changed, 1 insertion(+) diff --git a/crypto/skcipher.c b/crypto/skcipher.c index ceed7f33a67b..fd3273b519dc 100644 --- a/crypto/skcipher.c +++ b/crypto/skcipher.c @@ -844,6 +844,7 @@ struct crypto_sync_skcipher *crypto_alloc_sync_skcipher( /* Only sync algorithms allowed. */ mask |= CRYPTO_ALG_ASYNC | CRYPTO_ALG_SKCIPHER_REQSIZE_LARGE; + type &= ~(CRYPTO_ALG_ASYNC | CRYPTO_ALG_SKCIPHER_REQSIZE_LARGE); tfm = crypto_alloc_tfm(alg_name, &crypto_skcipher_type, type, mask); From 4d9fa2ebc01c492bf478bbdbfc5c9ebd4b27aeb4 Mon Sep 17 00:00:00 2001 From: Xiao Liang Date: Wed, 19 Feb 2025 20:50:33 +0800 Subject: [PATCH 14/91] net: ipv6: Init tunnel link-netns before registering dev [ Upstream commit db014522f35606031d8ac58b4aed6b1ed84f03d1 ] Currently some IPv6 tunnel drivers set tnl->net to dev_net(dev) in ndo_init(), which is called in register_netdevice(). However, it lacks the context of link-netns when we enable cross-net tunnels at device registration time. Let's move the init of tunnel link-netns before register_netdevice(). ip6_gre has already initialized netns, so just remove the redundant assignment. Signed-off-by: Xiao Liang Reviewed-by: Kuniyuki Iwashima Link: https://patch.msgid.link/20250219125039.18024-8-shaw.leon@gmail.com Signed-off-by: Jakub Kicinski Signed-off-by: Sasha Levin --- net/ipv6/ip6_gre.c | 2 -- net/ipv6/ip6_tunnel.c | 3 ++- net/ipv6/ip6_vti.c | 3 ++- net/ipv6/sit.c | 8 +++++--- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c index 235808cfec70..68e9a41eed49 100644 --- a/net/ipv6/ip6_gre.c +++ b/net/ipv6/ip6_gre.c @@ -1498,7 +1498,6 @@ static int ip6gre_tunnel_init_common(struct net_device *dev) tunnel = netdev_priv(dev); tunnel->dev = dev; - tunnel->net = dev_net(dev); strcpy(tunnel->parms.name, dev->name); ret = dst_cache_init(&tunnel->dst_cache, GFP_KERNEL); @@ -1882,7 +1881,6 @@ static int ip6erspan_tap_init(struct net_device *dev) tunnel = netdev_priv(dev); tunnel->dev = dev; - tunnel->net = dev_net(dev); strcpy(tunnel->parms.name, dev->name); ret = dst_cache_init(&tunnel->dst_cache, GFP_KERNEL); diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 48fd53b98972..5350c9bb2319 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -1878,7 +1878,6 @@ ip6_tnl_dev_init_gen(struct net_device *dev) int t_hlen; t->dev = dev; - t->net = dev_net(dev); ret = dst_cache_init(&t->dst_cache, GFP_KERNEL); if (ret) @@ -1940,6 +1939,7 @@ static int __net_init ip6_fb_tnl_dev_init(struct net_device *dev) struct net *net = dev_net(dev); struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); + t->net = net; t->parms.proto = IPPROTO_IPV6; rcu_assign_pointer(ip6n->tnls_wc[0], t); @@ -2013,6 +2013,7 @@ static int ip6_tnl_newlink(struct net *src_net, struct net_device *dev, int err; nt = netdev_priv(dev); + nt->net = net; if (ip_tunnel_netlink_encap_parms(data, &ipencap)) { err = ip6_tnl_encap_setup(nt, &ipencap); diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c index 590737c27537..012350469144 100644 --- a/net/ipv6/ip6_vti.c +++ b/net/ipv6/ip6_vti.c @@ -925,7 +925,6 @@ static inline int vti6_dev_init_gen(struct net_device *dev) struct ip6_tnl *t = netdev_priv(dev); t->dev = dev; - t->net = dev_net(dev); netdev_hold(dev, &t->dev_tracker, GFP_KERNEL); netdev_lockdep_set_classes(dev); return 0; @@ -958,6 +957,7 @@ static int __net_init vti6_fb_tnl_dev_init(struct net_device *dev) struct net *net = dev_net(dev); struct vti6_net *ip6n = net_generic(net, vti6_net_id); + t->net = net; t->parms.proto = IPPROTO_IPV6; rcu_assign_pointer(ip6n->tnls_wc[0], t); @@ -1008,6 +1008,7 @@ static int vti6_newlink(struct net *src_net, struct net_device *dev, vti6_netlink_parms(data, &nt->parms); nt->parms.proto = IPPROTO_IPV6; + nt->net = net; if (vti6_locate(net, &nt->parms, 0)) return -EEXIST; diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 39bd8951bfca..3c15a0ae228e 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -269,6 +269,7 @@ static struct ip_tunnel *ipip6_tunnel_locate(struct net *net, nt = netdev_priv(dev); + nt->net = net; nt->parms = *parms; if (ipip6_tunnel_create(dev) < 0) goto failed_free; @@ -1449,7 +1450,6 @@ static int ipip6_tunnel_init(struct net_device *dev) int err; tunnel->dev = dev; - tunnel->net = dev_net(dev); strcpy(tunnel->parms.name, dev->name); ipip6_tunnel_bind_dev(dev); @@ -1563,6 +1563,7 @@ static int ipip6_newlink(struct net *src_net, struct net_device *dev, int err; nt = netdev_priv(dev); + nt->net = net; if (ip_tunnel_netlink_encap_parms(data, &ipencap)) { err = ip_tunnel_encap_setup(nt, &ipencap); @@ -1858,6 +1859,9 @@ static int __net_init sit_init_net(struct net *net) */ sitn->fb_tunnel_dev->netns_local = true; + t = netdev_priv(sitn->fb_tunnel_dev); + t->net = net; + err = register_netdev(sitn->fb_tunnel_dev); if (err) goto err_reg_dev; @@ -1865,8 +1869,6 @@ static int __net_init sit_init_net(struct net *net) ipip6_tunnel_clone_6rd(sitn->fb_tunnel_dev, sitn); ipip6_fb_tunnel_init(sitn->fb_tunnel_dev); - t = netdev_priv(sitn->fb_tunnel_dev); - strcpy(t->parms.name, sitn->fb_tunnel_dev->name); return 0; From 9058b48578aea5c59189ccb72abbd0bc9fa43a45 Mon Sep 17 00:00:00 2001 From: Umesh Nerlige Ramappa Date: Tue, 11 Feb 2025 17:02:55 -0800 Subject: [PATCH 15/91] drm/xe/oa: Ensure that polled read returns latest data [ Upstream commit 98c9d27ab30aa9c6451d3a34e6e297171f273e51 ] In polled mode, user calls poll() for read data to be available before performing a read(). In the duration between these 2 calls, there may be new data available in the OA buffer. To ensure user reads all available data, check for latest data in the OA buffer in polled read. Signed-off-by: Umesh Nerlige Ramappa Reviewed-by: Ashutosh Dixit Link: https://patchwork.freedesktop.org/patch/msgid/20250212010255.1423343-1-umesh.nerlige.ramappa@intel.com Signed-off-by: Sasha Levin --- drivers/gpu/drm/xe/xe_oa.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/xe/xe_oa.c b/drivers/gpu/drm/xe/xe_oa.c index 448766033690..d306ed0a0443 100644 --- a/drivers/gpu/drm/xe/xe_oa.c +++ b/drivers/gpu/drm/xe/xe_oa.c @@ -535,6 +535,7 @@ static ssize_t xe_oa_read(struct file *file, char __user *buf, mutex_unlock(&stream->stream_lock); } while (!offset && !ret); } else { + xe_oa_buffer_check_unlocked(stream); mutex_lock(&stream->stream_lock); ret = __xe_oa_read(stream, buf, count, &offset); mutex_unlock(&stream->stream_lock); From af706d0e279fcc8e181ebe539a26e3a203c469a3 Mon Sep 17 00:00:00 2001 From: Bibo Mao Date: Tue, 9 Jun 2020 10:54:35 +0800 Subject: [PATCH 16/91] MIPS: Use arch specific syscall name match function [ Upstream commit 756276ce78d5624dc814f9d99f7d16c8fd51076e ] On MIPS system, most of the syscall function name begin with prefix sys_. Some syscalls are special such as clone/fork, function name of these begin with __sys_. Since scratch registers need be saved in stack when these system calls happens. With ftrace system call method, system call functions are declared with SYSCALL_DEFINEx, metadata of the system call symbol name begins with sys_. Here mips specific function arch_syscall_match_sym_name is used to compare function name between sys_call_table[] and metadata of syscall symbol. Signed-off-by: Bibo Mao Signed-off-by: Thomas Bogendoerfer Signed-off-by: Sasha Levin --- arch/mips/include/asm/ftrace.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/arch/mips/include/asm/ftrace.h b/arch/mips/include/asm/ftrace.h index dc025888f6d2..b41fc1044668 100644 --- a/arch/mips/include/asm/ftrace.h +++ b/arch/mips/include/asm/ftrace.h @@ -91,4 +91,20 @@ void prepare_ftrace_return(unsigned long *parent_ra_addr, unsigned long self_ra, #endif /* __ASSEMBLY__ */ #endif /* CONFIG_FUNCTION_TRACER */ + +#ifdef CONFIG_FTRACE_SYSCALLS +#ifndef __ASSEMBLY__ +/* + * Some syscall entry functions on mips start with "__sys_" (fork and clone, + * for instance). We should also match the sys_ variant with those. + */ +#define ARCH_HAS_SYSCALL_MATCH_SYM_NAME +static inline bool arch_syscall_match_sym_name(const char *sym, + const char *name) +{ + return !strcmp(sym, name) || + (!strncmp(sym, "__sys_", 6) && !strcmp(sym + 6, name + 4)); +} +#endif /* __ASSEMBLY__ */ +#endif /* CONFIG_FTRACE_SYSCALLS */ #endif /* _ASM_MIPS_FTRACE_H */ From 95b8f2b7d9312054209bfd80460a1c6adae1ac29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Wed, 29 Jan 2025 16:28:49 +0100 Subject: [PATCH 17/91] drm/amdgpu: remove all KFD fences from the BO on release MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit cb0de06d1b0afb2d0c600ad748069f5ce27730ec ] Remove all KFD BOs from the private dma_resv object. This prevents the KFD from being evict unecessarily when an exported BO is released. Signed-off-by: Christian König Signed-off-by: James Zhu Reviewed-by: Felix Kuehling Reviewed-and-tested-by: James Zhu Signed-off-by: Alex Deucher Signed-off-by: Sasha Levin --- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h | 5 +- .../gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 52 ++++++++----------- drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 38 ++++++++------ 3 files changed, 47 insertions(+), 48 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h index f9d119448442..581fe1a48f37 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h @@ -192,7 +192,7 @@ int kfd_debugfs_kfd_mem_limits(struct seq_file *m, void *data); #if IS_ENABLED(CONFIG_HSA_AMD) bool amdkfd_fence_check_mm(struct dma_fence *f, struct mm_struct *mm); struct amdgpu_amdkfd_fence *to_amdgpu_amdkfd_fence(struct dma_fence *f); -int amdgpu_amdkfd_remove_fence_on_pt_pd_bos(struct amdgpu_bo *bo); +void amdgpu_amdkfd_remove_all_eviction_fences(struct amdgpu_bo *bo); int amdgpu_amdkfd_evict_userptr(struct mmu_interval_notifier *mni, unsigned long cur_seq, struct kgd_mem *mem); int amdgpu_amdkfd_bo_validate_and_fence(struct amdgpu_bo *bo, @@ -212,9 +212,8 @@ struct amdgpu_amdkfd_fence *to_amdgpu_amdkfd_fence(struct dma_fence *f) } static inline -int amdgpu_amdkfd_remove_fence_on_pt_pd_bos(struct amdgpu_bo *bo) +void amdgpu_amdkfd_remove_all_eviction_fences(struct amdgpu_bo *bo) { - return 0; } static inline diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c index fa572ba7f9fc..1465b3adacb0 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c @@ -370,40 +370,32 @@ static int amdgpu_amdkfd_remove_eviction_fence(struct amdgpu_bo *bo, return 0; } -int amdgpu_amdkfd_remove_fence_on_pt_pd_bos(struct amdgpu_bo *bo) +/** + * amdgpu_amdkfd_remove_all_eviction_fences - Remove all eviction fences + * @bo: the BO where to remove the evictions fences from. + * + * This functions should only be used on release when all references to the BO + * are already dropped. We remove the eviction fence from the private copy of + * the dma_resv object here since that is what is used during release to + * determine of the BO is idle or not. + */ +void amdgpu_amdkfd_remove_all_eviction_fences(struct amdgpu_bo *bo) { - struct amdgpu_bo *root = bo; - struct amdgpu_vm_bo_base *vm_bo; - struct amdgpu_vm *vm; - struct amdkfd_process_info *info; - struct amdgpu_amdkfd_fence *ef; - int ret; + struct dma_resv *resv = &bo->tbo.base._resv; + struct dma_fence *fence, *stub; + struct dma_resv_iter cursor; - /* we can always get vm_bo from root PD bo.*/ - while (root->parent) - root = root->parent; + dma_resv_assert_held(resv); - vm_bo = root->vm_bo; - if (!vm_bo) - return 0; + stub = dma_fence_get_stub(); + dma_resv_for_each_fence(&cursor, resv, DMA_RESV_USAGE_BOOKKEEP, fence) { + if (!to_amdgpu_amdkfd_fence(fence)) + continue; - vm = vm_bo->vm; - if (!vm) - return 0; - - info = vm->process_info; - if (!info || !info->eviction_fence) - return 0; - - ef = container_of(dma_fence_get(&info->eviction_fence->base), - struct amdgpu_amdkfd_fence, base); - - BUG_ON(!dma_resv_trylock(bo->tbo.base.resv)); - ret = amdgpu_amdkfd_remove_eviction_fence(bo, ef); - dma_resv_unlock(bo->tbo.base.resv); - - dma_fence_put(&ef->base); - return ret; + dma_resv_replace_fences(resv, fence->context, stub, + DMA_RESV_USAGE_BOOKKEEP); + } + dma_fence_put(stub); } static int amdgpu_amdkfd_bo_validate(struct amdgpu_bo *bo, uint32_t domain, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index 4c4bdc4f51b2..fc588ef598c0 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -1246,28 +1246,36 @@ void amdgpu_bo_release_notify(struct ttm_buffer_object *bo) if (abo->kfd_bo) amdgpu_amdkfd_release_notify(abo); - /* We only remove the fence if the resv has individualized. */ - WARN_ON_ONCE(bo->type == ttm_bo_type_kernel - && bo->base.resv != &bo->base._resv); - if (bo->base.resv == &bo->base._resv) - amdgpu_amdkfd_remove_fence_on_pt_pd_bos(abo); + /* + * We lock the private dma_resv object here and since the BO is about to + * be released nobody else should have a pointer to it. + * So when this locking here fails something is wrong with the reference + * counting. + */ + if (WARN_ON_ONCE(!dma_resv_trylock(&bo->base._resv))) + return; + + amdgpu_amdkfd_remove_all_eviction_fences(abo); if (!bo->resource || bo->resource->mem_type != TTM_PL_VRAM || !(abo->flags & AMDGPU_GEM_CREATE_VRAM_WIPE_ON_RELEASE) || adev->in_suspend || drm_dev_is_unplugged(adev_to_drm(adev))) - return; + goto out; - if (WARN_ON_ONCE(!dma_resv_trylock(bo->base.resv))) - return; + r = dma_resv_reserve_fences(&bo->base._resv, 1); + if (r) + goto out; - r = amdgpu_fill_buffer(abo, 0, bo->base.resv, &fence, true); - if (!WARN_ON(r)) { - amdgpu_vram_mgr_set_cleared(bo->resource); - amdgpu_bo_fence(abo, fence, false); - dma_fence_put(fence); - } + r = amdgpu_fill_buffer(abo, 0, &bo->base._resv, &fence, true); + if (WARN_ON(r)) + goto out; - dma_resv_unlock(bo->base.resv); + amdgpu_vram_mgr_set_cleared(bo->resource); + dma_resv_add_fence(&bo->base._resv, fence, DMA_RESV_USAGE_KERNEL); + dma_fence_put(fence); + +out: + dma_resv_unlock(&bo->base._resv); } /** From 5111c2e0cf2b650ebf69003e3a75aa055eb9a3b0 Mon Sep 17 00:00:00 2001 From: Uros Bizjak Date: Fri, 14 Feb 2025 16:07:46 +0100 Subject: [PATCH 18/91] x86/locking: Use ALT_OUTPUT_SP() for percpu_{,try_}cmpxchg{64,128}_op() [ Upstream commit 4087e16b033140cf2ce509ec23503bddec818a16 ] percpu_{,try_}cmpxchg{64,128}() macros use CALL instruction inside asm statement in one of their alternatives. Use ALT_OUTPUT_SP() macro to add required dependence on %esp register. ALT_OUTPUT_SP() implements the above dependence by adding ASM_CALL_CONSTRAINT to its arguments. This constraint should be used for any inline asm which has a CALL instruction, otherwise the compiler may schedule the asm before the frame pointer gets set up by the containing function, causing objtool to print a "call without frame pointer save/setup" warning. Signed-off-by: Uros Bizjak Signed-off-by: Ingo Molnar Cc: Linus Torvalds Link: https://lore.kernel.org/r/20250214150929.5780-1-ubizjak@gmail.com Signed-off-by: Sasha Levin --- arch/x86/include/asm/percpu.h | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/arch/x86/include/asm/percpu.h b/arch/x86/include/asm/percpu.h index c55a79d5feae..2d9c250b3c8d 100644 --- a/arch/x86/include/asm/percpu.h +++ b/arch/x86/include/asm/percpu.h @@ -349,9 +349,9 @@ do { \ \ asm qual (ALTERNATIVE("call this_cpu_cmpxchg8b_emu", \ "cmpxchg8b " __percpu_arg([var]), X86_FEATURE_CX8) \ - : [var] "+m" (__my_cpu_var(_var)), \ - "+a" (old__.low), \ - "+d" (old__.high) \ + : ALT_OUTPUT_SP([var] "+m" (__my_cpu_var(_var)), \ + "+a" (old__.low), \ + "+d" (old__.high)) \ : "b" (new__.low), \ "c" (new__.high), \ "S" (&(_var)) \ @@ -380,10 +380,10 @@ do { \ asm qual (ALTERNATIVE("call this_cpu_cmpxchg8b_emu", \ "cmpxchg8b " __percpu_arg([var]), X86_FEATURE_CX8) \ CC_SET(z) \ - : CC_OUT(z) (success), \ - [var] "+m" (__my_cpu_var(_var)), \ - "+a" (old__.low), \ - "+d" (old__.high) \ + : ALT_OUTPUT_SP(CC_OUT(z) (success), \ + [var] "+m" (__my_cpu_var(_var)), \ + "+a" (old__.low), \ + "+d" (old__.high)) \ : "b" (new__.low), \ "c" (new__.high), \ "S" (&(_var)) \ @@ -420,9 +420,9 @@ do { \ \ asm qual (ALTERNATIVE("call this_cpu_cmpxchg16b_emu", \ "cmpxchg16b " __percpu_arg([var]), X86_FEATURE_CX16) \ - : [var] "+m" (__my_cpu_var(_var)), \ - "+a" (old__.low), \ - "+d" (old__.high) \ + : ALT_OUTPUT_SP([var] "+m" (__my_cpu_var(_var)), \ + "+a" (old__.low), \ + "+d" (old__.high)) \ : "b" (new__.low), \ "c" (new__.high), \ "S" (&(_var)) \ @@ -451,10 +451,10 @@ do { \ asm qual (ALTERNATIVE("call this_cpu_cmpxchg16b_emu", \ "cmpxchg16b " __percpu_arg([var]), X86_FEATURE_CX16) \ CC_SET(z) \ - : CC_OUT(z) (success), \ - [var] "+m" (__my_cpu_var(_var)), \ - "+a" (old__.low), \ - "+d" (old__.high) \ + : ALT_OUTPUT_SP(CC_OUT(z) (success), \ + [var] "+m" (__my_cpu_var(_var)), \ + "+a" (old__.low), \ + "+d" (old__.high)) \ : "b" (new__.low), \ "c" (new__.high), \ "S" (&(_var)) \ From 53f42776e435f63e5f8e61955e4c205dbfeaf524 Mon Sep 17 00:00:00 2001 From: Jason Gunthorpe Date: Wed, 19 Feb 2025 17:31:36 -0800 Subject: [PATCH 19/91] genirq/msi: Store the IOMMU IOVA directly in msi_desc instead of iommu_cookie [ Upstream commit 1f7df3a691740a7736bbc99dc4ed536120eb4746 ] The IOMMU translation for MSI message addresses has been a 2-step process, separated in time: 1) iommu_dma_prepare_msi(): A cookie pointer containing the IOVA address is stored in the MSI descriptor when an MSI interrupt is allocated. 2) iommu_dma_compose_msi_msg(): this cookie pointer is used to compute a translated message address. This has an inherent lifetime problem for the pointer stored in the cookie that must remain valid between the two steps. However, there is no locking at the irq layer that helps protect the lifetime. Today, this works under the assumption that the iommu domain is not changed while MSI interrupts being programmed. This is true for normal DMA API users within the kernel, as the iommu domain is attached before the driver is probed and cannot be changed while a driver is attached. Classic VFIO type1 also prevented changing the iommu domain while VFIO was running as it does not support changing the "container" after starting up. However, iommufd has improved this so that the iommu domain can be changed during VFIO operation. This potentially allows userspace to directly race VFIO_DEVICE_ATTACH_IOMMUFD_PT (which calls iommu_attach_group()) and VFIO_DEVICE_SET_IRQS (which calls into iommu_dma_compose_msi_msg()). This potentially causes both the cookie pointer and the unlocked call to iommu_get_domain_for_dev() on the MSI translation path to become UAFs. Fix the MSI cookie UAF by removing the cookie pointer. The translated IOVA address is already known during iommu_dma_prepare_msi() and cannot change. Thus, it can simply be stored as an integer in the MSI descriptor. The other UAF related to iommu_get_domain_for_dev() will be addressed in patch "iommu: Make iommu_dma_prepare_msi() into a generic operation" by using the IOMMU group mutex. Link: https://patch.msgid.link/r/a4f2cd76b9dc1833ee6c1cf325cba57def22231c.1740014950.git.nicolinc@nvidia.com Signed-off-by: Nicolin Chen Reviewed-by: Thomas Gleixner Signed-off-by: Jason Gunthorpe Signed-off-by: Sasha Levin --- drivers/iommu/dma-iommu.c | 28 +++++++++++++--------------- include/linux/msi.h | 33 ++++++++++++--------------------- 2 files changed, 25 insertions(+), 36 deletions(-) diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c index 2a9fa0c8cc00..0f0caf59023c 100644 --- a/drivers/iommu/dma-iommu.c +++ b/drivers/iommu/dma-iommu.c @@ -1815,7 +1815,7 @@ int iommu_dma_prepare_msi(struct msi_desc *desc, phys_addr_t msi_addr) static DEFINE_MUTEX(msi_prepare_lock); /* see below */ if (!domain || !domain->iova_cookie) { - desc->iommu_cookie = NULL; + msi_desc_set_iommu_msi_iova(desc, 0, 0); return 0; } @@ -1827,11 +1827,12 @@ int iommu_dma_prepare_msi(struct msi_desc *desc, phys_addr_t msi_addr) mutex_lock(&msi_prepare_lock); msi_page = iommu_dma_get_msi_page(dev, msi_addr, domain); mutex_unlock(&msi_prepare_lock); - - msi_desc_set_iommu_cookie(desc, msi_page); - if (!msi_page) return -ENOMEM; + + msi_desc_set_iommu_msi_iova( + desc, msi_page->iova, + ilog2(cookie_msi_granule(domain->iova_cookie))); return 0; } @@ -1842,18 +1843,15 @@ int iommu_dma_prepare_msi(struct msi_desc *desc, phys_addr_t msi_addr) */ void iommu_dma_compose_msi_msg(struct msi_desc *desc, struct msi_msg *msg) { - struct device *dev = msi_desc_to_dev(desc); - const struct iommu_domain *domain = iommu_get_domain_for_dev(dev); - const struct iommu_dma_msi_page *msi_page; +#ifdef CONFIG_IRQ_MSI_IOMMU + if (desc->iommu_msi_shift) { + u64 msi_iova = desc->iommu_msi_iova << desc->iommu_msi_shift; - msi_page = msi_desc_get_iommu_cookie(desc); - - if (!domain || !domain->iova_cookie || WARN_ON(!msi_page)) - return; - - msg->address_hi = upper_32_bits(msi_page->iova); - msg->address_lo &= cookie_msi_granule(domain->iova_cookie) - 1; - msg->address_lo += lower_32_bits(msi_page->iova); + msg->address_hi = upper_32_bits(msi_iova); + msg->address_lo = lower_32_bits(msi_iova) | + (msg->address_lo & ((1 << desc->iommu_msi_shift) - 1)); + } +#endif } static int iommu_dma_init(void) diff --git a/include/linux/msi.h b/include/linux/msi.h index 59a421fc42bf..63d0e51f7a80 100644 --- a/include/linux/msi.h +++ b/include/linux/msi.h @@ -165,6 +165,10 @@ struct msi_desc_data { * @dev: Pointer to the device which uses this descriptor * @msg: The last set MSI message cached for reuse * @affinity: Optional pointer to a cpu affinity mask for this descriptor + * @iommu_msi_iova: Optional shifted IOVA from the IOMMU to override the msi_addr. + * Only used if iommu_msi_shift != 0 + * @iommu_msi_shift: Indicates how many bits of the original address should be + * preserved when using iommu_msi_iova. * @sysfs_attr: Pointer to sysfs device attribute * * @write_msi_msg: Callback that may be called when the MSI message @@ -183,7 +187,8 @@ struct msi_desc { struct msi_msg msg; struct irq_affinity_desc *affinity; #ifdef CONFIG_IRQ_MSI_IOMMU - const void *iommu_cookie; + u64 iommu_msi_iova : 58; + u64 iommu_msi_shift : 6; #endif #ifdef CONFIG_SYSFS struct device_attribute *sysfs_attrs; @@ -284,28 +289,14 @@ struct msi_desc *msi_next_desc(struct device *dev, unsigned int domid, #define msi_desc_to_dev(desc) ((desc)->dev) +static inline void msi_desc_set_iommu_msi_iova(struct msi_desc *desc, u64 msi_iova, + unsigned int msi_shift) +{ #ifdef CONFIG_IRQ_MSI_IOMMU -static inline const void *msi_desc_get_iommu_cookie(struct msi_desc *desc) -{ - return desc->iommu_cookie; -} - -static inline void msi_desc_set_iommu_cookie(struct msi_desc *desc, - const void *iommu_cookie) -{ - desc->iommu_cookie = iommu_cookie; -} -#else -static inline const void *msi_desc_get_iommu_cookie(struct msi_desc *desc) -{ - return NULL; -} - -static inline void msi_desc_set_iommu_cookie(struct msi_desc *desc, - const void *iommu_cookie) -{ -} + desc->iommu_msi_iova = msi_iova >> msi_shift; + desc->iommu_msi_shift = msi_shift; #endif +} int msi_domain_insert_msi_desc(struct device *dev, unsigned int domid, struct msi_desc *init_desc); From 1a3529f36f26ef8ecb9c1f4fef49c2af3986da6d Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Wed, 29 Jan 2025 13:32:48 +0100 Subject: [PATCH 20/91] MIPS: pm-cps: Use per-CPU variables as per-CPU, not per-core [ Upstream commit 00a134fc2bb4a5f8fada58cf7ff4259149691d64 ] The pm-cps code has up until now used per-CPU variables indexed by core, rather than CPU number, in order to share data amongst sibling CPUs (ie. VPs/threads in a core). This works fine for single cluster systems, but with multi-cluster systems a core number is no longer unique in the system, leading to sharing between CPUs that are not actually siblings. Avoid this issue by using per-CPU variables as they are more generally used - ie. access them using CPU numbers rather than core numbers. Sharing between siblings is then accomplished by: - Assigning the same pointer to entries for each sibling CPU for the nc_asm_enter & ready_count variables, which allow this by virtue of being per-CPU pointers. - Indexing by the first CPU set in a CPUs cpu_sibling_map in the case of pm_barrier, for which we can't use the previous approach because the per-CPU variable is not a pointer. Signed-off-by: Paul Burton Signed-off-by: Dragan Mladjenovic Signed-off-by: Aleksandar Rikalo Tested-by: Serge Semin Tested-by: Gregory CLEMENT Signed-off-by: Thomas Bogendoerfer Signed-off-by: Sasha Levin --- arch/mips/kernel/pm-cps.c | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/arch/mips/kernel/pm-cps.c b/arch/mips/kernel/pm-cps.c index d09ca77e624d..9369a8dc385e 100644 --- a/arch/mips/kernel/pm-cps.c +++ b/arch/mips/kernel/pm-cps.c @@ -57,10 +57,7 @@ static DEFINE_PER_CPU_ALIGNED(u32*, ready_count); /* Indicates online CPUs coupled with the current CPU */ static DEFINE_PER_CPU_ALIGNED(cpumask_t, online_coupled); -/* - * Used to synchronize entry to deep idle states. Actually per-core rather - * than per-CPU. - */ +/* Used to synchronize entry to deep idle states */ static DEFINE_PER_CPU_ALIGNED(atomic_t, pm_barrier); /* Saved CPU state across the CPS_PM_POWER_GATED state */ @@ -112,9 +109,10 @@ int cps_pm_enter_state(enum cps_pm_state state) cps_nc_entry_fn entry; struct core_boot_config *core_cfg; struct vpe_boot_config *vpe_cfg; + atomic_t *barrier; /* Check that there is an entry function for this state */ - entry = per_cpu(nc_asm_enter, core)[state]; + entry = per_cpu(nc_asm_enter, cpu)[state]; if (!entry) return -EINVAL; @@ -150,7 +148,7 @@ int cps_pm_enter_state(enum cps_pm_state state) smp_mb__after_atomic(); /* Create a non-coherent mapping of the core ready_count */ - core_ready_count = per_cpu(ready_count, core); + core_ready_count = per_cpu(ready_count, cpu); nc_addr = kmap_noncoherent(virt_to_page(core_ready_count), (unsigned long)core_ready_count); nc_addr += ((unsigned long)core_ready_count & ~PAGE_MASK); @@ -158,7 +156,8 @@ int cps_pm_enter_state(enum cps_pm_state state) /* Ensure ready_count is zero-initialised before the assembly runs */ WRITE_ONCE(*nc_core_ready_count, 0); - coupled_barrier(&per_cpu(pm_barrier, core), online); + barrier = &per_cpu(pm_barrier, cpumask_first(&cpu_sibling_map[cpu])); + coupled_barrier(barrier, online); /* Run the generated entry code */ left = entry(online, nc_core_ready_count); @@ -629,12 +628,14 @@ out_err: static int cps_pm_online_cpu(unsigned int cpu) { - enum cps_pm_state state; - unsigned core = cpu_core(&cpu_data[cpu]); + unsigned int sibling, core; void *entry_fn, *core_rc; + enum cps_pm_state state; + + core = cpu_core(&cpu_data[cpu]); for (state = CPS_PM_NC_WAIT; state < CPS_PM_STATE_COUNT; state++) { - if (per_cpu(nc_asm_enter, core)[state]) + if (per_cpu(nc_asm_enter, cpu)[state]) continue; if (!test_bit(state, state_support)) continue; @@ -646,16 +647,19 @@ static int cps_pm_online_cpu(unsigned int cpu) clear_bit(state, state_support); } - per_cpu(nc_asm_enter, core)[state] = entry_fn; + for_each_cpu(sibling, &cpu_sibling_map[cpu]) + per_cpu(nc_asm_enter, sibling)[state] = entry_fn; } - if (!per_cpu(ready_count, core)) { + if (!per_cpu(ready_count, cpu)) { core_rc = kmalloc(sizeof(u32), GFP_KERNEL); if (!core_rc) { pr_err("Failed allocate core %u ready_count\n", core); return -ENOMEM; } - per_cpu(ready_count, core) = core_rc; + + for_each_cpu(sibling, &cpu_sibling_map[cpu]) + per_cpu(ready_count, sibling) = core_rc; } return 0; From 0b21e99cf638bc06f199204d2211034661f650b4 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Wed, 29 Jan 2025 13:32:47 +0100 Subject: [PATCH 21/91] clocksource: mips-gic-timer: Enable counter when CPUs start MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 3128b0a2e0cf6e07aa78e5f8cf7dd9cd59dc8174 ] In multi-cluster MIPS I6500 systems there is a GIC in each cluster, each with its own counter. When a cluster powers up the counter will be stopped, with the COUNTSTOP bit set in the GIC_CONFIG register. In single cluster systems, it has been fine to clear COUNTSTOP once in gic_clocksource_of_init() to start the counter. In multi-cluster systems, this will only have started the counter in the boot cluster, and any CPUs in other clusters will find their counter stopped which will break the GIC clock_event_device. Resolve this by having CPUs clear the COUNTSTOP bit when they come online, using the existing gic_starting_cpu() CPU hotplug callback. This will allow CPUs in secondary clusters to ensure that the cluster's GIC counter is running as expected. Signed-off-by: Paul Burton Signed-off-by: Chao-ying Fu Signed-off-by: Dragan Mladjenovic Signed-off-by: Aleksandar Rikalo Reviewed-by: Philippe Mathieu-Daudé Tested-by: Serge Semin Tested-by: Gregory CLEMENT Acked-by: Daniel Lezcano Signed-off-by: Thomas Bogendoerfer Signed-off-by: Sasha Levin --- drivers/clocksource/mips-gic-timer.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/clocksource/mips-gic-timer.c b/drivers/clocksource/mips-gic-timer.c index 110347707ff9..8592910710d1 100644 --- a/drivers/clocksource/mips-gic-timer.c +++ b/drivers/clocksource/mips-gic-timer.c @@ -115,6 +115,9 @@ static void gic_update_frequency(void *data) static int gic_starting_cpu(unsigned int cpu) { + /* Ensure the GIC counter is running */ + clear_gic_config(GIC_CONFIG_COUNTSTOP); + gic_clockevent_cpu_init(cpu, this_cpu_ptr(&gic_clockevent_device)); return 0; } @@ -252,9 +255,6 @@ static int __init gic_clocksource_of_init(struct device_node *node) pr_warn("Unable to register clock notifier\n"); } - /* And finally start the counter */ - clear_gic_config(GIC_CONFIG_COUNTSTOP); - /* * It's safe to use the MIPS GIC timer as a sched clock source only if * its ticks are stable, which is true on either the platforms with From b5038d313a3b7fcf56b2e9853a7cf663dc83c47f Mon Sep 17 00:00:00 2001 From: Mrinmay Sarkar Date: Thu, 5 Dec 2024 12:24:20 +0530 Subject: [PATCH 22/91] PCI: epf-mhi: Update device ID for SA8775P MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 4f13dd9e2b1d2b317bb36704f8a7bd1d3017f7a2 ] Update device ID for the Qcom SA8775P SoC. Signed-off-by: Mrinmay Sarkar Link: https://lore.kernel.org/r/20241205065422.2515086-3-quic_msarkar@quicinc.com [kwilczynski: commit log] Signed-off-by: Krzysztof Wilczyński Signed-off-by: Sasha Levin --- drivers/pci/endpoint/functions/pci-epf-mhi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pci/endpoint/functions/pci-epf-mhi.c b/drivers/pci/endpoint/functions/pci-epf-mhi.c index 54286a40bdfb..6643a88c7a0c 100644 --- a/drivers/pci/endpoint/functions/pci-epf-mhi.c +++ b/drivers/pci/endpoint/functions/pci-epf-mhi.c @@ -125,7 +125,7 @@ static const struct pci_epf_mhi_ep_info sm8450_info = { static struct pci_epf_header sa8775p_header = { .vendorid = PCI_VENDOR_ID_QCOM, - .deviceid = 0x0306, /* FIXME: Update deviceid for sa8775p EP */ + .deviceid = 0x0116, .baseclass_code = PCI_CLASS_OTHERS, .interrupt_pin = PCI_INTERRUPT_INTA, }; From 1653c72dabfd68b68e4aa94d10075a8f16ca3ac2 Mon Sep 17 00:00:00 2001 From: Shivasharan S Date: Wed, 12 Feb 2025 17:26:55 -0800 Subject: [PATCH 23/91] scsi: mpt3sas: Send a diag reset if target reset fails [ Upstream commit 5612d6d51ed2634a033c95de2edec7449409cbb9 ] When an IOCTL times out and driver issues a target reset, if firmware fails the task management elevate the recovery by issuing a diag reset to controller. Signed-off-by: Shivasharan S Link: https://lore.kernel.org/r/1739410016-27503-5-git-send-email-shivasharan.srikanteshwara@broadcom.com Signed-off-by: Martin K. Petersen Signed-off-by: Sasha Levin --- drivers/scsi/mpt3sas/mpt3sas_ctl.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/mpt3sas/mpt3sas_ctl.c b/drivers/scsi/mpt3sas/mpt3sas_ctl.c index 87784c96249a..47faa27bc355 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_ctl.c +++ b/drivers/scsi/mpt3sas/mpt3sas_ctl.c @@ -679,6 +679,7 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg, size_t data_in_sz = 0; long ret; u16 device_handle = MPT3SAS_INVALID_DEVICE_HANDLE; + int tm_ret; issue_reset = 0; @@ -1120,18 +1121,25 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg, if (pcie_device && (!ioc->tm_custom_handling) && (!(mpt3sas_scsih_is_pcie_scsi_device( pcie_device->device_info)))) - mpt3sas_scsih_issue_locked_tm(ioc, + tm_ret = mpt3sas_scsih_issue_locked_tm(ioc, le16_to_cpu(mpi_request->FunctionDependent1), 0, 0, 0, MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0, 0, pcie_device->reset_timeout, MPI26_SCSITASKMGMT_MSGFLAGS_PROTOCOL_LVL_RST_PCIE); else - mpt3sas_scsih_issue_locked_tm(ioc, + tm_ret = mpt3sas_scsih_issue_locked_tm(ioc, le16_to_cpu(mpi_request->FunctionDependent1), 0, 0, 0, MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0, 0, 30, MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET); + + if (tm_ret != SUCCESS) { + ioc_info(ioc, + "target reset failed, issue hard reset: handle (0x%04x)\n", + le16_to_cpu(mpi_request->FunctionDependent1)); + mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER); + } } else mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER); } From 9a3f80a727aac5e6c446d1386ad0c007734bf5cc Mon Sep 17 00:00:00 2001 From: Bitterblue Smith Date: Tue, 18 Feb 2025 01:30:48 +0200 Subject: [PATCH 24/91] wifi: rtw88: Fix rtw_init_vht_cap() for RTL8814AU [ Upstream commit 6be7544d19fcfcb729495e793bc6181f85bb8949 ] Set the MCS maps and the highest rates according to the number of spatial streams the chip has. For RTL8814AU that is 3. Signed-off-by: Bitterblue Smith Acked-by: Ping-Ke Shih Signed-off-by: Ping-Ke Shih Link: https://patch.msgid.link/e86aa009-b5bf-4b3a-8112-ea5e3cd49465@gmail.com Signed-off-by: Sasha Levin --- drivers/net/wireless/realtek/rtw88/main.c | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c index bbdef38c7e34..2c81e4cae039 100644 --- a/drivers/net/wireless/realtek/rtw88/main.c +++ b/drivers/net/wireless/realtek/rtw88/main.c @@ -1579,8 +1579,9 @@ static void rtw_init_vht_cap(struct rtw_dev *rtwdev, struct ieee80211_sta_vht_cap *vht_cap) { struct rtw_efuse *efuse = &rtwdev->efuse; - u16 mcs_map; + u16 mcs_map = 0; __le16 highest; + int i; if (efuse->hw_cap.ptcl != EFUSE_HW_CAP_IGNORE && efuse->hw_cap.ptcl != EFUSE_HW_CAP_PTCL_VHT) @@ -1603,21 +1604,15 @@ static void rtw_init_vht_cap(struct rtw_dev *rtwdev, if (rtw_chip_has_rx_ldpc(rtwdev)) vht_cap->cap |= IEEE80211_VHT_CAP_RXLDPC; - mcs_map = IEEE80211_VHT_MCS_SUPPORT_0_9 << 0 | - IEEE80211_VHT_MCS_NOT_SUPPORTED << 4 | - IEEE80211_VHT_MCS_NOT_SUPPORTED << 6 | - IEEE80211_VHT_MCS_NOT_SUPPORTED << 8 | - IEEE80211_VHT_MCS_NOT_SUPPORTED << 10 | - IEEE80211_VHT_MCS_NOT_SUPPORTED << 12 | - IEEE80211_VHT_MCS_NOT_SUPPORTED << 14; - if (efuse->hw_cap.nss > 1) { - highest = cpu_to_le16(780); - mcs_map |= IEEE80211_VHT_MCS_SUPPORT_0_9 << 2; - } else { - highest = cpu_to_le16(390); - mcs_map |= IEEE80211_VHT_MCS_NOT_SUPPORTED << 2; + for (i = 0; i < 8; i++) { + if (i < efuse->hw_cap.nss) + mcs_map |= IEEE80211_VHT_MCS_SUPPORT_0_9 << (i * 2); + else + mcs_map |= IEEE80211_VHT_MCS_NOT_SUPPORTED << (i * 2); } + highest = cpu_to_le16(390 * efuse->hw_cap.nss); + vht_cap->vht_mcs.rx_mcs_map = cpu_to_le16(mcs_map); vht_cap->vht_mcs.tx_mcs_map = cpu_to_le16(mcs_map); vht_cap->vht_mcs.rx_highest = highest; From adcc65afaa97921d430a662229ae8e573a4a8dec Mon Sep 17 00:00:00 2001 From: Bitterblue Smith Date: Tue, 18 Feb 2025 01:30:22 +0200 Subject: [PATCH 25/91] wifi: rtw88: Fix rtw_init_ht_cap() for RTL8814AU [ Upstream commit c7eea1ba05ca5b0dbf77a27cf2e1e6e2fb3c0043 ] Set the RX mask and the highest RX rate according to the number of spatial streams the chip can receive. For RTL8814AU that is 3. Signed-off-by: Bitterblue Smith Acked-by: Ping-Ke Shih Signed-off-by: Ping-Ke Shih Link: https://patch.msgid.link/4e786f50-ed1c-4387-8b28-e6ff00e35e81@gmail.com Signed-off-by: Sasha Levin --- drivers/net/wireless/realtek/rtw88/main.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c index 2c81e4cae039..a808af2f085e 100644 --- a/drivers/net/wireless/realtek/rtw88/main.c +++ b/drivers/net/wireless/realtek/rtw88/main.c @@ -1543,6 +1543,7 @@ static void rtw_init_ht_cap(struct rtw_dev *rtwdev, { const struct rtw_chip_info *chip = rtwdev->chip; struct rtw_efuse *efuse = &rtwdev->efuse; + int i; ht_cap->ht_supported = true; ht_cap->cap = 0; @@ -1562,17 +1563,11 @@ static void rtw_init_ht_cap(struct rtw_dev *rtwdev, ht_cap->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; ht_cap->ampdu_density = chip->ampdu_density; ht_cap->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; - if (efuse->hw_cap.nss > 1) { - ht_cap->mcs.rx_mask[0] = 0xFF; - ht_cap->mcs.rx_mask[1] = 0xFF; - ht_cap->mcs.rx_mask[4] = 0x01; - ht_cap->mcs.rx_highest = cpu_to_le16(300); - } else { - ht_cap->mcs.rx_mask[0] = 0xFF; - ht_cap->mcs.rx_mask[1] = 0x00; - ht_cap->mcs.rx_mask[4] = 0x01; - ht_cap->mcs.rx_highest = cpu_to_le16(150); - } + + for (i = 0; i < efuse->hw_cap.nss; i++) + ht_cap->mcs.rx_mask[i] = 0xFF; + ht_cap->mcs.rx_mask[4] = 0x01; + ht_cap->mcs.rx_highest = cpu_to_le16(150 * efuse->hw_cap.nss); } static void rtw_init_vht_cap(struct rtw_dev *rtwdev, From a4523765fa3a9f58012904c0329a8bb93ba20b0e Mon Sep 17 00:00:00 2001 From: Bitterblue Smith Date: Tue, 18 Feb 2025 01:29:52 +0200 Subject: [PATCH 26/91] wifi: rtw88: Fix rtw_desc_to_mcsrate() to handle MCS16-31 [ Upstream commit 86d04f8f991a0509e318fe886d5a1cf795736c7d ] This function translates the rate number reported by the hardware into something mac80211 can understand. It was ignoring the 3SS and 4SS HT rates. Translate them too. Also set *nss to 0 for the HT rates, just to make sure it's initialised. Signed-off-by: Bitterblue Smith Acked-by: Ping-Ke Shih Signed-off-by: Ping-Ke Shih Link: https://patch.msgid.link/d0a5a86b-4869-47f6-a5a7-01c0f987cc7f@gmail.com Signed-off-by: Sasha Levin --- drivers/net/wireless/realtek/rtw88/util.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/realtek/rtw88/util.c b/drivers/net/wireless/realtek/rtw88/util.c index e222d3c01a77..66819f694405 100644 --- a/drivers/net/wireless/realtek/rtw88/util.c +++ b/drivers/net/wireless/realtek/rtw88/util.c @@ -101,7 +101,8 @@ void rtw_desc_to_mcsrate(u16 rate, u8 *mcs, u8 *nss) *nss = 4; *mcs = rate - DESC_RATEVHT4SS_MCS0; } else if (rate >= DESC_RATEMCS0 && - rate <= DESC_RATEMCS15) { + rate <= DESC_RATEMCS31) { + *nss = 0; *mcs = rate - DESC_RATEMCS0; } } From 1cbef396c5f3bf89f4787c975d85533f373bb9ad Mon Sep 17 00:00:00 2001 From: Ping-Ke Shih Date: Mon, 17 Feb 2025 14:43:06 +0800 Subject: [PATCH 27/91] wifi: rtw89: fw: propagate error code from rtw89_h2c_tx() [ Upstream commit 56e1acaa0f80620b8e2c3410db35b4b975782b0a ] The error code should be propagated to callers during downloading firmware header and body. Remove unnecessary assignment of -1. Signed-off-by: Ping-Ke Shih Link: https://patch.msgid.link/20250217064308.43559-4-pkshih@realtek.com Signed-off-by: Sasha Levin --- drivers/net/wireless/realtek/rtw89/fw.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c index 620e076d1b59..9d26502a2885 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.c +++ b/drivers/net/wireless/realtek/rtw89/fw.c @@ -1234,7 +1234,6 @@ static int __rtw89_fw_download_hdr(struct rtw89_dev *rtwdev, ret = rtw89_h2c_tx(rtwdev, skb, false); if (ret) { rtw89_err(rtwdev, "failed to send h2c\n"); - ret = -1; goto fail; } @@ -1311,7 +1310,6 @@ static int __rtw89_fw_download_main(struct rtw89_dev *rtwdev, ret = rtw89_h2c_tx(rtwdev, skb, true); if (ret) { rtw89_err(rtwdev, "failed to send h2c\n"); - ret = -1; goto fail; } From 6ffcf25e6322630cc495fb3cde7f0e9ca56afc72 Mon Sep 17 00:00:00 2001 From: Ping-Ke Shih Date: Mon, 17 Feb 2025 14:43:05 +0800 Subject: [PATCH 28/91] wifi: rtw89: fw: get sb_sel_ver via get_unaligned_le32() [ Upstream commit 2f9da853f4d848d23bade4c22931ea0f5a011674 ] The sb_sel_ver is selection version for secure boot recorded in firmware binary data, and its size is 4 and offset is 58 (not natural alignment). Use get_unaligned_le32() to get this value safely. Find this by reviewing. Signed-off-by: Ping-Ke Shih Link: https://patch.msgid.link/20250217064308.43559-3-pkshih@realtek.com Signed-off-by: Sasha Levin --- drivers/net/wireless/realtek/rtw89/fw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c index 9d26502a2885..f0e87af68d8c 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.c +++ b/drivers/net/wireless/realtek/rtw89/fw.c @@ -285,7 +285,7 @@ static int __parse_formatted_mssc(struct rtw89_dev *rtwdev, if (!sec->secure_boot) goto out; - sb_sel_ver = le32_to_cpu(section_content->sb_sel_ver.v); + sb_sel_ver = get_unaligned_le32(§ion_content->sb_sel_ver.v); if (sb_sel_ver && sb_sel_ver != sec->sb_sel_mgn) goto ignore; From 7dafba4e854cd489790213a1af04986342b09c18 Mon Sep 17 00:00:00 2001 From: Ping-Ke Shih Date: Mon, 17 Feb 2025 14:43:04 +0800 Subject: [PATCH 29/91] wifi: rtw89: fw: add blacklist to avoid obsolete secure firmware [ Upstream commit f11d042b3a2e92ab1aa10e0da8e290bcdcf31d39 ] To ensure secure chip only runs expected secure firmware, stop using obsolete firmware in blacklist which weakness or flaw was found. Signed-off-by: Ping-Ke Shih Link: https://patch.msgid.link/20250217064308.43559-2-pkshih@realtek.com Signed-off-by: Sasha Levin --- drivers/net/wireless/realtek/rtw89/core.h | 2 + drivers/net/wireless/realtek/rtw89/fw.c | 52 ++++++++++++++++++- drivers/net/wireless/realtek/rtw89/fw.h | 12 +++++ drivers/net/wireless/realtek/rtw89/rtw8851b.c | 1 + drivers/net/wireless/realtek/rtw89/rtw8852a.c | 1 + drivers/net/wireless/realtek/rtw89/rtw8852b.c | 1 + .../net/wireless/realtek/rtw89/rtw8852bt.c | 1 + drivers/net/wireless/realtek/rtw89/rtw8852c.c | 1 + drivers/net/wireless/realtek/rtw89/rtw8922a.c | 1 + 9 files changed, 71 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h index ff3048d2489f..4f64ea392e6c 100644 --- a/drivers/net/wireless/realtek/rtw89/core.h +++ b/drivers/net/wireless/realtek/rtw89/core.h @@ -17,6 +17,7 @@ struct rtw89_dev; struct rtw89_pci_info; struct rtw89_mac_gen_def; struct rtw89_phy_gen_def; +struct rtw89_fw_blacklist; struct rtw89_efuse_block_cfg; struct rtw89_h2c_rf_tssi; struct rtw89_fw_txpwr_track_cfg; @@ -4232,6 +4233,7 @@ struct rtw89_chip_info { bool try_ce_fw; u8 bbmcu_nr; u32 needed_fw_elms; + const struct rtw89_fw_blacklist *fw_blacklist; u32 fifo_size; bool small_fifo_size; u32 dle_scc_rsvd_size; diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c index f0e87af68d8c..93d760b8b5e3 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.c +++ b/drivers/net/wireless/realtek/rtw89/fw.c @@ -38,6 +38,16 @@ struct rtw89_arp_rsp { static const u8 mss_signature[] = {0x4D, 0x53, 0x53, 0x4B, 0x50, 0x4F, 0x4F, 0x4C}; +const struct rtw89_fw_blacklist rtw89_fw_blacklist_default = { + .ver = 0x00, + .list = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + }, +}; +EXPORT_SYMBOL(rtw89_fw_blacklist_default); + union rtw89_fw_element_arg { size_t offset; enum rtw89_rf_path rf_path; @@ -315,6 +325,46 @@ ignore: return 0; } +static int __check_secure_blacklist(struct rtw89_dev *rtwdev, + struct rtw89_fw_bin_info *info, + struct rtw89_fw_hdr_section_info *section_info, + const void *content) +{ + const struct rtw89_fw_blacklist *chip_blacklist = rtwdev->chip->fw_blacklist; + const union rtw89_fw_section_mssc_content *section_content = content; + struct rtw89_fw_secure *sec = &rtwdev->fw.sec; + u8 byte_idx; + u8 bit_mask; + + if (!sec->secure_boot) + return 0; + + if (!info->secure_section_exist || section_info->ignore) + return 0; + + if (!chip_blacklist) { + rtw89_err(rtwdev, "chip no blacklist for secure firmware\n"); + return -ENOENT; + } + + byte_idx = section_content->blacklist.bit_in_chip_list >> 3; + bit_mask = BIT(section_content->blacklist.bit_in_chip_list & 0x7); + + if (section_content->blacklist.ver > chip_blacklist->ver) { + rtw89_err(rtwdev, "chip blacklist out of date (%u, %u)\n", + section_content->blacklist.ver, chip_blacklist->ver); + return -EINVAL; + } + + if (chip_blacklist->list[byte_idx] & bit_mask) { + rtw89_err(rtwdev, "firmware %u in chip blacklist\n", + section_content->blacklist.ver); + return -EPERM; + } + + return 0; +} + static int __parse_security_section(struct rtw89_dev *rtwdev, struct rtw89_fw_bin_info *info, struct rtw89_fw_hdr_section_info *section_info, @@ -340,7 +390,7 @@ static int __parse_security_section(struct rtw89_dev *rtwdev, info->secure_section_exist = true; } - return 0; + return __check_secure_blacklist(rtwdev, info, section_info, content); } static int rtw89_fw_hdr_parser_v1(struct rtw89_dev *rtwdev, const u8 *fw, u32 len, diff --git a/drivers/net/wireless/realtek/rtw89/fw.h b/drivers/net/wireless/realtek/rtw89/fw.h index ccbbc43f33fe..502ece540b9d 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.h +++ b/drivers/net/wireless/realtek/rtw89/fw.h @@ -639,6 +639,11 @@ struct rtw89_fw_mss_pool_hdr { } __packed; union rtw89_fw_section_mssc_content { + struct { + u8 pad[0x20]; + u8 bit_in_chip_list; + u8 ver; + } __packed blacklist; struct { u8 pad[58]; __le32 v; @@ -649,6 +654,13 @@ union rtw89_fw_section_mssc_content { } __packed key_sign_len; } __packed; +struct rtw89_fw_blacklist { + u8 ver; + u8 list[32]; +}; + +extern const struct rtw89_fw_blacklist rtw89_fw_blacklist_default; + static inline void SET_CTRL_INFO_MACID(void *table, u32 val) { le32p_replace_bits((__le32 *)(table) + 0, val, GENMASK(6, 0)); diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851b.c b/drivers/net/wireless/realtek/rtw89/rtw8851b.c index f9766bf30e71..0d2a1e712b34 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8851b.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8851b.c @@ -2443,6 +2443,7 @@ const struct rtw89_chip_info rtw8851b_chip_info = { .try_ce_fw = true, .bbmcu_nr = 0, .needed_fw_elms = 0, + .fw_blacklist = NULL, .fifo_size = 196608, .small_fifo_size = true, .dle_scc_rsvd_size = 98304, diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852a.c b/drivers/net/wireless/realtek/rtw89/rtw8852a.c index 42d369d2e916..5f08207936c6 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852a.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852a.c @@ -2159,6 +2159,7 @@ const struct rtw89_chip_info rtw8852a_chip_info = { .try_ce_fw = false, .bbmcu_nr = 0, .needed_fw_elms = 0, + .fw_blacklist = NULL, .fifo_size = 458752, .small_fifo_size = false, .dle_scc_rsvd_size = 0, diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852b.c b/drivers/net/wireless/realtek/rtw89/rtw8852b.c index 364aa21cbd44..0e03d97ba1cf 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852b.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852b.c @@ -797,6 +797,7 @@ const struct rtw89_chip_info rtw8852b_chip_info = { .try_ce_fw = true, .bbmcu_nr = 0, .needed_fw_elms = 0, + .fw_blacklist = &rtw89_fw_blacklist_default, .fifo_size = 196608, .small_fifo_size = true, .dle_scc_rsvd_size = 98304, diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852bt.c b/drivers/net/wireless/realtek/rtw89/rtw8852bt.c index dab7e71ec6a1..1dd3e51bab9f 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852bt.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852bt.c @@ -731,6 +731,7 @@ const struct rtw89_chip_info rtw8852bt_chip_info = { .try_ce_fw = true, .bbmcu_nr = 0, .needed_fw_elms = RTW89_AX_GEN_DEF_NEEDED_FW_ELEMENTS_NO_6GHZ, + .fw_blacklist = &rtw89_fw_blacklist_default, .fifo_size = 458752, .small_fifo_size = true, .dle_scc_rsvd_size = 98304, diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c.c b/drivers/net/wireless/realtek/rtw89/rtw8852c.c index dbe77abb2c48..5e2592cf1a9f 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852c.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852c.c @@ -2936,6 +2936,7 @@ const struct rtw89_chip_info rtw8852c_chip_info = { .try_ce_fw = false, .bbmcu_nr = 0, .needed_fw_elms = 0, + .fw_blacklist = &rtw89_fw_blacklist_default, .fifo_size = 458752, .small_fifo_size = false, .dle_scc_rsvd_size = 0, diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922a.c b/drivers/net/wireless/realtek/rtw89/rtw8922a.c index ef7747adbcc2..64a41f24b2ad 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8922a.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8922a.c @@ -2632,6 +2632,7 @@ const struct rtw89_chip_info rtw8922a_chip_info = { .try_ce_fw = false, .bbmcu_nr = 1, .needed_fw_elms = RTW89_BE_GEN_DEF_NEEDED_FW_ELEMENTS, + .fw_blacklist = &rtw89_fw_blacklist_default, .fifo_size = 589824, .small_fifo_size = false, .dle_scc_rsvd_size = 0, From d37783f25a3c8aa32d7fb2d61941dbbcd1ddb62b Mon Sep 17 00:00:00 2001 From: Kuan-Chung Chen Date: Mon, 17 Feb 2025 14:12:35 +0800 Subject: [PATCH 30/91] wifi: rtw89: 8922a: fix incorrect STA-ID in EHT MU PPDU [ Upstream commit bdce0574243b43b3bb2064f609c0c326df44c4c6 ] EHT MU PPDU contains user field of EHT-SIG field with STA-ID that must match AID subfield in the Associate Response. Add a necessary setting to prevent these from being inconsistent. Signed-off-by: Kuan-Chung Chen Signed-off-by: Ping-Ke Shih Link: https://patch.msgid.link/20250217061235.32031-1-pkshih@realtek.com Signed-off-by: Sasha Levin --- drivers/net/wireless/realtek/rtw89/fw.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c index 93d760b8b5e3..9346fe082040 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.c +++ b/drivers/net/wireless/realtek/rtw89/fw.c @@ -3128,9 +3128,10 @@ int rtw89_fw_h2c_assoc_cmac_tbl_g7(struct rtw89_dev *rtwdev, CCTLINFO_G7_W5_NOMINAL_PKT_PADDING3 | CCTLINFO_G7_W5_NOMINAL_PKT_PADDING4); - h2c->w6 = le32_encode_bits(vif->type == NL80211_IFTYPE_STATION ? 1 : 0, + h2c->w6 = le32_encode_bits(vif->cfg.aid, CCTLINFO_G7_W6_AID12_PAID) | + le32_encode_bits(vif->type == NL80211_IFTYPE_STATION ? 1 : 0, CCTLINFO_G7_W6_ULDL); - h2c->m6 = cpu_to_le32(CCTLINFO_G7_W6_ULDL); + h2c->m6 = cpu_to_le32(CCTLINFO_G7_W6_AID12_PAID | CCTLINFO_G7_W6_ULDL); if (rtwsta_link) { h2c->w8 = le32_encode_bits(link_sta->he_cap.has_he, From 6b1d3e9db82d01a88de1795b879df67c2116b4f4 Mon Sep 17 00:00:00 2001 From: Peter Seiderer Date: Wed, 19 Feb 2025 09:45:27 +0100 Subject: [PATCH 31/91] net: pktgen: fix access outside of user given buffer in pktgen_thread_write() [ Upstream commit 425e64440ad0a2f03bdaf04be0ae53dededbaa77 ] Honour the user given buffer size for the strn_len() calls (otherwise strn_len() will access memory outside of the user given buffer). Signed-off-by: Peter Seiderer Reviewed-by: Simon Horman Link: https://patch.msgid.link/20250219084527.20488-8-ps.report@gmx.net Signed-off-by: Jakub Kicinski Signed-off-by: Sasha Levin --- net/core/pktgen.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/net/core/pktgen.c b/net/core/pktgen.c index 4d87da56c56a..762ede027899 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -1898,8 +1898,8 @@ static ssize_t pktgen_thread_write(struct file *file, i = len; /* Read variable name */ - - len = strn_len(&user_buffer[i], sizeof(name) - 1); + max = min(sizeof(name) - 1, count - i); + len = strn_len(&user_buffer[i], max); if (len < 0) return len; @@ -1929,7 +1929,8 @@ static ssize_t pktgen_thread_write(struct file *file, if (!strcmp(name, "add_device")) { char f[32]; memset(f, 0, 32); - len = strn_len(&user_buffer[i], sizeof(f) - 1); + max = min(sizeof(f) - 1, count - i); + len = strn_len(&user_buffer[i], max); if (len < 0) { ret = len; goto out; From 4593aaf48fc16c7a06d05dd2db4b35d0deec718d Mon Sep 17 00:00:00 2001 From: Chris Morgan Date: Tue, 4 Feb 2025 09:58:33 -0600 Subject: [PATCH 32/91] power: supply: axp20x_battery: Update temp sensor for AXP717 from device tree [ Upstream commit bbcfe510ecd47f2db4c8653c7dfa9dc7a55b1583 ] Allow a boolean property of "x-powers,no-thermistor" to specify devices where the ts pin is not connected to anything. This works around an issue found with some devices where the efuse is not programmed correctly from the factory or when the register gets set erroneously. Signed-off-by: Chris Morgan Tested-by: Philippe Simons Link: https://lore.kernel.org/r/20250204155835.161973-4-macroalpha82@gmail.com Signed-off-by: Sebastian Reichel Signed-off-by: Sasha Levin --- drivers/power/supply/axp20x_battery.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/drivers/power/supply/axp20x_battery.c b/drivers/power/supply/axp20x_battery.c index 57eba1ddb17b..88fbae613e8b 100644 --- a/drivers/power/supply/axp20x_battery.c +++ b/drivers/power/supply/axp20x_battery.c @@ -89,6 +89,8 @@ #define AXP717_BAT_CC_MIN_UA 0 #define AXP717_BAT_CC_MAX_UA 3008000 +#define AXP717_TS_PIN_DISABLE BIT(4) + struct axp20x_batt_ps; struct axp_data { @@ -117,6 +119,7 @@ struct axp20x_batt_ps { /* Maximum constant charge current */ unsigned int max_ccc; const struct axp_data *data; + bool ts_disable; }; static int axp20x_battery_get_max_voltage(struct axp20x_batt_ps *axp20x_batt, @@ -983,6 +986,24 @@ static void axp717_set_battery_info(struct platform_device *pdev, int ccc = info->constant_charge_current_max_ua; int val; + axp_batt->ts_disable = (device_property_read_bool(axp_batt->dev, + "x-powers,no-thermistor")); + + /* + * Under rare conditions an incorrectly programmed efuse for + * the temp sensor on the PMIC may trigger a fault condition. + * Allow users to hard-code if the ts pin is not used to work + * around this problem. Note that this requires the battery + * be correctly defined in the device tree with a monitored + * battery node. + */ + if (axp_batt->ts_disable) { + regmap_update_bits(axp_batt->regmap, + AXP717_TS_PIN_CFG, + AXP717_TS_PIN_DISABLE, + AXP717_TS_PIN_DISABLE); + } + if (vmin > 0 && axp717_set_voltage_min_design(axp_batt, vmin)) dev_err(&pdev->dev, "couldn't set voltage_min_design\n"); From 7d0c92af8d3557131da00059d34712b82922aecb Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 22 Jan 2025 07:50:26 +0100 Subject: [PATCH 33/91] EDAC/ie31200: work around false positive build warning [ Upstream commit c29dfd661fe2f8d1b48c7f00590929c04b25bf40 ] gcc-14 produces a bogus warning in some configurations: drivers/edac/ie31200_edac.c: In function 'ie31200_probe1.isra': drivers/edac/ie31200_edac.c:412:26: error: 'dimm_info' is used uninitialized [-Werror=uninitialized] 412 | struct dimm_data dimm_info[IE31200_CHANNELS][IE31200_DIMMS_PER_CHANNEL]; | ^~~~~~~~~ drivers/edac/ie31200_edac.c:412:26: note: 'dimm_info' declared here 412 | struct dimm_data dimm_info[IE31200_CHANNELS][IE31200_DIMMS_PER_CHANNEL]; | ^~~~~~~~~ I don't see any way the unintialized access could really happen here, but I can see why the compiler gets confused by the two loops. Instead, rework the two nested loops to only read the addr_decode registers and then keep only one instance of the dimm info structure. [Tony: Qiuxu pointed out that the "populate DIMM info" comment was left behind in the refactor and suggested moving it. I deleted the comment as unnecessry in front os a call to populate_dimm_info(). That seems pretty self-describing.] Signed-off-by: Arnd Bergmann Acked-by: Jason Baron Signed-off-by: Tony Luck Link: https://lore.kernel.org/all/20250122065031.1321015-1-arnd@kernel.org Signed-off-by: Sasha Levin --- drivers/edac/ie31200_edac.c | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/drivers/edac/ie31200_edac.c b/drivers/edac/ie31200_edac.c index 56be8ef40f37..e3635fba63b4 100644 --- a/drivers/edac/ie31200_edac.c +++ b/drivers/edac/ie31200_edac.c @@ -405,10 +405,9 @@ static int ie31200_probe1(struct pci_dev *pdev, int dev_idx) int i, j, ret; struct mem_ctl_info *mci = NULL; struct edac_mc_layer layers[2]; - struct dimm_data dimm_info[IE31200_CHANNELS][IE31200_DIMMS_PER_CHANNEL]; void __iomem *window; struct ie31200_priv *priv; - u32 addr_decode, mad_offset; + u32 addr_decode[IE31200_CHANNELS], mad_offset; /* * Kaby Lake, Coffee Lake seem to work like Skylake. Please re-visit @@ -466,19 +465,10 @@ static int ie31200_probe1(struct pci_dev *pdev, int dev_idx) mad_offset = IE31200_MAD_DIMM_0_OFFSET; } - /* populate DIMM info */ for (i = 0; i < IE31200_CHANNELS; i++) { - addr_decode = readl(window + mad_offset + + addr_decode[i] = readl(window + mad_offset + (i * 4)); - edac_dbg(0, "addr_decode: 0x%x\n", addr_decode); - for (j = 0; j < IE31200_DIMMS_PER_CHANNEL; j++) { - populate_dimm_info(&dimm_info[i][j], addr_decode, j, - skl); - edac_dbg(0, "size: 0x%x, rank: %d, width: %d\n", - dimm_info[i][j].size, - dimm_info[i][j].dual_rank, - dimm_info[i][j].x16_width); - } + edac_dbg(0, "addr_decode: 0x%x\n", addr_decode[i]); } /* @@ -489,14 +479,22 @@ static int ie31200_probe1(struct pci_dev *pdev, int dev_idx) */ for (i = 0; i < IE31200_DIMMS_PER_CHANNEL; i++) { for (j = 0; j < IE31200_CHANNELS; j++) { + struct dimm_data dimm_info; struct dimm_info *dimm; unsigned long nr_pages; - nr_pages = IE31200_PAGES(dimm_info[j][i].size, skl); + populate_dimm_info(&dimm_info, addr_decode[j], i, + skl); + edac_dbg(0, "size: 0x%x, rank: %d, width: %d\n", + dimm_info.size, + dimm_info.dual_rank, + dimm_info.x16_width); + + nr_pages = IE31200_PAGES(dimm_info.size, skl); if (nr_pages == 0) continue; - if (dimm_info[j][i].dual_rank) { + if (dimm_info.dual_rank) { nr_pages = nr_pages / 2; dimm = edac_get_dimm(mci, (i * 2) + 1, j, 0); dimm->nr_pages = nr_pages; From a82c0c39967710d6232b51a78b71222e9ffec705 Mon Sep 17 00:00:00 2001 From: Frank Li Date: Wed, 29 Jan 2025 11:22:50 -0500 Subject: [PATCH 34/91] i3c: master: svc: Flush FIFO before sending Dynamic Address Assignment(DAA) [ Upstream commit a892ee4cf22a50e1d6988d0464a9a421f3e5db2f ] Ensure the FIFO is empty before issuing the DAA command to prevent incorrect command data from being sent. Align with other data transfers, such as svc_i3c_master_start_xfer_locked(), which flushes the FIFO before sending a command. Signed-off-by: Frank Li Reviewed-by: Miquel Raynal Link: https://lore.kernel.org/r/20250129162250.3629189-1-Frank.Li@nxp.com Signed-off-by: Alexandre Belloni Signed-off-by: Sasha Levin --- drivers/i3c/master/svc-i3c-master.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c index 6ffe022dbb5b..62913feae45d 100644 --- a/drivers/i3c/master/svc-i3c-master.c +++ b/drivers/i3c/master/svc-i3c-master.c @@ -860,6 +860,8 @@ static int svc_i3c_master_do_daa_locked(struct svc_i3c_master *master, u32 reg; int ret, i; + svc_i3c_master_flush_fifo(master); + while (true) { /* SVC_I3C_MCTRL_REQUEST_PROC_DAA have two mode, ENTER DAA or PROCESS DAA. * From 011a62d2d79ac5a1a14a1cc9d2f62490d25451b5 Mon Sep 17 00:00:00 2001 From: Chris Morgan Date: Tue, 4 Feb 2025 09:58:32 -0600 Subject: [PATCH 35/91] mfd: axp20x: AXP717: Add AXP717_TS_PIN_CFG to writeable regs [ Upstream commit bfad07fe298bfba0c7ddab87c5b5325970203a1e ] Add AXP717_TS_PIN_CFG (register 0x50) to the table of writeable registers so that the temperature sensor can be configured by the battery driver. Signed-off-by: Chris Morgan Link: https://lore.kernel.org/r/20250204155835.161973-3-macroalpha82@gmail.com Signed-off-by: Lee Jones Signed-off-by: Sasha Levin --- drivers/mfd/axp20x.c | 1 + include/linux/mfd/axp20x.h | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c index 4051551757f2..378092903971 100644 --- a/drivers/mfd/axp20x.c +++ b/drivers/mfd/axp20x.c @@ -214,6 +214,7 @@ static const struct regmap_range axp717_writeable_ranges[] = { regmap_reg_range(AXP717_VSYS_V_POWEROFF, AXP717_VSYS_V_POWEROFF), regmap_reg_range(AXP717_IRQ0_EN, AXP717_IRQ4_EN), regmap_reg_range(AXP717_IRQ0_STATE, AXP717_IRQ4_STATE), + regmap_reg_range(AXP717_TS_PIN_CFG, AXP717_TS_PIN_CFG), regmap_reg_range(AXP717_ICC_CHG_SET, AXP717_CV_CHG_SET), regmap_reg_range(AXP717_DCDC_OUTPUT_CONTROL, AXP717_CPUSLDO_CONTROL), regmap_reg_range(AXP717_ADC_CH_EN_CONTROL, AXP717_ADC_CH_EN_CONTROL), diff --git a/include/linux/mfd/axp20x.h b/include/linux/mfd/axp20x.h index f4dfc1871a95..d1c21ad6440d 100644 --- a/include/linux/mfd/axp20x.h +++ b/include/linux/mfd/axp20x.h @@ -135,6 +135,7 @@ enum axp20x_variants { #define AXP717_IRQ2_STATE 0x4a #define AXP717_IRQ3_STATE 0x4b #define AXP717_IRQ4_STATE 0x4c +#define AXP717_TS_PIN_CFG 0x50 #define AXP717_ICC_CHG_SET 0x62 #define AXP717_ITERM_CHG_SET 0x63 #define AXP717_CV_CHG_SET 0x64 From d85004266a32c69fb72243983bac9818c7998b01 Mon Sep 17 00:00:00 2001 From: Eddie James Date: Tue, 18 Feb 2025 16:09:59 -0600 Subject: [PATCH 36/91] eeprom: ee1004: Check chip before probing [ Upstream commit d9406677428e9234ea62bb2d2f5e996d1b777760 ] Like other eeprom drivers, check if the device is really there and functional before probing. Signed-off-by: Eddie James Link: https://lore.kernel.org/r/20250218220959.721698-1-eajames@linux.ibm.com Signed-off-by: Greg Kroah-Hartman Signed-off-by: Sasha Levin --- drivers/misc/eeprom/ee1004.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/misc/eeprom/ee1004.c b/drivers/misc/eeprom/ee1004.c index 89224d4af4a2..e13f9fdd9d7b 100644 --- a/drivers/misc/eeprom/ee1004.c +++ b/drivers/misc/eeprom/ee1004.c @@ -304,6 +304,10 @@ static int ee1004_probe(struct i2c_client *client) I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_READ_BYTE_DATA)) return -EPFNOSUPPORT; + err = i2c_smbus_read_byte(client); + if (err < 0) + return -ENODEV; + mutex_lock(&ee1004_bus_lock); err = ee1004_init_bus_data(client); From 098788e118d1e8e480735242934fbc80cee645c2 Mon Sep 17 00:00:00 2001 From: Anup Patel Date: Mon, 17 Feb 2025 14:26:53 +0530 Subject: [PATCH 37/91] irqchip/riscv-imsic: Separate next and previous pointers in IMSIC vector [ Upstream commit 0f67911e821c67ecfccc365a2103ce276a9a56fe ] Currently, there is only one "move" pointer in struct imsic_vector so during vector movement the old vector points to the new vector and new vector points to itself. To support forced cleanup of the old vector, add separate "move_next" and "move_prev" pointers to struct imsic_vector, where during vector movement the "move_next" pointer of the old vector points to the new vector and the "move_prev" pointer of the new vector points to the old vector. Both "move_next" and "move_prev" pointers are cleared separately by __imsic_local_sync() with a restriction that "move_prev" on the new CPU is cleared only after the old CPU has cleared "move_next". Signed-off-by: Anup Patel Signed-off-by: Thomas Gleixner Link: https://lore.kernel.org/all/20250217085657.789309-8-apatel@ventanamicro.com Signed-off-by: Sasha Levin --- drivers/irqchip/irq-riscv-imsic-early.c | 8 ++- drivers/irqchip/irq-riscv-imsic-state.c | 96 +++++++++++++++++-------- drivers/irqchip/irq-riscv-imsic-state.h | 7 +- 3 files changed, 78 insertions(+), 33 deletions(-) diff --git a/drivers/irqchip/irq-riscv-imsic-early.c b/drivers/irqchip/irq-riscv-imsic-early.c index c5c2e6929a2f..b5def6268936 100644 --- a/drivers/irqchip/irq-riscv-imsic-early.c +++ b/drivers/irqchip/irq-riscv-imsic-early.c @@ -77,6 +77,12 @@ static void imsic_handle_irq(struct irq_desc *desc) struct imsic_vector *vec; unsigned long local_id; + /* + * Process pending local synchronization instead of waiting + * for per-CPU local timer to expire. + */ + imsic_local_sync_all(false); + chained_irq_enter(chip, desc); while ((local_id = csr_swap(CSR_TOPEI, 0))) { @@ -120,7 +126,7 @@ static int imsic_starting_cpu(unsigned int cpu) * Interrupts identities might have been enabled/disabled while * this CPU was not running so sync-up local enable/disable state. */ - imsic_local_sync_all(); + imsic_local_sync_all(true); /* Enable local interrupt delivery */ imsic_local_delivery(true); diff --git a/drivers/irqchip/irq-riscv-imsic-state.c b/drivers/irqchip/irq-riscv-imsic-state.c index b97e6cd89ed7..1aeba76d7279 100644 --- a/drivers/irqchip/irq-riscv-imsic-state.c +++ b/drivers/irqchip/irq-riscv-imsic-state.c @@ -124,10 +124,11 @@ void __imsic_eix_update(unsigned long base_id, unsigned long num_id, bool pend, } } -static void __imsic_local_sync(struct imsic_local_priv *lpriv) +static bool __imsic_local_sync(struct imsic_local_priv *lpriv) { struct imsic_local_config *mlocal; struct imsic_vector *vec, *mvec; + bool ret = true; int i; lockdep_assert_held(&lpriv->lock); @@ -143,35 +144,75 @@ static void __imsic_local_sync(struct imsic_local_priv *lpriv) __imsic_id_clear_enable(i); /* - * If the ID was being moved to a new ID on some other CPU - * then we can get a MSI during the movement so check the - * ID pending bit and re-trigger the new ID on other CPU - * using MMIO write. + * Clear the previous vector pointer of the new vector only + * after the movement is complete on the old CPU. */ - mvec = READ_ONCE(vec->move); - WRITE_ONCE(vec->move, NULL); - if (mvec && mvec != vec) { + mvec = READ_ONCE(vec->move_prev); + if (mvec) { + /* + * If the old vector has not been updated then + * try again in the next sync-up call. + */ + if (READ_ONCE(mvec->move_next)) { + ret = false; + continue; + } + + WRITE_ONCE(vec->move_prev, NULL); + } + + /* + * If a vector was being moved to a new vector on some other + * CPU then we can get a MSI during the movement so check the + * ID pending bit and re-trigger the new ID on other CPU using + * MMIO write. + */ + mvec = READ_ONCE(vec->move_next); + if (mvec) { if (__imsic_id_read_clear_pending(i)) { mlocal = per_cpu_ptr(imsic->global.local, mvec->cpu); writel_relaxed(mvec->local_id, mlocal->msi_va); } + WRITE_ONCE(vec->move_next, NULL); imsic_vector_free(&lpriv->vectors[i]); } skip: bitmap_clear(lpriv->dirty_bitmap, i, 1); } + + return ret; } -void imsic_local_sync_all(void) +#ifdef CONFIG_SMP +static void __imsic_local_timer_start(struct imsic_local_priv *lpriv) +{ + lockdep_assert_held(&lpriv->lock); + + if (!timer_pending(&lpriv->timer)) { + lpriv->timer.expires = jiffies + 1; + add_timer_on(&lpriv->timer, smp_processor_id()); + } +} +#else +static inline void __imsic_local_timer_start(struct imsic_local_priv *lpriv) +{ +} +#endif + +void imsic_local_sync_all(bool force_all) { struct imsic_local_priv *lpriv = this_cpu_ptr(imsic->lpriv); unsigned long flags; raw_spin_lock_irqsave(&lpriv->lock, flags); - bitmap_fill(lpriv->dirty_bitmap, imsic->global.nr_ids + 1); - __imsic_local_sync(lpriv); + + if (force_all) + bitmap_fill(lpriv->dirty_bitmap, imsic->global.nr_ids + 1); + if (!__imsic_local_sync(lpriv)) + __imsic_local_timer_start(lpriv); + raw_spin_unlock_irqrestore(&lpriv->lock, flags); } @@ -190,12 +231,7 @@ void imsic_local_delivery(bool enable) #ifdef CONFIG_SMP static void imsic_local_timer_callback(struct timer_list *timer) { - struct imsic_local_priv *lpriv = this_cpu_ptr(imsic->lpriv); - unsigned long flags; - - raw_spin_lock_irqsave(&lpriv->lock, flags); - __imsic_local_sync(lpriv); - raw_spin_unlock_irqrestore(&lpriv->lock, flags); + imsic_local_sync_all(false); } static void __imsic_remote_sync(struct imsic_local_priv *lpriv, unsigned int cpu) @@ -216,14 +252,11 @@ static void __imsic_remote_sync(struct imsic_local_priv *lpriv, unsigned int cpu */ if (cpu_online(cpu)) { if (cpu == smp_processor_id()) { - __imsic_local_sync(lpriv); - return; + if (__imsic_local_sync(lpriv)) + return; } - if (!timer_pending(&lpriv->timer)) { - lpriv->timer.expires = jiffies + 1; - add_timer_on(&lpriv->timer, cpu); - } + __imsic_local_timer_start(lpriv); } } #else @@ -278,8 +311,9 @@ void imsic_vector_unmask(struct imsic_vector *vec) raw_spin_unlock(&lpriv->lock); } -static bool imsic_vector_move_update(struct imsic_local_priv *lpriv, struct imsic_vector *vec, - bool new_enable, struct imsic_vector *new_move) +static bool imsic_vector_move_update(struct imsic_local_priv *lpriv, + struct imsic_vector *vec, bool is_old_vec, + bool new_enable, struct imsic_vector *move_vec) { unsigned long flags; bool enabled; @@ -289,7 +323,10 @@ static bool imsic_vector_move_update(struct imsic_local_priv *lpriv, struct imsi /* Update enable and move details */ enabled = READ_ONCE(vec->enable); WRITE_ONCE(vec->enable, new_enable); - WRITE_ONCE(vec->move, new_move); + if (is_old_vec) + WRITE_ONCE(vec->move_next, move_vec); + else + WRITE_ONCE(vec->move_prev, move_vec); /* Mark the vector as dirty and synchronize */ bitmap_set(lpriv->dirty_bitmap, vec->local_id, 1); @@ -322,8 +359,8 @@ void imsic_vector_move(struct imsic_vector *old_vec, struct imsic_vector *new_ve * interrupt on the old vector while device was being moved * to the new vector. */ - enabled = imsic_vector_move_update(old_lpriv, old_vec, false, new_vec); - imsic_vector_move_update(new_lpriv, new_vec, enabled, new_vec); + enabled = imsic_vector_move_update(old_lpriv, old_vec, true, false, new_vec); + imsic_vector_move_update(new_lpriv, new_vec, false, enabled, old_vec); } #ifdef CONFIG_GENERIC_IRQ_DEBUGFS @@ -386,7 +423,8 @@ struct imsic_vector *imsic_vector_alloc(unsigned int hwirq, const struct cpumask vec = &lpriv->vectors[local_id]; vec->hwirq = hwirq; vec->enable = false; - vec->move = NULL; + vec->move_next = NULL; + vec->move_prev = NULL; return vec; } diff --git a/drivers/irqchip/irq-riscv-imsic-state.h b/drivers/irqchip/irq-riscv-imsic-state.h index 391e44280827..f02842b84ed5 100644 --- a/drivers/irqchip/irq-riscv-imsic-state.h +++ b/drivers/irqchip/irq-riscv-imsic-state.h @@ -23,7 +23,8 @@ struct imsic_vector { unsigned int hwirq; /* Details accessed using local lock held */ bool enable; - struct imsic_vector *move; + struct imsic_vector *move_next; + struct imsic_vector *move_prev; }; struct imsic_local_priv { @@ -74,7 +75,7 @@ static inline void __imsic_id_clear_enable(unsigned long id) __imsic_eix_update(id, 1, false, false); } -void imsic_local_sync_all(void); +void imsic_local_sync_all(bool force_all); void imsic_local_delivery(bool enable); void imsic_vector_mask(struct imsic_vector *vec); @@ -87,7 +88,7 @@ static inline bool imsic_vector_isenabled(struct imsic_vector *vec) static inline struct imsic_vector *imsic_vector_get_move(struct imsic_vector *vec) { - return READ_ONCE(vec->move); + return READ_ONCE(vec->move_prev); } void imsic_vector_move(struct imsic_vector *old_vec, struct imsic_vector *new_vec); From 94e6687ceda912d52d6e030f0079bc6a33a47f0b Mon Sep 17 00:00:00 2001 From: Lijo Lazar Date: Tue, 18 Feb 2025 17:43:01 +0530 Subject: [PATCH 38/91] drm/amd/pm: Fetch current power limit from PMFW [ Upstream commit b2a9e562dfa156bd53e62ce571f3f8f65d243f14 ] On SMU v13.0.12, always query the firmware to get the current power limit as it could be updated through other means also. Signed-off-by: Lijo Lazar Reviewed-by: Asad Kamal Signed-off-by: Alex Deucher Signed-off-by: Sasha Levin --- drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index 99d2d3092ea5..3fd8da5dc761 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -2772,6 +2772,7 @@ int smu_get_power_limit(void *handle, switch (amdgpu_ip_version(adev, MP1_HWIP, 0)) { case IP_VERSION(13, 0, 2): case IP_VERSION(13, 0, 6): + case IP_VERSION(13, 0, 12): case IP_VERSION(13, 0, 14): case IP_VERSION(11, 0, 7): case IP_VERSION(11, 0, 11): From b02b561bf7692d8db2b7218c076aad8c32e1261c Mon Sep 17 00:00:00 2001 From: Harry VanZyllDeJong Date: Fri, 7 Feb 2025 13:46:53 -0500 Subject: [PATCH 39/91] drm/amd/display: Add support for disconnected eDP streams [ Upstream commit 6571bef25fe48c642f7a69ccf7c3198b317c136a ] [Why] eDP may not be connected to the GPU on driver start causing fail enumeration. [How] Move the virtual signal type check before the eDP connector signal check. Reviewed-by: Wenjing Liu Signed-off-by: Harry VanZyllDeJong Signed-off-by: Roman Li Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher Signed-off-by: Sasha Levin --- .../drm/amd/display/dc/link/protocols/link_dp_capability.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c index 23e650e39910..d9a1e1a59967 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c @@ -945,6 +945,9 @@ bool link_decide_link_settings(struct dc_stream_state *stream, * TODO: add MST specific link training routine */ decide_mst_link_settings(link, link_setting); + } else if (stream->signal == SIGNAL_TYPE_VIRTUAL) { + link_setting->lane_count = LANE_COUNT_FOUR; + link_setting->link_rate = LINK_RATE_HIGH3; } else if (link->connector_signal == SIGNAL_TYPE_EDP) { /* enable edp link optimization for DSC eDP case */ if (stream->timing.flags.DSC) { @@ -967,9 +970,6 @@ bool link_decide_link_settings(struct dc_stream_state *stream, } else { edp_decide_link_settings(link, link_setting, req_bw); } - } else if (stream->signal == SIGNAL_TYPE_VIRTUAL) { - link_setting->lane_count = LANE_COUNT_FOUR; - link_setting->link_rate = LINK_RATE_HIGH3; } else { decide_dp_link_settings(link, link_setting, req_bw); } From 2bba67f03071a83dacbcaa9569a0541cdfe8083d Mon Sep 17 00:00:00 2001 From: Nicholas Kazlauskas Date: Mon, 3 Feb 2025 09:49:58 -0500 Subject: [PATCH 40/91] drm/amd/display: Guard against setting dispclk low when active [ Upstream commit 72d7a7fa1f2404fd31c84a8f808b1b37021a3a9e ] [Why] We should never apply a minimum dispclk value while in prepare_bandwidth or while displays are active. This is always an optimization for when all displays are disabled. [How] Defer dispclk optimization until safe_to_lower = true and display_count reaches 0. Since 0 has a special value in this logic (ie. no dispclk required) we also need adjust the logic that clamps it for the actual request to PMFW. Reviewed-by: Gabe Teeger Reviewed-by: Leo Chen Reviewed-by: Syed Hassan Signed-off-by: Nicholas Kazlauskas Signed-off-by: Roman Li Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher Signed-off-by: Sasha Levin --- .../amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c index 7d0d8852ce8d..a4ac601a30c3 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c @@ -452,14 +452,19 @@ void dcn35_update_clocks(struct clk_mgr *clk_mgr_base, update_dppclk = true; } - if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz)) { + if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz) && + (new_clocks->dispclk_khz > 0 || (safe_to_lower && display_count == 0))) { + int requested_dispclk_khz = new_clocks->dispclk_khz; + dcn35_disable_otg_wa(clk_mgr_base, context, safe_to_lower, true); - if (dc->debug.min_disp_clk_khz > 0 && new_clocks->dispclk_khz < dc->debug.min_disp_clk_khz) - new_clocks->dispclk_khz = dc->debug.min_disp_clk_khz; + /* Clamp the requested clock to PMFW based on their limit. */ + if (dc->debug.min_disp_clk_khz > 0 && requested_dispclk_khz < dc->debug.min_disp_clk_khz) + requested_dispclk_khz = dc->debug.min_disp_clk_khz; + dcn35_smu_set_dispclk(clk_mgr, requested_dispclk_khz); clk_mgr_base->clks.dispclk_khz = new_clocks->dispclk_khz; - dcn35_smu_set_dispclk(clk_mgr, clk_mgr_base->clks.dispclk_khz); + dcn35_disable_otg_wa(clk_mgr_base, context, safe_to_lower, false); update_dispclk = true; From 1e826acee1165a05c119366f4e902a4a11ee2460 Mon Sep 17 00:00:00 2001 From: Ilya Bakoulin Date: Wed, 29 Jan 2025 14:46:27 -0500 Subject: [PATCH 41/91] drm/amd/display: Fix BT2020 YCbCr limited/full range input [ Upstream commit 07bc2dcbcf403d47d6f305ef7f0d3d489491c5fb ] [Why] BT2020 YCbCr input is not handled properly when full range quantization is used and limited range is not supported at all. [How] - Add enums for BT2020 YCbCr limited/full range - Add limited range CSC matrix Reviewed-by: Krunoslav Kovac Signed-off-by: Ilya Bakoulin Signed-off-by: Roman Li Tested-by: Robert Mader Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher Signed-off-by: Sasha Levin --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 6 +++--- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 2 +- drivers/gpu/drm/amd/display/dc/basics/dc_common.c | 3 ++- drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c | 5 +++-- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 4 ++-- drivers/gpu/drm/amd/display/dc/dc_hw_types.h | 4 +++- drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c | 3 ++- .../gpu/drm/amd/display/dc/dio/dcn10/dcn10_stream_encoder.c | 3 ++- .../amd/display/dc/dio/dcn401/dcn401_dio_stream_encoder.c | 3 ++- .../amd/display/dc/hpo/dcn31/dcn31_hpo_dp_stream_encoder.c | 3 ++- drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h | 6 +++++- .../gpu/drm/amd/display/modules/info_packet/info_packet.c | 4 ++-- 12 files changed, 29 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 17c03b89abb3..c0ff501687f5 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -5552,9 +5552,9 @@ fill_plane_color_attributes(const struct drm_plane_state *plane_state, case DRM_COLOR_YCBCR_BT2020: if (full_range) - *color_space = COLOR_SPACE_2020_YCBCR; + *color_space = COLOR_SPACE_2020_YCBCR_FULL; else - return -EINVAL; + *color_space = COLOR_SPACE_2020_YCBCR_LIMITED; break; default: @@ -6050,7 +6050,7 @@ get_output_color_space(const struct dc_crtc_timing *dc_crtc_timing, if (dc_crtc_timing->pixel_encoding == PIXEL_ENCODING_RGB) color_space = COLOR_SPACE_2020_RGB_FULLRANGE; else - color_space = COLOR_SPACE_2020_YCBCR; + color_space = COLOR_SPACE_2020_YCBCR_LIMITED; break; case DRM_MODE_COLORIMETRY_DEFAULT: // ITU601 default: diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c index 98e88903d07d..15d94d2a0e2f 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c @@ -1145,7 +1145,7 @@ static int amdgpu_current_colorspace_show(struct seq_file *m, void *data) case COLOR_SPACE_2020_RGB_FULLRANGE: seq_puts(m, "BT2020_RGB"); break; - case COLOR_SPACE_2020_YCBCR: + case COLOR_SPACE_2020_YCBCR_LIMITED: seq_puts(m, "BT2020_YCC"); break; default: diff --git a/drivers/gpu/drm/amd/display/dc/basics/dc_common.c b/drivers/gpu/drm/amd/display/dc/basics/dc_common.c index b2fc4f8e6482..a51c2701da24 100644 --- a/drivers/gpu/drm/amd/display/dc/basics/dc_common.c +++ b/drivers/gpu/drm/amd/display/dc/basics/dc_common.c @@ -40,7 +40,8 @@ bool is_rgb_cspace(enum dc_color_space output_color_space) case COLOR_SPACE_YCBCR709: case COLOR_SPACE_YCBCR601_LIMITED: case COLOR_SPACE_YCBCR709_LIMITED: - case COLOR_SPACE_2020_YCBCR: + case COLOR_SPACE_2020_YCBCR_LIMITED: + case COLOR_SPACE_2020_YCBCR_FULL: return false; default: /* Add a case to switch */ diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c index d2342a91e7e7..d62b00314682 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c @@ -176,7 +176,7 @@ static bool is_ycbcr2020_type( { bool ret = false; - if (color_space == COLOR_SPACE_2020_YCBCR) + if (color_space == COLOR_SPACE_2020_YCBCR_LIMITED || color_space == COLOR_SPACE_2020_YCBCR_FULL) ret = true; return ret; } @@ -247,7 +247,8 @@ void color_space_to_black_color( case COLOR_SPACE_YCBCR709_BLACK: case COLOR_SPACE_YCBCR601_LIMITED: case COLOR_SPACE_YCBCR709_LIMITED: - case COLOR_SPACE_2020_YCBCR: + case COLOR_SPACE_2020_YCBCR_LIMITED: + case COLOR_SPACE_2020_YCBCR_FULL: *black_color = black_color_format[BLACK_COLOR_FORMAT_YUV_CV]; break; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index bfcbbea37729..6dbf139c51f7 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -4215,7 +4215,7 @@ static void set_avi_info_frame( break; case COLOR_SPACE_2020_RGB_FULLRANGE: case COLOR_SPACE_2020_RGB_LIMITEDRANGE: - case COLOR_SPACE_2020_YCBCR: + case COLOR_SPACE_2020_YCBCR_LIMITED: hdmi_info.bits.EC0_EC2 = COLORIMETRYEX_BT2020RGBYCBCR; hdmi_info.bits.C0_C1 = COLORIMETRY_EXTENDED; break; @@ -4229,7 +4229,7 @@ static void set_avi_info_frame( break; } - if (pixel_encoding && color_space == COLOR_SPACE_2020_YCBCR && + if (pixel_encoding && color_space == COLOR_SPACE_2020_YCBCR_LIMITED && stream->out_transfer_func.tf == TRANSFER_FUNCTION_GAMMA22) { hdmi_info.bits.EC0_EC2 = 0; hdmi_info.bits.C0_C1 = COLORIMETRY_ITU709; diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h index 0ded4bc7825b..6fd94c5f6da5 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h @@ -641,7 +641,8 @@ enum dc_color_space { COLOR_SPACE_YCBCR709_LIMITED, COLOR_SPACE_2020_RGB_FULLRANGE, COLOR_SPACE_2020_RGB_LIMITEDRANGE, - COLOR_SPACE_2020_YCBCR, + COLOR_SPACE_2020_YCBCR_LIMITED, + COLOR_SPACE_2020_YCBCR_FULL, COLOR_SPACE_ADOBERGB, COLOR_SPACE_DCIP3, COLOR_SPACE_DISPLAYNATIVE, @@ -649,6 +650,7 @@ enum dc_color_space { COLOR_SPACE_APPCTRL, COLOR_SPACE_CUSTOMPOINTS, COLOR_SPACE_YCBCR709_BLACK, + COLOR_SPACE_2020_YCBCR = COLOR_SPACE_2020_YCBCR_LIMITED, }; enum dc_dither_option { diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c index 5c2825bc9a87..654b919465f0 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c @@ -420,7 +420,7 @@ static void dce110_stream_encoder_dp_set_stream_attribute( dynamic_range_rgb = 1; /*limited range*/ break; case COLOR_SPACE_2020_RGB_FULLRANGE: - case COLOR_SPACE_2020_YCBCR: + case COLOR_SPACE_2020_YCBCR_LIMITED: case COLOR_SPACE_XR_RGB: case COLOR_SPACE_MSREF_SCRGB: case COLOR_SPACE_ADOBERGB: @@ -432,6 +432,7 @@ static void dce110_stream_encoder_dp_set_stream_attribute( case COLOR_SPACE_APPCTRL: case COLOR_SPACE_CUSTOMPOINTS: case COLOR_SPACE_UNKNOWN: + default: /* do nothing */ break; } diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_stream_encoder.c index f496e952ceec..f8f1e98f646e 100644 --- a/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_stream_encoder.c @@ -393,7 +393,7 @@ void enc1_stream_encoder_dp_set_stream_attribute( break; case COLOR_SPACE_2020_RGB_LIMITEDRANGE: case COLOR_SPACE_2020_RGB_FULLRANGE: - case COLOR_SPACE_2020_YCBCR: + case COLOR_SPACE_2020_YCBCR_LIMITED: case COLOR_SPACE_XR_RGB: case COLOR_SPACE_MSREF_SCRGB: case COLOR_SPACE_ADOBERGB: @@ -406,6 +406,7 @@ void enc1_stream_encoder_dp_set_stream_attribute( case COLOR_SPACE_CUSTOMPOINTS: case COLOR_SPACE_UNKNOWN: case COLOR_SPACE_YCBCR709_BLACK: + default: /* do nothing */ break; } diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_stream_encoder.c index 0a27e0942a12..0008816cf155 100644 --- a/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_stream_encoder.c @@ -634,7 +634,7 @@ void enc401_stream_encoder_dp_set_stream_attribute( break; case COLOR_SPACE_2020_RGB_LIMITEDRANGE: case COLOR_SPACE_2020_RGB_FULLRANGE: - case COLOR_SPACE_2020_YCBCR: + case COLOR_SPACE_2020_YCBCR_LIMITED: case COLOR_SPACE_XR_RGB: case COLOR_SPACE_MSREF_SCRGB: case COLOR_SPACE_ADOBERGB: @@ -647,6 +647,7 @@ void enc401_stream_encoder_dp_set_stream_attribute( case COLOR_SPACE_CUSTOMPOINTS: case COLOR_SPACE_UNKNOWN: case COLOR_SPACE_YCBCR709_BLACK: + default: /* do nothing */ break; } diff --git a/drivers/gpu/drm/amd/display/dc/hpo/dcn31/dcn31_hpo_dp_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/hpo/dcn31/dcn31_hpo_dp_stream_encoder.c index 678db949cfe3..759b453385c4 100644 --- a/drivers/gpu/drm/amd/display/dc/hpo/dcn31/dcn31_hpo_dp_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/hpo/dcn31/dcn31_hpo_dp_stream_encoder.c @@ -323,7 +323,7 @@ static void dcn31_hpo_dp_stream_enc_set_stream_attribute( break; case COLOR_SPACE_2020_RGB_LIMITEDRANGE: case COLOR_SPACE_2020_RGB_FULLRANGE: - case COLOR_SPACE_2020_YCBCR: + case COLOR_SPACE_2020_YCBCR_LIMITED: case COLOR_SPACE_XR_RGB: case COLOR_SPACE_MSREF_SCRGB: case COLOR_SPACE_ADOBERGB: @@ -336,6 +336,7 @@ static void dcn31_hpo_dp_stream_enc_set_stream_attribute( case COLOR_SPACE_CUSTOMPOINTS: case COLOR_SPACE_UNKNOWN: case COLOR_SPACE_YCBCR709_BLACK: + default: /* do nothing */ break; } diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h index 0150f2581ee4..0c5675d1c593 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h @@ -119,10 +119,14 @@ static const struct dpp_input_csc_matrix __maybe_unused dpp_input_csc_matrix[] = { 0x39a6, 0x2568, 0, 0xe0d6, 0xeedd, 0x2568, 0xf925, 0x9a8, 0, 0x2568, 0x43ee, 0xdbb2 } }, - { COLOR_SPACE_2020_YCBCR, + { COLOR_SPACE_2020_YCBCR_FULL, { 0x2F30, 0x2000, 0, 0xE869, 0xEDB7, 0x2000, 0xFABC, 0xBC6, 0, 0x2000, 0x3C34, 0xE1E6 } }, + { COLOR_SPACE_2020_YCBCR_LIMITED, + { 0x35B9, 0x2543, 0, 0xE2B2, + 0xEB2F, 0x2543, 0xFA01, 0x0B1F, + 0, 0x2543, 0x4489, 0xDB42 } }, { COLOR_SPACE_2020_RGB_LIMITEDRANGE, { 0x35E0, 0x255F, 0, 0xE2B3, 0xEB20, 0x255F, 0xF9FD, 0xB1E, diff --git a/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c b/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c index a344e2e49b0e..b3d55cac3569 100644 --- a/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c +++ b/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c @@ -383,10 +383,10 @@ void mod_build_vsc_infopacket(const struct dc_stream_state *stream, colorimetryFormat = ColorimetryYCC_DP_ITU709; else if (cs == COLOR_SPACE_ADOBERGB) colorimetryFormat = ColorimetryYCC_DP_AdobeYCC; - else if (cs == COLOR_SPACE_2020_YCBCR) + else if (cs == COLOR_SPACE_2020_YCBCR_LIMITED) colorimetryFormat = ColorimetryYCC_DP_ITU2020YCbCr; - if (cs == COLOR_SPACE_2020_YCBCR && tf == TRANSFER_FUNC_GAMMA_22) + if (cs == COLOR_SPACE_2020_YCBCR_LIMITED && tf == TRANSFER_FUNC_GAMMA_22) colorimetryFormat = ColorimetryYCC_DP_ITU709; break; From 775f3afa6ade18e5d7a89af092517bd38c7183d2 Mon Sep 17 00:00:00 2001 From: George Shen Date: Tue, 4 Feb 2025 14:34:02 -0500 Subject: [PATCH 42/91] drm/amd/display: Read LTTPR ALPM caps during link cap retrieval [ Upstream commit de84d580126eb2214937df755cfec5ef0901479e ] [Why] The latest DP spec requires the DP TX to read DPCD F0000h through F0009h when detecting LTTPR capabilities for the first time. [How] Update LTTPR cap retrieval to read up to F0009h (two more bytes than the previous F0007h), and store the LTTPR ALPM capabilities. Reviewed-by: Wenjing Liu Signed-off-by: George Shen Signed-off-by: Roman Li Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher Signed-off-by: Sasha Levin --- drivers/gpu/drm/amd/display/dc/dc_dp_types.h | 12 ++++++++++++ .../display/dc/link/protocols/link_dp_capability.c | 6 +++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h index 41bd95e9177a..223c3d55544b 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h @@ -959,6 +959,14 @@ union dp_128b_132b_supported_lttpr_link_rates { uint8_t raw; }; +union dp_alpm_lttpr_cap { + struct { + uint8_t AUX_LESS_ALPM_SUPPORTED :1; + uint8_t RESERVED :7; + } bits; + uint8_t raw; +}; + union dp_sink_video_fallback_formats { struct { uint8_t dp_1024x768_60Hz_24bpp_support :1; @@ -1103,6 +1111,7 @@ struct dc_lttpr_caps { uint8_t max_ext_timeout; union dp_main_link_channel_coding_lttpr_cap main_link_channel_coding; union dp_128b_132b_supported_lttpr_link_rates supported_128b_132b_rates; + union dp_alpm_lttpr_cap alpm; uint8_t aux_rd_interval[MAX_REPEATER_CNT - 1]; }; @@ -1352,6 +1361,9 @@ struct dp_trace { #ifndef DPCD_MAX_UNCOMPRESSED_PIXEL_RATE_CAP #define DPCD_MAX_UNCOMPRESSED_PIXEL_RATE_CAP 0x221c #endif +#ifndef DP_LTTPR_ALPM_CAPABILITIES +#define DP_LTTPR_ALPM_CAPABILITIES 0xF0009 +#endif #ifndef DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE #define DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE 0x50 #endif diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c index d9a1e1a59967..842636c7922b 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c @@ -1495,7 +1495,7 @@ static bool dpcd_read_sink_ext_caps(struct dc_link *link) enum dc_status dp_retrieve_lttpr_cap(struct dc_link *link) { - uint8_t lttpr_dpcd_data[8] = {0}; + uint8_t lttpr_dpcd_data[10] = {0}; enum dc_status status; bool is_lttpr_present; @@ -1545,6 +1545,10 @@ enum dc_status dp_retrieve_lttpr_cap(struct dc_link *link) lttpr_dpcd_data[DP_PHY_REPEATER_128B132B_RATES - DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV]; + link->dpcd_caps.lttpr_caps.alpm.raw = + lttpr_dpcd_data[DP_LTTPR_ALPM_CAPABILITIES - + DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV]; + /* If this chip cap is set, at least one retimer must exist in the chain * Override count to 1 if we receive a known bad count (0 or an invalid value) */ if ((link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) && From cee5d56fa783ff852a23da5ce3da17fd0d450d18 Mon Sep 17 00:00:00 2001 From: Leo Zeng Date: Fri, 31 Jan 2025 11:46:52 -0500 Subject: [PATCH 43/91] Revert "drm/amd/display: Request HW cursor on DCN3.2 with SubVP" [ Upstream commit 8ae6dfc0b61b170cf13832d4cfe2a0c744e621a7 ] This reverts commit 13437c91606c9232c747475e202fe3827cd53264. Reason to revert: idle power regression found in testing. Reviewed-by: Dillon Varone Signed-off-by: Leo Zeng Signed-off-by: Roman Li Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher Signed-off-by: Sasha Levin --- drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c index 56dda686e299..6f490d8d7038 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c @@ -626,7 +626,6 @@ static bool dcn32_assign_subvp_pipe(struct dc *dc, * - Not TMZ surface */ if (pipe->plane_state && !pipe->top_pipe && !pipe->prev_odm_pipe && !dcn32_is_center_timing(pipe) && - !pipe->stream->hw_cursor_req && !(pipe->stream->timing.pix_clk_100hz / 10000 > DCN3_2_MAX_SUBVP_PIXEL_RATE_MHZ) && (!dcn32_is_psr_capable(pipe) || (context->stream_count == 1 && dc->caps.dmub_caps.subvp_psr)) && dc_state_get_pipe_subvp_type(context, pipe) == SUBVP_NONE && From b14e726d57f61085485f107a6203c50a09695abd Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Fri, 31 Jan 2025 11:57:49 -0500 Subject: [PATCH 44/91] drm/amd/display: Don't treat wb connector as physical in create_validate_stream_for_sink [ Upstream commit cbf4890c6f28fb1ad733e14613fbd33c2004bced ] Don't try to operate on a drm_wb_connector as an amdgpu_dm_connector. While dereferencing aconnector->base will "work" it's wrong and might lead to unknown bad things. Just... don't. Reviewed-by: Alex Hung Signed-off-by: Harry Wentland Signed-off-by: Roman Li Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher Signed-off-by: Sasha Levin --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 26 ++++++++++++------- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 2 +- .../display/amdgpu_dm/amdgpu_dm_mst_types.c | 6 ++--- 3 files changed, 20 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index c0ff501687f5..1e5984e71bfd 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -7399,12 +7399,12 @@ cleanup: } struct dc_stream_state * -create_validate_stream_for_sink(struct amdgpu_dm_connector *aconnector, +create_validate_stream_for_sink(struct drm_connector *connector, const struct drm_display_mode *drm_mode, const struct dm_connector_state *dm_state, const struct dc_stream_state *old_stream) { - struct drm_connector *connector = &aconnector->base; + struct amdgpu_dm_connector *aconnector = NULL; struct amdgpu_device *adev = drm_to_adev(connector->dev); struct dc_stream_state *stream; const struct drm_connector_state *drm_state = dm_state ? &dm_state->base : NULL; @@ -7415,8 +7415,12 @@ create_validate_stream_for_sink(struct amdgpu_dm_connector *aconnector, if (!dm_state) return NULL; - if (aconnector->dc_link->connector_signal == SIGNAL_TYPE_HDMI_TYPE_A || - aconnector->dc_link->dpcd_caps.dongle_type == DISPLAY_DONGLE_DP_HDMI_CONVERTER) + if (connector->connector_type != DRM_MODE_CONNECTOR_WRITEBACK) + aconnector = to_amdgpu_dm_connector(connector); + + if (aconnector && + (aconnector->dc_link->connector_signal == SIGNAL_TYPE_HDMI_TYPE_A || + aconnector->dc_link->dpcd_caps.dongle_type == DISPLAY_DONGLE_DP_HDMI_CONVERTER)) bpc_limit = 8; do { @@ -7428,10 +7432,11 @@ create_validate_stream_for_sink(struct amdgpu_dm_connector *aconnector, break; } - if (aconnector->base.connector_type == DRM_MODE_CONNECTOR_WRITEBACK) + dc_result = dc_validate_stream(adev->dm.dc, stream); + + if (!aconnector) /* writeback connector */ return stream; - dc_result = dc_validate_stream(adev->dm.dc, stream); if (dc_result == DC_OK && stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) dc_result = dm_dp_mst_is_port_support_mode(aconnector, stream); @@ -7461,7 +7466,7 @@ create_validate_stream_for_sink(struct amdgpu_dm_connector *aconnector, __func__, __LINE__); aconnector->force_yuv420_output = true; - stream = create_validate_stream_for_sink(aconnector, drm_mode, + stream = create_validate_stream_for_sink(connector, drm_mode, dm_state, old_stream); aconnector->force_yuv420_output = false; } @@ -7476,6 +7481,9 @@ enum drm_mode_status amdgpu_dm_connector_mode_valid(struct drm_connector *connec struct dc_sink *dc_sink; /* TODO: Unhardcode stream count */ struct dc_stream_state *stream; + /* we always have an amdgpu_dm_connector here since we got + * here via the amdgpu_dm_connector_helper_funcs + */ struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); if ((mode->flags & DRM_MODE_FLAG_INTERLACE) || @@ -7500,7 +7508,7 @@ enum drm_mode_status amdgpu_dm_connector_mode_valid(struct drm_connector *connec drm_mode_set_crtcinfo(mode, 0); - stream = create_validate_stream_for_sink(aconnector, mode, + stream = create_validate_stream_for_sink(connector, mode, to_dm_connector_state(connector->state), NULL); if (stream) { @@ -10520,7 +10528,7 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm, if (!drm_atomic_crtc_needs_modeset(new_crtc_state)) goto skip_modeset; - new_stream = create_validate_stream_for_sink(aconnector, + new_stream = create_validate_stream_for_sink(connector, &new_crtc_state->mode, dm_new_conn_state, dm_old_crtc_state->stream); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h index 20ad72d1b0d9..9603352ee094 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -987,7 +987,7 @@ int amdgpu_dm_process_dmub_set_config_sync(struct dc_context *ctx, unsigned int struct set_config_cmd_payload *payload, enum set_config_status *operation_result); struct dc_stream_state * - create_validate_stream_for_sink(struct amdgpu_dm_connector *aconnector, + create_validate_stream_for_sink(struct drm_connector *connector, const struct drm_display_mode *drm_mode, const struct dm_connector_state *dm_state, const struct dc_stream_state *old_stream); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index fca0c31e14d8..92158009cfa7 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -1646,7 +1646,6 @@ int pre_validate_dsc(struct drm_atomic_state *state, if (ind >= 0) { struct drm_connector *connector; - struct amdgpu_dm_connector *aconnector; struct drm_connector_state *drm_new_conn_state; struct dm_connector_state *dm_new_conn_state; struct dm_crtc_state *dm_old_crtc_state; @@ -1654,15 +1653,14 @@ int pre_validate_dsc(struct drm_atomic_state *state, connector = amdgpu_dm_find_first_crtc_matching_connector(state, state->crtcs[ind].ptr); - aconnector = to_amdgpu_dm_connector(connector); drm_new_conn_state = drm_atomic_get_new_connector_state(state, - &aconnector->base); + connector); dm_new_conn_state = to_dm_connector_state(drm_new_conn_state); dm_old_crtc_state = to_dm_crtc_state(state->crtcs[ind].old_state); local_dc_state->streams[i] = - create_validate_stream_for_sink(aconnector, + create_validate_stream_for_sink(connector, &state->crtcs[ind].new_state->mode, dm_new_conn_state, dm_old_crtc_state->stream); From e6a46719a2369eb5186d4f7e6c0478720ca1ec3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexis=20Lothor=C3=A9?= Date: Mon, 17 Feb 2025 07:21:53 +0100 Subject: [PATCH 45/91] serial: mctrl_gpio: split disable_ms into sync and no_sync APIs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 1bd2aad57da95f7f2d2bb52f7ad15c0f4993a685 ] The following splat has been observed on a SAMA5D27 platform using atmel_serial: BUG: sleeping function called from invalid context at kernel/irq/manage.c:738 in_atomic(): 1, irqs_disabled(): 128, non_block: 0, pid: 27, name: kworker/u5:0 preempt_count: 1, expected: 0 INFO: lockdep is turned off. irq event stamp: 0 hardirqs last enabled at (0): [<00000000>] 0x0 hardirqs last disabled at (0): [] copy_process+0x1c4c/0x7bec softirqs last enabled at (0): [] copy_process+0x1ca0/0x7bec softirqs last disabled at (0): [<00000000>] 0x0 CPU: 0 UID: 0 PID: 27 Comm: kworker/u5:0 Not tainted 6.13.0-rc7+ #74 Hardware name: Atmel SAMA5 Workqueue: hci0 hci_power_on [bluetooth] Call trace: unwind_backtrace from show_stack+0x18/0x1c show_stack from dump_stack_lvl+0x44/0x70 dump_stack_lvl from __might_resched+0x38c/0x598 __might_resched from disable_irq+0x1c/0x48 disable_irq from mctrl_gpio_disable_ms+0x74/0xc0 mctrl_gpio_disable_ms from atmel_disable_ms.part.0+0x80/0x1f4 atmel_disable_ms.part.0 from atmel_set_termios+0x764/0x11e8 atmel_set_termios from uart_change_line_settings+0x15c/0x994 uart_change_line_settings from uart_set_termios+0x2b0/0x668 uart_set_termios from tty_set_termios+0x600/0x8ec tty_set_termios from ttyport_set_flow_control+0x188/0x1e0 ttyport_set_flow_control from wilc_setup+0xd0/0x524 [hci_wilc] wilc_setup [hci_wilc] from hci_dev_open_sync+0x330/0x203c [bluetooth] hci_dev_open_sync [bluetooth] from hci_dev_do_open+0x40/0xb0 [bluetooth] hci_dev_do_open [bluetooth] from hci_power_on+0x12c/0x664 [bluetooth] hci_power_on [bluetooth] from process_one_work+0x998/0x1a38 process_one_work from worker_thread+0x6e0/0xfb4 worker_thread from kthread+0x3d4/0x484 kthread from ret_from_fork+0x14/0x28 This warning is emitted when trying to toggle, at the highest level, some flow control (with serdev_device_set_flow_control) in a device driver. At the lowest level, the atmel_serial driver is using serial_mctrl_gpio lib to enable/disable the corresponding IRQs accordingly. The warning emitted by CONFIG_DEBUG_ATOMIC_SLEEP is due to disable_irq (called in mctrl_gpio_disable_ms) being possibly called in some atomic context (some tty drivers perform modem lines configuration in regions protected by port lock). Split mctrl_gpio_disable_ms into two differents APIs, a non-blocking one and a blocking one. Replace mctrl_gpio_disable_ms calls with the relevant version depending on whether the call is protected by some port lock. Suggested-by: Jiri Slaby Signed-off-by: Alexis Lothoré Acked-by: Richard Genoud Link: https://lore.kernel.org/r/20250217-atomic_sleep_mctrl_serial_gpio-v3-1-59324b313eef@bootlin.com Signed-off-by: Greg Kroah-Hartman Signed-off-by: Sasha Levin --- Documentation/driver-api/serial/driver.rst | 2 +- drivers/tty/serial/8250/8250_port.c | 2 +- drivers/tty/serial/atmel_serial.c | 2 +- drivers/tty/serial/imx.c | 2 +- drivers/tty/serial/serial_mctrl_gpio.c | 34 +++++++++++++++++----- drivers/tty/serial/serial_mctrl_gpio.h | 17 +++++++++-- drivers/tty/serial/sh-sci.c | 2 +- drivers/tty/serial/stm32-usart.c | 2 +- 8 files changed, 47 insertions(+), 16 deletions(-) diff --git a/Documentation/driver-api/serial/driver.rst b/Documentation/driver-api/serial/driver.rst index 84b43061c11b..60434f2b0286 100644 --- a/Documentation/driver-api/serial/driver.rst +++ b/Documentation/driver-api/serial/driver.rst @@ -103,4 +103,4 @@ Some helpers are provided in order to set/get modem control lines via GPIO. .. kernel-doc:: drivers/tty/serial/serial_mctrl_gpio.c :identifiers: mctrl_gpio_init mctrl_gpio_free mctrl_gpio_to_gpiod mctrl_gpio_set mctrl_gpio_get mctrl_gpio_enable_ms - mctrl_gpio_disable_ms + mctrl_gpio_disable_ms_sync mctrl_gpio_disable_ms_no_sync diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index c1376727642a..051967992965 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -1657,7 +1657,7 @@ static void serial8250_disable_ms(struct uart_port *port) if (up->bugs & UART_BUG_NOMSR) return; - mctrl_gpio_disable_ms(up->gpios); + mctrl_gpio_disable_ms_no_sync(up->gpios); up->ier &= ~UART_IER_MSI; serial_port_out(port, UART_IER, up->ier); diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index 09b246c9e389..8bd39586a49f 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -700,7 +700,7 @@ static void atmel_disable_ms(struct uart_port *port) atmel_port->ms_irq_enabled = false; - mctrl_gpio_disable_ms(atmel_port->gpios); + mctrl_gpio_disable_ms_no_sync(atmel_port->gpios); if (!mctrl_gpio_to_gpiod(atmel_port->gpios, UART_GPIO_CTS)) idr |= ATMEL_US_CTSIC; diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index 90974d338f3c..8e3b15534bc7 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -1596,7 +1596,7 @@ static void imx_uart_shutdown(struct uart_port *port) imx_uart_dma_exit(sport); } - mctrl_gpio_disable_ms(sport->gpios); + mctrl_gpio_disable_ms_sync(sport->gpios); uart_port_lock_irqsave(&sport->port, &flags); ucr2 = imx_uart_readl(sport, UCR2); diff --git a/drivers/tty/serial/serial_mctrl_gpio.c b/drivers/tty/serial/serial_mctrl_gpio.c index 8855688a5b6c..ca55bcc0b611 100644 --- a/drivers/tty/serial/serial_mctrl_gpio.c +++ b/drivers/tty/serial/serial_mctrl_gpio.c @@ -322,11 +322,7 @@ void mctrl_gpio_enable_ms(struct mctrl_gpios *gpios) } EXPORT_SYMBOL_GPL(mctrl_gpio_enable_ms); -/** - * mctrl_gpio_disable_ms - disable irqs and handling of changes to the ms lines - * @gpios: gpios to disable - */ -void mctrl_gpio_disable_ms(struct mctrl_gpios *gpios) +static void mctrl_gpio_disable_ms(struct mctrl_gpios *gpios, bool sync) { enum mctrl_gpio_idx i; @@ -342,10 +338,34 @@ void mctrl_gpio_disable_ms(struct mctrl_gpios *gpios) if (!gpios->irq[i]) continue; - disable_irq(gpios->irq[i]); + if (sync) + disable_irq(gpios->irq[i]); + else + disable_irq_nosync(gpios->irq[i]); } } -EXPORT_SYMBOL_GPL(mctrl_gpio_disable_ms); + +/** + * mctrl_gpio_disable_ms_sync - disable irqs and handling of changes to the ms + * lines, and wait for any pending IRQ to be processed + * @gpios: gpios to disable + */ +void mctrl_gpio_disable_ms_sync(struct mctrl_gpios *gpios) +{ + mctrl_gpio_disable_ms(gpios, true); +} +EXPORT_SYMBOL_GPL(mctrl_gpio_disable_ms_sync); + +/** + * mctrl_gpio_disable_ms_no_sync - disable irqs and handling of changes to the + * ms lines, and return immediately + * @gpios: gpios to disable + */ +void mctrl_gpio_disable_ms_no_sync(struct mctrl_gpios *gpios) +{ + mctrl_gpio_disable_ms(gpios, false); +} +EXPORT_SYMBOL_GPL(mctrl_gpio_disable_ms_no_sync); void mctrl_gpio_enable_irq_wake(struct mctrl_gpios *gpios) { diff --git a/drivers/tty/serial/serial_mctrl_gpio.h b/drivers/tty/serial/serial_mctrl_gpio.h index fc76910fb105..79e97838ebe5 100644 --- a/drivers/tty/serial/serial_mctrl_gpio.h +++ b/drivers/tty/serial/serial_mctrl_gpio.h @@ -87,9 +87,16 @@ void mctrl_gpio_free(struct device *dev, struct mctrl_gpios *gpios); void mctrl_gpio_enable_ms(struct mctrl_gpios *gpios); /* - * Disable gpio interrupts to report status line changes. + * Disable gpio interrupts to report status line changes, and block until + * any corresponding IRQ is processed */ -void mctrl_gpio_disable_ms(struct mctrl_gpios *gpios); +void mctrl_gpio_disable_ms_sync(struct mctrl_gpios *gpios); + +/* + * Disable gpio interrupts to report status line changes, and return + * immediately + */ +void mctrl_gpio_disable_ms_no_sync(struct mctrl_gpios *gpios); /* * Enable gpio wakeup interrupts to enable wake up source. @@ -148,7 +155,11 @@ static inline void mctrl_gpio_enable_ms(struct mctrl_gpios *gpios) { } -static inline void mctrl_gpio_disable_ms(struct mctrl_gpios *gpios) +static inline void mctrl_gpio_disable_ms_sync(struct mctrl_gpios *gpios) +{ +} + +static inline void mctrl_gpio_disable_ms_no_sync(struct mctrl_gpios *gpios) { } diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index f43059e1b5c2..80efe3b0ed0c 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -2297,7 +2297,7 @@ static void sci_shutdown(struct uart_port *port) dev_dbg(port->dev, "%s(%d)\n", __func__, port->line); s->autorts = false; - mctrl_gpio_disable_ms(to_sci_port(port)->gpios); + mctrl_gpio_disable_ms_sync(to_sci_port(port)->gpios); uart_port_lock_irqsave(port, &flags); sci_stop_rx(port); diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c index 9b9981352b1e..e685cace5c85 100644 --- a/drivers/tty/serial/stm32-usart.c +++ b/drivers/tty/serial/stm32-usart.c @@ -944,7 +944,7 @@ static void stm32_usart_enable_ms(struct uart_port *port) static void stm32_usart_disable_ms(struct uart_port *port) { - mctrl_gpio_disable_ms(to_stm32_port(port)->gpios); + mctrl_gpio_disable_ms_sync(to_stm32_port(port)->gpios); } /* Transmit stop */ From 3ccfdd5b337429079325f456e499706313e251e1 Mon Sep 17 00:00:00 2001 From: Michael Margolin Date: Mon, 17 Feb 2025 14:16:23 +0000 Subject: [PATCH 46/91] RDMA/core: Fix best page size finding when it can cross SG entries [ Upstream commit 486055f5e09df959ad4e3aa4ee75b5c91ddeec2e ] A single scatter-gather entry is limited by a 32 bits "length" field that is practically 4GB - PAGE_SIZE. This means that even when the memory is physically contiguous, we might need more than one entry to represent it. Additionally when using dmabuf, the sg_table might be originated outside the subsystem and optimized for other needs. For instance an SGT of 16GB GPU continuous memory might look like this: (a real life example) dma_address 34401400000, length fffff000 dma_address 345013ff000, length fffff000 dma_address 346013fe000, length fffff000 dma_address 347013fd000, length fffff000 dma_address 348013fc000, length 4000 Since ib_umem_find_best_pgsz works within SG entries, in the above case we will result with the worst possible 4KB page size. Fix this by taking into consideration only the alignment of addresses of real discontinuity points rather than treating SG entries as such, and adjust the page iterator to correctly handle cross SG entry pages. There is currently an assumption that drivers do not ask for pages bigger than maximal DMA size supported by their devices. Reviewed-by: Firas Jahjah Reviewed-by: Yonatan Nachum Signed-off-by: Michael Margolin Link: https://patch.msgid.link/20250217141623.12428-1-mrgolin@amazon.com Signed-off-by: Leon Romanovsky Signed-off-by: Sasha Levin --- drivers/infiniband/core/umem.c | 36 ++++++++++++++++++++++++--------- drivers/infiniband/core/verbs.c | 11 +++++----- 2 files changed, 32 insertions(+), 15 deletions(-) diff --git a/drivers/infiniband/core/umem.c b/drivers/infiniband/core/umem.c index 07c571c7b699..c5b686394760 100644 --- a/drivers/infiniband/core/umem.c +++ b/drivers/infiniband/core/umem.c @@ -80,9 +80,12 @@ unsigned long ib_umem_find_best_pgsz(struct ib_umem *umem, unsigned long pgsz_bitmap, unsigned long virt) { - struct scatterlist *sg; + unsigned long curr_len = 0; + dma_addr_t curr_base = ~0; unsigned long va, pgoff; + struct scatterlist *sg; dma_addr_t mask; + dma_addr_t end; int i; umem->iova = va = virt; @@ -107,17 +110,30 @@ unsigned long ib_umem_find_best_pgsz(struct ib_umem *umem, pgoff = umem->address & ~PAGE_MASK; for_each_sgtable_dma_sg(&umem->sgt_append.sgt, sg, i) { - /* Walk SGL and reduce max page size if VA/PA bits differ - * for any address. + /* If the current entry is physically contiguous with the previous + * one, no need to take its start addresses into consideration. */ - mask |= (sg_dma_address(sg) + pgoff) ^ va; + if (check_add_overflow(curr_base, curr_len, &end) || + end != sg_dma_address(sg)) { + + curr_base = sg_dma_address(sg); + curr_len = 0; + + /* Reduce max page size if VA/PA bits differ */ + mask |= (curr_base + pgoff) ^ va; + + /* The alignment of any VA matching a discontinuity point + * in the physical memory sets the maximum possible page + * size as this must be a starting point of a new page that + * needs to be aligned. + */ + if (i != 0) + mask |= va; + } + + curr_len += sg_dma_len(sg); va += sg_dma_len(sg) - pgoff; - /* Except for the last entry, the ending iova alignment sets - * the maximum possible page size as the low bits of the iova - * must be zero when starting the next chunk. - */ - if (i != (umem->sgt_append.sgt.nents - 1)) - mask |= va; + pgoff = 0; } diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c index 473ee0831307..dc40001072a5 100644 --- a/drivers/infiniband/core/verbs.c +++ b/drivers/infiniband/core/verbs.c @@ -3109,22 +3109,23 @@ EXPORT_SYMBOL(__rdma_block_iter_start); bool __rdma_block_iter_next(struct ib_block_iter *biter) { unsigned int block_offset; - unsigned int sg_delta; + unsigned int delta; if (!biter->__sg_nents || !biter->__sg) return false; biter->__dma_addr = sg_dma_address(biter->__sg) + biter->__sg_advance; block_offset = biter->__dma_addr & (BIT_ULL(biter->__pg_bit) - 1); - sg_delta = BIT_ULL(biter->__pg_bit) - block_offset; + delta = BIT_ULL(biter->__pg_bit) - block_offset; - if (sg_dma_len(biter->__sg) - biter->__sg_advance > sg_delta) { - biter->__sg_advance += sg_delta; - } else { + while (biter->__sg_nents && biter->__sg && + sg_dma_len(biter->__sg) - biter->__sg_advance <= delta) { + delta -= sg_dma_len(biter->__sg) - biter->__sg_advance; biter->__sg_advance = 0; biter->__sg = sg_next(biter->__sg); biter->__sg_nents--; } + biter->__sg_advance += delta; return true; } From a89326d35bf6fe7b0498311c88a06e35c743434c Mon Sep 17 00:00:00 2001 From: Ahmad Fatoum Date: Tue, 18 Feb 2025 20:18:32 +0100 Subject: [PATCH 47/91] pmdomain: imx: gpcv2: use proper helper for property detection [ Upstream commit 6568cb40e73163fa25e2779f7234b169b2e1a32e ] Starting with commit c141ecc3cecd7 ("of: Warn when of_property_read_bool() is used on non-boolean properties"), probing the gpcv2 device on i.MX8M SoCs leads to warnings when LOCKDEP is enabled. Fix this by checking property presence with of_property_present as intended. Signed-off-by: Ahmad Fatoum Link: https://lore.kernel.org/r/20250218-gpcv2-of-property-present-v1-1-3bb1a9789654@pengutronix.de Signed-off-by: Ulf Hansson Signed-off-by: Sasha Levin --- drivers/pmdomain/imx/gpcv2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pmdomain/imx/gpcv2.c b/drivers/pmdomain/imx/gpcv2.c index e03c2cb39a69..0dbf1893abfa 100644 --- a/drivers/pmdomain/imx/gpcv2.c +++ b/drivers/pmdomain/imx/gpcv2.c @@ -1361,7 +1361,7 @@ static int imx_pgc_domain_probe(struct platform_device *pdev) } if (IS_ENABLED(CONFIG_LOCKDEP) && - of_property_read_bool(domain->dev->of_node, "power-domains")) + of_property_present(domain->dev->of_node, "power-domains")) lockdep_set_subclass(&domain->genpd.mlock, 1); ret = of_genpd_add_provider_simple(domain->dev->of_node, From eaeb67bd851ce573490470b8afd21971d9db942a Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 12 Feb 2025 21:23:14 +0100 Subject: [PATCH 48/91] can: c_can: Use of_property_present() to test existence of DT property [ Upstream commit ab1bc2290fd8311d49b87c29f1eb123fcb581bee ] of_property_read_bool() should be used only on boolean properties. Cc: Rob Herring Signed-off-by: Krzysztof Kozlowski Reviewed-by: Vincent Mailhol Link: https://patch.msgid.link/20250212-syscon-phandle-args-can-v2-3-ac9a1253396b@linaro.org Signed-off-by: Marc Kleine-Budde Signed-off-by: Sasha Levin --- drivers/net/can/c_can/c_can_platform.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/can/c_can/c_can_platform.c b/drivers/net/can/c_can/c_can_platform.c index 399844809bbe..bb6071a758f3 100644 --- a/drivers/net/can/c_can/c_can_platform.c +++ b/drivers/net/can/c_can/c_can_platform.c @@ -324,7 +324,7 @@ static int c_can_plat_probe(struct platform_device *pdev) /* Check if we need custom RAMINIT via syscon. Mostly for TI * platforms. Only supported with DT boot. */ - if (np && of_property_read_bool(np, "syscon-raminit")) { + if (np && of_property_present(np, "syscon-raminit")) { u32 id; struct c_can_raminit *raminit = &priv->raminit_sys; From 2b129e89b8c6e261bd240f56989fc52ec5efbd87 Mon Sep 17 00:00:00 2001 From: Eduard Zingerman Date: Sat, 15 Feb 2025 03:03:54 -0800 Subject: [PATCH 49/91] bpf: don't do clean_live_states when state->loop_entry->branches > 0 [ Upstream commit 9e63fdb0cbdf3268c86638a8274f4d5549a82820 ] verifier.c:is_state_visited() uses RANGE_WITHIN states comparison rules for cached states that have loop_entry with non-zero branches count (meaning that loop_entry's verification is not yet done). The RANGE_WITHIN rules in regsafe()/stacksafe() require register and stack objects types to be identical in current and old states. verifier.c:clean_live_states() replaces registers and stack spills with NOT_INIT/STACK_INVALID marks, if these registers/stack spills are not read in any child state. This means that clean_live_states() works against loop convergence logic under some conditions. See selftest in the next patch for a specific example. Mitigate this by prohibiting clean_verifier_state() when state->loop_entry->branches > 0. This undoes negative verification performance impact of the copy_verifier_state() fix from the previous patch. Below is comparison between master and current patch. selftests: File Program Insns (A) Insns (B) Insns (DIFF) States (A) States (B) States (DIFF) ---------------------------------- ---------------------------- --------- --------- --------------- ---------- ---------- -------------- arena_htab.bpf.o arena_htab_llvm 717 423 -294 (-41.00%) 57 37 -20 (-35.09%) arena_htab_asm.bpf.o arena_htab_asm 597 445 -152 (-25.46%) 47 37 -10 (-21.28%) arena_list.bpf.o arena_list_add 1493 1822 +329 (+22.04%) 30 37 +7 (+23.33%) arena_list.bpf.o arena_list_del 309 261 -48 (-15.53%) 23 15 -8 (-34.78%) iters.bpf.o checkpoint_states_deletion 18125 22154 +4029 (+22.23%) 818 918 +100 (+12.22%) iters.bpf.o iter_nested_deeply_iters 593 367 -226 (-38.11%) 67 43 -24 (-35.82%) iters.bpf.o iter_nested_iters 813 772 -41 (-5.04%) 79 72 -7 (-8.86%) iters.bpf.o iter_subprog_check_stacksafe 155 135 -20 (-12.90%) 15 14 -1 (-6.67%) iters.bpf.o iter_subprog_iters 1094 808 -286 (-26.14%) 88 68 -20 (-22.73%) iters.bpf.o loop_state_deps2 479 356 -123 (-25.68%) 46 35 -11 (-23.91%) iters.bpf.o triple_continue 35 31 -4 (-11.43%) 3 3 +0 (+0.00%) kmem_cache_iter.bpf.o open_coded_iter 63 59 -4 (-6.35%) 7 6 -1 (-14.29%) mptcp_subflow.bpf.o _getsockopt_subflow 501 446 -55 (-10.98%) 25 23 -2 (-8.00%) pyperf600_iter.bpf.o on_event 12339 6379 -5960 (-48.30%) 441 286 -155 (-35.15%) verifier_bits_iter.bpf.o max_words 92 84 -8 (-8.70%) 8 7 -1 (-12.50%) verifier_iterating_callbacks.bpf.o cond_break2 113 192 +79 (+69.91%) 12 21 +9 (+75.00%) sched_ext: File Program Insns (A) Insns (B) Insns (DIFF) States (A) States (B) States (DIFF) ----------------- ---------------------- --------- --------- ----------------- ---------- ---------- ---------------- bpf.bpf.o layered_dispatch 11485 9039 -2446 (-21.30%) 848 662 -186 (-21.93%) bpf.bpf.o layered_dump 7422 5022 -2400 (-32.34%) 681 298 -383 (-56.24%) bpf.bpf.o layered_enqueue 16854 13753 -3101 (-18.40%) 1611 1308 -303 (-18.81%) bpf.bpf.o layered_init 1000001 5549 -994452 (-99.45%) 84672 523 -84149 (-99.38%) bpf.bpf.o layered_runnable 3149 1899 -1250 (-39.70%) 288 151 -137 (-47.57%) bpf.bpf.o p2dq_init 2343 1936 -407 (-17.37%) 201 170 -31 (-15.42%) bpf.bpf.o refresh_layer_cpumasks 16487 1285 -15202 (-92.21%) 1770 120 -1650 (-93.22%) bpf.bpf.o rusty_select_cpu 1937 1386 -551 (-28.45%) 177 125 -52 (-29.38%) scx_central.bpf.o central_dispatch 636 600 -36 (-5.66%) 63 59 -4 (-6.35%) scx_central.bpf.o central_init 913 632 -281 (-30.78%) 48 39 -9 (-18.75%) scx_nest.bpf.o nest_init 636 601 -35 (-5.50%) 60 58 -2 (-3.33%) scx_pair.bpf.o pair_dispatch 1000001 1914 -998087 (-99.81%) 58169 142 -58027 (-99.76%) scx_qmap.bpf.o qmap_dispatch 2393 2187 -206 (-8.61%) 196 174 -22 (-11.22%) scx_qmap.bpf.o qmap_init 16367 22777 +6410 (+39.16%) 603 768 +165 (+27.36%) 'layered_init' and 'pair_dispatch' hit 1M on master, but are verified ok with this patch. Signed-off-by: Eduard Zingerman Link: https://lore.kernel.org/r/20250215110411.3236773-4-eddyz87@gmail.com Signed-off-by: Alexei Starovoitov Signed-off-by: Sasha Levin --- kernel/bpf/verifier.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 294fbafbeba7..592ee3b47635 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -17282,12 +17282,16 @@ static void clean_verifier_state(struct bpf_verifier_env *env, static void clean_live_states(struct bpf_verifier_env *env, int insn, struct bpf_verifier_state *cur) { + struct bpf_verifier_state *loop_entry; struct bpf_verifier_state_list *sl; sl = *explored_state(env, insn); while (sl) { if (sl->state.branches) goto next; + loop_entry = get_loop_entry(&sl->state); + if (loop_entry && loop_entry->branches) + goto next; if (sl->state.insn_idx != insn || !same_callsites(&sl->state, cur)) goto next; From 46ba5757a7a4714e7d3f68cfe118208822cb3d78 Mon Sep 17 00:00:00 2001 From: Eduard Zingerman Date: Sat, 15 Feb 2025 03:03:52 -0800 Subject: [PATCH 50/91] bpf: copy_verifier_state() should copy 'loop_entry' field [ Upstream commit bbbc02b7445ebfda13e4847f4f1413c6480a85a9 ] The bpf_verifier_state.loop_entry state should be copied by copy_verifier_state(). Otherwise, .loop_entry values from unrelated states would poison env->cur_state. Additionally, env->stack should not contain any states with .loop_entry != NULL. The states in env->stack are yet to be verified, while .loop_entry is set for states that reached an equivalent state. This means that env->cur_state->loop_entry should always be NULL after pop_stack(). See the selftest in the next commit for an example of the program that is not safe yet is accepted by verifier w/o this fix. This change has some verification performance impact for selftests: File Program Insns (A) Insns (B) Insns (DIFF) States (A) States (B) States (DIFF) ---------------------------------- ---------------------------- --------- --------- -------------- ---------- ---------- ------------- arena_htab.bpf.o arena_htab_llvm 717 426 -291 (-40.59%) 57 37 -20 (-35.09%) arena_htab_asm.bpf.o arena_htab_asm 597 445 -152 (-25.46%) 47 37 -10 (-21.28%) arena_list.bpf.o arena_list_del 309 279 -30 (-9.71%) 23 14 -9 (-39.13%) iters.bpf.o iter_subprog_check_stacksafe 155 141 -14 (-9.03%) 15 14 -1 (-6.67%) iters.bpf.o iter_subprog_iters 1094 1003 -91 (-8.32%) 88 83 -5 (-5.68%) iters.bpf.o loop_state_deps2 479 725 +246 (+51.36%) 46 63 +17 (+36.96%) kmem_cache_iter.bpf.o open_coded_iter 63 59 -4 (-6.35%) 7 6 -1 (-14.29%) verifier_bits_iter.bpf.o max_words 92 84 -8 (-8.70%) 8 7 -1 (-12.50%) verifier_iterating_callbacks.bpf.o cond_break2 113 107 -6 (-5.31%) 12 12 +0 (+0.00%) And significant negative impact for sched_ext: File Program Insns (A) Insns (B) Insns (DIFF) States (A) States (B) States (DIFF) ----------------- ---------------------- --------- --------- -------------------- ---------- ---------- ------------------ bpf.bpf.o lavd_init 7039 14723 +7684 (+109.16%) 490 1139 +649 (+132.45%) bpf.bpf.o layered_dispatch 11485 10548 -937 (-8.16%) 848 762 -86 (-10.14%) bpf.bpf.o layered_dump 7422 1000001 +992579 (+13373.47%) 681 31178 +30497 (+4478.27%) bpf.bpf.o layered_enqueue 16854 71127 +54273 (+322.02%) 1611 6450 +4839 (+300.37%) bpf.bpf.o p2dq_dispatch 665 791 +126 (+18.95%) 68 78 +10 (+14.71%) bpf.bpf.o p2dq_init 2343 2980 +637 (+27.19%) 201 237 +36 (+17.91%) bpf.bpf.o refresh_layer_cpumasks 16487 674760 +658273 (+3992.68%) 1770 65370 +63600 (+3593.22%) bpf.bpf.o rusty_select_cpu 1937 40872 +38935 (+2010.07%) 177 3210 +3033 (+1713.56%) scx_central.bpf.o central_dispatch 636 2687 +2051 (+322.48%) 63 227 +164 (+260.32%) scx_nest.bpf.o nest_init 636 815 +179 (+28.14%) 60 73 +13 (+21.67%) scx_qmap.bpf.o qmap_dispatch 2393 3580 +1187 (+49.60%) 196 253 +57 (+29.08%) scx_qmap.bpf.o qmap_dump 233 318 +85 (+36.48%) 22 30 +8 (+36.36%) scx_qmap.bpf.o qmap_init 16367 17436 +1069 (+6.53%) 603 669 +66 (+10.95%) Note 'layered_dump' program, which now hits 1M instructions limit. This impact would be mitigated in the next patch. Signed-off-by: Eduard Zingerman Link: https://lore.kernel.org/r/20250215110411.3236773-2-eddyz87@gmail.com Signed-off-by: Alexei Starovoitov Signed-off-by: Sasha Levin --- kernel/bpf/verifier.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 592ee3b47635..1437108f9d7a 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -1447,6 +1447,7 @@ static int copy_verifier_state(struct bpf_verifier_state *dst_state, dst_state->callback_unroll_depth = src->callback_unroll_depth; dst_state->used_as_loop_entry = src->used_as_loop_entry; dst_state->may_goto_depth = src->may_goto_depth; + dst_state->loop_entry = src->loop_entry; for (i = 0; i <= src->curframe; i++) { dst = dst_state->frame[i]; if (!dst) { @@ -18720,6 +18721,8 @@ process_bpf_exit: return err; break; } else { + if (WARN_ON_ONCE(env->cur_state->loop_entry)) + env->cur_state->loop_entry = NULL; do_print_state = true; continue; } From 161cc125043a24cf14b86e61e57221a820e8fb5e Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Wed, 12 Feb 2025 17:06:33 -0800 Subject: [PATCH 51/91] eth: mlx4: don't try to complete XDP frames in netpoll [ Upstream commit 8fdeafd66edaf420ea0063a1f13442fe3470fe70 ] mlx4 doesn't support ndo_xdp_xmit / XDP_REDIRECT and wasn't using page pool until now, so it could run XDP completions in netpoll (NAPI budget == 0) just fine. Page pool has calling context requirements, make sure we don't try to call it from what is potentially HW IRQ context. Reviewed-by: Tariq Toukan Link: https://patch.msgid.link/20250213010635.1354034-3-kuba@kernel.org Signed-off-by: Jakub Kicinski Signed-off-by: Sasha Levin --- drivers/net/ethernet/mellanox/mlx4/en_tx.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlx4/en_tx.c b/drivers/net/ethernet/mellanox/mlx4/en_tx.c index 1ddb11cb25f9..6e077d202827 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_tx.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_tx.c @@ -450,6 +450,8 @@ int mlx4_en_process_tx_cq(struct net_device *dev, if (unlikely(!priv->port_up)) return 0; + if (unlikely(!napi_budget) && cq->type == TX_XDP) + return 0; netdev_txq_bql_complete_prefetchw(ring->tx_queue); From 82b54455b6b7f103cd71c7dafd07328331e4f3dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= Date: Mon, 16 Dec 2024 19:56:12 +0200 Subject: [PATCH 52/91] PCI: Fix old_size lower bound in calculate_iosize() too MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit ff61f380de5652e723168341480cc7adf1dd6213 ] Commit 903534fa7d30 ("PCI: Fix resource double counting on remove & rescan") fixed double counting of mem resources because of old_size being applied too early. Fix a similar counting bug on the io resource side. Link: https://lore.kernel.org/r/20241216175632.4175-6-ilpo.jarvinen@linux.intel.com Signed-off-by: Ilpo Järvinen Signed-off-by: Bjorn Helgaas Tested-by: Xiaochun Lee Signed-off-by: Sasha Levin --- drivers/pci/setup-bus.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index f16c7ce3bf3f..1eceabef9e84 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -814,11 +814,9 @@ static resource_size_t calculate_iosize(resource_size_t size, size = (size & 0xff) + ((size & ~0xffUL) << 2); #endif size = size + size1; - if (size < old_size) - size = old_size; - size = ALIGN(max(size, add_size) + children_add_size, align); - return size; + size = max(size, add_size) + children_add_size; + return ALIGN(max(size, old_size), align); } static resource_size_t calculate_memsize(resource_size_t size, From 1fb8106316a218256faf60b37d81134b6e7c798a Mon Sep 17 00:00:00 2001 From: Xiaofei Tan Date: Wed, 12 Feb 2025 14:34:08 +0800 Subject: [PATCH 53/91] ACPI: HED: Always initialize before evged [ Upstream commit cccf6ee090c8c133072d5d5b52ae25f3bc907a16 ] When the HED driver is built-in, it initializes after evged because they both are at the same initcall level, so the initialization ordering depends on the Makefile order. However, this prevents RAS records coming in between the evged driver initialization and the HED driver initialization from being handled. If the number of such RAS records is above the APEI HEST error source number, the HEST resources may be exhausted, and that may affect subsequent RAS error reporting. To fix this issue, change the initcall level of HED to subsys_initcall and prevent the driver from being built as a module by changing ACPI_HED in Kconfig from "tristate" to "bool". Signed-off-by: Xiaofei Tan Link: https://patch.msgid.link/20250212063408.927666-1-tanxiaofei@huawei.com [ rjw: Changelog edits ] Signed-off-by: Rafael J. Wysocki Signed-off-by: Sasha Levin --- drivers/acpi/Kconfig | 2 +- drivers/acpi/hed.c | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index d67f63d93b2a..89fa569d6370 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -443,7 +443,7 @@ config ACPI_SBS the modules will be called sbs and sbshc. config ACPI_HED - tristate "Hardware Error Device" + bool "Hardware Error Device" help This driver supports the Hardware Error Device (PNP0C33), which is used to report some hardware errors notified via diff --git a/drivers/acpi/hed.c b/drivers/acpi/hed.c index 7652515a6be1..3499f86c411e 100644 --- a/drivers/acpi/hed.c +++ b/drivers/acpi/hed.c @@ -80,7 +80,12 @@ static struct acpi_driver acpi_hed_driver = { .remove = acpi_hed_remove, }, }; -module_acpi_driver(acpi_hed_driver); + +static int __init acpi_hed_driver_init(void) +{ + return acpi_bus_register_driver(&acpi_hed_driver); +} +subsys_initcall(acpi_hed_driver_init); MODULE_AUTHOR("Huang Ying"); MODULE_DESCRIPTION("ACPI Hardware Error Device Driver"); From 7f131fda2654e880700d6826b362e6862ac9ba8a Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Fri, 14 Feb 2025 17:18:21 +0100 Subject: [PATCH 54/91] vxlan: Join / leave MC group after remote changes [ Upstream commit d42d543368343c0449a4e433b5f02e063a86209c ] When a vxlan netdevice is brought up, if its default remote is a multicast address, the device joins the indicated group. Therefore when the multicast remote address changes, the device should leave the current group and subscribe to the new one. Similarly when the interface used for endpoint communication is changed in a situation when multicast remote is configured. This is currently not done. Both vxlan_igmp_join() and vxlan_igmp_leave() can however fail. So it is possible that with such fix, the netdevice will end up in an inconsistent situation where the old group is not joined anymore, but joining the new group fails. Should we join the new group first, and leave the old one second, we might end up in the opposite situation, where both groups are joined. Undoing any of this during rollback is going to be similarly problematic. One solution would be to just forbid the change when the netdevice is up. However in vnifilter mode, changing the group address is allowed, and these problems are simply ignored (see vxlan_vni_update_group()): # ip link add name br up type bridge vlan_filtering 1 # ip link add vx1 up master br type vxlan external vnifilter local 192.0.2.1 dev lo dstport 4789 # bridge vni add dev vx1 vni 200 group 224.0.0.1 # tcpdump -i lo & # bridge vni add dev vx1 vni 200 group 224.0.0.2 18:55:46.523438 IP 0.0.0.0 > 224.0.0.22: igmp v3 report, 1 group record(s) 18:55:46.943447 IP 0.0.0.0 > 224.0.0.22: igmp v3 report, 1 group record(s) # bridge vni dev vni group/remote vx1 200 224.0.0.2 Having two different modes of operation for conceptually the same interface is silly, so in this patch, just do what the vnifilter code does and deal with the errors by crossing fingers real hard. The vnifilter code leaves old before joining new, and in case of join / leave failures does not roll back the configuration changes that have already been applied, but bails out of joining if it could not leave. Do the same here: leave before join, apply changes unconditionally and do not attempt to join if we couldn't leave. Signed-off-by: Petr Machata Reviewed-by: Ido Schimmel Reviewed-by: Nikolay Aleksandrov Signed-off-by: Paolo Abeni Signed-off-by: Sasha Levin --- drivers/net/vxlan/vxlan_core.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c index 5e7cdd1b806f..01f66760e132 100644 --- a/drivers/net/vxlan/vxlan_core.c +++ b/drivers/net/vxlan/vxlan_core.c @@ -4340,6 +4340,7 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[], struct netlink_ext_ack *extack) { struct vxlan_dev *vxlan = netdev_priv(dev); + bool rem_ip_changed, change_igmp; struct net_device *lowerdev; struct vxlan_config conf; struct vxlan_rdst *dst; @@ -4363,8 +4364,13 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[], if (err) return err; + rem_ip_changed = !vxlan_addr_equal(&conf.remote_ip, &dst->remote_ip); + change_igmp = vxlan->dev->flags & IFF_UP && + (rem_ip_changed || + dst->remote_ifindex != conf.remote_ifindex); + /* handle default dst entry */ - if (!vxlan_addr_equal(&conf.remote_ip, &dst->remote_ip)) { + if (rem_ip_changed) { u32 hash_index = fdb_head_index(vxlan, all_zeros_mac, conf.vni); spin_lock_bh(&vxlan->hash_lock[hash_index]); @@ -4408,6 +4414,9 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[], } } + if (change_igmp && vxlan_addr_multicast(&dst->remote_ip)) + err = vxlan_multicast_leave(vxlan); + if (conf.age_interval != vxlan->cfg.age_interval) mod_timer(&vxlan->age_timer, jiffies); @@ -4415,7 +4424,12 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[], if (lowerdev && lowerdev != dst->remote_dev) dst->remote_dev = lowerdev; vxlan_config_apply(dev, &conf, lowerdev, vxlan->net, true); - return 0; + + if (!err && change_igmp && + vxlan_addr_multicast(&dst->remote_ip)) + err = vxlan_multicast_join(vxlan); + + return err; } static void vxlan_dellink(struct net_device *dev, struct list_head *head) From dc5f5c9d2bbc634eb144beb7d2cea950725d03c8 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 14 Feb 2025 15:43:33 +0200 Subject: [PATCH 55/91] hrtimers: Replace hrtimer_clock_to_base_table with switch-case [ Upstream commit 4441b976dfeff0d3579e8da3c0283300c618a553 ] Clang and GCC complain about overlapped initialisers in the hrtimer_clock_to_base_table definition. With `make W=1` and CONFIG_WERROR=y (which is default nowadays) this breaks the build: CC kernel/time/hrtimer.o kernel/time/hrtimer.c:124:21: error: initializer overrides prior initialization of this subobject [-Werror,-Winitializer-overrides] 124 | [CLOCK_REALTIME] = HRTIMER_BASE_REALTIME, kernel/time/hrtimer.c:122:27: note: previous initialization is here 122 | [0 ... MAX_CLOCKS - 1] = HRTIMER_MAX_CLOCK_BASES, (and similar for CLOCK_MONOTONIC, CLOCK_BOOTTIME, and CLOCK_TAI). hrtimer_clockid_to_base(), which uses the table, is only used in __hrtimer_init(), which is not a hotpath. Therefore replace the table lookup with a switch case in hrtimer_clockid_to_base() to avoid this warning. Signed-off-by: Andy Shevchenko Signed-off-by: Thomas Gleixner Link: https://lore.kernel.org/all/20250214134424.3367619-1-andriy.shevchenko@linux.intel.com Signed-off-by: Sasha Levin --- kernel/time/hrtimer.c | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c index db9c06bb2311..06fbc226341f 100644 --- a/kernel/time/hrtimer.c +++ b/kernel/time/hrtimer.c @@ -117,16 +117,6 @@ DEFINE_PER_CPU(struct hrtimer_cpu_base, hrtimer_bases) = .csd = CSD_INIT(retrigger_next_event, NULL) }; -static const int hrtimer_clock_to_base_table[MAX_CLOCKS] = { - /* Make sure we catch unsupported clockids */ - [0 ... MAX_CLOCKS - 1] = HRTIMER_MAX_CLOCK_BASES, - - [CLOCK_REALTIME] = HRTIMER_BASE_REALTIME, - [CLOCK_MONOTONIC] = HRTIMER_BASE_MONOTONIC, - [CLOCK_BOOTTIME] = HRTIMER_BASE_BOOTTIME, - [CLOCK_TAI] = HRTIMER_BASE_TAI, -}; - static inline bool hrtimer_base_is_online(struct hrtimer_cpu_base *base) { if (!IS_ENABLED(CONFIG_HOTPLUG_CPU)) @@ -1597,14 +1587,19 @@ u64 hrtimer_next_event_without(const struct hrtimer *exclude) static inline int hrtimer_clockid_to_base(clockid_t clock_id) { - if (likely(clock_id < MAX_CLOCKS)) { - int base = hrtimer_clock_to_base_table[clock_id]; - - if (likely(base != HRTIMER_MAX_CLOCK_BASES)) - return base; + switch (clock_id) { + case CLOCK_REALTIME: + return HRTIMER_BASE_REALTIME; + case CLOCK_MONOTONIC: + return HRTIMER_BASE_MONOTONIC; + case CLOCK_BOOTTIME: + return HRTIMER_BASE_BOOTTIME; + case CLOCK_TAI: + return HRTIMER_BASE_TAI; + default: + WARN(1, "Invalid clockid %d. Using MONOTONIC\n", clock_id); + return HRTIMER_BASE_MONOTONIC; } - WARN(1, "Invalid clockid %d. Using MONOTONIC\n", clock_id); - return HRTIMER_BASE_MONOTONIC; } static void __hrtimer_init(struct hrtimer *timer, clockid_t clock_id, From 2fe6284364423d81b2f87d06da5617999e0f30cc Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Mon, 17 Feb 2025 14:26:47 +0530 Subject: [PATCH 56/91] irqchip/riscv-imsic: Set irq_set_affinity() for IMSIC base [ Upstream commit 999f458c1771354371ba367dd84f55f9a62a4233 ] The IMSIC driver assigns the IMSIC domain specific imsic_irq_set_affinity() callback to the per device leaf MSI domain. That's a layering violation as it is called with the leaf domain data and not with the IMSIC domain data. This prevents moving the IMSIC driver to the common MSI library which uses the generic msi_domain_set_affinity() callback for device MSI domains. Instead of using imsic_irq_set_affinity() for leaf MSI domains, use imsic_irq_set_affinity() for the non-leaf IMSIC base domain and use irq_chip_set_affinity_parent() for leaf MSI domains. [ tglx: Massaged change log ] Signed-off-by: Andrew Jones Signed-off-by: Anup Patel Signed-off-by: Thomas Gleixner Link: https://lore.kernel.org/all/20250217085657.789309-2-apatel@ventanamicro.com Signed-off-by: Sasha Levin --- drivers/irqchip/irq-riscv-imsic-platform.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/irqchip/irq-riscv-imsic-platform.c b/drivers/irqchip/irq-riscv-imsic-platform.c index c708780e8760..5d7c30ad8855 100644 --- a/drivers/irqchip/irq-riscv-imsic-platform.c +++ b/drivers/irqchip/irq-riscv-imsic-platform.c @@ -96,9 +96,8 @@ static int imsic_irq_set_affinity(struct irq_data *d, const struct cpumask *mask bool force) { struct imsic_vector *old_vec, *new_vec; - struct irq_data *pd = d->parent_data; - old_vec = irq_data_get_irq_chip_data(pd); + old_vec = irq_data_get_irq_chip_data(d); if (WARN_ON(!old_vec)) return -ENOENT; @@ -116,13 +115,13 @@ static int imsic_irq_set_affinity(struct irq_data *d, const struct cpumask *mask return -ENOSPC; /* Point device to the new vector */ - imsic_msi_update_msg(d, new_vec); + imsic_msi_update_msg(irq_get_irq_data(d->irq), new_vec); /* Update irq descriptors with the new vector */ - pd->chip_data = new_vec; + d->chip_data = new_vec; - /* Update effective affinity of parent irq data */ - irq_data_update_effective_affinity(pd, cpumask_of(new_vec->cpu)); + /* Update effective affinity */ + irq_data_update_effective_affinity(d, cpumask_of(new_vec->cpu)); /* Move state of the old vector to the new vector */ imsic_vector_move(old_vec, new_vec); @@ -135,6 +134,9 @@ static struct irq_chip imsic_irq_base_chip = { .name = "IMSIC", .irq_mask = imsic_irq_mask, .irq_unmask = imsic_irq_unmask, +#ifdef CONFIG_SMP + .irq_set_affinity = imsic_irq_set_affinity, +#endif .irq_retrigger = imsic_irq_retrigger, .irq_compose_msi_msg = imsic_irq_compose_msg, .flags = IRQCHIP_SKIP_SET_WAKE | @@ -245,7 +247,7 @@ static bool imsic_init_dev_msi_info(struct device *dev, if (WARN_ON_ONCE(domain != real_parent)) return false; #ifdef CONFIG_SMP - info->chip->irq_set_affinity = imsic_irq_set_affinity; + info->chip->irq_set_affinity = irq_chip_set_affinity_parent; #endif break; default: From 3770acff3110f0fa1438b34050d359e827cba59d Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 9 Dec 2024 16:00:16 +0100 Subject: [PATCH 57/91] media: test-drivers: vivid: don't call schedule in loop [ Upstream commit e4740118b752005cbed339aec9a1d1c43620e0b9 ] Artem reported that the CPU load was 100% when capturing from vivid at low resolution with ffmpeg. This was caused by: while (time_is_after_jiffies(cur_jiffies + wait_jiffies) && !kthread_should_stop()) schedule(); If there are no other processes running that can be scheduled, then this is basically a busy-loop. Change it to wait_event_interruptible_timeout() which doesn't have that problem. Signed-off-by: Hans Verkuil Reported-by: Artem S. Tashkinov Closes: https://bugzilla.kernel.org/show_bug.cgi?id=219570 Reviewed-by: Nicolas Dufresne Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Sasha Levin --- drivers/media/test-drivers/vivid/vivid-kthread-cap.c | 11 ++++++++--- drivers/media/test-drivers/vivid/vivid-kthread-out.c | 11 ++++++++--- .../media/test-drivers/vivid/vivid-kthread-touch.c | 11 ++++++++--- drivers/media/test-drivers/vivid/vivid-sdr-cap.c | 11 ++++++++--- 4 files changed, 32 insertions(+), 12 deletions(-) diff --git a/drivers/media/test-drivers/vivid/vivid-kthread-cap.c b/drivers/media/test-drivers/vivid/vivid-kthread-cap.c index 669bd96da4c7..273e8ed8c2a9 100644 --- a/drivers/media/test-drivers/vivid/vivid-kthread-cap.c +++ b/drivers/media/test-drivers/vivid/vivid-kthread-cap.c @@ -789,9 +789,14 @@ static int vivid_thread_vid_cap(void *data) next_jiffies_since_start = jiffies_since_start; wait_jiffies = next_jiffies_since_start - jiffies_since_start; - while (time_is_after_jiffies(cur_jiffies + wait_jiffies) && - !kthread_should_stop()) - schedule(); + if (!time_is_after_jiffies(cur_jiffies + wait_jiffies)) + continue; + + wait_queue_head_t wait; + + init_waitqueue_head(&wait); + wait_event_interruptible_timeout(wait, kthread_should_stop(), + cur_jiffies + wait_jiffies - jiffies); } dprintk(dev, 1, "Video Capture Thread End\n"); return 0; diff --git a/drivers/media/test-drivers/vivid/vivid-kthread-out.c b/drivers/media/test-drivers/vivid/vivid-kthread-out.c index fac6208b51da..015a7b166a1e 100644 --- a/drivers/media/test-drivers/vivid/vivid-kthread-out.c +++ b/drivers/media/test-drivers/vivid/vivid-kthread-out.c @@ -235,9 +235,14 @@ static int vivid_thread_vid_out(void *data) next_jiffies_since_start = jiffies_since_start; wait_jiffies = next_jiffies_since_start - jiffies_since_start; - while (time_is_after_jiffies(cur_jiffies + wait_jiffies) && - !kthread_should_stop()) - schedule(); + if (!time_is_after_jiffies(cur_jiffies + wait_jiffies)) + continue; + + wait_queue_head_t wait; + + init_waitqueue_head(&wait); + wait_event_interruptible_timeout(wait, kthread_should_stop(), + cur_jiffies + wait_jiffies - jiffies); } dprintk(dev, 1, "Video Output Thread End\n"); return 0; diff --git a/drivers/media/test-drivers/vivid/vivid-kthread-touch.c b/drivers/media/test-drivers/vivid/vivid-kthread-touch.c index fa711ee36a3f..c862689786b6 100644 --- a/drivers/media/test-drivers/vivid/vivid-kthread-touch.c +++ b/drivers/media/test-drivers/vivid/vivid-kthread-touch.c @@ -135,9 +135,14 @@ static int vivid_thread_touch_cap(void *data) next_jiffies_since_start = jiffies_since_start; wait_jiffies = next_jiffies_since_start - jiffies_since_start; - while (time_is_after_jiffies(cur_jiffies + wait_jiffies) && - !kthread_should_stop()) - schedule(); + if (!time_is_after_jiffies(cur_jiffies + wait_jiffies)) + continue; + + wait_queue_head_t wait; + + init_waitqueue_head(&wait); + wait_event_interruptible_timeout(wait, kthread_should_stop(), + cur_jiffies + wait_jiffies - jiffies); } dprintk(dev, 1, "Touch Capture Thread End\n"); return 0; diff --git a/drivers/media/test-drivers/vivid/vivid-sdr-cap.c b/drivers/media/test-drivers/vivid/vivid-sdr-cap.c index 38cda33dffb2..97cfc58b7057 100644 --- a/drivers/media/test-drivers/vivid/vivid-sdr-cap.c +++ b/drivers/media/test-drivers/vivid/vivid-sdr-cap.c @@ -206,9 +206,14 @@ static int vivid_thread_sdr_cap(void *data) next_jiffies_since_start = jiffies_since_start; wait_jiffies = next_jiffies_since_start - jiffies_since_start; - while (time_is_after_jiffies(cur_jiffies + wait_jiffies) && - !kthread_should_stop()) - schedule(); + if (!time_is_after_jiffies(cur_jiffies + wait_jiffies)) + continue; + + wait_queue_head_t wait; + + init_waitqueue_head(&wait); + wait_event_interruptible_timeout(wait, kthread_should_stop(), + cur_jiffies + wait_jiffies - jiffies); } dprintk(dev, 1, "SDR Capture Thread End\n"); return 0; From c4e1ce22b9ab964a09bc5532c9fae9b4738d36b8 Mon Sep 17 00:00:00 2001 From: Shahar Shitrit Date: Thu, 13 Feb 2025 11:46:40 +0200 Subject: [PATCH 58/91] net/mlx5: Modify LSB bitmask in temperature event to include only the first bit [ Upstream commit 633f16d7e07c129a36b882c05379e01ce5bdb542 ] In the sensor_count field of the MTEWE register, bits 1-62 are supported only for unmanaged switches, not for NICs, and bit 63 is reserved for internal use. To prevent confusing output that may include set bits that are not relevant to NIC sensors, we update the bitmask to retain only the first bit, which corresponds to the sensor ASIC. Signed-off-by: Shahar Shitrit Signed-off-by: Tariq Toukan Reviewed-by: Mateusz Polchlopek Link: https://patch.msgid.link/20250213094641.226501-4-tariqt@nvidia.com Signed-off-by: Jakub Kicinski Signed-off-by: Sasha Levin --- drivers/net/ethernet/mellanox/mlx5/core/events.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/events.c b/drivers/net/ethernet/mellanox/mlx5/core/events.c index d91ea53eb394..cd8d107f7d9e 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/events.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/events.c @@ -163,6 +163,10 @@ static int temp_warn(struct notifier_block *nb, unsigned long type, void *data) u64 value_msb; value_lsb = be64_to_cpu(eqe->data.temp_warning.sensor_warning_lsb); + /* bit 1-63 are not supported for NICs, + * hence read only bit 0 (asic) from lsb. + */ + value_lsb &= 0x1; value_msb = be64_to_cpu(eqe->data.temp_warning.sensor_warning_msb); mlx5_core_warn(events->dev, From 587386c56fb886577bac3e201ef57be43a6720a6 Mon Sep 17 00:00:00 2001 From: Shahar Shitrit Date: Thu, 13 Feb 2025 11:46:38 +0200 Subject: [PATCH 59/91] net/mlx5: Apply rate-limiting to high temperature warning [ Upstream commit 9dd3d5d258aceb37bdf09c8b91fa448f58ea81f0 ] Wrap the high temperature warning in a temperature event with a call to net_ratelimit() to prevent flooding the kernel log with repeated warning messages when temperature exceeds the threshold multiple times within a short duration. Signed-off-by: Shahar Shitrit Signed-off-by: Tariq Toukan Reviewed-by: Mateusz Polchlopek Link: https://patch.msgid.link/20250213094641.226501-2-tariqt@nvidia.com Signed-off-by: Jakub Kicinski Signed-off-by: Sasha Levin --- drivers/net/ethernet/mellanox/mlx5/core/events.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/events.c b/drivers/net/ethernet/mellanox/mlx5/core/events.c index cd8d107f7d9e..fc6e56305cbb 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/events.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/events.c @@ -169,9 +169,10 @@ static int temp_warn(struct notifier_block *nb, unsigned long type, void *data) value_lsb &= 0x1; value_msb = be64_to_cpu(eqe->data.temp_warning.sensor_warning_msb); - mlx5_core_warn(events->dev, - "High temperature on sensors with bit set %llx %llx", - value_msb, value_lsb); + if (net_ratelimit()) + mlx5_core_warn(events->dev, + "High temperature on sensors with bit set %llx %llx", + value_msb, value_lsb); return NOTIFY_OK; } From 3a3fab1be5a0c177d9d45bb3aa8d2897604fa601 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Mon, 17 Feb 2025 15:38:53 +0000 Subject: [PATCH 60/91] firmware: arm_ffa: Reject higher major version as incompatible [ Upstream commit efff6a7f16b34fd902f342b58bd8bafc2d6f2fd1 ] When the firmware compatibility was handled previously in the commit 8e3f9da608f1 ("firmware: arm_ffa: Handle compatibility with different firmware versions"), we only addressed firmware versions that have higher minor versions compared to the driver version which is should be considered compatible unless the firmware returns NOT_SUPPORTED. However, if the firmware reports higher major version than the driver supported, we need to reject it. If the firmware can work in a compatible mode with the driver requested version, it must return the same major version as requested. Tested-by: Viresh Kumar Message-Id: <20250217-ffa_updates-v3-12-bd1d9de615e7@arm.com> Signed-off-by: Sudeep Holla Signed-off-by: Sasha Levin --- drivers/firmware/arm_ffa/driver.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c index dce448687e28..8dc8654f9f4b 100644 --- a/drivers/firmware/arm_ffa/driver.c +++ b/drivers/firmware/arm_ffa/driver.c @@ -150,6 +150,14 @@ static int ffa_version_check(u32 *version) return -EOPNOTSUPP; } + if (FFA_MAJOR_VERSION(ver.a0) > FFA_MAJOR_VERSION(FFA_DRIVER_VERSION)) { + pr_err("Incompatible v%d.%d! Latest supported v%d.%d\n", + FFA_MAJOR_VERSION(ver.a0), FFA_MINOR_VERSION(ver.a0), + FFA_MAJOR_VERSION(FFA_DRIVER_VERSION), + FFA_MINOR_VERSION(FFA_DRIVER_VERSION)); + return -EINVAL; + } + if (ver.a0 < FFA_MIN_VERSION) { pr_err("Incompatible v%d.%d! Earliest supported v%d.%d\n", FFA_MAJOR_VERSION(ver.a0), FFA_MINOR_VERSION(ver.a0), From e1c4bb3774421fdcd941bbb6a6a20d86be555d26 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Mon, 17 Feb 2025 15:38:48 +0000 Subject: [PATCH 61/91] firmware: arm_ffa: Handle the presence of host partition in the partition info [ Upstream commit 2f622a8b0722d332a2a149794a3add47bc9bdcf3 ] Currently it is assumed that the firmware doesn't present the host partition in the list of partitions presented as part of the response to PARTITION_INFO_GET from the firmware. However, there are few platforms that prefer to present the same in the list of partitions. It is not manadatory but not restricted as well. So handle the same by making sure to check the presence of the host VM ID in the XArray partition information maintained/managed in the driver before attempting to add it. Tested-by: Viresh Kumar Message-Id: <20250217-ffa_updates-v3-7-bd1d9de615e7@arm.com> Signed-off-by: Sudeep Holla Signed-off-by: Sasha Levin --- drivers/firmware/arm_ffa/driver.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c index 8dc8654f9f4b..47751b2c057a 100644 --- a/drivers/firmware/arm_ffa/driver.c +++ b/drivers/firmware/arm_ffa/driver.c @@ -1449,6 +1449,10 @@ static int ffa_setup_partitions(void) kfree(pbuf); + /* Check if the host is already added as part of partition info */ + if (xa_load(&drv_info->partition_info, drv_info->vm_id)) + return 0; + /* Allocate for the host */ info = kzalloc(sizeof(*info), GFP_KERNEL); if (!info) { From 83ea9472389530b78d1a5daae267e7e75e4533dd Mon Sep 17 00:00:00 2001 From: Siva Durga Prasad Paladugu Date: Fri, 7 Feb 2025 11:19:51 +0530 Subject: [PATCH 62/91] firmware: xilinx: Dont send linux address to get fpga config get status [ Upstream commit 5abc174016052caff1bcf4cedb159bd388411e98 ] Fpga get config status just returns status through ret_payload and there is no need to allocate local buf and send its address through SMC args. Moreover, the address that is being passed till now is linux virtual address and is incorrect. Corresponding modification has been done in the firmware to avoid using the address sent by linux. Signed-off-by: Siva Durga Prasad Paladugu Signed-off-by: Nava kishore Manne Link: https://lore.kernel.org/r/20250207054951.1650534-1-nava.kishore.manne@amd.com Signed-off-by: Michal Simek Signed-off-by: Sasha Levin --- drivers/firmware/xilinx/zynqmp.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/firmware/xilinx/zynqmp.c b/drivers/firmware/xilinx/zynqmp.c index add8acf66a9c..5578158f1375 100644 --- a/drivers/firmware/xilinx/zynqmp.c +++ b/drivers/firmware/xilinx/zynqmp.c @@ -1012,17 +1012,13 @@ EXPORT_SYMBOL_GPL(zynqmp_pm_fpga_get_status); int zynqmp_pm_fpga_get_config_status(u32 *value) { u32 ret_payload[PAYLOAD_ARG_CNT]; - u32 buf, lower_addr, upper_addr; int ret; if (!value) return -EINVAL; - lower_addr = lower_32_bits((u64)&buf); - upper_addr = upper_32_bits((u64)&buf); - ret = zynqmp_pm_invoke_fn(PM_FPGA_READ, ret_payload, 4, - XILINX_ZYNQMP_PM_FPGA_CONFIG_STAT_OFFSET, lower_addr, upper_addr, + XILINX_ZYNQMP_PM_FPGA_CONFIG_STAT_OFFSET, 0, 0, XILINX_ZYNQMP_PM_FPGA_READ_CONFIG_REG); *value = ret_payload[1]; From 000dd6e3441fcb0094ad7960d6b9bd7c570f13ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Povi=C5=A1er?= Date: Sat, 8 Feb 2025 00:57:22 +0000 Subject: [PATCH 63/91] ASoC: ops: Enforce platform maximum on initial value MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 783db6851c1821d8b983ffb12b99c279ff64f2ee ] Lower the volume if it is violating the platform maximum at its initial value (i.e. at the time of the 'snd_soc_limit_volume' call). Signed-off-by: Martin Povišer [Cherry picked from the Asahi kernel with fixups -- broonie] Signed-off-by: Mark Brown Link: https://patch.msgid.link/20250208-asoc-volume-limit-v1-1-b98fcf4cdbad@kernel.org Signed-off-by: Mark Brown Signed-off-by: Sasha Levin --- sound/soc/soc-ops.c | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/sound/soc/soc-ops.c b/sound/soc/soc-ops.c index b0e4e4168f38..fb11003d56cf 100644 --- a/sound/soc/soc-ops.c +++ b/sound/soc/soc-ops.c @@ -639,6 +639,33 @@ int snd_soc_get_volsw_range(struct snd_kcontrol *kcontrol, } EXPORT_SYMBOL_GPL(snd_soc_get_volsw_range); +static int snd_soc_clip_to_platform_max(struct snd_kcontrol *kctl) +{ + struct soc_mixer_control *mc = (struct soc_mixer_control *)kctl->private_value; + struct snd_ctl_elem_value uctl; + int ret; + + if (!mc->platform_max) + return 0; + + ret = kctl->get(kctl, &uctl); + if (ret < 0) + return ret; + + if (uctl.value.integer.value[0] > mc->platform_max) + uctl.value.integer.value[0] = mc->platform_max; + + if (snd_soc_volsw_is_stereo(mc) && + uctl.value.integer.value[1] > mc->platform_max) + uctl.value.integer.value[1] = mc->platform_max; + + ret = kctl->put(kctl, &uctl); + if (ret < 0) + return ret; + + return 0; +} + /** * snd_soc_limit_volume - Set new limit to an existing volume control. * @@ -663,7 +690,7 @@ int snd_soc_limit_volume(struct snd_soc_card *card, struct soc_mixer_control *mc = (struct soc_mixer_control *)kctl->private_value; if (max <= mc->max - mc->min) { mc->platform_max = max; - ret = 0; + ret = snd_soc_clip_to_platform_max(kctl); } } return ret; From 8d8083881ecbb8112317e8e407ae617fa07c8077 Mon Sep 17 00:00:00 2001 From: Hector Martin Date: Sat, 8 Feb 2025 01:03:27 +0000 Subject: [PATCH 64/91] ASoC: tas2764: Add reg defaults for TAS2764_INT_CLK_CFG [ Upstream commit d64c4c3d1c578f98d70db1c5e2535b47adce9d07 ] Signed-off-by: Hector Martin Signed-off-by: Mark Brown Link: https://patch.msgid.link/20250208-asoc-tas2764-v1-4-dbab892a69b5@kernel.org Signed-off-by: Mark Brown Signed-off-by: Sasha Levin --- sound/soc/codecs/tas2764.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/codecs/tas2764.c b/sound/soc/codecs/tas2764.c index 58315eab492a..bc0a73fc7ab4 100644 --- a/sound/soc/codecs/tas2764.c +++ b/sound/soc/codecs/tas2764.c @@ -634,6 +634,7 @@ static const struct reg_default tas2764_reg_defaults[] = { { TAS2764_TDM_CFG2, 0x0a }, { TAS2764_TDM_CFG3, 0x10 }, { TAS2764_TDM_CFG5, 0x42 }, + { TAS2764_INT_CLK_CFG, 0x19 }, }; static const struct regmap_range_cfg tas2764_regmap_ranges[] = { From 409c12ce79b33c15ba668b883f17d14d948d22e4 Mon Sep 17 00:00:00 2001 From: Hector Martin Date: Sat, 8 Feb 2025 01:03:26 +0000 Subject: [PATCH 65/91] ASoC: tas2764: Mark SW_RESET as volatile [ Upstream commit f37f1748564ac51d32f7588bd7bfc99913ccab8e ] Since the bit is self-clearing. Signed-off-by: Hector Martin Signed-off-by: Mark Brown Link: https://patch.msgid.link/20250208-asoc-tas2764-v1-3-dbab892a69b5@kernel.org Signed-off-by: Mark Brown Signed-off-by: Sasha Levin --- sound/soc/codecs/tas2764.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/codecs/tas2764.c b/sound/soc/codecs/tas2764.c index bc0a73fc7ab4..31f94c8cf284 100644 --- a/sound/soc/codecs/tas2764.c +++ b/sound/soc/codecs/tas2764.c @@ -652,6 +652,7 @@ static const struct regmap_range_cfg tas2764_regmap_ranges[] = { static bool tas2764_volatile_register(struct device *dev, unsigned int reg) { switch (reg) { + case TAS2764_SW_RST: case TAS2764_INT_LTCH0 ... TAS2764_INT_LTCH4: case TAS2764_INT_CLK_CFG: return true; From 2ea042779621d5f79e1049114f7be62e414722b1 Mon Sep 17 00:00:00 2001 From: Hector Martin Date: Sat, 8 Feb 2025 01:03:24 +0000 Subject: [PATCH 66/91] ASoC: tas2764: Power up/down amp on mute ops [ Upstream commit 1c3b5f37409682184669457a5bdf761268eafbe5 ] The ASoC convention is that clocks are removed after codec mute, and power up/down is more about top level power management. For these chips, the "mute" state still expects a TDM clock, and yanking the clock in this state will trigger clock errors. So, do the full shutdown<->mute<->active transition on the mute operation, so the amp is in software shutdown by the time the clocks are removed. This fixes TDM clock errors when streams are stopped. Signed-off-by: Hector Martin Signed-off-by: Mark Brown Link: https://patch.msgid.link/20250208-asoc-tas2764-v1-1-dbab892a69b5@kernel.org Signed-off-by: Mark Brown Signed-off-by: Sasha Levin --- sound/soc/codecs/tas2764.c | 51 ++++++++++++++++---------------------- 1 file changed, 21 insertions(+), 30 deletions(-) diff --git a/sound/soc/codecs/tas2764.c b/sound/soc/codecs/tas2764.c index 31f94c8cf284..39a7d39536fe 100644 --- a/sound/soc/codecs/tas2764.c +++ b/sound/soc/codecs/tas2764.c @@ -180,33 +180,6 @@ static SOC_ENUM_SINGLE_DECL( static const struct snd_kcontrol_new tas2764_asi1_mux = SOC_DAPM_ENUM("ASI1 Source", tas2764_ASI1_src_enum); -static int tas2764_dac_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); - struct tas2764_priv *tas2764 = snd_soc_component_get_drvdata(component); - int ret; - - switch (event) { - case SND_SOC_DAPM_POST_PMU: - tas2764->dac_powered = true; - ret = tas2764_update_pwr_ctrl(tas2764); - break; - case SND_SOC_DAPM_PRE_PMD: - tas2764->dac_powered = false; - ret = tas2764_update_pwr_ctrl(tas2764); - break; - default: - dev_err(tas2764->dev, "Unsupported event\n"); - return -EINVAL; - } - - if (ret < 0) - return ret; - - return 0; -} - static const struct snd_kcontrol_new isense_switch = SOC_DAPM_SINGLE("Switch", TAS2764_PWR_CTRL, TAS2764_ISENSE_POWER_EN, 1, 1); static const struct snd_kcontrol_new vsense_switch = @@ -219,8 +192,7 @@ static const struct snd_soc_dapm_widget tas2764_dapm_widgets[] = { 1, &isense_switch), SND_SOC_DAPM_SWITCH("VSENSE", TAS2764_PWR_CTRL, TAS2764_VSENSE_POWER_EN, 1, &vsense_switch), - SND_SOC_DAPM_DAC_E("DAC", NULL, SND_SOC_NOPM, 0, 0, tas2764_dac_event, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_DAC("DAC", NULL, SND_SOC_NOPM, 0, 0), SND_SOC_DAPM_OUTPUT("OUT"), SND_SOC_DAPM_SIGGEN("VMON"), SND_SOC_DAPM_SIGGEN("IMON") @@ -241,9 +213,28 @@ static int tas2764_mute(struct snd_soc_dai *dai, int mute, int direction) { struct tas2764_priv *tas2764 = snd_soc_component_get_drvdata(dai->component); + int ret; + + if (!mute) { + tas2764->dac_powered = true; + ret = tas2764_update_pwr_ctrl(tas2764); + if (ret) + return ret; + } tas2764->unmuted = !mute; - return tas2764_update_pwr_ctrl(tas2764); + ret = tas2764_update_pwr_ctrl(tas2764); + if (ret) + return ret; + + if (mute) { + tas2764->dac_powered = false; + ret = tas2764_update_pwr_ctrl(tas2764); + if (ret) + return ret; + } + + return 0; } static int tas2764_set_bitwidth(struct tas2764_priv *tas2764, int bitwidth) From c4260bf83b4296a94b272291eac66dc52cc0cc46 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 12 Feb 2025 02:24:38 +0000 Subject: [PATCH 67/91] ASoC: soc-dai: check return value at snd_soc_dai_set_tdm_slot() [ Upstream commit 7f1186a8d738661b941b298fd6d1d5725ed71428 ] snd_soc_dai_set_tdm_slot() calls .xlate_tdm_slot_mask() or snd_soc_xlate_tdm_slot_mask(), but didn't check its return value. Let's check it. This patch might break existing driver. In such case, let's makes each func to void instead of int. Signed-off-by: Kuninori Morimoto Link: https://patch.msgid.link/87o6z7yk61.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown Signed-off-by: Sasha Levin --- sound/soc/soc-dai.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index 4e08892d24c6..de09d21add45 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -275,10 +275,11 @@ int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai, if (dai->driver->ops && dai->driver->ops->xlate_tdm_slot_mask) - dai->driver->ops->xlate_tdm_slot_mask(slots, - &tx_mask, &rx_mask); + ret = dai->driver->ops->xlate_tdm_slot_mask(slots, &tx_mask, &rx_mask); else - snd_soc_xlate_tdm_slot_mask(slots, &tx_mask, &rx_mask); + ret = snd_soc_xlate_tdm_slot_mask(slots, &tx_mask, &rx_mask); + if (ret) + goto err; for_each_pcm_streams(stream) snd_soc_dai_tdm_mask_set(dai, stream, *tdm_mask[stream]); @@ -287,6 +288,7 @@ int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai, dai->driver->ops->set_tdm_slot) ret = dai->driver->ops->set_tdm_slot(dai, tx_mask, rx_mask, slots, slot_width); +err: return soc_dai_ret(dai, ret); } EXPORT_SYMBOL_GPL(snd_soc_dai_set_tdm_slot); From 5b1b4cb46d9514bec053b392d2266f00e0d6ee19 Mon Sep 17 00:00:00 2001 From: Valentin Caron Date: Thu, 16 Jan 2025 18:00:09 +0100 Subject: [PATCH 68/91] pinctrl: devicetree: do not goto err when probing hogs in pinctrl_dt_to_map [ Upstream commit c98868e816209e568c9d72023ba0bc1e4d96e611 ] Cross case in pinctrl framework make impossible to an hogged pin and another, not hogged, used within the same device-tree node. For example with this simplified device-tree : &pinctrl { pinctrl_pin_1: pinctrl-pin-1 { pins = "dummy-pinctrl-pin"; }; }; &rtc { pinctrl-names = "default" pinctrl-0 = <&pinctrl_pin_1 &rtc_pin_1> rtc_pin_1: rtc-pin-1 { pins = "dummy-rtc-pin"; }; }; "pinctrl_pin_1" configuration is never set. This produces this path in the code: really_probe() pinctrl_bind_pins() | devm_pinctrl_get() | pinctrl_get() | create_pinctrl() | pinctrl_dt_to_map() | // Hog pin create an abort for all pins of the node | ret = dt_to_map_one_config() | | /* Do not defer probing of hogs (circular loop) */ | | if (np_pctldev == p->dev->of_node) | | return -ENODEV; | if (ret) | goto err | call_driver_probe() stm32_rtc_probe() pinctrl_enable() pinctrl_claim_hogs() create_pinctrl() for_each_maps(maps_node, i, map) // Not hog pin is skipped if (pctldev && strcmp(dev_name(pctldev->dev), map->ctrl_dev_name)) continue; At the first call of create_pinctrl() the hogged pin produces an abort to avoid a defer of hogged pins. All other pin configurations are trashed. At the second call, create_pinctrl is now called with pctldev parameter to get hogs, but in this context only hogs are set. And other pins are skipped. To handle this, do not produce an abort in the first call of create_pinctrl(). Classic pin configuration will be set in pinctrl_bind_pins() context. And the hogged pin configuration will be set in pinctrl_claim_hogs() context. Signed-off-by: Valentin Caron Link: https://lore.kernel.org/20250116170009.2075544-1-valentin.caron@foss.st.com Signed-off-by: Linus Walleij Signed-off-by: Sasha Levin --- drivers/pinctrl/devicetree.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/pinctrl/devicetree.c b/drivers/pinctrl/devicetree.c index 6a94ecd6a8de..0b7f74beb6a6 100644 --- a/drivers/pinctrl/devicetree.c +++ b/drivers/pinctrl/devicetree.c @@ -143,10 +143,14 @@ static int dt_to_map_one_config(struct pinctrl *p, pctldev = get_pinctrl_dev_from_of_node(np_pctldev); if (pctldev) break; - /* Do not defer probing of hogs (circular loop) */ + /* + * Do not defer probing of hogs (circular loop) + * + * Return 1 to let the caller catch the case. + */ if (np_pctldev == p->dev->of_node) { of_node_put(np_pctldev); - return -ENODEV; + return 1; } } of_node_put(np_pctldev); @@ -265,6 +269,8 @@ int pinctrl_dt_to_map(struct pinctrl *p, struct pinctrl_dev *pctldev) ret = dt_to_map_one_config(p, pctldev, statename, np_config); of_node_put(np_config); + if (ret == 1) + continue; if (ret < 0) goto err; } From 316f2911fb11aedee07d047feb958bfb7416159e Mon Sep 17 00:00:00 2001 From: Konstantin Andreev Date: Fri, 17 Jan 2025 02:40:34 +0300 Subject: [PATCH 69/91] smack: recognize ipv4 CIPSO w/o categories [ Upstream commit a158a937d864d0034fea14913c1f09c6d5f574b8 ] If SMACK label has CIPSO representation w/o categories, e.g.: | # cat /smack/cipso2 | foo 10 | @ 250/2 | ... then SMACK does not recognize such CIPSO in input ipv4 packets and substitues '*' label instead. Audit records may look like | lsm=SMACK fn=smack_socket_sock_rcv_skb action=denied | subject="*" object="_" requested=w pid=0 comm="swapper/1" ... This happens in two steps: 1) security/smack/smackfs.c`smk_set_cipso does not clear NETLBL_SECATTR_MLS_CAT from (struct smack_known *)skp->smk_netlabel.flags on assigning CIPSO w/o categories: | rcu_assign_pointer(skp->smk_netlabel.attr.mls.cat, ncats.attr.mls.cat); | skp->smk_netlabel.attr.mls.lvl = ncats.attr.mls.lvl; 2) security/smack/smack_lsm.c`smack_from_secattr can not match skp->smk_netlabel with input packet's struct netlbl_lsm_secattr *sap because sap->flags have not NETLBL_SECATTR_MLS_CAT (what is correct) but skp->smk_netlabel.flags have (what is incorrect): | if ((sap->flags & NETLBL_SECATTR_MLS_CAT) == 0) { | if ((skp->smk_netlabel.flags & | NETLBL_SECATTR_MLS_CAT) == 0) | found = 1; | break; | } This commit sets/clears NETLBL_SECATTR_MLS_CAT in skp->smk_netlabel.flags according to the presense of CIPSO categories. The update of smk_netlabel is not atomic, so input packets processing still may be incorrect during short time while update proceeds. Signed-off-by: Konstantin Andreev Signed-off-by: Casey Schaufler Signed-off-by: Sasha Levin --- security/smack/smackfs.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c index 5dd1e164f9b1..d27e8b916bfb 100644 --- a/security/smack/smackfs.c +++ b/security/smack/smackfs.c @@ -933,6 +933,10 @@ static ssize_t smk_set_cipso(struct file *file, const char __user *buf, if (rc >= 0) { old_cat = skp->smk_netlabel.attr.mls.cat; rcu_assign_pointer(skp->smk_netlabel.attr.mls.cat, ncats.attr.mls.cat); + if (ncats.attr.mls.cat) + skp->smk_netlabel.flags |= NETLBL_SECATTR_MLS_CAT; + else + skp->smk_netlabel.flags &= ~(u32)NETLBL_SECATTR_MLS_CAT; skp->smk_netlabel.attr.mls.lvl = ncats.attr.mls.lvl; synchronize_rcu(); netlbl_catmap_free(old_cat); From 8f5ce688c8318e4a68ccb235495a183286a49b79 Mon Sep 17 00:00:00 2001 From: Konstantin Andreev Date: Fri, 17 Jan 2025 02:40:33 +0300 Subject: [PATCH 70/91] smack: Revert "smackfs: Added check catlen" [ Upstream commit c7fb50cecff9cad19fdac5b37337eae4e42b94c7 ] This reverts commit ccfd889acb06eab10b98deb4b5eef0ec74157ea0 The indicated commit * does not describe the problem that change tries to solve * has programming issues * introduces a bug: forever clears NETLBL_SECATTR_MLS_CAT in (struct smack_known *)skp->smk_netlabel.flags Reverting the commit to reapproach original problem Signed-off-by: Konstantin Andreev Signed-off-by: Casey Schaufler Signed-off-by: Sasha Levin --- security/smack/smackfs.c | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c index d27e8b916bfb..1e35c9f807b2 100644 --- a/security/smack/smackfs.c +++ b/security/smack/smackfs.c @@ -830,7 +830,7 @@ static int smk_open_cipso(struct inode *inode, struct file *file) static ssize_t smk_set_cipso(struct file *file, const char __user *buf, size_t count, loff_t *ppos, int format) { - struct netlbl_lsm_catmap *old_cat, *new_cat = NULL; + struct netlbl_lsm_catmap *old_cat; struct smack_known *skp; struct netlbl_lsm_secattr ncats; char mapcatset[SMK_CIPSOLEN]; @@ -917,19 +917,8 @@ static ssize_t smk_set_cipso(struct file *file, const char __user *buf, smack_catset_bit(cat, mapcatset); } - ncats.flags = 0; - if (catlen == 0) { - ncats.attr.mls.cat = NULL; - ncats.attr.mls.lvl = maplevel; - new_cat = netlbl_catmap_alloc(GFP_ATOMIC); - if (new_cat) - new_cat->next = ncats.attr.mls.cat; - ncats.attr.mls.cat = new_cat; - skp->smk_netlabel.flags &= ~(1U << 3); - rc = 0; - } else { - rc = smk_netlbl_mls(maplevel, mapcatset, &ncats, SMK_CIPSOLEN); - } + + rc = smk_netlbl_mls(maplevel, mapcatset, &ncats, SMK_CIPSOLEN); if (rc >= 0) { old_cat = skp->smk_netlabel.attr.mls.cat; rcu_assign_pointer(skp->smk_netlabel.attr.mls.cat, ncats.attr.mls.cat); From 12aeff4944dc6263d1e5b00001097ff40aed9180 Mon Sep 17 00:00:00 2001 From: Brendan Jackman Date: Fri, 24 Jan 2025 11:01:42 +0000 Subject: [PATCH 71/91] kunit: tool: Use qboot on QEMU x86_64 [ Upstream commit 08fafac4c9f289a9d9a22d838921e4b3eb22c664 ] As noted in [0], SeaBIOS (QEMU default) makes a mess of the terminal, qboot does not. It turns out this is actually useful with kunit.py, since the user is exposed to this issue if they set --raw_output=all. qboot is also faster than SeaBIOS, but it's is marginal for this usecase. [0] https://lore.kernel.org/all/CA+i-1C0wYb-gZ8Mwh3WSVpbk-LF-Uo+njVbASJPe1WXDURoV7A@mail.gmail.com/ Both SeaBIOS and qboot are x86-specific. Link: https://lore.kernel.org/r/20250124-kunit-qboot-v1-1-815e4d4c6f7c@google.com Signed-off-by: Brendan Jackman Reviewed-by: David Gow Signed-off-by: Shuah Khan Signed-off-by: Sasha Levin --- tools/testing/kunit/qemu_configs/x86_64.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/testing/kunit/qemu_configs/x86_64.py b/tools/testing/kunit/qemu_configs/x86_64.py index dc7949076863..4a6bf4e048f5 100644 --- a/tools/testing/kunit/qemu_configs/x86_64.py +++ b/tools/testing/kunit/qemu_configs/x86_64.py @@ -7,4 +7,6 @@ CONFIG_SERIAL_8250_CONSOLE=y''', qemu_arch='x86_64', kernel_path='arch/x86/boot/bzImage', kernel_command_line='console=ttyS0', - extra_qemu_params=[]) + # qboot is faster than SeaBIOS and doesn't mess up + # the terminal. + extra_qemu_params=['-bios', 'qboot.rom']) From 9a981079097bee6a0583877798de0b240717bdde Mon Sep 17 00:00:00 2001 From: David Plowman Date: Tue, 4 Feb 2025 12:34:36 +0530 Subject: [PATCH 72/91] media: i2c: imx219: Correct the minimum vblanking value [ Upstream commit e3b82d49bf676f3c873e642038765eac32ab6d39 ] The datasheet for this sensor documents the minimum vblanking as being 32 lines. It does fix some problems with occasional black lines at the bottom of images (tested on Raspberry Pi). Signed-off-by: David Plowman Reviewed-by: Jacopo Mondi Reviewed-by: Dave Stevenson Signed-off-by: Jai Luthra Signed-off-by: Sakari Ailus Signed-off-by: Hans Verkuil Signed-off-by: Sasha Levin --- drivers/media/i2c/imx219.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/i2c/imx219.c b/drivers/media/i2c/imx219.c index 906aa314b7f8..eaa1496c71bb 100644 --- a/drivers/media/i2c/imx219.c +++ b/drivers/media/i2c/imx219.c @@ -74,7 +74,7 @@ #define IMX219_REG_VTS CCI_REG16(0x0160) #define IMX219_VTS_MAX 0xffff -#define IMX219_VBLANK_MIN 4 +#define IMX219_VBLANK_MIN 32 /* HBLANK control - read only */ #define IMX219_PPL_DEFAULT 3448 From 69689d1138c85f5a46485289d0691bdc95c91e00 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Mon, 16 Dec 2024 10:48:49 +0200 Subject: [PATCH 73/91] media: v4l: Memset argument to 0 before calling get_mbus_config pad op [ Upstream commit 91d6a99acfa5ce9f95ede775074b80f7193bd717 ] Memset the config argument to get_mbus_config V4L2 sub-device pad operation to zero before calling the operation. This ensures the callers don't need to bother with it nor the implementations need to set all fields that may not be relevant to them. Signed-off-by: Sakari Ailus Reviewed-by: Tomi Valkeinen Signed-off-by: Hans Verkuil Signed-off-by: Sasha Levin --- drivers/media/v4l2-core/v4l2-subdev.c | 2 ++ include/media/v4l2-subdev.h | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c index 3a4ba08810d2..1193852bad59 100644 --- a/drivers/media/v4l2-core/v4l2-subdev.c +++ b/drivers/media/v4l2-core/v4l2-subdev.c @@ -439,6 +439,8 @@ static int call_enum_dv_timings(struct v4l2_subdev *sd, static int call_get_mbus_config(struct v4l2_subdev *sd, unsigned int pad, struct v4l2_mbus_config *config) { + memset(config, 0, sizeof(*config)); + return check_pad(sd, pad) ? : sd->ops->pad->get_mbus_config(sd, pad, config); } diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index 8daa0929865c..43343f1586d1 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -821,7 +821,9 @@ struct v4l2_subdev_state { * possible configuration from the remote end, likely calling * this operation as close as possible to stream on time. The * operation shall fail if the pad index it has been called on - * is not valid or in case of unrecoverable failures. + * is not valid or in case of unrecoverable failures. The + * config argument has been memset to 0 just before calling + * the op. * * @set_routing: Enable or disable data connection routes described in the * subdevice routing table. Subdevs that implement this operation From 50c5bbb45c7dfea22c566c75ca62e306848f18ba Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Mon, 10 Feb 2025 09:45:05 -0800 Subject: [PATCH 74/91] net/mlx4_core: Avoid impossible mlx4_db_alloc() order value [ Upstream commit 4a6f18f28627e121bd1f74b5fcc9f945d6dbeb1e ] GCC can see that the value range for "order" is capped, but this leads it to consider that it might be negative, leading to a false positive warning (with GCC 15 with -Warray-bounds -fdiagnostics-details): ../drivers/net/ethernet/mellanox/mlx4/alloc.c:691:47: error: array subscript -1 is below array bounds of 'long unsigned int *[2]' [-Werror=array-bounds=] 691 | i = find_first_bit(pgdir->bits[o], MLX4_DB_PER_PAGE >> o); | ~~~~~~~~~~~^~~ 'mlx4_alloc_db_from_pgdir': events 1-2 691 | i = find_first_bit(pgdir->bits[o], MLX4_DB_PER_PAGE >> o); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | | | | | (2) out of array bounds here | (1) when the condition is evaluated to true In file included from ../drivers/net/ethernet/mellanox/mlx4/mlx4.h:53, from ../drivers/net/ethernet/mellanox/mlx4/alloc.c:42: ../include/linux/mlx4/device.h:664:33: note: while referencing 'bits' 664 | unsigned long *bits[2]; | ^~~~ Switch the argument to unsigned int, which removes the compiler needing to consider negative values. Signed-off-by: Kees Cook Link: https://patch.msgid.link/20250210174504.work.075-kees@kernel.org Signed-off-by: Jakub Kicinski Signed-off-by: Sasha Levin --- drivers/net/ethernet/mellanox/mlx4/alloc.c | 6 +++--- include/linux/mlx4/device.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx4/alloc.c b/drivers/net/ethernet/mellanox/mlx4/alloc.c index b330020dc0d6..f2bded847e61 100644 --- a/drivers/net/ethernet/mellanox/mlx4/alloc.c +++ b/drivers/net/ethernet/mellanox/mlx4/alloc.c @@ -682,9 +682,9 @@ static struct mlx4_db_pgdir *mlx4_alloc_db_pgdir(struct device *dma_device) } static int mlx4_alloc_db_from_pgdir(struct mlx4_db_pgdir *pgdir, - struct mlx4_db *db, int order) + struct mlx4_db *db, unsigned int order) { - int o; + unsigned int o; int i; for (o = order; o <= 1; ++o) { @@ -712,7 +712,7 @@ found: return 0; } -int mlx4_db_alloc(struct mlx4_dev *dev, struct mlx4_db *db, int order) +int mlx4_db_alloc(struct mlx4_dev *dev, struct mlx4_db *db, unsigned int order) { struct mlx4_priv *priv = mlx4_priv(dev); struct mlx4_db_pgdir *pgdir; diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h index 27f42f713c89..86f0f2a25a3d 100644 --- a/include/linux/mlx4/device.h +++ b/include/linux/mlx4/device.h @@ -1135,7 +1135,7 @@ int mlx4_write_mtt(struct mlx4_dev *dev, struct mlx4_mtt *mtt, int mlx4_buf_write_mtt(struct mlx4_dev *dev, struct mlx4_mtt *mtt, struct mlx4_buf *buf); -int mlx4_db_alloc(struct mlx4_dev *dev, struct mlx4_db *db, int order); +int mlx4_db_alloc(struct mlx4_dev *dev, struct mlx4_db *db, unsigned int order); void mlx4_db_free(struct mlx4_dev *dev, struct mlx4_db *db); int mlx4_alloc_hwq_res(struct mlx4_dev *dev, struct mlx4_hwq_resources *wqres, From 884d64e8e4dc6d4f1b0f69c31e4b4eadaf735648 Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Thu, 13 Feb 2025 11:29:01 -0800 Subject: [PATCH 75/91] drm/xe: Stop ignoring errors from xe_ttm_stolen_mgr_init() [ Upstream commit ff57025c358603555f1e0ae0d50282a460433594 ] Make sure to differentiate normal behavior, e.g. there's no stolen, from allocation errors or failure to initialize lower layers. Reviewed-by: Francois Dugast Reviewed-by: Himal Prasad Ghimiray Link: https://patchwork.freedesktop.org/patch/msgid/20250213192909.996148-5-lucas.demarchi@intel.com Signed-off-by: Lucas De Marchi Signed-off-by: Sasha Levin --- drivers/gpu/drm/xe/xe_device.c | 4 +++- drivers/gpu/drm/xe/xe_ttm_stolen_mgr.c | 17 +++++++++-------- drivers/gpu/drm/xe/xe_ttm_stolen_mgr.h | 2 +- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c index bb85208cf1a9..5c37bed3c948 100644 --- a/drivers/gpu/drm/xe/xe_device.c +++ b/drivers/gpu/drm/xe/xe_device.c @@ -694,7 +694,9 @@ int xe_device_probe(struct xe_device *xe) } /* Allocate and map stolen after potential VRAM resize */ - xe_ttm_stolen_mgr_init(xe); + err = xe_ttm_stolen_mgr_init(xe); + if (err) + return err; /* * Now that GT is initialized (TTM in particular), diff --git a/drivers/gpu/drm/xe/xe_ttm_stolen_mgr.c b/drivers/gpu/drm/xe/xe_ttm_stolen_mgr.c index f7113cf6109d..ef84fa757b26 100644 --- a/drivers/gpu/drm/xe/xe_ttm_stolen_mgr.c +++ b/drivers/gpu/drm/xe/xe_ttm_stolen_mgr.c @@ -201,17 +201,16 @@ static u64 detect_stolen(struct xe_device *xe, struct xe_ttm_stolen_mgr *mgr) #endif } -void xe_ttm_stolen_mgr_init(struct xe_device *xe) +int xe_ttm_stolen_mgr_init(struct xe_device *xe) { - struct xe_ttm_stolen_mgr *mgr = drmm_kzalloc(&xe->drm, sizeof(*mgr), GFP_KERNEL); struct pci_dev *pdev = to_pci_dev(xe->drm.dev); + struct xe_ttm_stolen_mgr *mgr; u64 stolen_size, io_size; int err; - if (!mgr) { - drm_dbg_kms(&xe->drm, "Stolen mgr init failed\n"); - return; - } + mgr = drmm_kzalloc(&xe->drm, sizeof(*mgr), GFP_KERNEL); + if (!mgr) + return -ENOMEM; if (IS_SRIOV_VF(xe)) stolen_size = 0; @@ -224,7 +223,7 @@ void xe_ttm_stolen_mgr_init(struct xe_device *xe) if (!stolen_size) { drm_dbg_kms(&xe->drm, "No stolen memory support\n"); - return; + return 0; } /* @@ -240,7 +239,7 @@ void xe_ttm_stolen_mgr_init(struct xe_device *xe) io_size, PAGE_SIZE); if (err) { drm_dbg_kms(&xe->drm, "Stolen mgr init failed: %i\n", err); - return; + return err; } drm_dbg_kms(&xe->drm, "Initialized stolen memory support with %llu bytes\n", @@ -248,6 +247,8 @@ void xe_ttm_stolen_mgr_init(struct xe_device *xe) if (io_size) mgr->mapping = devm_ioremap_wc(&pdev->dev, mgr->io_base, io_size); + + return 0; } u64 xe_ttm_stolen_io_offset(struct xe_bo *bo, u32 offset) diff --git a/drivers/gpu/drm/xe/xe_ttm_stolen_mgr.h b/drivers/gpu/drm/xe/xe_ttm_stolen_mgr.h index 1777245ff810..8e877d1e839b 100644 --- a/drivers/gpu/drm/xe/xe_ttm_stolen_mgr.h +++ b/drivers/gpu/drm/xe/xe_ttm_stolen_mgr.h @@ -12,7 +12,7 @@ struct ttm_resource; struct xe_bo; struct xe_device; -void xe_ttm_stolen_mgr_init(struct xe_device *xe); +int xe_ttm_stolen_mgr_init(struct xe_device *xe); int xe_ttm_stolen_io_mem_reserve(struct xe_device *xe, struct ttm_resource *mem); bool xe_ttm_stolen_cpu_access_needs_ggtt(struct xe_device *xe); u64 xe_ttm_stolen_io_offset(struct xe_bo *bo, u32 offset); From 01d28e67f567bcb0aa0533a4b805370131ffc4f4 Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Thu, 13 Feb 2025 11:29:00 -0800 Subject: [PATCH 76/91] drm/xe: Fix xe_tile_init_noalloc() error propagation [ Upstream commit 0bcf41171c64234e79eb3552d00f0aad8a47e8d3 ] Propagate the error to the caller so initialization properly stops if sysfs creation fails. Reviewed-by: Francois Dugast Reviewed-by: Himal Prasad Ghimiray Link: https://patchwork.freedesktop.org/patch/msgid/20250213192909.996148-4-lucas.demarchi@intel.com Signed-off-by: Lucas De Marchi Signed-off-by: Sasha Levin --- drivers/gpu/drm/xe/xe_tile.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_tile.c b/drivers/gpu/drm/xe/xe_tile.c index dda5268507d8..349beddf9b38 100644 --- a/drivers/gpu/drm/xe/xe_tile.c +++ b/drivers/gpu/drm/xe/xe_tile.c @@ -173,9 +173,7 @@ int xe_tile_init_noalloc(struct xe_tile *tile) xe_wa_apply_tile_workarounds(tile); - err = xe_tile_sysfs_init(tile); - - return 0; + return xe_tile_sysfs_init(tile); } void xe_tile_migrate_wait(struct xe_tile *tile) From 328a2ec198e70f2a3eae206a2718468602a178db Mon Sep 17 00:00:00 2001 From: Karl Chan Date: Tue, 8 Oct 2024 00:34:12 +0800 Subject: [PATCH 77/91] clk: qcom: ipq5018: allow it to be bulid on arm32 [ Upstream commit 5d02941c83997b58e8fc15390290c7c6975acaff ] There are some ipq5018 based device's firmware only can able to boot arm32 but the clock driver dont allow it to be compiled on arm32. Therefore allow GCC for IPQ5018 to be selected when building ARM32 kernel Signed-off-by: Karl Chan Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20241007163414.32458-4-exxxxkc@getgoogleoff.me [bjorn: Updated commit message, per Dmitry's suggestion] Signed-off-by: Bjorn Andersson Signed-off-by: Sasha Levin --- drivers/clk/qcom/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index 16145f74bbc8..fd605bccf48d 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -199,7 +199,7 @@ config IPQ_GCC_4019 config IPQ_GCC_5018 tristate "IPQ5018 Global Clock Controller" - depends on ARM64 || COMPILE_TEST + depends on ARM || ARM64 || COMPILE_TEST help Support for global clock controller on ipq5018 devices. Say Y if you want to use peripheral devices such as UART, SPI, From 6469a2b1140d0be363b72dfafe0fc0bbc9504493 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 12 Feb 2025 21:01:35 +0100 Subject: [PATCH 78/91] clk: qcom: clk-alpha-pll: Do not use random stack value for recalc rate [ Upstream commit 7a243e1b814a02ab40793026ef64223155d86395 ] If regmap_read() fails, random stack value was used in calculating new frequency in recalc_rate() callbacks. Such failure is really not expected as these are all MMIO reads, however code should be here correct and bail out. This also avoids possible warning on uninitialized value. Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20250212-b4-clk-qcom-clean-v3-1-499f37444f5d@linaro.org Signed-off-by: Bjorn Andersson Signed-off-by: Sasha Levin --- drivers/clk/qcom/clk-alpha-pll.c | 52 ++++++++++++++++++++++---------- 1 file changed, 36 insertions(+), 16 deletions(-) diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c index 10e276dabff9..e76ecc466351 100644 --- a/drivers/clk/qcom/clk-alpha-pll.c +++ b/drivers/clk/qcom/clk-alpha-pll.c @@ -670,14 +670,19 @@ clk_alpha_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); u32 alpha_width = pll_alpha_width(pll); - regmap_read(pll->clkr.regmap, PLL_L_VAL(pll), &l); + if (regmap_read(pll->clkr.regmap, PLL_L_VAL(pll), &l)) + return 0; + + if (regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &ctl)) + return 0; - regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &ctl); if (ctl & PLL_ALPHA_EN) { - regmap_read(pll->clkr.regmap, PLL_ALPHA_VAL(pll), &low); + if (regmap_read(pll->clkr.regmap, PLL_ALPHA_VAL(pll), &low)) + return 0; if (alpha_width > 32) { - regmap_read(pll->clkr.regmap, PLL_ALPHA_VAL_U(pll), - &high); + if (regmap_read(pll->clkr.regmap, PLL_ALPHA_VAL_U(pll), + &high)) + return 0; a = (u64)high << 32 | low; } else { a = low & GENMASK(alpha_width - 1, 0); @@ -903,8 +908,11 @@ alpha_pll_huayra_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); u32 l, alpha = 0, ctl, alpha_m, alpha_n; - regmap_read(pll->clkr.regmap, PLL_L_VAL(pll), &l); - regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &ctl); + if (regmap_read(pll->clkr.regmap, PLL_L_VAL(pll), &l)) + return 0; + + if (regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &ctl)) + return 0; if (ctl & PLL_ALPHA_EN) { regmap_read(pll->clkr.regmap, PLL_ALPHA_VAL(pll), &alpha); @@ -1098,8 +1106,11 @@ clk_trion_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); u32 l, frac, alpha_width = pll_alpha_width(pll); - regmap_read(pll->clkr.regmap, PLL_L_VAL(pll), &l); - regmap_read(pll->clkr.regmap, PLL_ALPHA_VAL(pll), &frac); + if (regmap_read(pll->clkr.regmap, PLL_L_VAL(pll), &l)) + return 0; + + if (regmap_read(pll->clkr.regmap, PLL_ALPHA_VAL(pll), &frac)) + return 0; return alpha_pll_calc_rate(parent_rate, l, frac, alpha_width); } @@ -1157,7 +1168,8 @@ clk_alpha_pll_postdiv_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw); u32 ctl; - regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &ctl); + if (regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &ctl)) + return 0; ctl >>= PLL_POST_DIV_SHIFT; ctl &= PLL_POST_DIV_MASK(pll); @@ -1373,8 +1385,11 @@ static unsigned long alpha_pll_fabia_recalc_rate(struct clk_hw *hw, struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); u32 l, frac, alpha_width = pll_alpha_width(pll); - regmap_read(pll->clkr.regmap, PLL_L_VAL(pll), &l); - regmap_read(pll->clkr.regmap, PLL_FRAC(pll), &frac); + if (regmap_read(pll->clkr.regmap, PLL_L_VAL(pll), &l)) + return 0; + + if (regmap_read(pll->clkr.regmap, PLL_FRAC(pll), &frac)) + return 0; return alpha_pll_calc_rate(parent_rate, l, frac, alpha_width); } @@ -1524,7 +1539,8 @@ clk_trion_pll_postdiv_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) struct regmap *regmap = pll->clkr.regmap; u32 i, div = 1, val; - regmap_read(regmap, PLL_USER_CTL(pll), &val); + if (regmap_read(regmap, PLL_USER_CTL(pll), &val)) + return 0; val >>= pll->post_div_shift; val &= PLL_POST_DIV_MASK(pll); @@ -2451,9 +2467,12 @@ static unsigned long alpha_pll_lucid_evo_recalc_rate(struct clk_hw *hw, struct regmap *regmap = pll->clkr.regmap; u32 l, frac; - regmap_read(regmap, PLL_L_VAL(pll), &l); + if (regmap_read(regmap, PLL_L_VAL(pll), &l)) + return 0; l &= LUCID_EVO_PLL_L_VAL_MASK; - regmap_read(regmap, PLL_ALPHA_VAL(pll), &frac); + + if (regmap_read(regmap, PLL_ALPHA_VAL(pll), &frac)) + return 0; return alpha_pll_calc_rate(parent_rate, l, frac, pll_alpha_width(pll)); } @@ -2528,7 +2547,8 @@ static unsigned long clk_rivian_evo_pll_recalc_rate(struct clk_hw *hw, struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); u32 l; - regmap_read(pll->clkr.regmap, PLL_L_VAL(pll), &l); + if (regmap_read(pll->clkr.regmap, PLL_L_VAL(pll), &l)) + return 0; return parent_rate * l; } From cf126a14584e5f49647824d4b266567359f0e297 Mon Sep 17 00:00:00 2001 From: Xin Wang Date: Fri, 14 Feb 2025 06:36:15 +0800 Subject: [PATCH 79/91] drm/xe/debugfs: fixed the return value of wedged_mode_set [ Upstream commit 6884d2051011f4db9e2f0b85709c79a8ced13bd6 ] It is generally expected that the write() function should return a positive value indicating the number of bytes written or a negative error code if an error occurs. Returning 0 is unusual and can lead to unexpected behavior. When the user program writes the same value to wedged_mode twice in a row, a lockup will occur, because the value expected to be returned by the write() function inside the program should be equal to the actual written value instead of 0. To reproduce the issue: echo 1 > /sys/kernel/debug/dri/0/wedged_mode echo 1 > /sys/kernel/debug/dri/0/wedged_mode <- lockup here Signed-off-by: Xin Wang Cc: Rodrigo Vivi Cc: Fei Yang Cc: Shuicheng Lin Reviewed-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20250213223615.2327367-1-x.wang@intel.com Signed-off-by: Rodrigo Vivi Signed-off-by: Sasha Levin --- drivers/gpu/drm/xe/xe_debugfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/xe/xe_debugfs.c b/drivers/gpu/drm/xe/xe_debugfs.c index fe4319eb13fd..051a37e477f4 100644 --- a/drivers/gpu/drm/xe/xe_debugfs.c +++ b/drivers/gpu/drm/xe/xe_debugfs.c @@ -147,7 +147,7 @@ static ssize_t wedged_mode_set(struct file *f, const char __user *ubuf, return -EINVAL; if (xe->wedged.mode == wedged_mode) - return 0; + return size; xe->wedged.mode = wedged_mode; From b870651021223b127efe51b11772b0078a7a49fe Mon Sep 17 00:00:00 2001 From: Shuicheng Lin Date: Thu, 13 Feb 2025 23:03:22 +0000 Subject: [PATCH 80/91] drm/xe/debugfs: Add missing xe_pm_runtime_put in wedge_mode_set [ Upstream commit b31e668d3111b100d16fd7db8db335328ce8c6d5 ] xe_pm_runtime_put is missed in the failure path. Cc: Rodrigo Vivi Signed-off-by: Shuicheng Lin Reviewed-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20250213230322.1180621-1-shuicheng.lin@intel.com Signed-off-by: Rodrigo Vivi Signed-off-by: Sasha Levin --- drivers/gpu/drm/xe/xe_debugfs.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/xe/xe_debugfs.c b/drivers/gpu/drm/xe/xe_debugfs.c index 051a37e477f4..278ce1c37b39 100644 --- a/drivers/gpu/drm/xe/xe_debugfs.c +++ b/drivers/gpu/drm/xe/xe_debugfs.c @@ -156,6 +156,7 @@ static ssize_t wedged_mode_set(struct file *f, const char __user *ubuf, ret = xe_guc_ads_scheduler_policy_toggle_reset(>->uc.guc.ads); if (ret) { xe_gt_err(gt, "Failed to update GuC ADS scheduler policy. GuC may still cause engine reset even with wedged_mode=2\n"); + xe_pm_runtime_put(xe); return -EIO; } } From eb6fd16b4fc4feb370c68ec17b59f6078f276a51 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Thu, 13 Feb 2025 12:45:47 +0100 Subject: [PATCH 81/91] x86/ibt: Handle FineIBT in handle_cfi_failure() [ Upstream commit 882b86fd4e0d49bf91148dbadcdbece19ded40e6 ] Sami reminded me that FineIBT failure does not hook into the regular CFI failure case, and as such CFI_PERMISSIVE does not work. Reported-by: Sami Tolvanen Signed-off-by: Peter Zijlstra (Intel) Reviewed-by: Sami Tolvanen Link: https://lkml.kernel.org/r/20250214092619.GB21726@noisy.programming.kicks-ass.net Signed-off-by: Sasha Levin --- arch/x86/include/asm/cfi.h | 11 +++++++++++ arch/x86/kernel/alternative.c | 30 ++++++++++++++++++++++++++++++ arch/x86/kernel/cfi.c | 22 ++++++++++++++++++---- 3 files changed, 59 insertions(+), 4 deletions(-) diff --git a/arch/x86/include/asm/cfi.h b/arch/x86/include/asm/cfi.h index 31d19c815f99..7dd5ab239c87 100644 --- a/arch/x86/include/asm/cfi.h +++ b/arch/x86/include/asm/cfi.h @@ -126,6 +126,17 @@ static inline int cfi_get_offset(void) extern u32 cfi_get_func_hash(void *func); +#ifdef CONFIG_FINEIBT +extern bool decode_fineibt_insn(struct pt_regs *regs, unsigned long *target, u32 *type); +#else +static inline bool +decode_fineibt_insn(struct pt_regs *regs, unsigned long *target, u32 *type) +{ + return false; +} + +#endif + #else static inline enum bug_trap_type handle_cfi_failure(struct pt_regs *regs) { diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c index 66e77bd7d511..6ab96bc764cf 100644 --- a/arch/x86/kernel/alternative.c +++ b/arch/x86/kernel/alternative.c @@ -1254,6 +1254,7 @@ asm( ".pushsection .rodata \n" " endbr64 \n" " subl $0x12345678, %r10d \n" " je fineibt_preamble_end \n" + "fineibt_preamble_ud2: \n" " ud2 \n" " nop \n" "fineibt_preamble_end: \n" @@ -1261,9 +1262,11 @@ asm( ".pushsection .rodata \n" ); extern u8 fineibt_preamble_start[]; +extern u8 fineibt_preamble_ud2[]; extern u8 fineibt_preamble_end[]; #define fineibt_preamble_size (fineibt_preamble_end - fineibt_preamble_start) +#define fineibt_preamble_ud2 (fineibt_preamble_ud2 - fineibt_preamble_start) #define fineibt_preamble_hash 7 asm( ".pushsection .rodata \n" @@ -1568,6 +1571,33 @@ static void poison_cfi(void *addr) } } +/* + * regs->ip points to a UD2 instruction, return true and fill out target and + * type when this UD2 is from a FineIBT preamble. + * + * We check the preamble by checking for the ENDBR instruction relative to the + * UD2 instruction. + */ +bool decode_fineibt_insn(struct pt_regs *regs, unsigned long *target, u32 *type) +{ + unsigned long addr = regs->ip - fineibt_preamble_ud2; + u32 endbr, hash; + + __get_kernel_nofault(&endbr, addr, u32, Efault); + if (endbr != gen_endbr()) + return false; + + *target = addr + fineibt_preamble_size; + + __get_kernel_nofault(&hash, addr + fineibt_preamble_hash, u32, Efault); + *type = (u32)regs->r10 + hash; + + return true; + +Efault: + return false; +} + #else static void __apply_fineibt(s32 *start_retpoline, s32 *end_retpoline, diff --git a/arch/x86/kernel/cfi.c b/arch/x86/kernel/cfi.c index e6bf78fac146..f6905bef0af8 100644 --- a/arch/x86/kernel/cfi.c +++ b/arch/x86/kernel/cfi.c @@ -70,11 +70,25 @@ enum bug_trap_type handle_cfi_failure(struct pt_regs *regs) unsigned long target; u32 type; - if (!is_cfi_trap(regs->ip)) - return BUG_TRAP_TYPE_NONE; + switch (cfi_mode) { + case CFI_KCFI: + if (!is_cfi_trap(regs->ip)) + return BUG_TRAP_TYPE_NONE; - if (!decode_cfi_insn(regs, &target, &type)) - return report_cfi_failure_noaddr(regs, regs->ip); + if (!decode_cfi_insn(regs, &target, &type)) + return report_cfi_failure_noaddr(regs, regs->ip); + + break; + + case CFI_FINEIBT: + if (!decode_fineibt_insn(regs, &target, &type)) + return BUG_TRAP_TYPE_NONE; + + break; + + default: + return BUG_TRAP_TYPE_NONE; + } return report_cfi_failure(regs, regs->ip, &target, type); } From 9c5f85b72fa6d285c91e7d867b4c3643a6952efb Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Fri, 7 Feb 2025 13:15:36 +0100 Subject: [PATCH 82/91] x86/traps: Cleanup and robustify decode_bug() [ Upstream commit c20ad96c9a8f0aeaf4e4057730a22de2657ad0c2 ] Notably, don't attempt to decode an immediate when MOD == 3. Additionally have it return the instruction length, such that WARN like bugs can more reliably skip to the correct instruction. Signed-off-by: Peter Zijlstra (Intel) Reviewed-by: Sami Tolvanen Link: https://lore.kernel.org/r/20250207122546.721120726@infradead.org Signed-off-by: Sasha Levin --- arch/x86/include/asm/bug.h | 5 ++- arch/x86/include/asm/ibt.h | 4 +- arch/x86/kernel/traps.c | 82 ++++++++++++++++++++++++++++---------- 3 files changed, 65 insertions(+), 26 deletions(-) diff --git a/arch/x86/include/asm/bug.h b/arch/x86/include/asm/bug.h index 806649c7f23d..9a0f29be1a9e 100644 --- a/arch/x86/include/asm/bug.h +++ b/arch/x86/include/asm/bug.h @@ -22,8 +22,9 @@ #define SECOND_BYTE_OPCODE_UD2 0x0b #define BUG_NONE 0xffff -#define BUG_UD1 0xfffe -#define BUG_UD2 0xfffd +#define BUG_UD2 0xfffe +#define BUG_UD1 0xfffd +#define BUG_UD1_UBSAN 0xfffc #ifdef CONFIG_GENERIC_BUG diff --git a/arch/x86/include/asm/ibt.h b/arch/x86/include/asm/ibt.h index 1e59581d500c..b778ae6e67ee 100644 --- a/arch/x86/include/asm/ibt.h +++ b/arch/x86/include/asm/ibt.h @@ -41,7 +41,7 @@ _ASM_PTR fname "\n\t" \ ".popsection\n\t" -static inline __attribute_const__ u32 gen_endbr(void) +static __always_inline __attribute_const__ u32 gen_endbr(void) { u32 endbr; @@ -56,7 +56,7 @@ static inline __attribute_const__ u32 gen_endbr(void) return endbr; } -static inline __attribute_const__ u32 gen_endbr_poison(void) +static __always_inline __attribute_const__ u32 gen_endbr_poison(void) { /* * 4 byte NOP that isn't NOP4 (in fact it is OSP NOP3), such that it diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index 5e3e036e6e53..b18fc7539b8d 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c @@ -94,10 +94,17 @@ __always_inline int is_valid_bugaddr(unsigned long addr) /* * Check for UD1 or UD2, accounting for Address Size Override Prefixes. - * If it's a UD1, get the ModRM byte to pass along to UBSan. + * If it's a UD1, further decode to determine its use: + * + * UBSan{0}: 67 0f b9 00 ud1 (%eax),%eax + * UBSan{10}: 67 0f b9 40 10 ud1 0x10(%eax),%eax + * static_call: 0f b9 cc ud1 %esp,%ecx + * + * Notably UBSAN uses EAX, static_call uses ECX. */ -__always_inline int decode_bug(unsigned long addr, u32 *imm) +__always_inline int decode_bug(unsigned long addr, s32 *imm, int *len) { + unsigned long start = addr; u8 v; if (addr < TASK_SIZE_MAX) @@ -110,24 +117,42 @@ __always_inline int decode_bug(unsigned long addr, u32 *imm) return BUG_NONE; v = *(u8 *)(addr++); - if (v == SECOND_BYTE_OPCODE_UD2) + if (v == SECOND_BYTE_OPCODE_UD2) { + *len = addr - start; return BUG_UD2; + } - if (!IS_ENABLED(CONFIG_UBSAN_TRAP) || v != SECOND_BYTE_OPCODE_UD1) + if (v != SECOND_BYTE_OPCODE_UD1) return BUG_NONE; - /* Retrieve the immediate (type value) for the UBSAN UD1 */ - v = *(u8 *)(addr++); - if (X86_MODRM_RM(v) == 4) - addr++; - *imm = 0; - if (X86_MODRM_MOD(v) == 1) - *imm = *(u8 *)addr; - else if (X86_MODRM_MOD(v) == 2) - *imm = *(u32 *)addr; - else - WARN_ONCE(1, "Unexpected MODRM_MOD: %u\n", X86_MODRM_MOD(v)); + v = *(u8 *)(addr++); /* ModRM */ + + if (X86_MODRM_MOD(v) != 3 && X86_MODRM_RM(v) == 4) + addr++; /* SIB */ + + /* Decode immediate, if present */ + switch (X86_MODRM_MOD(v)) { + case 0: if (X86_MODRM_RM(v) == 5) + addr += 4; /* RIP + disp32 */ + break; + + case 1: *imm = *(s8 *)addr; + addr += 1; + break; + + case 2: *imm = *(s32 *)addr; + addr += 4; + break; + + case 3: break; + } + + /* record instruction length */ + *len = addr - start; + + if (X86_MODRM_REG(v) == 0) /* EAX */ + return BUG_UD1_UBSAN; return BUG_UD1; } @@ -258,10 +283,10 @@ static inline void handle_invalid_op(struct pt_regs *regs) static noinstr bool handle_bug(struct pt_regs *regs) { bool handled = false; - int ud_type; - u32 imm; + int ud_type, ud_len; + s32 ud_imm; - ud_type = decode_bug(regs->ip, &imm); + ud_type = decode_bug(regs->ip, &ud_imm, &ud_len); if (ud_type == BUG_NONE) return handled; @@ -281,15 +306,28 @@ static noinstr bool handle_bug(struct pt_regs *regs) */ if (regs->flags & X86_EFLAGS_IF) raw_local_irq_enable(); - if (ud_type == BUG_UD2) { + + switch (ud_type) { + case BUG_UD2: if (report_bug(regs->ip, regs) == BUG_TRAP_TYPE_WARN || handle_cfi_failure(regs) == BUG_TRAP_TYPE_WARN) { - regs->ip += LEN_UD2; + regs->ip += ud_len; handled = true; } - } else if (IS_ENABLED(CONFIG_UBSAN_TRAP)) { - pr_crit("%s at %pS\n", report_ubsan_failure(regs, imm), (void *)regs->ip); + break; + + case BUG_UD1_UBSAN: + if (IS_ENABLED(CONFIG_UBSAN_TRAP)) { + pr_crit("%s at %pS\n", + report_ubsan_failure(regs, ud_imm), + (void *)regs->ip); + } + break; + + default: + break; } + if (regs->flags & X86_EFLAGS_IF) raw_local_irq_disable(); instrumentation_end(); From e6e31b0182de596f73baf298cae12e04fcf6498b Mon Sep 17 00:00:00 2001 From: zihan zhou <15645113830zzh@gmail.com> Date: Sat, 8 Feb 2025 15:53:23 +0800 Subject: [PATCH 83/91] sched: Reduce the default slice to avoid tasks getting an extra tick [ Upstream commit 2ae891b826958b60919ea21c727f77bcd6ffcc2c ] The old default value for slice is 0.75 msec * (1 + ilog(ncpus)) which means that we have a default slice of: 0.75 for 1 cpu 1.50 up to 3 cpus 2.25 up to 7 cpus 3.00 for 8 cpus and above. For HZ=250 and HZ=100, because of the tick accuracy, the runtime of tasks is far higher than their slice. For HZ=1000 with 8 cpus or more, the accuracy of tick is already satisfactory, but there is still an issue that tasks will get an extra tick because the tick often arrives a little faster than expected. In this case, the task can only wait until the next tick to consider that it has reached its deadline, and will run 1ms longer. vruntime + sysctl_sched_base_slice = deadline |-----------|-----------|-----------|-----------| 1ms 1ms 1ms 1ms ^ ^ ^ ^ tick1 tick2 tick3 tick4(nearly 4ms) There are two reasons for tick error: clockevent precision and the CONFIG_IRQ_TIME_ACCOUNTING/CONFIG_PARAVIRT_TIME_ACCOUNTING. with CONFIG_IRQ_TIME_ACCOUNTING every tick will be less than 1ms, but even without it, because of clockevent precision, tick still often less than 1ms. In order to make scheduling more precise, we changed 0.75 to 0.70, Using 0.70 instead of 0.75 should not change much for other configs and would fix this issue: 0.70 for 1 cpu 1.40 up to 3 cpus 2.10 up to 7 cpus 2.8 for 8 cpus and above. This does not guarantee that tasks can run the slice time accurately every time, but occasionally running an extra tick has little impact. Signed-off-by: zihan zhou <15645113830zzh@gmail.com> Signed-off-by: Peter Zijlstra (Intel) Reviewed-by: Vincent Guittot Link: https://lkml.kernel.org/r/20250208075322.13139-1-15645113830zzh@gmail.com Signed-off-by: Sasha Levin --- kernel/sched/fair.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 990d0828bf2a..443f6a9ef3f8 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -71,10 +71,10 @@ unsigned int sysctl_sched_tunable_scaling = SCHED_TUNABLESCALING_LOG; /* * Minimal preemption granularity for CPU-bound tasks: * - * (default: 0.75 msec * (1 + ilog(ncpus)), units: nanoseconds) + * (default: 0.70 msec * (1 + ilog(ncpus)), units: nanoseconds) */ -unsigned int sysctl_sched_base_slice = 750000ULL; -static unsigned int normalized_sysctl_sched_base_slice = 750000ULL; +unsigned int sysctl_sched_base_slice = 700000ULL; +static unsigned int normalized_sysctl_sched_base_slice = 700000ULL; const_debug unsigned int sysctl_sched_migration_cost = 500000UL; From 5de11f82cbfd17be1f3d36a15d54396206eccf11 Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Fri, 7 Feb 2025 13:33:13 +0200 Subject: [PATCH 84/91] serial: sh-sci: Update the suspend/resume support [ Upstream commit 22a6984c5b5df8eab864d7f3e8b94d5a554d31ab ] The Renesas RZ/G3S supports a power saving mode where power to most of the SoC components is turned off. When returning from this power saving mode, SoC components need to be re-configured. The SCIFs on the Renesas RZ/G3S need to be re-configured as well when returning from this power saving mode. The sh-sci code already configures the SCIF clocks, power domain and registers by calling uart_resume_port() in sci_resume(). On suspend path the SCIF UART ports are suspended accordingly (by calling uart_suspend_port() in sci_suspend()). The only missing setting is the reset signal. For this assert/de-assert the reset signal on driver suspend/resume. In case the no_console_suspend is specified by the user, the registers need to be saved on suspend path and restore on resume path. To do this the sci_console_save()/sci_console_restore() functions were added. There is no need to cache/restore the status or FIFO registers. Only the control registers. The registers that will be saved/restored on suspend/resume are specified by the struct sci_suspend_regs data structure. Signed-off-by: Claudiu Beznea Reviewed-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20250207113313.545432-1-claudiu.beznea.uj@bp.renesas.com Signed-off-by: Greg Kroah-Hartman Signed-off-by: Sasha Levin --- drivers/tty/serial/sh-sci.c | 71 +++++++++++++++++++++++++++++++++++-- 1 file changed, 69 insertions(+), 2 deletions(-) diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 80efe3b0ed0c..779074b1c2be 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -104,6 +104,15 @@ struct plat_sci_reg { u8 offset, size; }; +struct sci_suspend_regs { + u16 scsmr; + u16 scscr; + u16 scfcr; + u16 scsptr; + u8 scbrr; + u8 semr; +}; + struct sci_port_params { const struct plat_sci_reg regs[SCIx_NR_REGS]; unsigned int fifosize; @@ -134,6 +143,8 @@ struct sci_port { struct dma_chan *chan_tx; struct dma_chan *chan_rx; + struct reset_control *rstc; + #ifdef CONFIG_SERIAL_SH_SCI_DMA struct dma_chan *chan_tx_saved; struct dma_chan *chan_rx_saved; @@ -153,6 +164,7 @@ struct sci_port { int rx_trigger; struct timer_list rx_fifo_timer; int rx_fifo_timeout; + struct sci_suspend_regs suspend_regs; u16 hscif_tot; bool has_rtscts; @@ -3384,6 +3396,7 @@ static struct plat_sci_port *sci_parse_dt(struct platform_device *pdev, } sp = &sci_ports[id]; + sp->rstc = rstc; *dev_id = id; p->type = SCI_OF_TYPE(data); @@ -3532,13 +3545,57 @@ static int sci_probe(struct platform_device *dev) return 0; } +static void sci_console_save(struct sci_port *s) +{ + struct sci_suspend_regs *regs = &s->suspend_regs; + struct uart_port *port = &s->port; + + if (sci_getreg(port, SCSMR)->size) + regs->scsmr = sci_serial_in(port, SCSMR); + if (sci_getreg(port, SCSCR)->size) + regs->scscr = sci_serial_in(port, SCSCR); + if (sci_getreg(port, SCFCR)->size) + regs->scfcr = sci_serial_in(port, SCFCR); + if (sci_getreg(port, SCSPTR)->size) + regs->scsptr = sci_serial_in(port, SCSPTR); + if (sci_getreg(port, SCBRR)->size) + regs->scbrr = sci_serial_in(port, SCBRR); + if (sci_getreg(port, SEMR)->size) + regs->semr = sci_serial_in(port, SEMR); +} + +static void sci_console_restore(struct sci_port *s) +{ + struct sci_suspend_regs *regs = &s->suspend_regs; + struct uart_port *port = &s->port; + + if (sci_getreg(port, SCSMR)->size) + sci_serial_out(port, SCSMR, regs->scsmr); + if (sci_getreg(port, SCSCR)->size) + sci_serial_out(port, SCSCR, regs->scscr); + if (sci_getreg(port, SCFCR)->size) + sci_serial_out(port, SCFCR, regs->scfcr); + if (sci_getreg(port, SCSPTR)->size) + sci_serial_out(port, SCSPTR, regs->scsptr); + if (sci_getreg(port, SCBRR)->size) + sci_serial_out(port, SCBRR, regs->scbrr); + if (sci_getreg(port, SEMR)->size) + sci_serial_out(port, SEMR, regs->semr); +} + static __maybe_unused int sci_suspend(struct device *dev) { struct sci_port *sport = dev_get_drvdata(dev); - if (sport) + if (sport) { uart_suspend_port(&sci_uart_driver, &sport->port); + if (!console_suspend_enabled && uart_console(&sport->port)) + sci_console_save(sport); + else + return reset_control_assert(sport->rstc); + } + return 0; } @@ -3546,8 +3603,18 @@ static __maybe_unused int sci_resume(struct device *dev) { struct sci_port *sport = dev_get_drvdata(dev); - if (sport) + if (sport) { + if (!console_suspend_enabled && uart_console(&sport->port)) { + sci_console_restore(sport); + } else { + int ret = reset_control_deassert(sport->rstc); + + if (ret) + return ret; + } + uart_resume_port(&sci_uart_driver, &sport->port); + } return 0; } From a507a213e82ca368b18a31f14a2f4813bc14771b Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Wed, 5 Feb 2025 12:01:16 +0200 Subject: [PATCH 85/91] pinctrl: renesas: rzg2l: Add suspend/resume support for pull up/down [ Upstream commit b2bd65fbb617353e3c46ba5206b3b030fa0f260c ] The Renesas RZ/G3S supports a power-saving mode where power to most of the SoC components is lost, including the PIN controller. Save and restore the pull-up/pull-down register contents to ensure the functionality is preserved after a suspend/resume cycle. Signed-off-by: Claudiu Beznea Reviewed-by: Lad Prabhakar Reviewed-by: Geert Uytterhoeven Link: https://lore.kernel.org/20250205100116.2032765-1-claudiu.beznea.uj@bp.renesas.com Signed-off-by: Geert Uytterhoeven Signed-off-by: Sasha Levin --- drivers/pinctrl/renesas/pinctrl-rzg2l.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/drivers/pinctrl/renesas/pinctrl-rzg2l.c b/drivers/pinctrl/renesas/pinctrl-rzg2l.c index d90685cfe2e1..bde58f5a743c 100644 --- a/drivers/pinctrl/renesas/pinctrl-rzg2l.c +++ b/drivers/pinctrl/renesas/pinctrl-rzg2l.c @@ -311,6 +311,7 @@ struct rzg2l_pinctrl_pin_settings { * @pmc: PMC registers cache * @pfc: PFC registers cache * @iolh: IOLH registers cache + * @pupd: PUPD registers cache * @ien: IEN registers cache * @sd_ch: SD_CH registers cache * @eth_poc: ET_POC registers cache @@ -324,6 +325,7 @@ struct rzg2l_pinctrl_reg_cache { u32 *pfc; u32 *iolh[2]; u32 *ien[2]; + u32 *pupd[2]; u8 sd_ch[2]; u8 eth_poc[2]; u8 eth_mode; @@ -2539,6 +2541,11 @@ static int rzg2l_pinctrl_reg_cache_alloc(struct rzg2l_pinctrl *pctrl) if (!cache->ien[i]) return -ENOMEM; + cache->pupd[i] = devm_kcalloc(pctrl->dev, nports, sizeof(*cache->pupd[i]), + GFP_KERNEL); + if (!cache->pupd[i]) + return -ENOMEM; + /* Allocate dedicated cache. */ dedicated_cache->iolh[i] = devm_kcalloc(pctrl->dev, n_dedicated_pins, sizeof(*dedicated_cache->iolh[i]), @@ -2779,7 +2786,7 @@ static void rzg2l_pinctrl_pm_setup_regs(struct rzg2l_pinctrl *pctrl, bool suspen struct rzg2l_pinctrl_reg_cache *cache = pctrl->cache; for (u32 port = 0; port < nports; port++) { - bool has_iolh, has_ien; + bool has_iolh, has_ien, has_pupd; u32 off, caps; u8 pincnt; u64 cfg; @@ -2791,6 +2798,7 @@ static void rzg2l_pinctrl_pm_setup_regs(struct rzg2l_pinctrl *pctrl, bool suspen caps = FIELD_GET(PIN_CFG_MASK, cfg); has_iolh = !!(caps & (PIN_CFG_IOLH_A | PIN_CFG_IOLH_B | PIN_CFG_IOLH_C)); has_ien = !!(caps & PIN_CFG_IEN); + has_pupd = !!(caps & PIN_CFG_PUPD); if (suspend) RZG2L_PCTRL_REG_ACCESS32(suspend, pctrl->base + PFC(off), cache->pfc[port]); @@ -2809,6 +2817,15 @@ static void rzg2l_pinctrl_pm_setup_regs(struct rzg2l_pinctrl *pctrl, bool suspen } } + if (has_pupd) { + RZG2L_PCTRL_REG_ACCESS32(suspend, pctrl->base + PUPD(off), + cache->pupd[0][port]); + if (pincnt >= 4) { + RZG2L_PCTRL_REG_ACCESS32(suspend, pctrl->base + PUPD(off), + cache->pupd[1][port]); + } + } + RZG2L_PCTRL_REG_ACCESS16(suspend, pctrl->base + PM(off), cache->pm[port]); RZG2L_PCTRL_REG_ACCESS8(suspend, pctrl->base + P(off), cache->p[port]); From afb512502f2d74b2b4ee76fe0b698ece3a1dc789 Mon Sep 17 00:00:00 2001 From: Damon Ding Date: Wed, 5 Feb 2025 18:51:54 +0800 Subject: [PATCH 86/91] phy: phy-rockchip-samsung-hdptx: Swap the definitions of LCPLL_REF and ROPLL_REF [ Upstream commit 2947c8065e9efdd3b6434d2817dc8896234a3fc0 ] According to the datasheet, setting the dig_clk_sel bit of CMN_REG(0097) to 1'b1 selects LCPLL as the reference clock, while setting it to 1'b0 selects the ROPLL. Signed-off-by: Damon Ding Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20250205105157.580060-2-damon.ding@rock-chips.com Signed-off-by: Vinod Koul Signed-off-by: Sasha Levin --- drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c index be6f1ca9095a..dc6e01dff5c7 100644 --- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c +++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c @@ -94,8 +94,8 @@ #define LCPLL_ALONE_MODE BIT(1) /* CMN_REG(0097) */ #define DIG_CLK_SEL BIT(1) -#define ROPLL_REF BIT(1) -#define LCPLL_REF 0 +#define LCPLL_REF BIT(1) +#define ROPLL_REF 0 /* CMN_REG(0099) */ #define CMN_ROPLL_ALONE_MODE BIT(2) #define ROPLL_ALONE_MODE BIT(2) From ef31dc41cf67ba0363c990ece8ccaa23fd16f7e6 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Sun, 9 Feb 2025 14:31:45 +0200 Subject: [PATCH 87/91] phy: core: don't require set_mode() callback for phy_get_mode() to work [ Upstream commit d58c04e305afbaa9dda7969151f06c4efe2c98b0 ] As reported by Damon Ding, the phy_get_mode() call doesn't work as expected unless the PHY driver has a .set_mode() call. This prompts PHY drivers to have empty stubs for .set_mode() for the sake of being able to get the mode. Make .set_mode() callback truly optional and update PHY's mode even if it there is none. Cc: Damon Ding Link: https://lore.kernel.org/r/96f8310f-93f1-4bcb-8637-137e1159ff83@rock-chips.com Tested-by: Damon Ding Signed-off-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20250209-phy-fix-set-moe-v2-1-76e248503856@linaro.org Signed-off-by: Vinod Koul Signed-off-by: Sasha Levin --- drivers/phy/phy-core.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c index 413f76e2d174..e0a6a272f571 100644 --- a/drivers/phy/phy-core.c +++ b/drivers/phy/phy-core.c @@ -405,13 +405,14 @@ EXPORT_SYMBOL_GPL(phy_power_off); int phy_set_mode_ext(struct phy *phy, enum phy_mode mode, int submode) { - int ret; + int ret = 0; - if (!phy || !phy->ops->set_mode) + if (!phy) return 0; mutex_lock(&phy->mutex); - ret = phy->ops->set_mode(phy, mode, submode); + if (phy->ops->set_mode) + ret = phy->ops->set_mode(phy, mode, submode); if (!ret) phy->attrs.mode = mode; mutex_unlock(&phy->mutex); From 164c9f5edf2aea7314b06bc50b607973ce461551 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Draszik?= Date: Fri, 6 Dec 2024 16:31:04 +0000 Subject: [PATCH 88/91] phy: exynos5-usbdrd: fix EDS distribution tuning (gs101) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 21860f340ba76ee042e5431ff92537f89bc11476 ] This code's intention is to configure lane0 and lane2 tunings, but for lane2 there is a typo and it ends up tuning something else. Fix the typo, as it doesn't appear to make sense to apply different tunings for lane0 vs lane2. The same typo appears to exist in the bootloader, hence we restore the original value in the typo'd registers as well. This can be removed once / if the bootloader is updated. Note that this is incorrect in the downstream driver as well - the values had been copied from there. Reviewed-by: Peter Griffin Tested-by: Peter Griffin Signed-off-by: André Draszik Tested-by: Will McVicker Link: https://lore.kernel.org/r/20241206-gs101-phy-lanes-orientation-phy-v4-4-f5961268b149@linaro.org Signed-off-by: Vinod Koul Signed-off-by: Sasha Levin --- drivers/phy/samsung/phy-exynos5-usbdrd.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/phy/samsung/phy-exynos5-usbdrd.c b/drivers/phy/samsung/phy-exynos5-usbdrd.c index 46b8f6987c62..28d02ae60cc1 100644 --- a/drivers/phy/samsung/phy-exynos5-usbdrd.c +++ b/drivers/phy/samsung/phy-exynos5-usbdrd.c @@ -1513,8 +1513,11 @@ static const struct exynos5_usbdrd_phy_tuning gs101_tunes_pipe3_preinit[] = { PHY_TUNING_ENTRY_PMA(0x09e0, -1, 0x00), PHY_TUNING_ENTRY_PMA(0x09e4, -1, 0x36), PHY_TUNING_ENTRY_PMA(0x1e7c, -1, 0x06), - PHY_TUNING_ENTRY_PMA(0x1e90, -1, 0x00), - PHY_TUNING_ENTRY_PMA(0x1e94, -1, 0x36), + PHY_TUNING_ENTRY_PMA(0x19e0, -1, 0x00), + PHY_TUNING_ENTRY_PMA(0x19e4, -1, 0x36), + /* fix bootloader bug */ + PHY_TUNING_ENTRY_PMA(0x1e90, -1, 0x02), + PHY_TUNING_ENTRY_PMA(0x1e94, -1, 0x0b), /* improve LVCC */ PHY_TUNING_ENTRY_PMA(0x08f0, -1, 0x30), PHY_TUNING_ENTRY_PMA(0x18f0, -1, 0x30), From c043867b654ec9c709cb3697a7ebbaf0ae2e0cc6 Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Fri, 7 Feb 2025 12:28:36 +0530 Subject: [PATCH 89/91] soundwire: amd: change the soundwire wake enable/disable sequence [ Upstream commit dcc48a73eae7f791b1a6856ea1bcc4079282c88d ] During runtime suspend scenario, SoundWire wake should be enabled and during system level suspend scenario SoundWire wake should be disabled. Implement the SoundWire wake enable/disable sequence as per design flow for SoundWire poweroff mode. Signed-off-by: Vijendar Mukunda Link: https://lore.kernel.org/r/20250207065841.4718-2-Vijendar.Mukunda@amd.com Signed-off-by: Vinod Koul Signed-off-by: Sasha Levin --- drivers/soundwire/amd_manager.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/soundwire/amd_manager.c b/drivers/soundwire/amd_manager.c index 0d01849c3586..e3d5e6c1d582 100644 --- a/drivers/soundwire/amd_manager.c +++ b/drivers/soundwire/amd_manager.c @@ -1110,6 +1110,7 @@ static int __maybe_unused amd_suspend(struct device *dev) amd_sdw_wake_enable(amd_manager, false); return amd_sdw_clock_stop(amd_manager); } else if (amd_manager->power_mode_mask & AMD_SDW_POWER_OFF_MODE) { + amd_sdw_wake_enable(amd_manager, false); /* * As per hardware programming sequence on AMD platforms, * clock stop should be invoked first before powering-off @@ -1137,6 +1138,7 @@ static int __maybe_unused amd_suspend_runtime(struct device *dev) amd_sdw_wake_enable(amd_manager, true); return amd_sdw_clock_stop(amd_manager); } else if (amd_manager->power_mode_mask & AMD_SDW_POWER_OFF_MODE) { + amd_sdw_wake_enable(amd_manager, true); ret = amd_sdw_clock_stop(amd_manager); if (ret) return ret; From 97dba4472e4840bae874561542c7f41ed3eb22db Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Wed, 5 Feb 2025 15:42:31 +0800 Subject: [PATCH 90/91] soundwire: cadence_master: set frame shape and divider based on actual clk freq MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit e738d77f78b3ac085dfb51be414e93464abba7ec ] Frame shape and curr_dr_freq could be updated by sdw_compute_bus_params(). Peripherals will set curr_dr_freq as their frequency. Managers should do the same. Then update frame shape according to the actual bus frequency. Signed-off-by: Bard Liao Reviewed-by: Ranjani Sridharan Reviewed-by: Péter Ujfalusi Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20250205074232.87537-2-yung-chuan.liao@linux.intel.com Signed-off-by: Vinod Koul Signed-off-by: Sasha Levin --- drivers/soundwire/cadence_master.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/drivers/soundwire/cadence_master.c b/drivers/soundwire/cadence_master.c index 05652e983539..6f2b5ec5c87c 100644 --- a/drivers/soundwire/cadence_master.c +++ b/drivers/soundwire/cadence_master.c @@ -1341,7 +1341,7 @@ static u32 cdns_set_initial_frame_shape(int n_rows, int n_cols) return val; } -static void cdns_init_clock_ctrl(struct sdw_cdns *cdns) +static int cdns_init_clock_ctrl(struct sdw_cdns *cdns) { struct sdw_bus *bus = &cdns->bus; struct sdw_master_prop *prop = &bus->prop; @@ -1355,14 +1355,25 @@ static void cdns_init_clock_ctrl(struct sdw_cdns *cdns) prop->default_row, prop->default_col); + if (!prop->default_frame_rate || !prop->default_row) { + dev_err(cdns->dev, "Default frame_rate %d or row %d is invalid\n", + prop->default_frame_rate, prop->default_row); + return -EINVAL; + } + /* Set clock divider */ - divider = (prop->mclk_freq / prop->max_clk_freq) - 1; + divider = (prop->mclk_freq * SDW_DOUBLE_RATE_FACTOR / + bus->params.curr_dr_freq) - 1; cdns_updatel(cdns, CDNS_MCP_CLK_CTRL0, CDNS_MCP_CLK_MCLKD_MASK, divider); cdns_updatel(cdns, CDNS_MCP_CLK_CTRL1, CDNS_MCP_CLK_MCLKD_MASK, divider); + /* Set frame shape base on the actual bus frequency. */ + prop->default_col = bus->params.curr_dr_freq / + prop->default_frame_rate / prop->default_row; + /* * Frame shape changes after initialization have to be done * with the bank switch mechanism @@ -1375,6 +1386,8 @@ static void cdns_init_clock_ctrl(struct sdw_cdns *cdns) ssp_interval = prop->default_frame_rate / SDW_CADENCE_GSYNC_HZ; cdns_writel(cdns, CDNS_MCP_SSP_CTRL0, ssp_interval); cdns_writel(cdns, CDNS_MCP_SSP_CTRL1, ssp_interval); + + return 0; } /** @@ -1383,9 +1396,12 @@ static void cdns_init_clock_ctrl(struct sdw_cdns *cdns) */ int sdw_cdns_init(struct sdw_cdns *cdns) { + int ret; u32 val; - cdns_init_clock_ctrl(cdns); + ret = cdns_init_clock_ctrl(cdns); + if (ret) + return ret; sdw_cdns_check_self_clearing_bits(cdns, __func__, false, 0); From 11c7fa11fa0763a1cff17a5de81511437c9cffd7 Mon Sep 17 00:00:00 2001 From: Huacai Chen Date: Mon, 10 Feb 2025 21:43:28 +0800 Subject: [PATCH 91/91] net: stmmac: dwmac-loongson: Set correct {tx,rx}_fifo_size [ Upstream commit 8dbf0c7556454b52af91bae305ca71500c31495c ] Now for dwmac-loongson {tx,rx}_fifo_size are uninitialised, which means zero. This means dwmac-loongson doesn't support changing MTU because in stmmac_change_mtu() it requires the fifo size be no less than MTU. Thus, set the correct tx_fifo_size and rx_fifo_size for it (16KB multiplied by queue counts). Here {tx,rx}_fifo_size is initialised with the initial value (also the maximum value) of {tx,rx}_queues_to_use. So it will keep as 16KB if we don't change the queue count, and will be larger than 16KB if we change (decrease) the queue count. However stmmac_change_mtu() still work well with current logic (MTU cannot be larger than 16KB for stmmac). Note: the Fixes tag picked here is the oldest commit and key commit of the dwmac-loongson series "stmmac: Add Loongson platform support". Acked-by: Yanteng Si Reviewed-by: Simon Horman Signed-off-by: Chong Qiao Signed-off-by: Huacai Chen Link: https://patch.msgid.link/20250210134328.2755328-1-chenhuacai@loongson.cn Signed-off-by: Jakub Kicinski Signed-off-by: Sasha Levin --- drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c index ab7c2750c104..702ea5a00b56 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c @@ -590,6 +590,9 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id if (ret) goto err_disable_device; + plat->tx_fifo_size = SZ_16K * plat->tx_queues_to_use; + plat->rx_fifo_size = SZ_16K * plat->rx_queues_to_use; + if (dev_of_node(&pdev->dev)) ret = loongson_dwmac_dt_config(pdev, plat, &res); else