From d3ffbbb0bca5fa8ec475d0fbe7af256b1ddab0c5 Mon Sep 17 00:00:00 2001 From: Andrew Davis Date: Mon, 13 Nov 2023 12:16:04 -0600 Subject: ARM: dts: dra7: Fix DRA7 L3 NoC node register size [ Upstream commit 1e5caee2ba8f1426e8098afb4ca38dc40a0ca71b ] This node can access any part of the L3 configuration registers space, including CLK1 and CLK2 which are 0x800000 offset. Restore this area size to include these areas. Fixes: 7f2659ce657e ("ARM: dts: Move dra7 l3 noc to a separate node") Signed-off-by: Andrew Davis Message-ID: <20231113181604.546444-1-afd@ti.com> Signed-off-by: Tony Lindgren Signed-off-by: Sasha Levin --- arch/arm/boot/dts/dra7.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/dra7.dtsi b/arch/arm/boot/dts/dra7.dtsi index 61a3fb3e2a2f..0cb5ec39e33a 100644 --- a/arch/arm/boot/dts/dra7.dtsi +++ b/arch/arm/boot/dts/dra7.dtsi @@ -144,7 +144,7 @@ l3-noc@44000000 { compatible = "ti,dra7-l3-noc"; - reg = <0x44000000 0x1000>, + reg = <0x44000000 0x1000000>, <0x45000000 0x1000>; interrupts-extended = <&crossbar_mpu GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>, <&wakeupgen GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>; -- cgit v1.2.3 From 52c69a070b942cae778333282cbf36bec8a330e3 Mon Sep 17 00:00:00 2001 From: Kunwu Chan Date: Thu, 23 Nov 2023 22:52:37 +0800 Subject: ARM: OMAP2+: Fix null pointer dereference and memory leak in omap_soc_device_init [ Upstream commit c72b9c33ef9695ad7ce7a6eb39a9df8a01b70796 ] kasprintf() returns a pointer to dynamically allocated memory which can be NULL upon failure. When 'soc_dev_attr->family' is NULL,it'll trigger the null pointer dereference issue, such as in 'soc_info_show'. And when 'soc_device_register' fails, it's necessary to release 'soc_dev_attr->family' to avoid memory leaks. Fixes: 6770b2114325 ("ARM: OMAP2+: Export SoC information to userspace") Signed-off-by: Kunwu Chan Message-ID: <20231123145237.609442-1-chentao@kylinos.cn> Signed-off-by: Tony Lindgren Signed-off-by: Sasha Levin --- arch/arm/mach-omap2/id.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm/mach-omap2/id.c b/arch/arm/mach-omap2/id.c index 59755b5a1ad7..75091aa7269a 100644 --- a/arch/arm/mach-omap2/id.c +++ b/arch/arm/mach-omap2/id.c @@ -793,11 +793,16 @@ void __init omap_soc_device_init(void) soc_dev_attr->machine = soc_name; soc_dev_attr->family = omap_get_family(); + if (!soc_dev_attr->family) { + kfree(soc_dev_attr); + return; + } soc_dev_attr->revision = soc_rev; soc_dev_attr->custom_attr_group = omap_soc_groups[0]; soc_dev = soc_device_register(soc_dev_attr); if (IS_ERR(soc_dev)) { + kfree(soc_dev_attr->family); kfree(soc_dev_attr); return; } -- cgit v1.2.3 From 58f3fc83332181468b924c44f188d8bab2835ec1 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 29 Nov 2023 17:55:33 +0100 Subject: reset: Fix crash when freeing non-existent optional resets [ Upstream commit 4a6756f56bcf8e64c87144a626ce53aea4899c0e ] When obtaining one or more optional resets, non-existent resets are stored as NULL pointers, and all related error and cleanup paths need to take this into account. Currently only reset_control_put() and reset_control_bulk_put() get this right. All of __reset_control_bulk_get(), of_reset_control_array_get(), and reset_control_array_put() lack the proper checking, causing NULL pointer dereferences on failure or release. Fix this by moving the existing check from reset_control_bulk_put() to __reset_control_put_internal(), so it applies to all callers. The double check in reset_control_put() doesn't hurt. Fixes: 17c82e206d2a3cd8 ("reset: Add APIs to manage array of resets") Fixes: 48d71395896d54ee ("reset: Add reset_control_bulk API") Signed-off-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/2440edae7ca8534628cdbaf559ded288f2998178.1701276806.git.geert+renesas@glider.be Signed-off-by: Philipp Zabel Signed-off-by: Sasha Levin --- drivers/reset/core.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/reset/core.c b/drivers/reset/core.c index 61e688882643..320412e513c0 100644 --- a/drivers/reset/core.c +++ b/drivers/reset/core.c @@ -806,6 +806,9 @@ static void __reset_control_put_internal(struct reset_control *rstc) { lockdep_assert_held(&reset_list_mutex); + if (IS_ERR_OR_NULL(rstc)) + return; + kref_put(&rstc->refcnt, __reset_control_release); } @@ -1016,11 +1019,8 @@ EXPORT_SYMBOL_GPL(reset_control_put); void reset_control_bulk_put(int num_rstcs, struct reset_control_bulk_data *rstcs) { mutex_lock(&reset_list_mutex); - while (num_rstcs--) { - if (IS_ERR_OR_NULL(rstcs[num_rstcs].rstc)) - continue; + while (num_rstcs--) __reset_control_put_internal(rstcs[num_rstcs].rstc); - } mutex_unlock(&reset_list_mutex); } EXPORT_SYMBOL_GPL(reset_control_bulk_put); -- cgit v1.2.3 From 183ea95f7374e04157b871824680aa93783c46e6 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Fri, 8 Dec 2023 15:03:15 +0100 Subject: s390/vx: fix save/restore of fpu kernel context [ Upstream commit e6b2dab41888332bf83f592131e7ea07756770a4 ] The KERNEL_FPR mask only contains a flag for the first eight vector registers. However floating point registers overlay parts of the first sixteen vector registers. This could lead to vector register corruption if a kernel fpu context uses any of the vector registers 8 to 15 and is interrupted or calls a KERNEL_FPR context. If that context uses also vector registers 8 to 15, their contents will be corrupted on return. Luckily this is currently not a real bug, since the kernel has only one KERNEL_FPR user with s390_adjust_jiffies() and it is only using floating point registers 0 to 2. Fix this by using the correct bits for KERNEL_FPR. Fixes: 7f79695cc1b6 ("s390/fpu: improve kernel_fpu_[begin|end]") Signed-off-by: Heiko Carstens Reviewed-by: Hendrik Brueckner Signed-off-by: Alexander Gordeev Signed-off-by: Sasha Levin --- arch/s390/include/asm/fpu/api.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/s390/include/asm/fpu/api.h b/arch/s390/include/asm/fpu/api.h index a959b815a58b..b8c7e8538c85 100644 --- a/arch/s390/include/asm/fpu/api.h +++ b/arch/s390/include/asm/fpu/api.h @@ -78,7 +78,7 @@ static inline int test_fp_ctl(u32 fpc) #define KERNEL_VXR_HIGH (KERNEL_VXR_V16V23|KERNEL_VXR_V24V31) #define KERNEL_VXR (KERNEL_VXR_LOW|KERNEL_VXR_HIGH) -#define KERNEL_FPR (KERNEL_FPC|KERNEL_VXR_V0V7) +#define KERNEL_FPR (KERNEL_FPC|KERNEL_VXR_LOW) struct kernel_fpu; -- cgit v1.2.3 From 6558f4aa203215d32053bbbb430d00de56d45b33 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 8 Dec 2023 18:32:02 +0200 Subject: wifi: iwlwifi: pcie: add another missing bh-disable for rxq->lock [ Upstream commit a4754182dc936b97ec7e9f6b08cdf7ed97ef9069 ] Evidently I had only looked at all the ones in rx.c, and missed this. Add bh-disable to this use of the rxq->lock as well. Fixes: 25edc8f259c7 ("iwlwifi: pcie: properly implement NAPI") Reported-by: Brian Norris Signed-off-by: Johannes Berg Signed-off-by: Miri Korenblit Link: https://msgid.link/20231208183100.e79ad3dae649.I8f19713c4383707f8be7fc20ff5cc1ecf12429bb@changeid Signed-off-by: Johannes Berg Signed-off-by: Sasha Levin --- drivers/net/wireless/intel/iwlwifi/pcie/trans.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index b7b2d28b3e43..8a19463bc81c 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -2960,7 +2960,7 @@ static u32 iwl_trans_pcie_dump_rbs(struct iwl_trans *trans, struct iwl_rxq *rxq = &trans_pcie->rxq[0]; u32 i, r, j, rb_len = 0; - spin_lock(&rxq->lock); + spin_lock_bh(&rxq->lock); r = le16_to_cpu(iwl_get_closed_rb_stts(trans, rxq)) & 0x0FFF; @@ -2984,7 +2984,7 @@ static u32 iwl_trans_pcie_dump_rbs(struct iwl_trans *trans, *data = iwl_fw_error_next_data(*data); } - spin_unlock(&rxq->lock); + spin_unlock_bh(&rxq->lock); return rb_len; } -- cgit v1.2.3 From b387f06849b4662becbb45a4ddcb636adfb5fa30 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 11 Dec 2023 09:05:31 +0200 Subject: wifi: mac80211: mesh_plink: fix matches_local logic [ Upstream commit 8c386b166e2517cf3a123018e77941ec22625d0f ] During refactoring the "else" here got lost, add it back. Fixes: c99a89edb106 ("mac80211: factor out plink event gathering") Signed-off-by: Johannes Berg Signed-off-by: Miri Korenblit Link: https://msgid.link/20231211085121.795480fa0e0b.I017d501196a5bbdcd9afd33338d342d6fe1edd79@changeid Signed-off-by: Johannes Berg Signed-off-by: Sasha Levin --- net/mac80211/mesh_plink.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index a829470dd59e..44ce979a9fd5 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c @@ -1050,8 +1050,8 @@ mesh_plink_get_event(struct ieee80211_sub_if_data *sdata, case WLAN_SP_MESH_PEERING_OPEN: if (!matches_local) event = OPN_RJCT; - if (!mesh_plink_free_count(sdata) || - (sta->mesh->plid && sta->mesh->plid != plid)) + else if (!mesh_plink_free_count(sdata) || + (sta->mesh->plid && sta->mesh->plid != plid)) event = OPN_IGNR; else event = OPN_ACPT; @@ -1059,9 +1059,9 @@ mesh_plink_get_event(struct ieee80211_sub_if_data *sdata, case WLAN_SP_MESH_PEERING_CONFIRM: if (!matches_local) event = CNF_RJCT; - if (!mesh_plink_free_count(sdata) || - sta->mesh->llid != llid || - (sta->mesh->plid && sta->mesh->plid != plid)) + else if (!mesh_plink_free_count(sdata) || + sta->mesh->llid != llid || + (sta->mesh->plid && sta->mesh->plid != plid)) event = CNF_IGNR; else event = CNF_ACPT; -- cgit v1.2.3 From 135fa6fac9b6a13f974c1bad123a83044179bfe5 Mon Sep 17 00:00:00 2001 From: Vlad Buslov Date: Tue, 21 Nov 2023 13:51:52 +0100 Subject: Revert "net/mlx5e: fix double free of encap_header in update funcs" [ Upstream commit 66ca8d4deca09bce3fc7bcf8ea7997fa1a51c33c ] This reverts commit 3a4aa3cb83563df942be49d145ee3b7ddf17d6bb. This patch is causing a null ptr issue, the proper fix is in the next patch. Fixes: 3a4aa3cb8356 ("net/mlx5e: fix double free of encap_header in update funcs") Signed-off-by: Vlad Buslov Signed-off-by: Saeed Mahameed Signed-off-by: Sasha Levin --- drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c index 303e6e7a5c44..44071592bd6e 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c @@ -397,12 +397,16 @@ int mlx5e_tc_tun_update_header_ipv4(struct mlx5e_priv *priv, if (err) goto free_encap; + e->encap_size = ipv4_encap_size; + kfree(e->encap_header); + e->encap_header = encap_header; + if (!(nud_state & NUD_VALID)) { neigh_event_send(attr.n, NULL); /* the encap entry will be made valid on neigh update event * and not used before that. */ - goto free_encap; + goto release_neigh; } memset(&reformat_params, 0, sizeof(reformat_params)); @@ -416,10 +420,6 @@ int mlx5e_tc_tun_update_header_ipv4(struct mlx5e_priv *priv, goto free_encap; } - e->encap_size = ipv4_encap_size; - kfree(e->encap_header); - e->encap_header = encap_header; - e->flags |= MLX5_ENCAP_ENTRY_VALID; mlx5e_rep_queue_neigh_stats_work(netdev_priv(attr.out_dev)); mlx5e_route_lookup_ipv4_put(&attr); @@ -660,12 +660,16 @@ int mlx5e_tc_tun_update_header_ipv6(struct mlx5e_priv *priv, if (err) goto free_encap; + e->encap_size = ipv6_encap_size; + kfree(e->encap_header); + e->encap_header = encap_header; + if (!(nud_state & NUD_VALID)) { neigh_event_send(attr.n, NULL); /* the encap entry will be made valid on neigh update event * and not used before that. */ - goto free_encap; + goto release_neigh; } memset(&reformat_params, 0, sizeof(reformat_params)); @@ -679,10 +683,6 @@ int mlx5e_tc_tun_update_header_ipv6(struct mlx5e_priv *priv, goto free_encap; } - e->encap_size = ipv6_encap_size; - kfree(e->encap_header); - e->encap_header = encap_header; - e->flags |= MLX5_ENCAP_ENTRY_VALID; mlx5e_rep_queue_neigh_stats_work(netdev_priv(attr.out_dev)); mlx5e_route_lookup_ipv6_put(&attr); -- cgit v1.2.3 From 5ae420f65affccaa6f69042f87d6fbb4757b6de3 Mon Sep 17 00:00:00 2001 From: Vlad Buslov Date: Tue, 21 Nov 2023 13:52:28 +0100 Subject: Revert "net/mlx5e: fix double free of encap_header" [ Upstream commit 5d089684dc434a31e08d32f0530066d0025c52e4 ] This reverts commit 6f9b1a0731662648949a1c0587f6acb3b7f8acf1. This patch is causing a null ptr issue, the proper fix is in the next patch. Fixes: 6f9b1a073166 ("net/mlx5e: fix double free of encap_header") Signed-off-by: Vlad Buslov Signed-off-by: Saeed Mahameed Signed-off-by: Sasha Levin --- drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c index 44071592bd6e..d90c6dc41c9f 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c @@ -294,6 +294,9 @@ int mlx5e_tc_tun_create_header_ipv4(struct mlx5e_priv *priv, if (err) goto destroy_neigh_entry; + e->encap_size = ipv4_encap_size; + e->encap_header = encap_header; + if (!(nud_state & NUD_VALID)) { neigh_event_send(attr.n, NULL); /* the encap entry will be made valid on neigh update event @@ -313,8 +316,6 @@ int mlx5e_tc_tun_create_header_ipv4(struct mlx5e_priv *priv, goto destroy_neigh_entry; } - e->encap_size = ipv4_encap_size; - e->encap_header = encap_header; e->flags |= MLX5_ENCAP_ENTRY_VALID; mlx5e_rep_queue_neigh_stats_work(netdev_priv(attr.out_dev)); mlx5e_route_lookup_ipv4_put(&attr); @@ -558,6 +559,9 @@ int mlx5e_tc_tun_create_header_ipv6(struct mlx5e_priv *priv, if (err) goto destroy_neigh_entry; + e->encap_size = ipv6_encap_size; + e->encap_header = encap_header; + if (!(nud_state & NUD_VALID)) { neigh_event_send(attr.n, NULL); /* the encap entry will be made valid on neigh update event @@ -577,8 +581,6 @@ int mlx5e_tc_tun_create_header_ipv6(struct mlx5e_priv *priv, goto destroy_neigh_entry; } - e->encap_size = ipv6_encap_size; - e->encap_header = encap_header; e->flags |= MLX5_ENCAP_ENTRY_VALID; mlx5e_rep_queue_neigh_stats_work(netdev_priv(attr.out_dev)); mlx5e_route_lookup_ipv6_put(&attr); -- cgit v1.2.3 From 4ddba57b659a4d462170754d96db4f37b39c9f51 Mon Sep 17 00:00:00 2001 From: Shifeng Li Date: Thu, 30 Nov 2023 01:46:56 -0800 Subject: net/mlx5e: Fix slab-out-of-bounds in mlx5_query_nic_vport_mac_list() [ Upstream commit ddb38ddff9c71026bad481b791a94d446ee37603 ] Out_sz that the size of out buffer is calculated using query_nic_vport _context_in structure when driver query the MAC list. However query_nic _vport_context_in structure is smaller than query_nic_vport_context_out. When allowed_list_size is greater than 96, calling ether_addr_copy() will trigger an slab-out-of-bounds. [ 1170.055866] BUG: KASAN: slab-out-of-bounds in mlx5_query_nic_vport_mac_list+0x481/0x4d0 [mlx5_core] [ 1170.055869] Read of size 4 at addr ffff88bdbc57d912 by task kworker/u128:1/461 [ 1170.055870] [ 1170.055932] Workqueue: mlx5_esw_wq esw_vport_change_handler [mlx5_core] [ 1170.055936] Call Trace: [ 1170.055949] dump_stack+0x8b/0xbb [ 1170.055958] print_address_description+0x6a/0x270 [ 1170.055961] kasan_report+0x179/0x2c0 [ 1170.056061] mlx5_query_nic_vport_mac_list+0x481/0x4d0 [mlx5_core] [ 1170.056162] esw_update_vport_addr_list+0x2c5/0xcd0 [mlx5_core] [ 1170.056257] esw_vport_change_handle_locked+0xd08/0x1a20 [mlx5_core] [ 1170.056377] esw_vport_change_handler+0x6b/0x90 [mlx5_core] [ 1170.056381] process_one_work+0x65f/0x12d0 [ 1170.056383] worker_thread+0x87/0xb50 [ 1170.056390] kthread+0x2e9/0x3a0 [ 1170.056394] ret_from_fork+0x1f/0x40 Fixes: e16aea2744ab ("net/mlx5: Introduce access functions to modify/query vport mac lists") Cc: Ding Hui Signed-off-by: Shifeng Li Reviewed-by: Simon Horman Signed-off-by: Saeed Mahameed Signed-off-by: Sasha Levin --- drivers/net/ethernet/mellanox/mlx5/core/vport.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/vport.c b/drivers/net/ethernet/mellanox/mlx5/core/vport.c index 4c1440a95ad7..0478e5ecd491 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/vport.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/vport.c @@ -277,7 +277,7 @@ int mlx5_query_nic_vport_mac_list(struct mlx5_core_dev *dev, req_list_size = max_list_size; } - out_sz = MLX5_ST_SZ_BYTES(query_nic_vport_context_in) + + out_sz = MLX5_ST_SZ_BYTES(query_nic_vport_context_out) + req_list_size * MLX5_ST_SZ_BYTES(mac_address_layout); out = kzalloc(out_sz, GFP_KERNEL); -- cgit v1.2.3 From b0873aa484e9224cffc35887bc14649232fc68f1 Mon Sep 17 00:00:00 2001 From: Dinghao Liu Date: Tue, 28 Nov 2023 17:40:53 +0800 Subject: net/mlx5e: fix a potential double-free in fs_udp_create_groups [ Upstream commit e75efc6466ae289e599fb12a5a86545dff245c65 ] When kcalloc() for ft->g succeeds but kvzalloc() for in fails, fs_udp_create_groups() will free ft->g. However, its caller fs_udp_create_table() will free ft->g again through calling mlx5e_destroy_flow_table(), which will lead to a double-free. Fix this by setting ft->g to NULL in fs_udp_create_groups(). Fixes: 1c80bd684388 ("net/mlx5e: Introduce Flow Steering UDP API") Signed-off-by: Dinghao Liu Reviewed-by: Tariq Toukan Reviewed-by: Simon Horman Signed-off-by: Saeed Mahameed Signed-off-by: Sasha Levin --- drivers/net/ethernet/mellanox/mlx5/core/en/fs_tt_redirect.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/fs_tt_redirect.c b/drivers/net/ethernet/mellanox/mlx5/core/en/fs_tt_redirect.c index 7aa25a5e29d7..b26edbc53cad 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/fs_tt_redirect.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/fs_tt_redirect.c @@ -156,6 +156,7 @@ static int fs_udp_create_groups(struct mlx5e_flow_table *ft, enum fs_udp_type ty in = kvzalloc(inlen, GFP_KERNEL); if (!in || !ft->g) { kfree(ft->g); + ft->g = NULL; kvfree(in); return -ENOMEM; } -- cgit v1.2.3 From da2396b54625079e0ee1817bdea97ef88fac86e7 Mon Sep 17 00:00:00 2001 From: Moshe Shemesh Date: Thu, 30 Nov 2023 11:30:34 +0200 Subject: net/mlx5: Fix fw tracer first block check [ Upstream commit 4261edf11cb7c9224af713a102e5616329306932 ] While handling new traces, to verify it is not the first block being written, last_timestamp is checked. But instead of checking it is non zero it is verified to be zero. Fix to verify last_timestamp is not zero. Fixes: c71ad41ccb0c ("net/mlx5: FW tracer, events handling") Signed-off-by: Moshe Shemesh Reviewed-by: Feras Daoud Signed-off-by: Saeed Mahameed Signed-off-by: Sasha Levin --- drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c index b69ab30ecf03..efa2e0a8fa1d 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c @@ -691,7 +691,7 @@ static void mlx5_fw_tracer_handle_traces(struct work_struct *work) while (block_timestamp > tracer->last_timestamp) { /* Check block override if it's not the first block */ - if (!tracer->last_timestamp) { + if (tracer->last_timestamp) { u64 *ts_event; /* To avoid block override be the HW in case of buffer * wraparound, the time stamp of the previous block -- cgit v1.2.3 From 242670aab84b582e8443388cf2e99cc70fc99f1b Mon Sep 17 00:00:00 2001 From: Rahul Rameshbabu Date: Tue, 21 Nov 2023 15:00:22 -0800 Subject: net/mlx5e: Correct snprintf truncation handling for fw_version buffer used by representors [ Upstream commit b13559b76157de9d74f04d3ca0e49d69de3b5675 ] snprintf returns the length of the formatted string, excluding the trailing null, without accounting for truncation. This means that is the return value is greater than or equal to the size parameter, the fw_version string was truncated. Link: https://docs.kernel.org/core-api/kernel-api.html#c.snprintf Fixes: 1b2bd0c0264f ("net/mlx5e: Check return value of snprintf writing to fw_version buffer for representors") Signed-off-by: Rahul Rameshbabu Reviewed-by: Simon Horman Signed-off-by: Saeed Mahameed Signed-off-by: Sasha Levin --- drivers/net/ethernet/mellanox/mlx5/core/en_rep.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c index 7a00faa62d99..de168d8cf33f 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c @@ -73,7 +73,7 @@ static void mlx5e_rep_get_drvinfo(struct net_device *dev, count = snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version), "%d.%d.%04d (%.16s)", fw_rev_maj(mdev), fw_rev_min(mdev), fw_rev_sub(mdev), mdev->board_id); - if (count == sizeof(drvinfo->fw_version)) + if (count >= sizeof(drvinfo->fw_version)) snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version), "%d.%d.%04d", fw_rev_maj(mdev), fw_rev_min(mdev), fw_rev_sub(mdev)); -- cgit v1.2.3 From 87255af408df98f4e1409a08e52019465bad03b7 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 14 Dec 2023 11:30:38 +0000 Subject: net: sched: ife: fix potential use-after-free [ Upstream commit 19391a2ca98baa7b80279306cdf7dd43f81fa595 ] ife_decode() calls pskb_may_pull() two times, we need to reload ifehdr after the second one, or risk use-after-free as reported by syzbot: BUG: KASAN: slab-use-after-free in __ife_tlv_meta_valid net/ife/ife.c:108 [inline] BUG: KASAN: slab-use-after-free in ife_tlv_meta_decode+0x1d1/0x210 net/ife/ife.c:131 Read of size 2 at addr ffff88802d7300a4 by task syz-executor.5/22323 CPU: 0 PID: 22323 Comm: syz-executor.5 Not tainted 6.7.0-rc3-syzkaller-00804-g074ac38d5b95 #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 11/10/2023 Call Trace: __dump_stack lib/dump_stack.c:88 [inline] dump_stack_lvl+0xd9/0x1b0 lib/dump_stack.c:106 print_address_description mm/kasan/report.c:364 [inline] print_report+0xc4/0x620 mm/kasan/report.c:475 kasan_report+0xda/0x110 mm/kasan/report.c:588 __ife_tlv_meta_valid net/ife/ife.c:108 [inline] ife_tlv_meta_decode+0x1d1/0x210 net/ife/ife.c:131 tcf_ife_decode net/sched/act_ife.c:739 [inline] tcf_ife_act+0x4e3/0x1cd0 net/sched/act_ife.c:879 tc_act include/net/tc_wrapper.h:221 [inline] tcf_action_exec+0x1ac/0x620 net/sched/act_api.c:1079 tcf_exts_exec include/net/pkt_cls.h:344 [inline] mall_classify+0x201/0x310 net/sched/cls_matchall.c:42 tc_classify include/net/tc_wrapper.h:227 [inline] __tcf_classify net/sched/cls_api.c:1703 [inline] tcf_classify+0x82f/0x1260 net/sched/cls_api.c:1800 hfsc_classify net/sched/sch_hfsc.c:1147 [inline] hfsc_enqueue+0x315/0x1060 net/sched/sch_hfsc.c:1546 dev_qdisc_enqueue+0x3f/0x230 net/core/dev.c:3739 __dev_xmit_skb net/core/dev.c:3828 [inline] __dev_queue_xmit+0x1de1/0x3d30 net/core/dev.c:4311 dev_queue_xmit include/linux/netdevice.h:3165 [inline] packet_xmit+0x237/0x350 net/packet/af_packet.c:276 packet_snd net/packet/af_packet.c:3081 [inline] packet_sendmsg+0x24aa/0x5200 net/packet/af_packet.c:3113 sock_sendmsg_nosec net/socket.c:730 [inline] __sock_sendmsg+0xd5/0x180 net/socket.c:745 __sys_sendto+0x255/0x340 net/socket.c:2190 __do_sys_sendto net/socket.c:2202 [inline] __se_sys_sendto net/socket.c:2198 [inline] __x64_sys_sendto+0xe0/0x1b0 net/socket.c:2198 do_syscall_x64 arch/x86/entry/common.c:51 [inline] do_syscall_64+0x40/0x110 arch/x86/entry/common.c:82 entry_SYSCALL_64_after_hwframe+0x63/0x6b RIP: 0033:0x7fe9acc7cae9 Code: 28 00 00 00 75 05 48 83 c4 28 c3 e8 e1 20 00 00 90 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 b0 ff ff ff f7 d8 64 89 01 48 RSP: 002b:00007fe9ada450c8 EFLAGS: 00000246 ORIG_RAX: 000000000000002c RAX: ffffffffffffffda RBX: 00007fe9acd9bf80 RCX: 00007fe9acc7cae9 RDX: 000000000000fce0 RSI: 00000000200002c0 RDI: 0000000000000003 RBP: 00007fe9accc847a R08: 0000000020000140 R09: 0000000000000014 R10: 0000000000000004 R11: 0000000000000246 R12: 0000000000000000 R13: 000000000000000b R14: 00007fe9acd9bf80 R15: 00007ffd5427ae78 Allocated by task 22323: kasan_save_stack+0x33/0x50 mm/kasan/common.c:45 kasan_set_track+0x25/0x30 mm/kasan/common.c:52 ____kasan_kmalloc mm/kasan/common.c:374 [inline] __kasan_kmalloc+0xa2/0xb0 mm/kasan/common.c:383 kasan_kmalloc include/linux/kasan.h:198 [inline] __do_kmalloc_node mm/slab_common.c:1007 [inline] __kmalloc_node_track_caller+0x5a/0x90 mm/slab_common.c:1027 kmalloc_reserve+0xef/0x260 net/core/skbuff.c:582 __alloc_skb+0x12b/0x330 net/core/skbuff.c:651 alloc_skb include/linux/skbuff.h:1298 [inline] alloc_skb_with_frags+0xe4/0x710 net/core/skbuff.c:6331 sock_alloc_send_pskb+0x7e4/0x970 net/core/sock.c:2780 packet_alloc_skb net/packet/af_packet.c:2930 [inline] packet_snd net/packet/af_packet.c:3024 [inline] packet_sendmsg+0x1e2a/0x5200 net/packet/af_packet.c:3113 sock_sendmsg_nosec net/socket.c:730 [inline] __sock_sendmsg+0xd5/0x180 net/socket.c:745 __sys_sendto+0x255/0x340 net/socket.c:2190 __do_sys_sendto net/socket.c:2202 [inline] __se_sys_sendto net/socket.c:2198 [inline] __x64_sys_sendto+0xe0/0x1b0 net/socket.c:2198 do_syscall_x64 arch/x86/entry/common.c:51 [inline] do_syscall_64+0x40/0x110 arch/x86/entry/common.c:82 entry_SYSCALL_64_after_hwframe+0x63/0x6b Freed by task 22323: kasan_save_stack+0x33/0x50 mm/kasan/common.c:45 kasan_set_track+0x25/0x30 mm/kasan/common.c:52 kasan_save_free_info+0x2b/0x40 mm/kasan/generic.c:522 ____kasan_slab_free mm/kasan/common.c:236 [inline] ____kasan_slab_free+0x15b/0x1b0 mm/kasan/common.c:200 kasan_slab_free include/linux/kasan.h:164 [inline] slab_free_hook mm/slub.c:1800 [inline] slab_free_freelist_hook+0x114/0x1e0 mm/slub.c:1826 slab_free mm/slub.c:3809 [inline] __kmem_cache_free+0xc0/0x180 mm/slub.c:3822 skb_kfree_head net/core/skbuff.c:950 [inline] skb_free_head+0x110/0x1b0 net/core/skbuff.c:962 pskb_expand_head+0x3c5/0x1170 net/core/skbuff.c:2130 __pskb_pull_tail+0xe1/0x1830 net/core/skbuff.c:2655 pskb_may_pull_reason include/linux/skbuff.h:2685 [inline] pskb_may_pull include/linux/skbuff.h:2693 [inline] ife_decode+0x394/0x4f0 net/ife/ife.c:82 tcf_ife_decode net/sched/act_ife.c:727 [inline] tcf_ife_act+0x43b/0x1cd0 net/sched/act_ife.c:879 tc_act include/net/tc_wrapper.h:221 [inline] tcf_action_exec+0x1ac/0x620 net/sched/act_api.c:1079 tcf_exts_exec include/net/pkt_cls.h:344 [inline] mall_classify+0x201/0x310 net/sched/cls_matchall.c:42 tc_classify include/net/tc_wrapper.h:227 [inline] __tcf_classify net/sched/cls_api.c:1703 [inline] tcf_classify+0x82f/0x1260 net/sched/cls_api.c:1800 hfsc_classify net/sched/sch_hfsc.c:1147 [inline] hfsc_enqueue+0x315/0x1060 net/sched/sch_hfsc.c:1546 dev_qdisc_enqueue+0x3f/0x230 net/core/dev.c:3739 __dev_xmit_skb net/core/dev.c:3828 [inline] __dev_queue_xmit+0x1de1/0x3d30 net/core/dev.c:4311 dev_queue_xmit include/linux/netdevice.h:3165 [inline] packet_xmit+0x237/0x350 net/packet/af_packet.c:276 packet_snd net/packet/af_packet.c:3081 [inline] packet_sendmsg+0x24aa/0x5200 net/packet/af_packet.c:3113 sock_sendmsg_nosec net/socket.c:730 [inline] __sock_sendmsg+0xd5/0x180 net/socket.c:745 __sys_sendto+0x255/0x340 net/socket.c:2190 __do_sys_sendto net/socket.c:2202 [inline] __se_sys_sendto net/socket.c:2198 [inline] __x64_sys_sendto+0xe0/0x1b0 net/socket.c:2198 do_syscall_x64 arch/x86/entry/common.c:51 [inline] do_syscall_64+0x40/0x110 arch/x86/entry/common.c:82 entry_SYSCALL_64_after_hwframe+0x63/0x6b The buggy address belongs to the object at ffff88802d730000 which belongs to the cache kmalloc-8k of size 8192 The buggy address is located 164 bytes inside of freed 8192-byte region [ffff88802d730000, ffff88802d732000) The buggy address belongs to the physical page: page:ffffea0000b5cc00 refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x2d730 head:ffffea0000b5cc00 order:3 entire_mapcount:0 nr_pages_mapped:0 pincount:0 flags: 0xfff00000000840(slab|head|node=0|zone=1|lastcpupid=0x7ff) page_type: 0xffffffff() raw: 00fff00000000840 ffff888013042280 dead000000000122 0000000000000000 raw: 0000000000000000 0000000080020002 00000001ffffffff 0000000000000000 page dumped because: kasan: bad access detected page_owner tracks the page as allocated page last allocated via order 3, migratetype Unmovable, gfp_mask 0x1d20c0(__GFP_IO|__GFP_FS|__GFP_NOWARN|__GFP_NORETRY|__GFP_COMP|__GFP_NOMEMALLOC|__GFP_HARDWALL), pid 22323, tgid 22320 (syz-executor.5), ts 950317230369, free_ts 950233467461 set_page_owner include/linux/page_owner.h:31 [inline] post_alloc_hook+0x2d0/0x350 mm/page_alloc.c:1544 prep_new_page mm/page_alloc.c:1551 [inline] get_page_from_freelist+0xa28/0x3730 mm/page_alloc.c:3319 __alloc_pages+0x22e/0x2420 mm/page_alloc.c:4575 alloc_pages_mpol+0x258/0x5f0 mm/mempolicy.c:2133 alloc_slab_page mm/slub.c:1870 [inline] allocate_slab mm/slub.c:2017 [inline] new_slab+0x283/0x3c0 mm/slub.c:2070 ___slab_alloc+0x979/0x1500 mm/slub.c:3223 __slab_alloc.constprop.0+0x56/0xa0 mm/slub.c:3322 __slab_alloc_node mm/slub.c:3375 [inline] slab_alloc_node mm/slub.c:3468 [inline] __kmem_cache_alloc_node+0x131/0x310 mm/slub.c:3517 __do_kmalloc_node mm/slab_common.c:1006 [inline] __kmalloc_node_track_caller+0x4a/0x90 mm/slab_common.c:1027 kmalloc_reserve+0xef/0x260 net/core/skbuff.c:582 __alloc_skb+0x12b/0x330 net/core/skbuff.c:651 alloc_skb include/linux/skbuff.h:1298 [inline] alloc_skb_with_frags+0xe4/0x710 net/core/skbuff.c:6331 sock_alloc_send_pskb+0x7e4/0x970 net/core/sock.c:2780 packet_alloc_skb net/packet/af_packet.c:2930 [inline] packet_snd net/packet/af_packet.c:3024 [inline] packet_sendmsg+0x1e2a/0x5200 net/packet/af_packet.c:3113 sock_sendmsg_nosec net/socket.c:730 [inline] __sock_sendmsg+0xd5/0x180 net/socket.c:745 __sys_sendto+0x255/0x340 net/socket.c:2190 page last free stack trace: reset_page_owner include/linux/page_owner.h:24 [inline] free_pages_prepare mm/page_alloc.c:1144 [inline] free_unref_page_prepare+0x53c/0xb80 mm/page_alloc.c:2354 free_unref_page+0x33/0x3b0 mm/page_alloc.c:2494 __unfreeze_partials+0x226/0x240 mm/slub.c:2655 qlink_free mm/kasan/quarantine.c:168 [inline] qlist_free_all+0x6a/0x170 mm/kasan/quarantine.c:187 kasan_quarantine_reduce+0x18e/0x1d0 mm/kasan/quarantine.c:294 __kasan_slab_alloc+0x65/0x90 mm/kasan/common.c:305 kasan_slab_alloc include/linux/kasan.h:188 [inline] slab_post_alloc_hook mm/slab.h:763 [inline] slab_alloc_node mm/slub.c:3478 [inline] slab_alloc mm/slub.c:3486 [inline] __kmem_cache_alloc_lru mm/slub.c:3493 [inline] kmem_cache_alloc_lru+0x219/0x6f0 mm/slub.c:3509 alloc_inode_sb include/linux/fs.h:2937 [inline] ext4_alloc_inode+0x28/0x650 fs/ext4/super.c:1408 alloc_inode+0x5d/0x220 fs/inode.c:261 new_inode_pseudo fs/inode.c:1006 [inline] new_inode+0x22/0x260 fs/inode.c:1032 __ext4_new_inode+0x333/0x5200 fs/ext4/ialloc.c:958 ext4_symlink+0x5d7/0xa20 fs/ext4/namei.c:3398 vfs_symlink fs/namei.c:4464 [inline] vfs_symlink+0x3e5/0x620 fs/namei.c:4448 do_symlinkat+0x25f/0x310 fs/namei.c:4490 __do_sys_symlinkat fs/namei.c:4506 [inline] __se_sys_symlinkat fs/namei.c:4503 [inline] __x64_sys_symlinkat+0x97/0xc0 fs/namei.c:4503 do_syscall_x64 arch/x86/entry/common.c:51 [inline] do_syscall_64+0x40/0x110 arch/x86/entry/common.c:82 Fixes: d57493d6d1be ("net: sched: ife: check on metadata length") Reported-by: syzbot Signed-off-by: Eric Dumazet Cc: Jamal Hadi Salim Cc: Alexander Aring Acked-by: Jamal Hadi Salim Signed-off-by: David S. Miller Signed-off-by: Sasha Levin --- net/ife/ife.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/ife/ife.c b/net/ife/ife.c index 13bbf8cb6a39..be05b690b9ef 100644 --- a/net/ife/ife.c +++ b/net/ife/ife.c @@ -82,6 +82,7 @@ void *ife_decode(struct sk_buff *skb, u16 *metalen) if (unlikely(!pskb_may_pull(skb, total_pull))) return NULL; + ifehdr = (struct ifeheadr *)(skb->data + skb->dev->hard_header_len); skb_set_mac_header(skb, total_pull); __skb_pull(skb, total_pull); *metalen = ifehdrln - IFE_METAHDRLEN; -- cgit v1.2.3 From 66d2116880e6f415e4fac7ed9882c76d55438e1e Mon Sep 17 00:00:00 2001 From: Zhipeng Lu Date: Thu, 14 Dec 2023 21:04:04 +0800 Subject: ethernet: atheros: fix a memleak in atl1e_setup_ring_resources [ Upstream commit 309fdb1c33fe726d92d0030481346f24e1b01f07 ] In the error handling of 'offset > adapter->ring_size', the tx_ring->tx_buffer allocated by kzalloc should be freed, instead of 'goto failed' instantly. Fixes: a6a5325239c2 ("atl1e: Atheros L1E Gigabit Ethernet driver") Signed-off-by: Zhipeng Lu Reviewed-by: Suman Ghosh Signed-off-by: David S. Miller Signed-off-by: Sasha Levin --- drivers/net/ethernet/atheros/atl1e/atl1e_main.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c index db13311e77e7..dc1165f11b6e 100644 --- a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c +++ b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c @@ -866,10 +866,13 @@ static int atl1e_setup_ring_resources(struct atl1e_adapter *adapter) netdev_err(adapter->netdev, "offset(%d) > ring size(%d) !!\n", offset, adapter->ring_size); err = -1; - goto failed; + goto free_buffer; } return 0; +free_buffer: + kfree(tx_ring->tx_buffer); + tx_ring->tx_buffer = NULL; failed: if (adapter->ring_vir_addr != NULL) { dma_free_coherent(&pdev->dev, adapter->ring_size, -- cgit v1.2.3 From c0e527c532a07556ca44642f5873b002c44da22c Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 14 Dec 2023 15:27:47 +0000 Subject: net/rose: fix races in rose_kill_by_device() [ Upstream commit 64b8bc7d5f1434c636a40bdcfcd42b278d1714be ] syzbot found an interesting netdev refcounting issue in net/rose/af_rose.c, thanks to CONFIG_NET_DEV_REFCNT_TRACKER=y [1] Problem is that rose_kill_by_device() can change rose->device while other threads do not expect the pointer to be changed. We have to first collect sockets in a temporary array, then perform the changes while holding the socket lock and rose_list_lock spinlock (in this order) Change rose_release() to also acquire rose_list_lock before releasing the netdev refcount. [1] [ 1185.055088][ T7889] ref_tracker: reference already released. [ 1185.061476][ T7889] ref_tracker: allocated in: [ 1185.066081][ T7889] rose_bind+0x4ab/0xd10 [ 1185.070446][ T7889] __sys_bind+0x1ec/0x220 [ 1185.074818][ T7889] __x64_sys_bind+0x72/0xb0 [ 1185.079356][ T7889] do_syscall_64+0x40/0x110 [ 1185.083897][ T7889] entry_SYSCALL_64_after_hwframe+0x63/0x6b [ 1185.089835][ T7889] ref_tracker: freed in: [ 1185.094088][ T7889] rose_release+0x2f5/0x570 [ 1185.098629][ T7889] __sock_release+0xae/0x260 [ 1185.103262][ T7889] sock_close+0x1c/0x20 [ 1185.107453][ T7889] __fput+0x270/0xbb0 [ 1185.111467][ T7889] task_work_run+0x14d/0x240 [ 1185.116085][ T7889] get_signal+0x106f/0x2790 [ 1185.120622][ T7889] arch_do_signal_or_restart+0x90/0x7f0 [ 1185.126205][ T7889] exit_to_user_mode_prepare+0x121/0x240 [ 1185.131846][ T7889] syscall_exit_to_user_mode+0x1e/0x60 [ 1185.137293][ T7889] do_syscall_64+0x4d/0x110 [ 1185.141783][ T7889] entry_SYSCALL_64_after_hwframe+0x63/0x6b [ 1185.148085][ T7889] ------------[ cut here ]------------ WARNING: CPU: 1 PID: 7889 at lib/ref_tracker.c:255 ref_tracker_free+0x61a/0x810 lib/ref_tracker.c:255 Modules linked in: CPU: 1 PID: 7889 Comm: syz-executor.2 Not tainted 6.7.0-rc4-syzkaller-00162-g65c95f78917e #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 11/10/2023 RIP: 0010:ref_tracker_free+0x61a/0x810 lib/ref_tracker.c:255 Code: 00 44 8b 6b 18 31 ff 44 89 ee e8 21 62 f5 fc 45 85 ed 0f 85 a6 00 00 00 e8 a3 66 f5 fc 48 8b 34 24 48 89 ef e8 27 5f f1 05 90 <0f> 0b 90 bb ea ff ff ff e9 52 fd ff ff e8 84 66 f5 fc 4c 8d 6d 44 RSP: 0018:ffffc90004917850 EFLAGS: 00010202 RAX: 0000000000000201 RBX: ffff88802618f4c0 RCX: 0000000000000000 RDX: 0000000000000202 RSI: ffffffff8accb920 RDI: 0000000000000001 RBP: ffff8880269ea5b8 R08: 0000000000000001 R09: fffffbfff23e35f6 R10: ffffffff91f1afb7 R11: 0000000000000001 R12: 1ffff92000922f0c R13: 0000000005a2039b R14: ffff88802618f4d8 R15: 00000000ffffffff FS: 00007f0a720ef6c0(0000) GS:ffff8880b9900000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007f43a819d988 CR3: 0000000076c64000 CR4: 00000000003506f0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 Call Trace: netdev_tracker_free include/linux/netdevice.h:4127 [inline] netdev_put include/linux/netdevice.h:4144 [inline] netdev_put include/linux/netdevice.h:4140 [inline] rose_kill_by_device net/rose/af_rose.c:195 [inline] rose_device_event+0x25d/0x330 net/rose/af_rose.c:218 notifier_call_chain+0xb6/0x3b0 kernel/notifier.c:93 call_netdevice_notifiers_info+0xbe/0x130 net/core/dev.c:1967 call_netdevice_notifiers_extack net/core/dev.c:2005 [inline] call_netdevice_notifiers net/core/dev.c:2019 [inline] __dev_notify_flags+0x1f5/0x2e0 net/core/dev.c:8646 dev_change_flags+0x122/0x170 net/core/dev.c:8682 dev_ifsioc+0x9ad/0x1090 net/core/dev_ioctl.c:529 dev_ioctl+0x224/0x1090 net/core/dev_ioctl.c:786 sock_do_ioctl+0x198/0x270 net/socket.c:1234 sock_ioctl+0x22e/0x6b0 net/socket.c:1339 vfs_ioctl fs/ioctl.c:51 [inline] __do_sys_ioctl fs/ioctl.c:871 [inline] __se_sys_ioctl fs/ioctl.c:857 [inline] __x64_sys_ioctl+0x18f/0x210 fs/ioctl.c:857 do_syscall_x64 arch/x86/entry/common.c:52 [inline] do_syscall_64+0x40/0x110 arch/x86/entry/common.c:83 entry_SYSCALL_64_after_hwframe+0x63/0x6b RIP: 0033:0x7f0a7147cba9 Code: 28 00 00 00 75 05 48 83 c4 28 c3 e8 e1 20 00 00 90 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 b0 ff ff ff f7 d8 64 89 01 48 RSP: 002b:00007f0a720ef0c8 EFLAGS: 00000246 ORIG_RAX: 0000000000000010 RAX: ffffffffffffffda RBX: 00007f0a7159bf80 RCX: 00007f0a7147cba9 RDX: 0000000020000040 RSI: 0000000000008914 RDI: 0000000000000004 RBP: 00007f0a714c847a R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000 R13: 000000000000000b R14: 00007f0a7159bf80 R15: 00007ffc8bb3a5f8 Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Reported-by: syzbot Signed-off-by: Eric Dumazet Cc: Bernard Pidoux Signed-off-by: David S. Miller Signed-off-by: Sasha Levin --- net/rose/af_rose.c | 39 ++++++++++++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c index b3e7a92f1ec1..1d95ff34b13c 100644 --- a/net/rose/af_rose.c +++ b/net/rose/af_rose.c @@ -181,21 +181,47 @@ void rose_kill_by_neigh(struct rose_neigh *neigh) */ static void rose_kill_by_device(struct net_device *dev) { - struct sock *s; + struct sock *sk, *array[16]; + struct rose_sock *rose; + bool rescan; + int i, cnt; +start: + rescan = false; + cnt = 0; spin_lock_bh(&rose_list_lock); - sk_for_each(s, &rose_list) { - struct rose_sock *rose = rose_sk(s); + sk_for_each(sk, &rose_list) { + rose = rose_sk(sk); + if (rose->device == dev) { + if (cnt == ARRAY_SIZE(array)) { + rescan = true; + break; + } + sock_hold(sk); + array[cnt++] = sk; + } + } + spin_unlock_bh(&rose_list_lock); + for (i = 0; i < cnt; i++) { + sk = array[cnt]; + rose = rose_sk(sk); + lock_sock(sk); + spin_lock_bh(&rose_list_lock); if (rose->device == dev) { - rose_disconnect(s, ENETUNREACH, ROSE_OUT_OF_ORDER, 0); + rose_disconnect(sk, ENETUNREACH, ROSE_OUT_OF_ORDER, 0); if (rose->neighbour) rose->neighbour->use--; dev_put(rose->device); rose->device = NULL; } + spin_unlock_bh(&rose_list_lock); + release_sock(sk); + sock_put(sk); + cond_resched(); } - spin_unlock_bh(&rose_list_lock); + if (rescan) + goto start; } /* @@ -655,7 +681,10 @@ static int rose_release(struct socket *sock) break; } + spin_lock_bh(&rose_list_lock); dev_put(rose->device); + rose->device = NULL; + spin_unlock_bh(&rose_list_lock); sock->sk = NULL; release_sock(sk); sock_put(sk); -- cgit v1.2.3 From c124a75b2497f93353194fac29f1e890034d903c Mon Sep 17 00:00:00 2001 From: Yury Norov Date: Fri, 15 Dec 2023 12:33:53 -0800 Subject: net: mana: select PAGE_POOL [ Upstream commit 340943fbff3d8faa44d2223ca04917df28786a07 ] Mana uses PAGE_POOL API. x86_64 defconfig doesn't select it: ld: vmlinux.o: in function `mana_create_page_pool.isra.0': mana_en.c:(.text+0x9ae36f): undefined reference to `page_pool_create' ld: vmlinux.o: in function `mana_get_rxfrag': mana_en.c:(.text+0x9afed1): undefined reference to `page_pool_alloc_pages' make[3]: *** [/home/yury/work/linux/scripts/Makefile.vmlinux:37: vmlinux] Error 1 make[2]: *** [/home/yury/work/linux/Makefile:1154: vmlinux] Error 2 make[1]: *** [/home/yury/work/linux/Makefile:234: __sub-make] Error 2 make[1]: Leaving directory '/home/yury/work/build-linux-x86_64' make: *** [Makefile:234: __sub-make] Error 2 So we need to select it explicitly. Signed-off-by: Yury Norov Reviewed-by: Simon Horman Tested-by: Simon Horman # build-tested Fixes: ca9c54d2 ("net: mana: Add a driver for Microsoft Azure Network Adapter") Link: https://lore.kernel.org/r/20231215203353.635379-1-yury.norov@gmail.com Signed-off-by: Paolo Abeni Signed-off-by: Sasha Levin --- drivers/net/ethernet/microsoft/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ethernet/microsoft/Kconfig b/drivers/net/ethernet/microsoft/Kconfig index fe4e7a7d9c0b..8b6c4cc37c53 100644 --- a/drivers/net/ethernet/microsoft/Kconfig +++ b/drivers/net/ethernet/microsoft/Kconfig @@ -19,6 +19,7 @@ config MICROSOFT_MANA tristate "Microsoft Azure Network Adapter (MANA) support" depends on PCI_MSI && X86_64 depends on PCI_HYPERV + select PAGE_POOL help This driver supports Microsoft Azure Network Adapter (MANA). So far, the driver is only supported on X86_64. -- cgit v1.2.3 From 3739e0a52d4d7fe49da89093da04b47e70a28b38 Mon Sep 17 00:00:00 2001 From: Liu Jian Date: Sat, 16 Dec 2023 15:52:18 +0800 Subject: net: check vlan filter feature in vlan_vids_add_by_dev() and vlan_vids_del_by_dev() [ Upstream commit 01a564bab4876007ce35f312e16797dfe40e4823 ] I got the below warning trace: WARNING: CPU: 4 PID: 4056 at net/core/dev.c:11066 unregister_netdevice_many_notify CPU: 4 PID: 4056 Comm: ip Not tainted 6.7.0-rc4+ #15 Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.15.0-1 04/01/2014 RIP: 0010:unregister_netdevice_many_notify+0x9a4/0x9b0 Call Trace: rtnl_dellink rtnetlink_rcv_msg netlink_rcv_skb netlink_unicast netlink_sendmsg __sock_sendmsg ____sys_sendmsg ___sys_sendmsg __sys_sendmsg do_syscall_64 entry_SYSCALL_64_after_hwframe It can be repoduced via: ip netns add ns1 ip netns exec ns1 ip link add bond0 type bond mode 0 ip netns exec ns1 ip link add bond_slave_1 type veth peer veth2 ip netns exec ns1 ip link set bond_slave_1 master bond0 [1] ip netns exec ns1 ethtool -K bond0 rx-vlan-filter off [2] ip netns exec ns1 ip link add link bond_slave_1 name bond_slave_1.0 type vlan id 0 [3] ip netns exec ns1 ip link add link bond0 name bond0.0 type vlan id 0 [4] ip netns exec ns1 ip link set bond_slave_1 nomaster [5] ip netns exec ns1 ip link del veth2 ip netns del ns1 This is all caused by command [1] turning off the rx-vlan-filter function of bond0. The reason is the same as commit 01f4fd270870 ("bonding: Fix incorrect deletion of ETH_P_8021AD protocol vid from slaves"). Commands [2] [3] add the same vid to slave and master respectively, causing command [4] to empty slave->vlan_info. The following command [5] triggers this problem. To fix this problem, we should add VLAN_FILTER feature checks in vlan_vids_add_by_dev() and vlan_vids_del_by_dev() to prevent incorrect addition or deletion of vlan_vid information. Fixes: 348a1443cc43 ("vlan: introduce functions to do mass addition/deletion of vids by another device") Signed-off-by: Liu Jian Signed-off-by: Paolo Abeni Signed-off-by: Sasha Levin --- net/8021q/vlan_core.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c index 59bc13b5f14f..8710d5d7d3c1 100644 --- a/net/8021q/vlan_core.c +++ b/net/8021q/vlan_core.c @@ -407,6 +407,8 @@ int vlan_vids_add_by_dev(struct net_device *dev, return 0; list_for_each_entry(vid_info, &vlan_info->vid_list, list) { + if (!vlan_hw_filter_capable(by_dev, vid_info->proto)) + continue; err = vlan_vid_add(dev, vid_info->proto, vid_info->vid); if (err) goto unwind; @@ -417,6 +419,8 @@ unwind: list_for_each_entry_continue_reverse(vid_info, &vlan_info->vid_list, list) { + if (!vlan_hw_filter_capable(by_dev, vid_info->proto)) + continue; vlan_vid_del(dev, vid_info->proto, vid_info->vid); } @@ -436,8 +440,11 @@ void vlan_vids_del_by_dev(struct net_device *dev, if (!vlan_info) return; - list_for_each_entry(vid_info, &vlan_info->vid_list, list) + list_for_each_entry(vid_info, &vlan_info->vid_list, list) { + if (!vlan_hw_filter_capable(by_dev, vid_info->proto)) + continue; vlan_vid_del(dev, vid_info->proto, vid_info->vid); + } } EXPORT_SYMBOL(vlan_vids_del_by_dev); -- cgit v1.2.3 From 3f85785bc4ac744fc500094690d9f1470d8cfa53 Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 11 Dec 2023 15:08:57 +0000 Subject: afs: Fix the dynamic root's d_delete to always delete unused dentries [ Upstream commit 71f8b55bc30e82d6355e07811213d847981a32e2 ] Fix the afs dynamic root's d_delete function to always delete unused dentries rather than only deleting them if they're positive. With things as they stand upstream, negative dentries stemming from failed DNS lookups stick around preventing retries. Fixes: 66c7e1d319a5 ("afs: Split the dynroot stuff out and give it its own ops tables") Signed-off-by: David Howells Tested-by: Markus Suvanto cc: Marc Dionne cc: linux-afs@lists.infradead.org Signed-off-by: Sasha Levin --- fs/afs/dynroot.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/fs/afs/dynroot.c b/fs/afs/dynroot.c index b35c6081dbfe..4ddc4846a807 100644 --- a/fs/afs/dynroot.c +++ b/fs/afs/dynroot.c @@ -251,20 +251,9 @@ static int afs_dynroot_d_revalidate(struct dentry *dentry, unsigned int flags) return 1; } -/* - * Allow the VFS to enquire as to whether a dentry should be unhashed (mustn't - * sleep) - * - called from dput() when d_count is going to 0. - * - return 1 to request dentry be unhashed, 0 otherwise - */ -static int afs_dynroot_d_delete(const struct dentry *dentry) -{ - return d_really_is_positive(dentry); -} - const struct dentry_operations afs_dynroot_dentry_operations = { .d_revalidate = afs_dynroot_d_revalidate, - .d_delete = afs_dynroot_d_delete, + .d_delete = always_delete_dentry, .d_release = afs_d_release, .d_automount = afs_d_automount, }; -- cgit v1.2.3 From 56eaa3ec314098a18ed935313268679a1e3ccd9a Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 11 Dec 2023 15:15:02 +0000 Subject: afs: Fix dynamic root lookup DNS check [ Upstream commit 74cef6872ceaefb5b6c5c60641371ea28702d358 ] In the afs dynamic root directory, the ->lookup() function does a DNS check on the cell being asked for and if the DNS upcall reports an error it will report an error back to userspace (typically ENOENT). However, if a failed DNS upcall returns a new-style result, it will return a valid result, with the status field set appropriately to indicate the type of failure - and in that case, dns_query() doesn't return an error and we let stat() complete with no error - which can cause confusion in userspace as subsequent calls that trigger d_automount then fail with ENOENT. Fix this by checking the status result from a valid dns_query() and returning an error if it indicates a failure. Fixes: bbb4c4323a4d ("dns: Allow the dns resolver to retrieve a server set") Reported-by: Markus Suvanto Closes: https://bugzilla.kernel.org/show_bug.cgi?id=216637 Signed-off-by: David Howells Tested-by: Markus Suvanto cc: Marc Dionne cc: linux-afs@lists.infradead.org Signed-off-by: Sasha Levin --- fs/afs/dynroot.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/fs/afs/dynroot.c b/fs/afs/dynroot.c index 4ddc4846a807..96b404d9e13a 100644 --- a/fs/afs/dynroot.c +++ b/fs/afs/dynroot.c @@ -113,6 +113,7 @@ static int afs_probe_cell_name(struct dentry *dentry) struct afs_net *net = afs_d2net(dentry); const char *name = dentry->d_name.name; size_t len = dentry->d_name.len; + char *result = NULL; int ret; /* Names prefixed with a dot are R/W mounts. */ @@ -130,9 +131,22 @@ static int afs_probe_cell_name(struct dentry *dentry) } ret = dns_query(net->net, "afsdb", name, len, "srv=1", - NULL, NULL, false); - if (ret == -ENODATA || ret == -ENOKEY) + &result, NULL, false); + if (ret == -ENODATA || ret == -ENOKEY || ret == 0) ret = -ENOENT; + if (ret > 0 && ret >= sizeof(struct dns_server_list_v1_header)) { + struct dns_server_list_v1_header *v1 = (void *)result; + + if (v1->hdr.zero == 0 && + v1->hdr.content == DNS_PAYLOAD_IS_SERVER_LIST && + v1->hdr.version == 1 && + (v1->status != DNS_LOOKUP_GOOD && + v1->status != DNS_LOOKUP_GOOD_WITH_BAD)) + return -ENOENT; + + } + + kfree(result); return ret; } -- cgit v1.2.3 From a1ab650f1421af85657b436ec10e6cd7b9e43b0c Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 19 Dec 2023 12:53:31 +0000 Subject: net: check dev->gso_max_size in gso_features_check() [ Upstream commit 24ab059d2ebd62fdccc43794796f6ffbabe49ebc ] Some drivers might misbehave if TSO packets get too big. GVE for instance uses a 16bit field in its TX descriptor, and will do bad things if a packet is bigger than 2^16 bytes. Linux TCP stack honors dev->gso_max_size, but there are other ways for too big packets to reach an ndo_start_xmit() handler : virtio_net, af_packet, GRO... Add a generic check in gso_features_check() and fallback to GSO when needed. gso_max_size was added in the blamed commit. Fixes: 82cc1a7a5687 ("[NET]: Add per-connection option to set max TSO frame size") Signed-off-by: Eric Dumazet Link: https://lore.kernel.org/r/20231219125331.4127498-1-edumazet@google.com Signed-off-by: Paolo Abeni Signed-off-by: Sasha Levin --- net/core/dev.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/core/dev.c b/net/core/dev.c index 8f4f355a963f..8501645ff67d 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -3540,6 +3540,9 @@ static netdev_features_t gso_features_check(const struct sk_buff *skb, if (gso_segs > dev->gso_max_segs) return features & ~NETIF_F_GSO_MASK; + if (unlikely(skb->len >= READ_ONCE(dev->gso_max_size))) + return features & ~NETIF_F_GSO_MASK; + if (!skb_shinfo(skb)->gso_type) { skb_warn_bad_offload(skb); return features & ~NETIF_F_GSO_MASK; -- cgit v1.2.3 From 2552b32b0b349df160a509fe49f5f308cb922f2b Mon Sep 17 00:00:00 2001 From: David Howells Date: Sat, 9 Dec 2023 00:41:55 +0000 Subject: keys, dns: Allow key types (eg. DNS) to be reclaimed immediately on expiry [ Upstream commit 39299bdd2546688d92ed9db4948f6219ca1b9542 ] If a key has an expiration time, then when that time passes, the key is left around for a certain amount of time before being collected (5 mins by default) so that EKEYEXPIRED can be returned instead of ENOKEY. This is a problem for DNS keys because we want to redo the DNS lookup immediately at that point. Fix this by allowing key types to be marked such that keys of that type don't have this extra period, but are reclaimed as soon as they expire and turn this on for dns_resolver-type keys. To make this easier to handle, key->expiry is changed to be permanent if TIME64_MAX rather than 0. Furthermore, give such new-style negative DNS results a 1s default expiry if no other expiry time is set rather than allowing it to stick around indefinitely. This shouldn't be zero as ls will follow a failing stat call immediately with a second with AT_SYMLINK_NOFOLLOW added. Fixes: 1a4240f4764a ("DNS: Separate out CIFS DNS Resolver code") Signed-off-by: David Howells Tested-by: Markus Suvanto cc: Wang Lei cc: Jeff Layton cc: Steve French cc: Marc Dionne cc: Jarkko Sakkinen cc: "David S. Miller" cc: Eric Dumazet cc: Jakub Kicinski cc: Paolo Abeni cc: linux-afs@lists.infradead.org cc: linux-cifs@vger.kernel.org cc: linux-nfs@vger.kernel.org cc: ceph-devel@vger.kernel.org cc: keyrings@vger.kernel.org cc: netdev@vger.kernel.org Signed-off-by: Sasha Levin --- include/linux/key-type.h | 1 + net/dns_resolver/dns_key.c | 10 +++++++++- security/keys/gc.c | 31 +++++++++++++++++++++---------- security/keys/internal.h | 11 ++++++++++- security/keys/key.c | 15 +++++---------- security/keys/proc.c | 2 +- 6 files changed, 47 insertions(+), 23 deletions(-) diff --git a/include/linux/key-type.h b/include/linux/key-type.h index 7d985a1dfe4a..5caf3ce82373 100644 --- a/include/linux/key-type.h +++ b/include/linux/key-type.h @@ -73,6 +73,7 @@ struct key_type { unsigned int flags; #define KEY_TYPE_NET_DOMAIN 0x00000001 /* Keys of this type have a net namespace domain */ +#define KEY_TYPE_INSTANT_REAP 0x00000002 /* Keys of this type don't have a delay after expiring */ /* vet a description */ int (*vet_description)(const char *description); diff --git a/net/dns_resolver/dns_key.c b/net/dns_resolver/dns_key.c index 3aced951d5ab..03f8f33dc134 100644 --- a/net/dns_resolver/dns_key.c +++ b/net/dns_resolver/dns_key.c @@ -91,6 +91,7 @@ const struct cred *dns_resolver_cache; static int dns_resolver_preparse(struct key_preparsed_payload *prep) { + const struct dns_server_list_v1_header *v1; const struct dns_payload_header *bin; struct user_key_payload *upayload; unsigned long derrno; @@ -122,6 +123,13 @@ dns_resolver_preparse(struct key_preparsed_payload *prep) return -EINVAL; } + v1 = (const struct dns_server_list_v1_header *)bin; + if ((v1->status != DNS_LOOKUP_GOOD && + v1->status != DNS_LOOKUP_GOOD_WITH_BAD)) { + if (prep->expiry == TIME64_MAX) + prep->expiry = ktime_get_real_seconds() + 1; + } + result_len = datalen; goto store_result; } @@ -314,7 +322,7 @@ static long dns_resolver_read(const struct key *key, struct key_type key_type_dns_resolver = { .name = "dns_resolver", - .flags = KEY_TYPE_NET_DOMAIN, + .flags = KEY_TYPE_NET_DOMAIN | KEY_TYPE_INSTANT_REAP, .preparse = dns_resolver_preparse, .free_preparse = dns_resolver_free_preparse, .instantiate = generic_key_instantiate, diff --git a/security/keys/gc.c b/security/keys/gc.c index 3c90807476eb..eaddaceda14e 100644 --- a/security/keys/gc.c +++ b/security/keys/gc.c @@ -66,6 +66,19 @@ void key_schedule_gc(time64_t gc_at) } } +/* + * Set the expiration time on a key. + */ +void key_set_expiry(struct key *key, time64_t expiry) +{ + key->expiry = expiry; + if (expiry != TIME64_MAX) { + if (!(key->type->flags & KEY_TYPE_INSTANT_REAP)) + expiry += key_gc_delay; + key_schedule_gc(expiry); + } +} + /* * Schedule a dead links collection run. */ @@ -176,7 +189,6 @@ static void key_garbage_collector(struct work_struct *work) static u8 gc_state; /* Internal persistent state */ #define KEY_GC_REAP_AGAIN 0x01 /* - Need another cycle */ #define KEY_GC_REAPING_LINKS 0x02 /* - We need to reap links */ -#define KEY_GC_SET_TIMER 0x04 /* - We need to restart the timer */ #define KEY_GC_REAPING_DEAD_1 0x10 /* - We need to mark dead keys */ #define KEY_GC_REAPING_DEAD_2 0x20 /* - We need to reap dead key links */ #define KEY_GC_REAPING_DEAD_3 0x40 /* - We need to reap dead keys */ @@ -184,21 +196,17 @@ static void key_garbage_collector(struct work_struct *work) struct rb_node *cursor; struct key *key; - time64_t new_timer, limit; + time64_t new_timer, limit, expiry; kenter("[%lx,%x]", key_gc_flags, gc_state); limit = ktime_get_real_seconds(); - if (limit > key_gc_delay) - limit -= key_gc_delay; - else - limit = key_gc_delay; /* Work out what we're going to be doing in this pass */ gc_state &= KEY_GC_REAPING_DEAD_1 | KEY_GC_REAPING_DEAD_2; gc_state <<= 1; if (test_and_clear_bit(KEY_GC_KEY_EXPIRED, &key_gc_flags)) - gc_state |= KEY_GC_REAPING_LINKS | KEY_GC_SET_TIMER; + gc_state |= KEY_GC_REAPING_LINKS; if (test_and_clear_bit(KEY_GC_REAP_KEYTYPE, &key_gc_flags)) gc_state |= KEY_GC_REAPING_DEAD_1; @@ -233,8 +241,11 @@ continue_scanning: } } - if (gc_state & KEY_GC_SET_TIMER) { - if (key->expiry > limit && key->expiry < new_timer) { + expiry = key->expiry; + if (expiry != TIME64_MAX) { + if (!(key->type->flags & KEY_TYPE_INSTANT_REAP)) + expiry += key_gc_delay; + if (expiry > limit && expiry < new_timer) { kdebug("will expire %x in %lld", key_serial(key), key->expiry - limit); new_timer = key->expiry; @@ -276,7 +287,7 @@ maybe_resched: */ kdebug("pass complete"); - if (gc_state & KEY_GC_SET_TIMER && new_timer != (time64_t)TIME64_MAX) { + if (new_timer != TIME64_MAX) { new_timer += key_gc_delay; key_schedule_gc(new_timer); } diff --git a/security/keys/internal.h b/security/keys/internal.h index 9b9cf3b6fcbb..bede6c71ffd9 100644 --- a/security/keys/internal.h +++ b/security/keys/internal.h @@ -176,6 +176,7 @@ extern unsigned key_gc_delay; extern void keyring_gc(struct key *keyring, time64_t limit); extern void keyring_restriction_gc(struct key *keyring, struct key_type *dead_type); +void key_set_expiry(struct key *key, time64_t expiry); extern void key_schedule_gc(time64_t gc_at); extern void key_schedule_gc_links(void); extern void key_gc_keytype(struct key_type *ktype); @@ -224,10 +225,18 @@ extern struct key *key_get_instantiation_authkey(key_serial_t target_id); */ static inline bool key_is_dead(const struct key *key, time64_t limit) { + time64_t expiry = key->expiry; + + if (expiry != TIME64_MAX) { + if (!(key->type->flags & KEY_TYPE_INSTANT_REAP)) + expiry += key_gc_delay; + if (expiry <= limit) + return true; + } + return key->flags & ((1 << KEY_FLAG_DEAD) | (1 << KEY_FLAG_INVALIDATED)) || - (key->expiry > 0 && key->expiry <= limit) || key->domain_tag->removed; } diff --git a/security/keys/key.c b/security/keys/key.c index c45afdd1dfbb..e65240641ca5 100644 --- a/security/keys/key.c +++ b/security/keys/key.c @@ -294,6 +294,7 @@ struct key *key_alloc(struct key_type *type, const char *desc, key->uid = uid; key->gid = gid; key->perm = perm; + key->expiry = TIME64_MAX; key->restrict_link = restrict_link; key->last_used_at = ktime_get_real_seconds(); @@ -463,10 +464,7 @@ static int __key_instantiate_and_link(struct key *key, if (authkey) key_invalidate(authkey); - if (prep->expiry != TIME64_MAX) { - key->expiry = prep->expiry; - key_schedule_gc(prep->expiry + key_gc_delay); - } + key_set_expiry(key, prep->expiry); } } @@ -606,8 +604,7 @@ int key_reject_and_link(struct key *key, atomic_inc(&key->user->nikeys); mark_key_instantiated(key, -error); notify_key(key, NOTIFY_KEY_INSTANTIATED, -error); - key->expiry = ktime_get_real_seconds() + timeout; - key_schedule_gc(key->expiry + key_gc_delay); + key_set_expiry(key, ktime_get_real_seconds() + timeout); if (test_and_clear_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags)) awaken = 1; @@ -722,16 +719,14 @@ found_kernel_type: void key_set_timeout(struct key *key, unsigned timeout) { - time64_t expiry = 0; + time64_t expiry = TIME64_MAX; /* make the changes with the locks held to prevent races */ down_write(&key->sem); if (timeout > 0) expiry = ktime_get_real_seconds() + timeout; - - key->expiry = expiry; - key_schedule_gc(key->expiry + key_gc_delay); + key_set_expiry(key, expiry); up_write(&key->sem); } diff --git a/security/keys/proc.c b/security/keys/proc.c index d0cde6685627..4f4e2c1824f1 100644 --- a/security/keys/proc.c +++ b/security/keys/proc.c @@ -198,7 +198,7 @@ static int proc_keys_show(struct seq_file *m, void *v) /* come up with a suitable timeout value */ expiry = READ_ONCE(key->expiry); - if (expiry == 0) { + if (expiry == TIME64_MAX) { memcpy(xbuf, "perm", 5); } else if (now >= expiry) { memcpy(xbuf, "expd", 5); -- cgit v1.2.3 From d1fe946cb5b27afaed2e491860b227c19ecee982 Mon Sep 17 00:00:00 2001 From: David Howells Date: Thu, 21 Dec 2023 15:09:31 +0000 Subject: afs: Fix overwriting of result of DNS query [ Upstream commit a9e01ac8c5ff32669119c40dfdc9e80eb0b7d7aa ] In afs_update_cell(), ret is the result of the DNS lookup and the errors are to be handled by a switch - however, the value gets clobbered in between by setting it to -ENOMEM in case afs_alloc_vlserver_list() fails. Fix this by moving the setting of -ENOMEM into the error handling for OOM failure. Further, only do it if we don't have an alternative error to return. Found by Linux Verification Center (linuxtesting.org) with SVACE. Based on a patch from Anastasia Belova [1]. Fixes: d5c32c89b208 ("afs: Fix cell DNS lookup") Signed-off-by: David Howells Reviewed-by: Jeffrey Altman cc: Anastasia Belova cc: Marc Dionne cc: linux-afs@lists.infradead.org cc: lvc-project@linuxtesting.org Link: https://lore.kernel.org/r/20231221085849.1463-1-abelova@astralinux.ru/ [1] Link: https://lore.kernel.org/r/1700862.1703168632@warthog.procyon.org.uk/ # v1 Signed-off-by: Linus Torvalds Signed-off-by: Sasha Levin --- fs/afs/cell.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/fs/afs/cell.c b/fs/afs/cell.c index d88407fb9bc0..b5d20a3c0829 100644 --- a/fs/afs/cell.c +++ b/fs/afs/cell.c @@ -409,10 +409,12 @@ static int afs_update_cell(struct afs_cell *cell) if (ret == -ENOMEM) goto out_wake; - ret = -ENOMEM; vllist = afs_alloc_vlserver_list(0); - if (!vllist) + if (!vllist) { + if (ret >= 0) + ret = -ENOMEM; goto out_wake; + } switch (ret) { case -ENODATA: -- cgit v1.2.3 From 57bf56295068af01afb0a644b65dc09f3fd34481 Mon Sep 17 00:00:00 2001 From: David Howells Date: Wed, 6 Jul 2022 10:52:14 +0100 Subject: afs: Use refcount_t rather than atomic_t [ Upstream commit c56f9ec8b20f931014574b943590c4d830109380 ] Use refcount_t rather than atomic_t in afs to make use of the count checking facilities provided. Signed-off-by: David Howells Reviewed-by: Marc Dionne cc: linux-afs@lists.infradead.org Link: https://lore.kernel.org/r/165911277768.3745403.423349776836296452.stgit@warthog.procyon.org.uk/ # v1 Stable-dep-of: 9a6b294ab496 ("afs: Fix use-after-free due to get/remove race in volume tree") Signed-off-by: Sasha Levin --- fs/afs/cell.c | 61 ++++++++++++++++++++++------------------------ fs/afs/cmservice.c | 2 +- fs/afs/internal.h | 16 ++++++------ fs/afs/proc.c | 6 ++--- fs/afs/rxrpc.c | 26 +++++++++++--------- fs/afs/server.c | 40 +++++++++++++++++------------- fs/afs/vl_list.c | 19 +++++---------- fs/afs/volume.c | 21 ++++++++++------ include/trace/events/afs.h | 26 ++++++++++---------- 9 files changed, 110 insertions(+), 107 deletions(-) diff --git a/fs/afs/cell.c b/fs/afs/cell.c index b5d20a3c0829..77571372888d 100644 --- a/fs/afs/cell.c +++ b/fs/afs/cell.c @@ -158,7 +158,7 @@ static struct afs_cell *afs_alloc_cell(struct afs_net *net, cell->name[i] = tolower(name[i]); cell->name[i] = 0; - atomic_set(&cell->ref, 1); + refcount_set(&cell->ref, 1); atomic_set(&cell->active, 0); INIT_WORK(&cell->manager, afs_manage_cell_work); cell->volumes = RB_ROOT; @@ -287,7 +287,7 @@ struct afs_cell *afs_lookup_cell(struct afs_net *net, cell = candidate; candidate = NULL; atomic_set(&cell->active, 2); - trace_afs_cell(cell->debug_id, atomic_read(&cell->ref), 2, afs_cell_trace_insert); + trace_afs_cell(cell->debug_id, refcount_read(&cell->ref), 2, afs_cell_trace_insert); rb_link_node_rcu(&cell->net_node, parent, pp); rb_insert_color(&cell->net_node, &net->cells); up_write(&net->cells_lock); @@ -295,7 +295,7 @@ struct afs_cell *afs_lookup_cell(struct afs_net *net, afs_queue_cell(cell, afs_cell_trace_get_queue_new); wait_for_cell: - trace_afs_cell(cell->debug_id, atomic_read(&cell->ref), atomic_read(&cell->active), + trace_afs_cell(cell->debug_id, refcount_read(&cell->ref), atomic_read(&cell->active), afs_cell_trace_wait); _debug("wait_for_cell"); wait_var_event(&cell->state, @@ -492,13 +492,13 @@ static void afs_cell_destroy(struct rcu_head *rcu) { struct afs_cell *cell = container_of(rcu, struct afs_cell, rcu); struct afs_net *net = cell->net; - int u; + int r; _enter("%p{%s}", cell, cell->name); - u = atomic_read(&cell->ref); - ASSERTCMP(u, ==, 0); - trace_afs_cell(cell->debug_id, u, atomic_read(&cell->active), afs_cell_trace_free); + r = refcount_read(&cell->ref); + ASSERTCMP(r, ==, 0); + trace_afs_cell(cell->debug_id, r, atomic_read(&cell->active), afs_cell_trace_free); afs_put_vlserverlist(net, rcu_access_pointer(cell->vl_servers)); afs_unuse_cell(net, cell->alias_of, afs_cell_trace_unuse_alias); @@ -541,13 +541,10 @@ void afs_cells_timer(struct timer_list *timer) */ struct afs_cell *afs_get_cell(struct afs_cell *cell, enum afs_cell_trace reason) { - int u; + int r; - if (atomic_read(&cell->ref) <= 0) - BUG(); - - u = atomic_inc_return(&cell->ref); - trace_afs_cell(cell->debug_id, u, atomic_read(&cell->active), reason); + __refcount_inc(&cell->ref, &r); + trace_afs_cell(cell->debug_id, r + 1, atomic_read(&cell->active), reason); return cell; } @@ -558,12 +555,14 @@ void afs_put_cell(struct afs_cell *cell, enum afs_cell_trace reason) { if (cell) { unsigned int debug_id = cell->debug_id; - unsigned int u, a; + unsigned int a; + bool zero; + int r; a = atomic_read(&cell->active); - u = atomic_dec_return(&cell->ref); - trace_afs_cell(debug_id, u, a, reason); - if (u == 0) { + zero = __refcount_dec_and_test(&cell->ref, &r); + trace_afs_cell(debug_id, r - 1, a, reason); + if (zero) { a = atomic_read(&cell->active); WARN(a != 0, "Cell active count %u > 0\n", a); call_rcu(&cell->rcu, afs_cell_destroy); @@ -576,14 +575,12 @@ void afs_put_cell(struct afs_cell *cell, enum afs_cell_trace reason) */ struct afs_cell *afs_use_cell(struct afs_cell *cell, enum afs_cell_trace reason) { - int u, a; - - if (atomic_read(&cell->ref) <= 0) - BUG(); + int r, a; - u = atomic_read(&cell->ref); + r = refcount_read(&cell->ref); + WARN_ON(r == 0); a = atomic_inc_return(&cell->active); - trace_afs_cell(cell->debug_id, u, a, reason); + trace_afs_cell(cell->debug_id, r, a, reason); return cell; } @@ -595,7 +592,7 @@ void afs_unuse_cell(struct afs_net *net, struct afs_cell *cell, enum afs_cell_tr { unsigned int debug_id; time64_t now, expire_delay; - int u, a; + int r, a; if (!cell) return; @@ -609,9 +606,9 @@ void afs_unuse_cell(struct afs_net *net, struct afs_cell *cell, enum afs_cell_tr expire_delay = afs_cell_gc_delay; debug_id = cell->debug_id; - u = atomic_read(&cell->ref); + r = refcount_read(&cell->ref); a = atomic_dec_return(&cell->active); - trace_afs_cell(debug_id, u, a, reason); + trace_afs_cell(debug_id, r, a, reason); WARN_ON(a == 0); if (a == 1) /* 'cell' may now be garbage collected. */ @@ -623,11 +620,11 @@ void afs_unuse_cell(struct afs_net *net, struct afs_cell *cell, enum afs_cell_tr */ void afs_see_cell(struct afs_cell *cell, enum afs_cell_trace reason) { - int u, a; + int r, a; - u = atomic_read(&cell->ref); + r = refcount_read(&cell->ref); a = atomic_read(&cell->active); - trace_afs_cell(cell->debug_id, u, a, reason); + trace_afs_cell(cell->debug_id, r, a, reason); } /* @@ -753,7 +750,7 @@ again: active = 1; if (atomic_try_cmpxchg_relaxed(&cell->active, &active, 0)) { rb_erase(&cell->net_node, &net->cells); - trace_afs_cell(cell->debug_id, atomic_read(&cell->ref), 0, + trace_afs_cell(cell->debug_id, refcount_read(&cell->ref), 0, afs_cell_trace_unuse_delete); smp_store_release(&cell->state, AFS_CELL_REMOVED); } @@ -880,7 +877,7 @@ void afs_manage_cells(struct work_struct *work) bool sched_cell = false; active = atomic_read(&cell->active); - trace_afs_cell(cell->debug_id, atomic_read(&cell->ref), + trace_afs_cell(cell->debug_id, refcount_read(&cell->ref), active, afs_cell_trace_manage); ASSERTCMP(active, >=, 1); @@ -888,7 +885,7 @@ void afs_manage_cells(struct work_struct *work) if (purging) { if (test_and_clear_bit(AFS_CELL_FL_NO_GC, &cell->flags)) { active = atomic_dec_return(&cell->active); - trace_afs_cell(cell->debug_id, atomic_read(&cell->ref), + trace_afs_cell(cell->debug_id, refcount_read(&cell->ref), active, afs_cell_trace_unuse_pin); } } diff --git a/fs/afs/cmservice.c b/fs/afs/cmservice.c index a3f5de28be79..cedd627e1fae 100644 --- a/fs/afs/cmservice.c +++ b/fs/afs/cmservice.c @@ -213,7 +213,7 @@ static void SRXAFSCB_CallBack(struct work_struct *work) */ if (call->server) { trace_afs_server(call->server, - atomic_read(&call->server->ref), + refcount_read(&call->server->ref), atomic_read(&call->server->active), afs_server_trace_callback); afs_break_callbacks(call->server, call->count, call->request); diff --git a/fs/afs/internal.h b/fs/afs/internal.h index 183200c6ce20..b29e9c206f78 100644 --- a/fs/afs/internal.h +++ b/fs/afs/internal.h @@ -123,7 +123,7 @@ struct afs_call { }; struct afs_operation *op; unsigned int server_index; - atomic_t usage; + refcount_t ref; enum afs_call_state state; spinlock_t state_lock; int error; /* error code */ @@ -368,7 +368,7 @@ struct afs_cell { #endif time64_t dns_expiry; /* Time AFSDB/SRV record expires */ time64_t last_inactive; /* Time of last drop of usage count */ - atomic_t ref; /* Struct refcount */ + refcount_t ref; /* Struct refcount */ atomic_t active; /* Active usage counter */ unsigned long flags; #define AFS_CELL_FL_NO_GC 0 /* The cell was added manually, don't auto-gc */ @@ -413,7 +413,7 @@ struct afs_vlserver { #define AFS_VLSERVER_FL_IS_YFS 2 /* Server is YFS not AFS */ #define AFS_VLSERVER_FL_RESPONDING 3 /* VL server is responding */ rwlock_t lock; /* Lock on addresses */ - atomic_t usage; + refcount_t ref; unsigned int rtt; /* Server's current RTT in uS */ /* Probe state */ @@ -449,7 +449,7 @@ struct afs_vlserver_entry { struct afs_vlserver_list { struct rcu_head rcu; - atomic_t usage; + refcount_t ref; u8 nr_servers; u8 index; /* Server currently in use */ u8 preferred; /* Preferred server */ @@ -520,7 +520,7 @@ struct afs_server { #define AFS_SERVER_FL_NO_IBULK 17 /* Fileserver doesn't support FS.InlineBulkStatus */ #define AFS_SERVER_FL_NO_RM2 18 /* Fileserver doesn't support YFS.RemoveFile2 */ #define AFS_SERVER_FL_HAS_FS64 19 /* Fileserver supports FS.{Fetch,Store}Data64 */ - atomic_t ref; /* Object refcount */ + refcount_t ref; /* Object refcount */ atomic_t active; /* Active user count */ u32 addr_version; /* Address list version */ unsigned int rtt; /* Server's current RTT in uS */ @@ -575,7 +575,7 @@ struct afs_volume { struct rcu_head rcu; afs_volid_t vid; /* volume ID */ }; - atomic_t usage; + refcount_t ref; time64_t update_at; /* Time at which to next update */ struct afs_cell *cell; /* Cell to which belongs (pins ref) */ struct rb_node cell_node; /* Link in cell->volumes */ @@ -1483,14 +1483,14 @@ extern int afs_end_vlserver_operation(struct afs_vl_cursor *); */ static inline struct afs_vlserver *afs_get_vlserver(struct afs_vlserver *vlserver) { - atomic_inc(&vlserver->usage); + refcount_inc(&vlserver->ref); return vlserver; } static inline struct afs_vlserver_list *afs_get_vlserverlist(struct afs_vlserver_list *vllist) { if (vllist) - atomic_inc(&vllist->usage); + refcount_inc(&vllist->ref); return vllist; } diff --git a/fs/afs/proc.c b/fs/afs/proc.c index 065a28bfa3f1..254ccf1d592f 100644 --- a/fs/afs/proc.c +++ b/fs/afs/proc.c @@ -47,7 +47,7 @@ static int afs_proc_cells_show(struct seq_file *m, void *v) /* display one cell per line on subsequent lines */ seq_printf(m, "%3u %3u %6lld %2u %2u %s\n", - atomic_read(&cell->ref), + refcount_read(&cell->ref), atomic_read(&cell->active), cell->dns_expiry - ktime_get_real_seconds(), vllist ? vllist->nr_servers : 0, @@ -217,7 +217,7 @@ static int afs_proc_cell_volumes_show(struct seq_file *m, void *v) } seq_printf(m, "%3d %08llx %s %s\n", - atomic_read(&vol->usage), vol->vid, + refcount_read(&vol->ref), vol->vid, afs_vol_types[vol->type], vol->name); @@ -388,7 +388,7 @@ static int afs_proc_servers_show(struct seq_file *m, void *v) alist = rcu_dereference(server->addresses); seq_printf(m, "%pU %3d %3d\n", &server->uuid, - atomic_read(&server->ref), + refcount_read(&server->ref), atomic_read(&server->active)); seq_printf(m, " - info: fl=%lx rtt=%u brk=%x\n", server->flags, server->rtt, server->cb_s_break); diff --git a/fs/afs/rxrpc.c b/fs/afs/rxrpc.c index f7305f2791fe..ea40da937fcd 100644 --- a/fs/afs/rxrpc.c +++ b/fs/afs/rxrpc.c @@ -145,7 +145,7 @@ static struct afs_call *afs_alloc_call(struct afs_net *net, call->type = type; call->net = net; call->debug_id = atomic_inc_return(&rxrpc_debug_id); - atomic_set(&call->usage, 1); + refcount_set(&call->ref, 1); INIT_WORK(&call->async_work, afs_process_async_call); init_waitqueue_head(&call->waitq); spin_lock_init(&call->state_lock); @@ -163,14 +163,15 @@ static struct afs_call *afs_alloc_call(struct afs_net *net, void afs_put_call(struct afs_call *call) { struct afs_net *net = call->net; - int n = atomic_dec_return(&call->usage); - int o = atomic_read(&net->nr_outstanding_calls); + bool zero; + int r, o; - trace_afs_call(call, afs_call_trace_put, n, o, + zero = __refcount_dec_and_test(&call->ref, &r); + o = atomic_read(&net->nr_outstanding_calls); + trace_afs_call(call, afs_call_trace_put, r - 1, o, __builtin_return_address(0)); - ASSERTCMP(n, >=, 0); - if (n == 0) { + if (zero) { ASSERT(!work_pending(&call->async_work)); ASSERT(call->type->name != NULL); @@ -198,9 +199,11 @@ void afs_put_call(struct afs_call *call) static struct afs_call *afs_get_call(struct afs_call *call, enum afs_call_trace why) { - int u = atomic_inc_return(&call->usage); + int r; - trace_afs_call(call, why, u, + __refcount_inc(&call->ref, &r); + + trace_afs_call(call, why, r + 1, atomic_read(&call->net->nr_outstanding_calls), __builtin_return_address(0)); return call; @@ -663,14 +666,13 @@ static void afs_wake_up_async_call(struct sock *sk, struct rxrpc_call *rxcall, unsigned long call_user_ID) { struct afs_call *call = (struct afs_call *)call_user_ID; - int u; + int r; trace_afs_notify_call(rxcall, call); call->need_attention = true; - u = atomic_fetch_add_unless(&call->usage, 1, 0); - if (u != 0) { - trace_afs_call(call, afs_call_trace_wake, u + 1, + if (__refcount_inc_not_zero(&call->ref, &r)) { + trace_afs_call(call, afs_call_trace_wake, r + 1, atomic_read(&call->net->nr_outstanding_calls), __builtin_return_address(0)); diff --git a/fs/afs/server.c b/fs/afs/server.c index 6e5b9a19b234..ffed828622b6 100644 --- a/fs/afs/server.c +++ b/fs/afs/server.c @@ -228,7 +228,7 @@ static struct afs_server *afs_alloc_server(struct afs_cell *cell, if (!server) goto enomem; - atomic_set(&server->ref, 1); + refcount_set(&server->ref, 1); atomic_set(&server->active, 1); server->debug_id = atomic_inc_return(&afs_server_debug_id); RCU_INIT_POINTER(server->addresses, alist); @@ -352,9 +352,10 @@ void afs_servers_timer(struct timer_list *timer) struct afs_server *afs_get_server(struct afs_server *server, enum afs_server_trace reason) { - unsigned int u = atomic_inc_return(&server->ref); + int r; - trace_afs_server(server, u, atomic_read(&server->active), reason); + __refcount_inc(&server->ref, &r); + trace_afs_server(server, r + 1, atomic_read(&server->active), reason); return server; } @@ -364,14 +365,14 @@ struct afs_server *afs_get_server(struct afs_server *server, static struct afs_server *afs_maybe_use_server(struct afs_server *server, enum afs_server_trace reason) { - unsigned int r = atomic_fetch_add_unless(&server->ref, 1, 0); unsigned int a; + int r; - if (r == 0) + if (!__refcount_inc_not_zero(&server->ref, &r)) return NULL; a = atomic_inc_return(&server->active); - trace_afs_server(server, r, a, reason); + trace_afs_server(server, r + 1, a, reason); return server; } @@ -380,10 +381,13 @@ static struct afs_server *afs_maybe_use_server(struct afs_server *server, */ struct afs_server *afs_use_server(struct afs_server *server, enum afs_server_trace reason) { - unsigned int r = atomic_inc_return(&server->ref); - unsigned int a = atomic_inc_return(&server->active); + unsigned int a; + int r; + + __refcount_inc(&server->ref, &r); + a = atomic_inc_return(&server->active); - trace_afs_server(server, r, a, reason); + trace_afs_server(server, r + 1, a, reason); return server; } @@ -393,14 +397,15 @@ struct afs_server *afs_use_server(struct afs_server *server, enum afs_server_tra void afs_put_server(struct afs_net *net, struct afs_server *server, enum afs_server_trace reason) { - unsigned int usage; + bool zero; + int r; if (!server) return; - usage = atomic_dec_return(&server->ref); - trace_afs_server(server, usage, atomic_read(&server->active), reason); - if (unlikely(usage == 0)) + zero = __refcount_dec_and_test(&server->ref, &r); + trace_afs_server(server, r - 1, atomic_read(&server->active), reason); + if (unlikely(zero)) __afs_put_server(net, server); } @@ -436,7 +441,7 @@ static void afs_server_rcu(struct rcu_head *rcu) { struct afs_server *server = container_of(rcu, struct afs_server, rcu); - trace_afs_server(server, atomic_read(&server->ref), + trace_afs_server(server, refcount_read(&server->ref), atomic_read(&server->active), afs_server_trace_free); afs_put_addrlist(rcu_access_pointer(server->addresses)); kfree(server); @@ -487,7 +492,7 @@ static void afs_gc_servers(struct afs_net *net, struct afs_server *gc_list) active = atomic_read(&server->active); if (active == 0) { - trace_afs_server(server, atomic_read(&server->ref), + trace_afs_server(server, refcount_read(&server->ref), active, afs_server_trace_gc); next = rcu_dereference_protected( server->uuid_next, lockdep_is_held(&net->fs_lock.lock)); @@ -553,7 +558,7 @@ void afs_manage_servers(struct work_struct *work) _debug("manage %pU %u", &server->uuid, active); if (purging) { - trace_afs_server(server, atomic_read(&server->ref), + trace_afs_server(server, refcount_read(&server->ref), active, afs_server_trace_purging); if (active != 0) pr_notice("Can't purge s=%08x\n", server->debug_id); @@ -633,7 +638,8 @@ static noinline bool afs_update_server_record(struct afs_operation *op, _enter(""); - trace_afs_server(server, atomic_read(&server->ref), atomic_read(&server->active), + trace_afs_server(server, refcount_read(&server->ref), + atomic_read(&server->active), afs_server_trace_update); alist = afs_vl_lookup_addrs(op->volume->cell, op->key, &server->uuid); diff --git a/fs/afs/vl_list.c b/fs/afs/vl_list.c index 38b2ba1d9ec0..acc48216136a 100644 --- a/fs/afs/vl_list.c +++ b/fs/afs/vl_list.c @@ -17,7 +17,7 @@ struct afs_vlserver *afs_alloc_vlserver(const char *name, size_t name_len, vlserver = kzalloc(struct_size(vlserver, name, name_len + 1), GFP_KERNEL); if (vlserver) { - atomic_set(&vlserver->usage, 1); + refcount_set(&vlserver->ref, 1); rwlock_init(&vlserver->lock); init_waitqueue_head(&vlserver->probe_wq); spin_lock_init(&vlserver->probe_lock); @@ -39,13 +39,9 @@ static void afs_vlserver_rcu(struct rcu_head *rcu) void afs_put_vlserver(struct afs_net *net, struct afs_vlserver *vlserver) { - if (vlserver) { - unsigned int u = atomic_dec_return(&vlserver->usage); - //_debug("VL PUT %p{%u}", vlserver, u); - - if (u == 0) - call_rcu(&vlserver->rcu, afs_vlserver_rcu); - } + if (vlserver && + refcount_dec_and_test(&vlserver->ref)) + call_rcu(&vlserver->rcu, afs_vlserver_rcu); } struct afs_vlserver_list *afs_alloc_vlserver_list(unsigned int nr_servers) @@ -54,7 +50,7 @@ struct afs_vlserver_list *afs_alloc_vlserver_list(unsigned int nr_servers) vllist = kzalloc(struct_size(vllist, servers, nr_servers), GFP_KERNEL); if (vllist) { - atomic_set(&vllist->usage, 1); + refcount_set(&vllist->ref, 1); rwlock_init(&vllist->lock); } @@ -64,10 +60,7 @@ struct afs_vlserver_list *afs_alloc_vlserver_list(unsigned int nr_servers) void afs_put_vlserverlist(struct afs_net *net, struct afs_vlserver_list *vllist) { if (vllist) { - unsigned int u = atomic_dec_return(&vllist->usage); - - //_debug("VLLS PUT %p{%u}", vllist, u); - if (u == 0) { + if (refcount_dec_and_test(&vllist->ref)) { int i; for (i = 0; i < vllist->nr_servers; i++) { diff --git a/fs/afs/volume.c b/fs/afs/volume.c index f84194b791d3..32941bffa2ec 100644 --- a/fs/afs/volume.c +++ b/fs/afs/volume.c @@ -53,7 +53,7 @@ static void afs_remove_volume_from_cell(struct afs_volume *volume) struct afs_cell *cell = volume->cell; if (!hlist_unhashed(&volume->proc_link)) { - trace_afs_volume(volume->vid, atomic_read(&volume->usage), + trace_afs_volume(volume->vid, refcount_read(&cell->ref), afs_volume_trace_remove); write_seqlock(&cell->volume_lock); hlist_del_rcu(&volume->proc_link); @@ -88,7 +88,7 @@ static struct afs_volume *afs_alloc_volume(struct afs_fs_context *params, volume->type_force = params->force; volume->name_len = vldb->name_len; - atomic_set(&volume->usage, 1); + refcount_set(&volume->ref, 1); INIT_HLIST_NODE(&volume->proc_link); rwlock_init(&volume->servers_lock); rwlock_init(&volume->cb_v_break_lock); @@ -229,7 +229,7 @@ static void afs_destroy_volume(struct afs_net *net, struct afs_volume *volume) afs_remove_volume_from_cell(volume); afs_put_serverlist(net, rcu_access_pointer(volume->servers)); afs_put_cell(volume->cell, afs_cell_trace_put_vol); - trace_afs_volume(volume->vid, atomic_read(&volume->usage), + trace_afs_volume(volume->vid, refcount_read(&volume->ref), afs_volume_trace_free); kfree_rcu(volume, rcu); @@ -243,8 +243,10 @@ struct afs_volume *afs_get_volume(struct afs_volume *volume, enum afs_volume_trace reason) { if (volume) { - int u = atomic_inc_return(&volume->usage); - trace_afs_volume(volume->vid, u, reason); + int r; + + __refcount_inc(&volume->ref, &r); + trace_afs_volume(volume->vid, r + 1, reason); } return volume; } @@ -258,9 +260,12 @@ void afs_put_volume(struct afs_net *net, struct afs_volume *volume, { if (volume) { afs_volid_t vid = volume->vid; - int u = atomic_dec_return(&volume->usage); - trace_afs_volume(vid, u, reason); - if (u == 0) + bool zero; + int r; + + zero = __refcount_dec_and_test(&volume->ref, &r); + trace_afs_volume(vid, r - 1, reason); + if (zero) afs_destroy_volume(net, volume); } } diff --git a/include/trace/events/afs.h b/include/trace/events/afs.h index bca73e8c8cde..5556c5da117f 100644 --- a/include/trace/events/afs.h +++ b/include/trace/events/afs.h @@ -728,14 +728,14 @@ TRACE_EVENT(afs_cb_call, TRACE_EVENT(afs_call, TP_PROTO(struct afs_call *call, enum afs_call_trace op, - int usage, int outstanding, const void *where), + int ref, int outstanding, const void *where), - TP_ARGS(call, op, usage, outstanding, where), + TP_ARGS(call, op, ref, outstanding, where), TP_STRUCT__entry( __field(unsigned int, call ) __field(int, op ) - __field(int, usage ) + __field(int, ref ) __field(int, outstanding ) __field(const void *, where ) ), @@ -743,15 +743,15 @@ TRACE_EVENT(afs_call, TP_fast_assign( __entry->call = call->debug_id; __entry->op = op; - __entry->usage = usage; + __entry->ref = ref; __entry->outstanding = outstanding; __entry->where = where; ), - TP_printk("c=%08x %s u=%d o=%d sp=%pSR", + TP_printk("c=%08x %s r=%d o=%d sp=%pSR", __entry->call, __print_symbolic(__entry->op, afs_call_traces), - __entry->usage, + __entry->ref, __entry->outstanding, __entry->where) ); @@ -1475,36 +1475,36 @@ TRACE_EVENT(afs_volume, __entry->reason = reason; ), - TP_printk("V=%llx %s u=%d", + TP_printk("V=%llx %s ur=%d", __entry->vid, __print_symbolic(__entry->reason, afs_volume_traces), __entry->ref) ); TRACE_EVENT(afs_cell, - TP_PROTO(unsigned int cell_debug_id, int usage, int active, + TP_PROTO(unsigned int cell_debug_id, int ref, int active, enum afs_cell_trace reason), - TP_ARGS(cell_debug_id, usage, active, reason), + TP_ARGS(cell_debug_id, ref, active, reason), TP_STRUCT__entry( __field(unsigned int, cell ) - __field(int, usage ) + __field(int, ref ) __field(int, active ) __field(int, reason ) ), TP_fast_assign( __entry->cell = cell_debug_id; - __entry->usage = usage; + __entry->ref = ref; __entry->active = active; __entry->reason = reason; ), - TP_printk("L=%08x %s u=%d a=%d", + TP_printk("L=%08x %s r=%d a=%d", __entry->cell, __print_symbolic(__entry->reason, afs_cell_traces), - __entry->usage, + __entry->ref, __entry->active) ); -- cgit v1.2.3 From 98fb5eaade749e9d366fdd1f622d560ad68bdedd Mon Sep 17 00:00:00 2001 From: David Howells Date: Thu, 21 Dec 2023 13:57:31 +0000 Subject: afs: Fix use-after-free due to get/remove race in volume tree [ Upstream commit 9a6b294ab496650e9f270123730df37030911b55 ] When an afs_volume struct is put, its refcount is reduced to 0 before the cell->volume_lock is taken and the volume removed from the cell->volumes tree. Unfortunately, this means that the lookup code can race and see a volume with a zero ref in the tree, resulting in a use-after-free: refcount_t: addition on 0; use-after-free. WARNING: CPU: 3 PID: 130782 at lib/refcount.c:25 refcount_warn_saturate+0x7a/0xda ... RIP: 0010:refcount_warn_saturate+0x7a/0xda ... Call Trace: afs_get_volume+0x3d/0x55 afs_create_volume+0x126/0x1de afs_validate_fc+0xfe/0x130 afs_get_tree+0x20/0x2e5 vfs_get_tree+0x1d/0xc9 do_new_mount+0x13b/0x22e do_mount+0x5d/0x8a __do_sys_mount+0x100/0x12a do_syscall_64+0x3a/0x94 entry_SYSCALL_64_after_hwframe+0x62/0x6a Fix this by: (1) When putting, use a flag to indicate if the volume has been removed from the tree and skip the rb_erase if it has. (2) When looking up, use a conditional ref increment and if it fails because the refcount is 0, replace the node in the tree and set the removal flag. Fixes: 20325960f875 ("afs: Reorganise volume and server trees to be rooted on the cell") Signed-off-by: David Howells Reviewed-by: Jeffrey Altman cc: Marc Dionne cc: linux-afs@lists.infradead.org Signed-off-by: Linus Torvalds Signed-off-by: Sasha Levin --- fs/afs/internal.h | 2 ++ fs/afs/volume.c | 26 +++++++++++++++++++++++--- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/fs/afs/internal.h b/fs/afs/internal.h index b29e9c206f78..0c03877cdaf7 100644 --- a/fs/afs/internal.h +++ b/fs/afs/internal.h @@ -589,6 +589,7 @@ struct afs_volume { #define AFS_VOLUME_OFFLINE 4 /* - T if volume offline notice given */ #define AFS_VOLUME_BUSY 5 /* - T if volume busy notice given */ #define AFS_VOLUME_MAYBE_NO_IBULK 6 /* - T if some servers don't have InlineBulkStatus */ +#define AFS_VOLUME_RM_TREE 7 /* - Set if volume removed from cell->volumes */ #ifdef CONFIG_AFS_FSCACHE struct fscache_cookie *cache; /* caching cookie */ #endif @@ -1507,6 +1508,7 @@ extern struct afs_vlserver_list *afs_extract_vlserver_list(struct afs_cell *, extern struct afs_volume *afs_create_volume(struct afs_fs_context *); extern void afs_activate_volume(struct afs_volume *); extern void afs_deactivate_volume(struct afs_volume *); +bool afs_try_get_volume(struct afs_volume *volume, enum afs_volume_trace reason); extern struct afs_volume *afs_get_volume(struct afs_volume *, enum afs_volume_trace); extern void afs_put_volume(struct afs_net *, struct afs_volume *, enum afs_volume_trace); extern int afs_check_volume_status(struct afs_volume *, struct afs_operation *); diff --git a/fs/afs/volume.c b/fs/afs/volume.c index 32941bffa2ec..137a970c19fb 100644 --- a/fs/afs/volume.c +++ b/fs/afs/volume.c @@ -33,8 +33,13 @@ static struct afs_volume *afs_insert_volume_into_cell(struct afs_cell *cell, } else if (p->vid > volume->vid) { pp = &(*pp)->rb_right; } else { - volume = afs_get_volume(p, afs_volume_trace_get_cell_insert); - goto found; + if (afs_try_get_volume(p, afs_volume_trace_get_cell_insert)) { + volume = p; + goto found; + } + + set_bit(AFS_VOLUME_RM_TREE, &volume->flags); + rb_replace_node_rcu(&p->cell_node, &volume->cell_node, &cell->volumes); } } @@ -57,7 +62,8 @@ static void afs_remove_volume_from_cell(struct afs_volume *volume) afs_volume_trace_remove); write_seqlock(&cell->volume_lock); hlist_del_rcu(&volume->proc_link); - rb_erase(&volume->cell_node, &cell->volumes); + if (!test_and_set_bit(AFS_VOLUME_RM_TREE, &volume->flags)) + rb_erase(&volume->cell_node, &cell->volumes); write_sequnlock(&cell->volume_lock); } } @@ -236,6 +242,20 @@ static void afs_destroy_volume(struct afs_net *net, struct afs_volume *volume) _leave(" [destroyed]"); } +/* + * Try to get a reference on a volume record. + */ +bool afs_try_get_volume(struct afs_volume *volume, enum afs_volume_trace reason) +{ + int r; + + if (__refcount_inc_not_zero(&volume->ref, &r)) { + trace_afs_volume(volume->vid, r + 1, reason); + return true; + } + return false; +} + /* * Get a reference on a volume record. */ -- cgit v1.2.3 From c87ab6e306bab660a2093a638b3316812721997d Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Mon, 18 Dec 2023 15:56:52 +0100 Subject: ASoC: hdmi-codec: fix missing report for jack initial status [ Upstream commit 025222a9d6d25eee2ad9a1bb5a8b29b34b5ba576 ] This fixes a problem introduced while fixing ELD reporting with no jack set. Most driver using the hdmi-codec will call the 'plugged_cb' callback directly when registered to report the initial state of the HDMI connector. With the commit mentionned, this occurs before jack is ready and the initial report is lost for platforms actually providing a jack for HDMI. Fix this by storing the hdmi connector status regardless of jack being set or not and report the last status when jack gets set. With this, the initial state is reported correctly even if it is disconnected. This was not done initially and is also a fix. Fixes: 15be353d55f9 ("ASoC: hdmi-codec: register hpd callback on component probe") Reported-by: Zhengqiao Xia Closes: https://lore.kernel.org/alsa-devel/CADYyEwTNyY+fR9SgfDa-g6iiDwkU3MUdPVCYexs2_3wbcM8_vg@mail.gmail.com/ Cc: Hsin-Yi Wang Tested-by: Zhengqiao Xia Signed-off-by: Jerome Brunet Link: https://msgid.link/r/20231218145655.134929-1-jbrunet@baylibre.com Signed-off-by: Mark Brown Signed-off-by: Sasha Levin --- sound/soc/codecs/hdmi-codec.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c index 0a7e2f8ca71a..410fb59807f1 100644 --- a/sound/soc/codecs/hdmi-codec.c +++ b/sound/soc/codecs/hdmi-codec.c @@ -843,8 +843,9 @@ static int hdmi_dai_probe(struct snd_soc_dai *dai) static void hdmi_codec_jack_report(struct hdmi_codec_priv *hcp, unsigned int jack_status) { - if (hcp->jack && jack_status != hcp->jack_status) { - snd_soc_jack_report(hcp->jack, jack_status, SND_JACK_LINEOUT); + if (jack_status != hcp->jack_status) { + if (hcp->jack) + snd_soc_jack_report(hcp->jack, jack_status, SND_JACK_LINEOUT); hcp->jack_status = jack_status; } } @@ -873,6 +874,13 @@ static int hdmi_codec_set_jack(struct snd_soc_component *component, if (hcp->hcd.ops->hook_plugged_cb) { hcp->jack = jack; + + /* + * Report the initial jack status which may have been provided + * by the parent hdmi driver while the hpd hook was registered. + */ + snd_soc_jack_report(jack, hcp->jack_status, SND_JACK_LINEOUT); + return 0; } -- cgit v1.2.3 From f0c52b790a00afd6576ac9a569dd96fbfb34330b Mon Sep 17 00:00:00 2001 From: Quan Nguyen Date: Mon, 11 Dec 2023 17:22:16 +0700 Subject: i2c: aspeed: Handle the coalesced stop conditions with the start conditions. [ Upstream commit b4cc1cbba5195a4dd497cf2f8f09e7807977d543 ] Some masters may drive the transfers with low enough latency between the nak/stop phase of the current command and the start/address phase of the following command that the interrupts are coalesced by the time we process them. Handle the stop conditions before processing SLAVE_MATCH to fix the complaints that sometimes occur below. "aspeed-i2c-bus 1e78a040.i2c-bus: irq handled != irq. Expected 0x00000086, but was 0x00000084" Fixes: f9eb91350bb2 ("i2c: aspeed: added slave support for Aspeed I2C driver") Signed-off-by: Quan Nguyen Reviewed-by: Andrew Jeffery Reviewed-by: Andi Shyti Signed-off-by: Wolfram Sang Signed-off-by: Sasha Levin --- drivers/i2c/busses/i2c-aspeed.c | 48 +++++++++++++++++++++++++++-------------- 1 file changed, 32 insertions(+), 16 deletions(-) diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c index b7cad1bed3dc..e61ed702a12c 100644 --- a/drivers/i2c/busses/i2c-aspeed.c +++ b/drivers/i2c/busses/i2c-aspeed.c @@ -250,18 +250,46 @@ static u32 aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus, u32 irq_status) if (!slave) return 0; - command = readl(bus->base + ASPEED_I2C_CMD_REG); + /* + * Handle stop conditions early, prior to SLAVE_MATCH. Some masters may drive + * transfers with low enough latency between the nak/stop phase of the current + * command and the start/address phase of the following command that the + * interrupts are coalesced by the time we process them. + */ + if (irq_status & ASPEED_I2CD_INTR_NORMAL_STOP) { + irq_handled |= ASPEED_I2CD_INTR_NORMAL_STOP; + bus->slave_state = ASPEED_I2C_SLAVE_STOP; + } + + if (irq_status & ASPEED_I2CD_INTR_TX_NAK && + bus->slave_state == ASPEED_I2C_SLAVE_READ_PROCESSED) { + irq_handled |= ASPEED_I2CD_INTR_TX_NAK; + bus->slave_state = ASPEED_I2C_SLAVE_STOP; + } + + /* Propagate any stop conditions to the slave implementation. */ + if (bus->slave_state == ASPEED_I2C_SLAVE_STOP) { + i2c_slave_event(slave, I2C_SLAVE_STOP, &value); + bus->slave_state = ASPEED_I2C_SLAVE_INACTIVE; + } - /* Slave was requested, restart state machine. */ + /* + * Now that we've dealt with any potentially coalesced stop conditions, + * address any start conditions. + */ if (irq_status & ASPEED_I2CD_INTR_SLAVE_MATCH) { irq_handled |= ASPEED_I2CD_INTR_SLAVE_MATCH; bus->slave_state = ASPEED_I2C_SLAVE_START; } - /* Slave is not currently active, irq was for someone else. */ + /* + * If the slave has been stopped and not started then slave interrupt + * handling is complete. + */ if (bus->slave_state == ASPEED_I2C_SLAVE_INACTIVE) return irq_handled; + command = readl(bus->base + ASPEED_I2C_CMD_REG); dev_dbg(bus->dev, "slave irq status 0x%08x, cmd 0x%08x\n", irq_status, command); @@ -280,17 +308,6 @@ static u32 aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus, u32 irq_status) irq_handled |= ASPEED_I2CD_INTR_RX_DONE; } - /* Slave was asked to stop. */ - if (irq_status & ASPEED_I2CD_INTR_NORMAL_STOP) { - irq_handled |= ASPEED_I2CD_INTR_NORMAL_STOP; - bus->slave_state = ASPEED_I2C_SLAVE_STOP; - } - if (irq_status & ASPEED_I2CD_INTR_TX_NAK && - bus->slave_state == ASPEED_I2C_SLAVE_READ_PROCESSED) { - irq_handled |= ASPEED_I2CD_INTR_TX_NAK; - bus->slave_state = ASPEED_I2C_SLAVE_STOP; - } - switch (bus->slave_state) { case ASPEED_I2C_SLAVE_READ_REQUESTED: if (unlikely(irq_status & ASPEED_I2CD_INTR_TX_ACK)) @@ -319,8 +336,7 @@ static u32 aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus, u32 irq_status) i2c_slave_event(slave, I2C_SLAVE_WRITE_RECEIVED, &value); break; case ASPEED_I2C_SLAVE_STOP: - i2c_slave_event(slave, I2C_SLAVE_STOP, &value); - bus->slave_state = ASPEED_I2C_SLAVE_INACTIVE; + /* Stop event handling is done early. Unreachable. */ break; case ASPEED_I2C_SLAVE_START: /* Slave was just started. Waiting for the next event. */; -- cgit v1.2.3 From 8bdcedfdb026ff5141d53f435df4eeda5c6b12f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexis=20Lothor=C3=A9?= Date: Fri, 15 Dec 2023 22:34:24 +0100 Subject: pinctrl: at91-pio4: use dedicated lock class for IRQ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 14694179e561b5f2f7e56a0f590e2cb49a9cc7ab ] Trying to suspend to RAM on SAMA5D27 EVK leads to the following lockdep warning: ============================================ WARNING: possible recursive locking detected 6.7.0-rc5-wt+ #532 Not tainted -------------------------------------------- sh/92 is trying to acquire lock: c3cf306c (&irq_desc_lock_class){-.-.}-{2:2}, at: __irq_get_desc_lock+0xe8/0x100 but task is already holding lock: c3d7c46c (&irq_desc_lock_class){-.-.}-{2:2}, at: __irq_get_desc_lock+0xe8/0x100 other info that might help us debug this: Possible unsafe locking scenario: CPU0 ---- lock(&irq_desc_lock_class); lock(&irq_desc_lock_class); *** DEADLOCK *** May be due to missing lock nesting notation 6 locks held by sh/92: #0: c3aa0258 (sb_writers#6){.+.+}-{0:0}, at: ksys_write+0xd8/0x178 #1: c4c2df44 (&of->mutex){+.+.}-{3:3}, at: kernfs_fop_write_iter+0x138/0x284 #2: c32684a0 (kn->active){.+.+}-{0:0}, at: kernfs_fop_write_iter+0x148/0x284 #3: c232b6d4 (system_transition_mutex){+.+.}-{3:3}, at: pm_suspend+0x13c/0x4e8 #4: c387b088 (&dev->mutex){....}-{3:3}, at: __device_suspend+0x1e8/0x91c #5: c3d7c46c (&irq_desc_lock_class){-.-.}-{2:2}, at: __irq_get_desc_lock+0xe8/0x100 stack backtrace: CPU: 0 PID: 92 Comm: sh Not tainted 6.7.0-rc5-wt+ #532 Hardware name: Atmel SAMA5 unwind_backtrace from show_stack+0x18/0x1c show_stack from dump_stack_lvl+0x34/0x48 dump_stack_lvl from __lock_acquire+0x19ec/0x3a0c __lock_acquire from lock_acquire.part.0+0x124/0x2d0 lock_acquire.part.0 from _raw_spin_lock_irqsave+0x5c/0x78 _raw_spin_lock_irqsave from __irq_get_desc_lock+0xe8/0x100 __irq_get_desc_lock from irq_set_irq_wake+0xa8/0x204 irq_set_irq_wake from atmel_gpio_irq_set_wake+0x58/0xb4 atmel_gpio_irq_set_wake from irq_set_irq_wake+0x100/0x204 irq_set_irq_wake from gpio_keys_suspend+0xec/0x2b8 gpio_keys_suspend from dpm_run_callback+0xe4/0x248 dpm_run_callback from __device_suspend+0x234/0x91c __device_suspend from dpm_suspend+0x224/0x43c dpm_suspend from dpm_suspend_start+0x9c/0xa8 dpm_suspend_start from suspend_devices_and_enter+0x1e0/0xa84 suspend_devices_and_enter from pm_suspend+0x460/0x4e8 pm_suspend from state_store+0x78/0xe4 state_store from kernfs_fop_write_iter+0x1a0/0x284 kernfs_fop_write_iter from vfs_write+0x38c/0x6f4 vfs_write from ksys_write+0xd8/0x178 ksys_write from ret_fast_syscall+0x0/0x1c Exception stack(0xc52b3fa8 to 0xc52b3ff0) 3fa0: 00000004 005a0ae8 00000001 005a0ae8 00000004 00000001 3fc0: 00000004 005a0ae8 00000001 00000004 00000004 b6c616c0 00000020 0059d190 3fe0: 00000004 b6c61678 aec5a041 aebf1a26 This warning is raised because pinctrl-at91-pio4 uses chained IRQ. Whenever a wake up source configures an IRQ through irq_set_irq_wake, it will lock the corresponding IRQ desc, and then call irq_set_irq_wake on "parent" IRQ which will do the same on its own IRQ desc, but since those two locks share the same class, lockdep reports this as an issue. Fix lockdep false positive by setting a different class for parent and children IRQ Fixes: 776180848b57 ("pinctrl: introduce driver for Atmel PIO4 controller") Signed-off-by: Alexis Lothoré Link: https://lore.kernel.org/r/20231215-lockdep_warning-v1-1-8137b2510ed5@bootlin.com Signed-off-by: Linus Walleij Signed-off-by: Sasha Levin --- drivers/pinctrl/pinctrl-at91-pio4.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/pinctrl/pinctrl-at91-pio4.c b/drivers/pinctrl/pinctrl-at91-pio4.c index 62b9a94c10ba..d80c3911b5b1 100644 --- a/drivers/pinctrl/pinctrl-at91-pio4.c +++ b/drivers/pinctrl/pinctrl-at91-pio4.c @@ -1038,6 +1038,13 @@ static const struct of_device_id atmel_pctrl_of_match[] = { } }; +/* + * This lock class allows to tell lockdep that parent IRQ and children IRQ do + * not share the same class so it does not raise false positive + */ +static struct lock_class_key atmel_lock_key; +static struct lock_class_key atmel_request_key; + static int atmel_pinctrl_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -1193,6 +1200,7 @@ static int atmel_pinctrl_probe(struct platform_device *pdev) irq_set_chip_and_handler(irq, &atmel_gpio_irq_chip, handle_simple_irq); irq_set_chip_data(irq, atmel_pioctrl); + irq_set_lockdep_class(irq, &atmel_lock_key, &atmel_request_key); dev_dbg(dev, "atmel gpio irq domain: hwirq: %d, linux irq: %d\n", i, irq); -- cgit v1.2.3 From c0c4e9767e57b6693f9a99b4e21f043d810f67a7 Mon Sep 17 00:00:00 2001 From: Kent Gibson Date: Thu, 21 Dec 2023 09:20:36 +0800 Subject: gpiolib: cdev: add gpio_device locking wrapper around gpio_ioctl() [ Upstream commit 1d656bd259edb89dc1d9938ec5c5389867088546 ] While the GPIO cdev gpio_ioctl() call is in progress, the kernel can call gpiochip_remove() which will set gdev->chip to NULL, after which any subsequent access will cause a crash. gpio_ioctl() was overlooked by the previous fix to protect syscalls (bdbbae241a04), so add protection for that. Fixes: bdbbae241a04 ("gpiolib: protect the GPIO device against being dropped while in use by user-space") Fixes: d7c51b47ac11 ("gpio: userspace ABI for reading/writing GPIO lines") Fixes: 3c0d9c635ae2 ("gpiolib: cdev: support GPIO_V2_GET_LINE_IOCTL and GPIO_V2_LINE_GET_VALUES_IOCTL") Fixes: aad955842d1c ("gpiolib: cdev: support GPIO_V2_GET_LINEINFO_IOCTL and GPIO_V2_GET_LINEINFO_WATCH_IOCTL") Signed-off-by: Kent Gibson Signed-off-by: Bartosz Golaszewski Signed-off-by: Sasha Levin --- drivers/gpio/gpiolib-cdev.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/gpio/gpiolib-cdev.c b/drivers/gpio/gpiolib-cdev.c index 2a2e0691462b..1db991cb2efc 100644 --- a/drivers/gpio/gpiolib-cdev.c +++ b/drivers/gpio/gpiolib-cdev.c @@ -2224,10 +2224,7 @@ static int lineinfo_unwatch(struct gpio_chardev_data *cdev, void __user *ip) return 0; } -/* - * gpio_ioctl() - ioctl handler for the GPIO chardev - */ -static long gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +static long gpio_ioctl_unlocked(struct file *file, unsigned int cmd, unsigned long arg) { struct gpio_chardev_data *cdev = file->private_data; struct gpio_device *gdev = cdev->gdev; @@ -2264,6 +2261,17 @@ static long gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg) } } +/* + * gpio_ioctl() - ioctl handler for the GPIO chardev + */ +static long gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + struct gpio_chardev_data *cdev = file->private_data; + + return call_ioctl_locked(file, cmd, arg, cdev->gdev, + gpio_ioctl_unlocked); +} + #ifdef CONFIG_COMPAT static long gpio_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) -- cgit v1.2.3 From 6bbeb3960aad0c6bf847db2f7f0e902780c1e4fe Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Wed, 6 Dec 2023 08:23:49 +0900 Subject: ksmbd: fix wrong name of SMB2_CREATE_ALLOCATION_SIZE [ Upstream commit 13736654481198e519059d4a2e2e3b20fa9fdb3e ] MS confirm that "AISi" name of SMB2_CREATE_ALLOCATION_SIZE in MS-SMB2 specification is a typo. cifs/ksmbd have been using this wrong name from MS-SMB2. It should be "AlSi". Also It will cause problem when running smb2.create.open test in smbtorture against ksmbd. Cc: stable@vger.kernel.org Fixes: 12197a7fdda9 ("Clarify SMB2/SMB3 create context and add missing ones") Signed-off-by: Namjae Jeon Reviewed-by: Paulo Alcantara (SUSE) Signed-off-by: Steve French Signed-off-by: Sasha Levin --- fs/cifs/smb2pdu.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h index f32c99c9ba13..301c155c5267 100644 --- a/fs/cifs/smb2pdu.h +++ b/fs/cifs/smb2pdu.h @@ -779,7 +779,7 @@ struct smb2_tree_disconnect_rsp { #define SMB2_CREATE_SD_BUFFER "SecD" /* security descriptor */ #define SMB2_CREATE_DURABLE_HANDLE_REQUEST "DHnQ" #define SMB2_CREATE_DURABLE_HANDLE_RECONNECT "DHnC" -#define SMB2_CREATE_ALLOCATION_SIZE "AISi" +#define SMB2_CREATE_ALLOCATION_SIZE "AlSi" #define SMB2_CREATE_QUERY_MAXIMAL_ACCESS_REQUEST "MxAc" #define SMB2_CREATE_TIMEWARP_REQUEST "TWrp" #define SMB2_CREATE_QUERY_ON_DISK_ID "QFid" -- cgit v1.2.3 From 2a4ef0d6e5f0b9a32b4ace3e584320f55bd21d78 Mon Sep 17 00:00:00 2001 From: Luca Coelho Date: Fri, 23 Dec 2022 15:05:08 +0200 Subject: drm/i915/mtl: limit second scaler vertical scaling in ver >= 14 [ Upstream commit 8d4312e2b228ba7a5ac79154458098274ec61e9b ] In newer hardware versions (i.e. display version >= 14), the second scaler doesn't support vertical scaling. The current implementation of the scaling limits is simplified and only occurs when the planes are created, so we don't know which scaler is being used. In order to handle separate scaling limits for horizontal and vertical scaling, and different limits per scaler, split the checks in two phases. We first do a simple check during plane creation and use the best-case scenario (because we don't know the scaler that may be used at a later point) and then do a more specific check when the scalers are actually being set up. Signed-off-by: Luca Coelho Reviewed-by: Stanislav Lisovskiy Signed-off-by: Radhakrishna Sripada Link: https://patchwork.freedesktop.org/patch/msgid/20221223130509.43245-2-luciano.coelho@intel.com Stable-dep-of: c3070f080f9b ("drm/i915: Fix intel_atomic_setup_scalers() plane_state handling") Signed-off-by: Sasha Levin --- drivers/gpu/drm/i915/display/intel_atomic.c | 85 +++++++++++++++++++++++++---- 1 file changed, 75 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_atomic.c b/drivers/gpu/drm/i915/display/intel_atomic.c index b4e7ac51aa31..4b4514ce6d88 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic.c +++ b/drivers/gpu/drm/i915/display/intel_atomic.c @@ -40,6 +40,7 @@ #include "intel_global_state.h" #include "intel_hdcp.h" #include "intel_psr.h" +#include "intel_fb.h" #include "skl_universal_plane.h" /** @@ -310,11 +311,11 @@ intel_crtc_destroy_state(struct drm_crtc *crtc, kfree(crtc_state); } -static void intel_atomic_setup_scaler(struct intel_crtc_scaler_state *scaler_state, - int num_scalers_need, struct intel_crtc *intel_crtc, - const char *name, int idx, - struct intel_plane_state *plane_state, - int *scaler_id) +static int intel_atomic_setup_scaler(struct intel_crtc_scaler_state *scaler_state, + int num_scalers_need, struct intel_crtc *intel_crtc, + const char *name, int idx, + struct intel_plane_state *plane_state, + int *scaler_id) { struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev); int j; @@ -334,7 +335,7 @@ static void intel_atomic_setup_scaler(struct intel_crtc_scaler_state *scaler_sta if (drm_WARN(&dev_priv->drm, *scaler_id < 0, "Cannot find scaler for %s:%d\n", name, idx)) - return; + return -EINVAL; /* set scaler mode */ if (plane_state && plane_state->hw.fb && @@ -375,9 +376,71 @@ static void intel_atomic_setup_scaler(struct intel_crtc_scaler_state *scaler_sta mode = SKL_PS_SCALER_MODE_DYN; } + /* + * FIXME: we should also check the scaler factors for pfit, so + * this shouldn't be tied directly to planes. + */ + if (plane_state && plane_state->hw.fb) { + const struct drm_framebuffer *fb = plane_state->hw.fb; + const struct drm_rect *src = &plane_state->uapi.src; + const struct drm_rect *dst = &plane_state->uapi.dst; + int hscale, vscale, max_vscale, max_hscale; + + /* + * FIXME: When two scalers are needed, but only one of + * them needs to downscale, we should make sure that + * the one that needs downscaling support is assigned + * as the first scaler, so we don't reject downscaling + * unnecessarily. + */ + + if (DISPLAY_VER(dev_priv) >= 14) { + /* + * On versions 14 and up, only the first + * scaler supports a vertical scaling factor + * of more than 1.0, while a horizontal + * scaling factor of 3.0 is supported. + */ + max_hscale = 0x30000 - 1; + if (*scaler_id == 0) + max_vscale = 0x30000 - 1; + else + max_vscale = 0x10000; + + } else if (DISPLAY_VER(dev_priv) >= 10 || + !intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier)) { + max_hscale = 0x30000 - 1; + max_vscale = 0x30000 - 1; + } else { + max_hscale = 0x20000 - 1; + max_vscale = 0x20000 - 1; + } + + /* + * FIXME: We should change the if-else block above to + * support HQ vs dynamic scaler properly. + */ + + /* Check if required scaling is within limits */ + hscale = drm_rect_calc_hscale(src, dst, 1, max_hscale); + vscale = drm_rect_calc_vscale(src, dst, 1, max_vscale); + + if (hscale < 0 || vscale < 0) { + drm_dbg_kms(&dev_priv->drm, + "Scaler %d doesn't support required plane scaling\n", + *scaler_id); + drm_rect_debug_print("src: ", src, true); + drm_rect_debug_print("dst: ", dst, false); + + return -EINVAL; + } + } + drm_dbg_kms(&dev_priv->drm, "Attached scaler id %u.%u to %s:%d\n", intel_crtc->pipe, *scaler_id, name, idx); scaler_state->scalers[*scaler_id].mode = mode; + + return 0; } /** @@ -437,7 +500,7 @@ int intel_atomic_setup_scalers(struct drm_i915_private *dev_priv, for (i = 0; i < sizeof(scaler_state->scaler_users) * 8; i++) { int *scaler_id; const char *name; - int idx; + int idx, ret; /* skip if scaler not required */ if (!(scaler_state->scaler_users & (1 << i))) @@ -494,9 +557,11 @@ int intel_atomic_setup_scalers(struct drm_i915_private *dev_priv, scaler_id = &plane_state->scaler_id; } - intel_atomic_setup_scaler(scaler_state, num_scalers_need, - intel_crtc, name, idx, - plane_state, scaler_id); + ret = intel_atomic_setup_scaler(scaler_state, num_scalers_need, + intel_crtc, name, idx, + plane_state, scaler_id); + if (ret < 0) + return ret; } return 0; -- cgit v1.2.3 From f9954b18c4faaeeb9bacc38ecffd3f0f94cc257e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 18 Apr 2023 20:55:16 +0300 Subject: drm/i915: Relocate intel_atomic_setup_scalers() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 8976b18249407df8bf6ea18ecae0640a15341a50 ] Move intel_atomic_setup_scalers() next to the other scaler code in skl_scaler.c. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20230418175528.13117-4-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula Stable-dep-of: c3070f080f9b ("drm/i915: Fix intel_atomic_setup_scalers() plane_state handling") Signed-off-by: Sasha Levin --- drivers/gpu/drm/i915/display/intel_atomic.c | 256 --------------------------- drivers/gpu/drm/i915/display/intel_atomic.h | 4 - drivers/gpu/drm/i915/display/skl_scaler.c | 257 ++++++++++++++++++++++++++++ drivers/gpu/drm/i915/display/skl_scaler.h | 10 +- 4 files changed, 265 insertions(+), 262 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_atomic.c b/drivers/gpu/drm/i915/display/intel_atomic.c index 4b4514ce6d88..655c039a9c8f 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic.c +++ b/drivers/gpu/drm/i915/display/intel_atomic.c @@ -311,262 +311,6 @@ intel_crtc_destroy_state(struct drm_crtc *crtc, kfree(crtc_state); } -static int intel_atomic_setup_scaler(struct intel_crtc_scaler_state *scaler_state, - int num_scalers_need, struct intel_crtc *intel_crtc, - const char *name, int idx, - struct intel_plane_state *plane_state, - int *scaler_id) -{ - struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev); - int j; - u32 mode; - - if (*scaler_id < 0) { - /* find a free scaler */ - for (j = 0; j < intel_crtc->num_scalers; j++) { - if (scaler_state->scalers[j].in_use) - continue; - - *scaler_id = j; - scaler_state->scalers[*scaler_id].in_use = 1; - break; - } - } - - if (drm_WARN(&dev_priv->drm, *scaler_id < 0, - "Cannot find scaler for %s:%d\n", name, idx)) - return -EINVAL; - - /* set scaler mode */ - if (plane_state && plane_state->hw.fb && - plane_state->hw.fb->format->is_yuv && - plane_state->hw.fb->format->num_planes > 1) { - struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); - if (DISPLAY_VER(dev_priv) == 9) { - mode = SKL_PS_SCALER_MODE_NV12; - } else if (icl_is_hdr_plane(dev_priv, plane->id)) { - /* - * On gen11+'s HDR planes we only use the scaler for - * scaling. They have a dedicated chroma upsampler, so - * we don't need the scaler to upsample the UV plane. - */ - mode = PS_SCALER_MODE_NORMAL; - } else { - struct intel_plane *linked = - plane_state->planar_linked_plane; - - mode = PS_SCALER_MODE_PLANAR; - - if (linked) - mode |= PS_PLANE_Y_SEL(linked->id); - } - } else if (DISPLAY_VER(dev_priv) >= 10) { - mode = PS_SCALER_MODE_NORMAL; - } else if (num_scalers_need == 1 && intel_crtc->num_scalers > 1) { - /* - * when only 1 scaler is in use on a pipe with 2 scalers - * scaler 0 operates in high quality (HQ) mode. - * In this case use scaler 0 to take advantage of HQ mode - */ - scaler_state->scalers[*scaler_id].in_use = 0; - *scaler_id = 0; - scaler_state->scalers[0].in_use = 1; - mode = SKL_PS_SCALER_MODE_HQ; - } else { - mode = SKL_PS_SCALER_MODE_DYN; - } - - /* - * FIXME: we should also check the scaler factors for pfit, so - * this shouldn't be tied directly to planes. - */ - if (plane_state && plane_state->hw.fb) { - const struct drm_framebuffer *fb = plane_state->hw.fb; - const struct drm_rect *src = &plane_state->uapi.src; - const struct drm_rect *dst = &plane_state->uapi.dst; - int hscale, vscale, max_vscale, max_hscale; - - /* - * FIXME: When two scalers are needed, but only one of - * them needs to downscale, we should make sure that - * the one that needs downscaling support is assigned - * as the first scaler, so we don't reject downscaling - * unnecessarily. - */ - - if (DISPLAY_VER(dev_priv) >= 14) { - /* - * On versions 14 and up, only the first - * scaler supports a vertical scaling factor - * of more than 1.0, while a horizontal - * scaling factor of 3.0 is supported. - */ - max_hscale = 0x30000 - 1; - if (*scaler_id == 0) - max_vscale = 0x30000 - 1; - else - max_vscale = 0x10000; - - } else if (DISPLAY_VER(dev_priv) >= 10 || - !intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier)) { - max_hscale = 0x30000 - 1; - max_vscale = 0x30000 - 1; - } else { - max_hscale = 0x20000 - 1; - max_vscale = 0x20000 - 1; - } - - /* - * FIXME: We should change the if-else block above to - * support HQ vs dynamic scaler properly. - */ - - /* Check if required scaling is within limits */ - hscale = drm_rect_calc_hscale(src, dst, 1, max_hscale); - vscale = drm_rect_calc_vscale(src, dst, 1, max_vscale); - - if (hscale < 0 || vscale < 0) { - drm_dbg_kms(&dev_priv->drm, - "Scaler %d doesn't support required plane scaling\n", - *scaler_id); - drm_rect_debug_print("src: ", src, true); - drm_rect_debug_print("dst: ", dst, false); - - return -EINVAL; - } - } - - drm_dbg_kms(&dev_priv->drm, "Attached scaler id %u.%u to %s:%d\n", - intel_crtc->pipe, *scaler_id, name, idx); - scaler_state->scalers[*scaler_id].mode = mode; - - return 0; -} - -/** - * intel_atomic_setup_scalers() - setup scalers for crtc per staged requests - * @dev_priv: i915 device - * @intel_crtc: intel crtc - * @crtc_state: incoming crtc_state to validate and setup scalers - * - * This function sets up scalers based on staged scaling requests for - * a @crtc and its planes. It is called from crtc level check path. If request - * is a supportable request, it attaches scalers to requested planes and crtc. - * - * This function takes into account the current scaler(s) in use by any planes - * not being part of this atomic state - * - * Returns: - * 0 - scalers were setup succesfully - * error code - otherwise - */ -int intel_atomic_setup_scalers(struct drm_i915_private *dev_priv, - struct intel_crtc *intel_crtc, - struct intel_crtc_state *crtc_state) -{ - struct drm_plane *plane = NULL; - struct intel_plane *intel_plane; - struct intel_plane_state *plane_state = NULL; - struct intel_crtc_scaler_state *scaler_state = - &crtc_state->scaler_state; - struct drm_atomic_state *drm_state = crtc_state->uapi.state; - struct intel_atomic_state *intel_state = to_intel_atomic_state(drm_state); - int num_scalers_need; - int i; - - num_scalers_need = hweight32(scaler_state->scaler_users); - - /* - * High level flow: - * - staged scaler requests are already in scaler_state->scaler_users - * - check whether staged scaling requests can be supported - * - add planes using scalers that aren't in current transaction - * - assign scalers to requested users - * - as part of plane commit, scalers will be committed - * (i.e., either attached or detached) to respective planes in hw - * - as part of crtc_commit, scaler will be either attached or detached - * to crtc in hw - */ - - /* fail if required scalers > available scalers */ - if (num_scalers_need > intel_crtc->num_scalers){ - drm_dbg_kms(&dev_priv->drm, - "Too many scaling requests %d > %d\n", - num_scalers_need, intel_crtc->num_scalers); - return -EINVAL; - } - - /* walkthrough scaler_users bits and start assigning scalers */ - for (i = 0; i < sizeof(scaler_state->scaler_users) * 8; i++) { - int *scaler_id; - const char *name; - int idx, ret; - - /* skip if scaler not required */ - if (!(scaler_state->scaler_users & (1 << i))) - continue; - - if (i == SKL_CRTC_INDEX) { - name = "CRTC"; - idx = intel_crtc->base.base.id; - - /* panel fitter case: assign as a crtc scaler */ - scaler_id = &scaler_state->scaler_id; - } else { - name = "PLANE"; - - /* plane scaler case: assign as a plane scaler */ - /* find the plane that set the bit as scaler_user */ - plane = drm_state->planes[i].ptr; - - /* - * to enable/disable hq mode, add planes that are using scaler - * into this transaction - */ - if (!plane) { - struct drm_plane_state *state; - - /* - * GLK+ scalers don't have a HQ mode so it - * isn't necessary to change between HQ and dyn mode - * on those platforms. - */ - if (DISPLAY_VER(dev_priv) >= 10) - continue; - - plane = drm_plane_from_index(&dev_priv->drm, i); - state = drm_atomic_get_plane_state(drm_state, plane); - if (IS_ERR(state)) { - drm_dbg_kms(&dev_priv->drm, - "Failed to add [PLANE:%d] to drm_state\n", - plane->base.id); - return PTR_ERR(state); - } - } - - intel_plane = to_intel_plane(plane); - idx = plane->base.id; - - /* plane on different crtc cannot be a scaler user of this crtc */ - if (drm_WARN_ON(&dev_priv->drm, - intel_plane->pipe != intel_crtc->pipe)) - continue; - - plane_state = intel_atomic_get_new_plane_state(intel_state, - intel_plane); - scaler_id = &plane_state->scaler_id; - } - - ret = intel_atomic_setup_scaler(scaler_state, num_scalers_need, - intel_crtc, name, idx, - plane_state, scaler_id); - if (ret < 0) - return ret; - } - - return 0; -} - struct drm_atomic_state * intel_atomic_state_alloc(struct drm_device *dev) { diff --git a/drivers/gpu/drm/i915/display/intel_atomic.h b/drivers/gpu/drm/i915/display/intel_atomic.h index d2700c74c9da..509deb75f698 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic.h +++ b/drivers/gpu/drm/i915/display/intel_atomic.h @@ -54,8 +54,4 @@ struct intel_crtc_state * intel_atomic_get_crtc_state(struct drm_atomic_state *state, struct intel_crtc *crtc); -int intel_atomic_setup_scalers(struct drm_i915_private *dev_priv, - struct intel_crtc *intel_crtc, - struct intel_crtc_state *crtc_state); - #endif /* __INTEL_ATOMIC_H__ */ diff --git a/drivers/gpu/drm/i915/display/skl_scaler.c b/drivers/gpu/drm/i915/display/skl_scaler.c index 37eabeff8197..a9cc5cfad0bd 100644 --- a/drivers/gpu/drm/i915/display/skl_scaler.c +++ b/drivers/gpu/drm/i915/display/skl_scaler.c @@ -294,6 +294,263 @@ int skl_update_scaler_plane(struct intel_crtc_state *crtc_state, return 0; } +static int intel_atomic_setup_scaler(struct intel_crtc_scaler_state *scaler_state, + int num_scalers_need, struct intel_crtc *intel_crtc, + const char *name, int idx, + struct intel_plane_state *plane_state, + int *scaler_id) +{ + struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev); + int j; + u32 mode; + + if (*scaler_id < 0) { + /* find a free scaler */ + for (j = 0; j < intel_crtc->num_scalers; j++) { + if (scaler_state->scalers[j].in_use) + continue; + + *scaler_id = j; + scaler_state->scalers[*scaler_id].in_use = 1; + break; + } + } + + if (drm_WARN(&dev_priv->drm, *scaler_id < 0, + "Cannot find scaler for %s:%d\n", name, idx)) + return -EINVAL; + + /* set scaler mode */ + if (plane_state && plane_state->hw.fb && + plane_state->hw.fb->format->is_yuv && + plane_state->hw.fb->format->num_planes > 1) { + struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); + + if (DISPLAY_VER(dev_priv) == 9) { + mode = SKL_PS_SCALER_MODE_NV12; + } else if (icl_is_hdr_plane(dev_priv, plane->id)) { + /* + * On gen11+'s HDR planes we only use the scaler for + * scaling. They have a dedicated chroma upsampler, so + * we don't need the scaler to upsample the UV plane. + */ + mode = PS_SCALER_MODE_NORMAL; + } else { + struct intel_plane *linked = + plane_state->planar_linked_plane; + + mode = PS_SCALER_MODE_PLANAR; + + if (linked) + mode |= PS_PLANE_Y_SEL(linked->id); + } + } else if (DISPLAY_VER(dev_priv) >= 10) { + mode = PS_SCALER_MODE_NORMAL; + } else if (num_scalers_need == 1 && intel_crtc->num_scalers > 1) { + /* + * when only 1 scaler is in use on a pipe with 2 scalers + * scaler 0 operates in high quality (HQ) mode. + * In this case use scaler 0 to take advantage of HQ mode + */ + scaler_state->scalers[*scaler_id].in_use = 0; + *scaler_id = 0; + scaler_state->scalers[0].in_use = 1; + mode = SKL_PS_SCALER_MODE_HQ; + } else { + mode = SKL_PS_SCALER_MODE_DYN; + } + + /* + * FIXME: we should also check the scaler factors for pfit, so + * this shouldn't be tied directly to planes. + */ + if (plane_state && plane_state->hw.fb) { + const struct drm_framebuffer *fb = plane_state->hw.fb; + const struct drm_rect *src = &plane_state->uapi.src; + const struct drm_rect *dst = &plane_state->uapi.dst; + int hscale, vscale, max_vscale, max_hscale; + + /* + * FIXME: When two scalers are needed, but only one of + * them needs to downscale, we should make sure that + * the one that needs downscaling support is assigned + * as the first scaler, so we don't reject downscaling + * unnecessarily. + */ + + if (DISPLAY_VER(dev_priv) >= 14) { + /* + * On versions 14 and up, only the first + * scaler supports a vertical scaling factor + * of more than 1.0, while a horizontal + * scaling factor of 3.0 is supported. + */ + max_hscale = 0x30000 - 1; + if (*scaler_id == 0) + max_vscale = 0x30000 - 1; + else + max_vscale = 0x10000; + + } else if (DISPLAY_VER(dev_priv) >= 10 || + !intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier)) { + max_hscale = 0x30000 - 1; + max_vscale = 0x30000 - 1; + } else { + max_hscale = 0x20000 - 1; + max_vscale = 0x20000 - 1; + } + + /* + * FIXME: We should change the if-else block above to + * support HQ vs dynamic scaler properly. + */ + + /* Check if required scaling is within limits */ + hscale = drm_rect_calc_hscale(src, dst, 1, max_hscale); + vscale = drm_rect_calc_vscale(src, dst, 1, max_vscale); + + if (hscale < 0 || vscale < 0) { + drm_dbg_kms(&dev_priv->drm, + "Scaler %d doesn't support required plane scaling\n", + *scaler_id); + drm_rect_debug_print("src: ", src, true); + drm_rect_debug_print("dst: ", dst, false); + + return -EINVAL; + } + } + + drm_dbg_kms(&dev_priv->drm, "Attached scaler id %u.%u to %s:%d\n", + intel_crtc->pipe, *scaler_id, name, idx); + scaler_state->scalers[*scaler_id].mode = mode; + + return 0; +} + +/** + * intel_atomic_setup_scalers() - setup scalers for crtc per staged requests + * @dev_priv: i915 device + * @intel_crtc: intel crtc + * @crtc_state: incoming crtc_state to validate and setup scalers + * + * This function sets up scalers based on staged scaling requests for + * a @crtc and its planes. It is called from crtc level check path. If request + * is a supportable request, it attaches scalers to requested planes and crtc. + * + * This function takes into account the current scaler(s) in use by any planes + * not being part of this atomic state + * + * Returns: + * 0 - scalers were setup successfully + * error code - otherwise + */ +int intel_atomic_setup_scalers(struct drm_i915_private *dev_priv, + struct intel_crtc *intel_crtc, + struct intel_crtc_state *crtc_state) +{ + struct drm_plane *plane = NULL; + struct intel_plane *intel_plane; + struct intel_plane_state *plane_state = NULL; + struct intel_crtc_scaler_state *scaler_state = + &crtc_state->scaler_state; + struct drm_atomic_state *drm_state = crtc_state->uapi.state; + struct intel_atomic_state *intel_state = to_intel_atomic_state(drm_state); + int num_scalers_need; + int i; + + num_scalers_need = hweight32(scaler_state->scaler_users); + + /* + * High level flow: + * - staged scaler requests are already in scaler_state->scaler_users + * - check whether staged scaling requests can be supported + * - add planes using scalers that aren't in current transaction + * - assign scalers to requested users + * - as part of plane commit, scalers will be committed + * (i.e., either attached or detached) to respective planes in hw + * - as part of crtc_commit, scaler will be either attached or detached + * to crtc in hw + */ + + /* fail if required scalers > available scalers */ + if (num_scalers_need > intel_crtc->num_scalers) { + drm_dbg_kms(&dev_priv->drm, + "Too many scaling requests %d > %d\n", + num_scalers_need, intel_crtc->num_scalers); + return -EINVAL; + } + + /* walkthrough scaler_users bits and start assigning scalers */ + for (i = 0; i < sizeof(scaler_state->scaler_users) * 8; i++) { + int *scaler_id; + const char *name; + int idx, ret; + + /* skip if scaler not required */ + if (!(scaler_state->scaler_users & (1 << i))) + continue; + + if (i == SKL_CRTC_INDEX) { + name = "CRTC"; + idx = intel_crtc->base.base.id; + + /* panel fitter case: assign as a crtc scaler */ + scaler_id = &scaler_state->scaler_id; + } else { + name = "PLANE"; + + /* plane scaler case: assign as a plane scaler */ + /* find the plane that set the bit as scaler_user */ + plane = drm_state->planes[i].ptr; + + /* + * to enable/disable hq mode, add planes that are using scaler + * into this transaction + */ + if (!plane) { + struct drm_plane_state *state; + + /* + * GLK+ scalers don't have a HQ mode so it + * isn't necessary to change between HQ and dyn mode + * on those platforms. + */ + if (DISPLAY_VER(dev_priv) >= 10) + continue; + + plane = drm_plane_from_index(&dev_priv->drm, i); + state = drm_atomic_get_plane_state(drm_state, plane); + if (IS_ERR(state)) { + drm_dbg_kms(&dev_priv->drm, + "Failed to add [PLANE:%d] to drm_state\n", + plane->base.id); + return PTR_ERR(state); + } + } + + intel_plane = to_intel_plane(plane); + idx = plane->base.id; + + /* plane on different crtc cannot be a scaler user of this crtc */ + if (drm_WARN_ON(&dev_priv->drm, + intel_plane->pipe != intel_crtc->pipe)) + continue; + + plane_state = intel_atomic_get_new_plane_state(intel_state, + intel_plane); + scaler_id = &plane_state->scaler_id; + } + + ret = intel_atomic_setup_scaler(scaler_state, num_scalers_need, + intel_crtc, name, idx, + plane_state, scaler_id); + if (ret < 0) + return ret; + } + + return 0; +} + static int glk_coef_tap(int i) { return i % 7; diff --git a/drivers/gpu/drm/i915/display/skl_scaler.h b/drivers/gpu/drm/i915/display/skl_scaler.h index 0097d5d08e10..f040f6ac061f 100644 --- a/drivers/gpu/drm/i915/display/skl_scaler.h +++ b/drivers/gpu/drm/i915/display/skl_scaler.h @@ -8,17 +8,22 @@ #include enum drm_scaling_filter; +enum pipe; struct drm_i915_private; +struct intel_crtc; struct intel_crtc_state; -struct intel_plane_state; struct intel_plane; -enum pipe; +struct intel_plane_state; int skl_update_scaler_crtc(struct intel_crtc_state *crtc_state); int skl_update_scaler_plane(struct intel_crtc_state *crtc_state, struct intel_plane_state *plane_state); +int intel_atomic_setup_scalers(struct drm_i915_private *dev_priv, + struct intel_crtc *intel_crtc, + struct intel_crtc_state *crtc_state); + void skl_pfit_enable(const struct intel_crtc_state *crtc_state); void skl_program_plane_scaler(struct intel_plane *plane, @@ -26,4 +31,5 @@ void skl_program_plane_scaler(struct intel_plane *plane, const struct intel_plane_state *plane_state); void skl_detach_scalers(const struct intel_crtc_state *crtc_state); void skl_scaler_disable(const struct intel_crtc_state *old_crtc_state); + #endif -- cgit v1.2.3 From 6ded9038e4b1a1c2900848a369e5cd81434f0d7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 7 Dec 2023 21:34:34 +0200 Subject: drm/i915: Fix intel_atomic_setup_scalers() plane_state handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit c3070f080f9ba18dea92eaa21730f7ab85b5c8f4 ] Since the plane_state variable is declared outside the scaler_users loop in intel_atomic_setup_scalers(), and it's never reset back to NULL inside the loop we may end up calling intel_atomic_setup_scaler() with a non-NULL plane state for the pipe scaling case. That is bad because intel_atomic_setup_scaler() determines whether we are doing plane scaling or pipe scaling based on plane_state!=NULL. The end result is that we may miscalculate the scaler mode for pipe scaling. The hardware becomes somewhat upset if we end up in this situation when scanning out a planar format on a SDR plane. We end up programming the pipe scaler into planar mode as well, and the result is a screenfull of garbage. Fix the situation by making sure we pass the correct plane_state==NULL when calculating the scaler mode for pipe scaling. Cc: stable@vger.kernel.org Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20231207193441.20206-2-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula (cherry picked from commit e81144106e21271c619f0c722a09e27ccb8c043d) Signed-off-by: Jani Nikula Signed-off-by: Sasha Levin --- drivers/gpu/drm/i915/display/skl_scaler.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/skl_scaler.c b/drivers/gpu/drm/i915/display/skl_scaler.c index a9cc5cfad0bd..e55df2f05cbd 100644 --- a/drivers/gpu/drm/i915/display/skl_scaler.c +++ b/drivers/gpu/drm/i915/display/skl_scaler.c @@ -450,7 +450,6 @@ int intel_atomic_setup_scalers(struct drm_i915_private *dev_priv, { struct drm_plane *plane = NULL; struct intel_plane *intel_plane; - struct intel_plane_state *plane_state = NULL; struct intel_crtc_scaler_state *scaler_state = &crtc_state->scaler_state; struct drm_atomic_state *drm_state = crtc_state->uapi.state; @@ -482,6 +481,7 @@ int intel_atomic_setup_scalers(struct drm_i915_private *dev_priv, /* walkthrough scaler_users bits and start assigning scalers */ for (i = 0; i < sizeof(scaler_state->scaler_users) * 8; i++) { + struct intel_plane_state *plane_state = NULL; int *scaler_id; const char *name; int idx, ret; -- cgit v1.2.3 From fd3951b798c86874015f0be81a7530694e954dc7 Mon Sep 17 00:00:00 2001 From: Paulo Alcantara Date: Mon, 11 Dec 2023 10:26:42 -0300 Subject: smb: client: fix NULL deref in asn1_ber_decoder() [ Upstream commit 90d025c2e953c11974e76637977c473200593a46 ] If server replied SMB2_NEGOTIATE with a zero SecurityBufferOffset, smb2_get_data_area() sets @len to non-zero but return NULL, so decode_negTokeninit() ends up being called with a NULL @security_blob: BUG: kernel NULL pointer dereference, address: 0000000000000000 #PF: supervisor read access in kernel mode #PF: error_code(0x0000) - not-present page PGD 0 P4D 0 Oops: 0000 [#1] PREEMPT SMP NOPTI CPU: 2 PID: 871 Comm: mount.cifs Not tainted 6.7.0-rc4 #2 Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.16.2-3-gd478f380-rebuilt.opensuse.org 04/01/2014 RIP: 0010:asn1_ber_decoder+0x173/0xc80 Code: 01 4c 39 2c 24 75 09 45 84 c9 0f 85 2f 03 00 00 48 8b 14 24 4c 29 ea 48 83 fa 01 0f 86 1e 07 00 00 48 8b 74 24 28 4d 8d 5d 01 <42> 0f b6 3c 2e 89 fa 40 88 7c 24 5c f7 d2 83 e2 1f 0f 84 3d 07 00 RSP: 0018:ffffc9000063f950 EFLAGS: 00010202 RAX: 0000000000000002 RBX: 0000000000000000 RCX: 000000000000004a RDX: 000000000000004a RSI: 0000000000000000 RDI: 0000000000000000 RBP: 0000000000000000 R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000000002 R11: 0000000000000001 R12: 0000000000000000 R13: 0000000000000000 R14: 000000000000004d R15: 0000000000000000 FS: 00007fce52b0fbc0(0000) GS:ffff88806ba00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000000000000000 CR3: 000000001ae64000 CR4: 0000000000750ef0 PKRU: 55555554 Call Trace: ? __die+0x23/0x70 ? page_fault_oops+0x181/0x480 ? __stack_depot_save+0x1e6/0x480 ? exc_page_fault+0x6f/0x1c0 ? asm_exc_page_fault+0x26/0x30 ? asn1_ber_decoder+0x173/0xc80 ? check_object+0x40/0x340 decode_negTokenInit+0x1e/0x30 [cifs] SMB2_negotiate+0xc99/0x17c0 [cifs] ? smb2_negotiate+0x46/0x60 [cifs] ? srso_alias_return_thunk+0x5/0xfbef5 smb2_negotiate+0x46/0x60 [cifs] cifs_negotiate_protocol+0xae/0x130 [cifs] cifs_get_smb_ses+0x517/0x1040 [cifs] ? srso_alias_return_thunk+0x5/0xfbef5 ? srso_alias_return_thunk+0x5/0xfbef5 ? queue_delayed_work_on+0x5d/0x90 cifs_mount_get_session+0x78/0x200 [cifs] dfs_mount_share+0x13a/0x9f0 [cifs] ? srso_alias_return_thunk+0x5/0xfbef5 ? lock_acquire+0xbf/0x2b0 ? find_nls+0x16/0x80 ? srso_alias_return_thunk+0x5/0xfbef5 cifs_mount+0x7e/0x350 [cifs] cifs_smb3_do_mount+0x128/0x780 [cifs] smb3_get_tree+0xd9/0x290 [cifs] vfs_get_tree+0x2c/0x100 ? capable+0x37/0x70 path_mount+0x2d7/0xb80 ? srso_alias_return_thunk+0x5/0xfbef5 ? _raw_spin_unlock_irqrestore+0x44/0x60 __x64_sys_mount+0x11a/0x150 do_syscall_64+0x47/0xf0 entry_SYSCALL_64_after_hwframe+0x6f/0x77 RIP: 0033:0x7fce52c2ab1e Fix this by setting @len to zero when @off == 0 so callers won't attempt to dereference non-existing data areas. Reported-by: Robert Morris Cc: stable@vger.kernel.org Signed-off-by: Paulo Alcantara (SUSE) Signed-off-by: Steve French Signed-off-by: Sasha Levin --- fs/cifs/smb2misc.c | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/fs/cifs/smb2misc.c b/fs/cifs/smb2misc.c index 29b5554f6263..e2f401c8c5ce 100644 --- a/fs/cifs/smb2misc.c +++ b/fs/cifs/smb2misc.c @@ -298,6 +298,9 @@ static const bool has_smb2_data_area[NUMBER_OF_SMB2_COMMANDS] = { char * smb2_get_data_area_len(int *off, int *len, struct smb2_sync_hdr *shdr) { + const int max_off = 4096; + const int max_len = 128 * 1024; + *off = 0; *len = 0; @@ -369,29 +372,20 @@ smb2_get_data_area_len(int *off, int *len, struct smb2_sync_hdr *shdr) * Invalid length or offset probably means data area is invalid, but * we have little choice but to ignore the data area in this case. */ - if (*off > 4096) { - cifs_dbg(VFS, "offset %d too large, data area ignored\n", *off); - *len = 0; - *off = 0; - } else if (*off < 0) { - cifs_dbg(VFS, "negative offset %d to data invalid ignore data area\n", - *off); + if (unlikely(*off < 0 || *off > max_off || + *len < 0 || *len > max_len)) { + cifs_dbg(VFS, "%s: invalid data area (off=%d len=%d)\n", + __func__, *off, *len); *off = 0; *len = 0; - } else if (*len < 0) { - cifs_dbg(VFS, "negative data length %d invalid, data area ignored\n", - *len); - *len = 0; - } else if (*len > 128 * 1024) { - cifs_dbg(VFS, "data area larger than 128K: %d\n", *len); + } else if (*off == 0) { *len = 0; } /* return pointer to beginning of data area, ie offset from SMB start */ - if ((*off != 0) && (*len != 0)) + if (*off > 0 && *len > 0) return (char *)shdr + *off; - else - return NULL; + return NULL; } /* -- cgit v1.2.3 From f47e3f60f239153c272840af8817839f266994d9 Mon Sep 17 00:00:00 2001 From: Paulo Alcantara Date: Mon, 11 Dec 2023 10:26:43 -0300 Subject: smb: client: fix OOB in smb2_query_reparse_point() [ Upstream commit 3a42709fa909e22b0be4bb1e2795aa04ada732a3 ] Validate @ioctl_rsp->OutputOffset and @ioctl_rsp->OutputCount so that their sum does not wrap to a number that is smaller than @reparse_buf and we end up with a wild pointer as follows: BUG: unable to handle page fault for address: ffff88809c5cd45f #PF: supervisor read access in kernel mode #PF: error_code(0x0000) - not-present page PGD 4a01067 P4D 4a01067 PUD 0 Oops: 0000 [#1] PREEMPT SMP NOPTI CPU: 2 PID: 1260 Comm: mount.cifs Not tainted 6.7.0-rc4 #2 Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.16.2-3-gd478f380-rebuilt.opensuse.org 04/01/2014 RIP: 0010:smb2_query_reparse_point+0x3e0/0x4c0 [cifs] Code: ff ff e8 f3 51 fe ff 41 89 c6 58 5a 45 85 f6 0f 85 14 fe ff ff 49 8b 57 48 8b 42 60 44 8b 42 64 42 8d 0c 00 49 39 4f 50 72 40 <8b> 04 02 48 8b 9d f0 fe ff ff 49 8b 57 50 89 03 48 8b 9d e8 fe ff RSP: 0018:ffffc90000347a90 EFLAGS: 00010212 RAX: 000000008000001f RBX: ffff88800ae11000 RCX: 00000000000000ec RDX: ffff88801c5cd440 RSI: 0000000000000000 RDI: ffffffff82004aa4 RBP: ffffc90000347bb0 R08: 00000000800000cd R09: 0000000000000001 R10: 0000000000000000 R11: 0000000000000024 R12: ffff8880114d4100 R13: ffff8880114d4198 R14: 0000000000000000 R15: ffff8880114d4000 FS: 00007f02c07babc0(0000) GS:ffff88806ba00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: ffff88809c5cd45f CR3: 0000000011750000 CR4: 0000000000750ef0 PKRU: 55555554 Call Trace: ? __die+0x23/0x70 ? page_fault_oops+0x181/0x480 ? search_module_extables+0x19/0x60 ? srso_alias_return_thunk+0x5/0xfbef5 ? exc_page_fault+0x1b6/0x1c0 ? asm_exc_page_fault+0x26/0x30 ? _raw_spin_unlock_irqrestore+0x44/0x60 ? smb2_query_reparse_point+0x3e0/0x4c0 [cifs] cifs_get_fattr+0x16e/0xa50 [cifs] ? srso_alias_return_thunk+0x5/0xfbef5 ? lock_acquire+0xbf/0x2b0 cifs_root_iget+0x163/0x5f0 [cifs] cifs_smb3_do_mount+0x5bd/0x780 [cifs] smb3_get_tree+0xd9/0x290 [cifs] vfs_get_tree+0x2c/0x100 ? capable+0x37/0x70 path_mount+0x2d7/0xb80 ? srso_alias_return_thunk+0x5/0xfbef5 ? _raw_spin_unlock_irqrestore+0x44/0x60 __x64_sys_mount+0x11a/0x150 do_syscall_64+0x47/0xf0 entry_SYSCALL_64_after_hwframe+0x6f/0x77 RIP: 0033:0x7f02c08d5b1e Fixes: 2e4564b31b64 ("smb3: add support for stat of WSL reparse points for special file types") Cc: stable@vger.kernel.org Reported-by: Robert Morris Signed-off-by: Paulo Alcantara (SUSE) Signed-off-by: Steve French Signed-off-by: Sasha Levin --- fs/cifs/smb2ops.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c index 7c2ecbb17f54..f31da2647d04 100644 --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c @@ -3263,7 +3263,7 @@ smb2_query_reparse_tag(const unsigned int xid, struct cifs_tcon *tcon, struct kvec close_iov[1]; struct smb2_ioctl_rsp *ioctl_rsp; struct reparse_data_buffer *reparse_buf; - u32 plen; + u32 off, count, len; cifs_dbg(FYI, "%s: path: %s\n", __func__, full_path); @@ -3343,16 +3343,22 @@ smb2_query_reparse_tag(const unsigned int xid, struct cifs_tcon *tcon, */ if (rc == 0) { /* See MS-FSCC 2.3.23 */ + off = le32_to_cpu(ioctl_rsp->OutputOffset); + count = le32_to_cpu(ioctl_rsp->OutputCount); + if (check_add_overflow(off, count, &len) || + len > rsp_iov[1].iov_len) { + cifs_tcon_dbg(VFS, "%s: invalid ioctl: off=%d count=%d\n", + __func__, off, count); + rc = -EIO; + goto query_rp_exit; + } - reparse_buf = (struct reparse_data_buffer *) - ((char *)ioctl_rsp + - le32_to_cpu(ioctl_rsp->OutputOffset)); - plen = le32_to_cpu(ioctl_rsp->OutputCount); - - if (plen + le32_to_cpu(ioctl_rsp->OutputOffset) > - rsp_iov[1].iov_len) { - cifs_tcon_dbg(FYI, "srv returned invalid ioctl len: %d\n", - plen); + reparse_buf = (void *)((u8 *)ioctl_rsp + off); + len = sizeof(*reparse_buf); + if (count < len || + count < le16_to_cpu(reparse_buf->ReparseDataLength) + len) { + cifs_tcon_dbg(VFS, "%s: invalid ioctl: off=%d count=%d\n", + __func__, off, count); rc = -EIO; goto query_rp_exit; } -- cgit v1.2.3 From 3cbae23d481be4837b8c49403c26cad64c2c9001 Mon Sep 17 00:00:00 2001 From: Mike Tipton Date: Wed, 25 Oct 2023 07:58:29 -0700 Subject: interconnect: Treat xlate() returning NULL node as an error [ Upstream commit ad2ab1297d0c80899125a842bb7a078abfe1e6ce ] Currently, if provider->xlate() or provider->xlate_extended() "successfully" return a NULL node, then of_icc_get_from_provider() won't consider that an error and will successfully return the NULL node. This bypasses error handling in of_icc_get_by_index() and leads to NULL dereferences in path_find(). This could be avoided by ensuring provider callbacks always return an error for NULL nodes, but it's better to explicitly protect against this in the common framework. Fixes: 87e3031b6fbd ("interconnect: Allow endpoints translation via DT") Signed-off-by: Mike Tipton Link: https://lore.kernel.org/r/20231025145829.11603-1-quic_mdtipton@quicinc.com Signed-off-by: Georgi Djakov Signed-off-by: Sasha Levin --- drivers/interconnect/core.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/interconnect/core.c b/drivers/interconnect/core.c index b7c41bd7409c..aadb2b97498a 100644 --- a/drivers/interconnect/core.c +++ b/drivers/interconnect/core.c @@ -382,6 +382,9 @@ struct icc_node_data *of_icc_get_from_provider(struct of_phandle_args *spec) } mutex_unlock(&icc_lock); + if (!node) + return ERR_PTR(-EINVAL); + if (IS_ERR(node)) return ERR_CAST(node); -- cgit v1.2.3 From 25c441a07360e8f877055ecd9601bb661182be9a Mon Sep 17 00:00:00 2001 From: Su Hui Date: Mon, 30 Oct 2023 10:02:19 +0800 Subject: iio: imu: inv_mpu6050: fix an error code problem in inv_mpu6050_read_raw [ Upstream commit c3df0e29fb7788c4b3ddf37d5ed87dda2b822943 ] inv_mpu6050_sensor_show() can return -EINVAL or IIO_VAL_INT. Return the true value rather than only return IIO_VAL_INT. Fixes: d5098447147c ("iio: imu: mpu6050: add calibration offset support") Signed-off-by: Su Hui Link: https://lore.kernel.org/r/20231030020218.65728-1-suhui@nfschina.com Signed-off-by: Jonathan Cameron Signed-off-by: Sasha Levin --- drivers/iio/imu/inv_mpu6050/inv_mpu_core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c index 597768c29a72..caeef03b8c62 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c @@ -727,13 +727,13 @@ inv_mpu6050_read_raw(struct iio_dev *indio_dev, ret = inv_mpu6050_sensor_show(st, st->reg->gyro_offset, chan->channel2, val); mutex_unlock(&st->lock); - return IIO_VAL_INT; + return ret; case IIO_ACCEL: mutex_lock(&st->lock); ret = inv_mpu6050_sensor_show(st, st->reg->accl_offset, chan->channel2, val); mutex_unlock(&st->lock); - return IIO_VAL_INT; + return ret; default: return -EINVAL; -- cgit v1.2.3 From 1e3effe67e75d3339526dc23c9b7fa209040f373 Mon Sep 17 00:00:00 2001 From: Haoran Liu Date: Sun, 3 Dec 2023 19:00:23 +0000 Subject: Input: ipaq-micro-keys - add error handling for devm_kmemdup [ Upstream commit 59b6a747e2d39227ac2325c5e29d6ab3bb070c2a ] Check the return value of i2c_add_adapter. Static analysis revealed that the function did not properly handle potential failures of i2c_add_adapter, which could lead to partial initialization of the I2C adapter and unstable operation. Signed-off-by: Haoran Liu Link: https://lore.kernel.org/r/20231203164653.38983-1-liuhaoran14@163.com Fixes: d7535ffa427b ("Input: driver for microcontroller keys on the iPaq h3xxx") Signed-off-by: Dmitry Torokhov Signed-off-by: Sasha Levin --- drivers/input/keyboard/ipaq-micro-keys.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/input/keyboard/ipaq-micro-keys.c b/drivers/input/keyboard/ipaq-micro-keys.c index 13a66a8e3411..e0c51189e329 100644 --- a/drivers/input/keyboard/ipaq-micro-keys.c +++ b/drivers/input/keyboard/ipaq-micro-keys.c @@ -105,6 +105,9 @@ static int micro_key_probe(struct platform_device *pdev) keys->codes = devm_kmemdup(&pdev->dev, micro_keycodes, keys->input->keycodesize * keys->input->keycodemax, GFP_KERNEL); + if (!keys->codes) + return -ENOMEM; + keys->input->keycode = keys->codes; __set_bit(EV_KEY, keys->input->evbit); -- cgit v1.2.3 From f1d9a66e9ce9ff5d204cd4b787ca23771488a7dd Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Mon, 14 Nov 2022 11:06:26 +0000 Subject: scsi: bnx2fc: Fix skb double free in bnx2fc_rcv() [ Upstream commit 08c94d80b2da481652fb633e79cbc41e9e326a91 ] skb_share_check() already drops the reference to the skb when returning NULL. Using kfree_skb() in the error handling path leads to an skb double free. Fix this by removing the variable tmp_skb, and return directly when skb_share_check() returns NULL. Fixes: 01a4cc4d0cd6 ("bnx2fc: do not add shared skbs to the fcoe_rx_list") Signed-off-by: Wei Yongjun Link: https://lore.kernel.org/r/20221114110626.526643-1-weiyongjun@huaweicloud.com Signed-off-by: Martin K. Petersen Signed-off-by: Sasha Levin --- drivers/scsi/bnx2fc/bnx2fc_fcoe.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c index e2586472ecad..6090434ad6f3 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c +++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c @@ -432,7 +432,6 @@ static int bnx2fc_rcv(struct sk_buff *skb, struct net_device *dev, struct fcoe_ctlr *ctlr; struct fcoe_rcv_info *fr; struct fcoe_percpu_s *bg; - struct sk_buff *tmp_skb; interface = container_of(ptype, struct bnx2fc_interface, fcoe_packet_type); @@ -444,11 +443,9 @@ static int bnx2fc_rcv(struct sk_buff *skb, struct net_device *dev, goto err; } - tmp_skb = skb_share_check(skb, GFP_ATOMIC); - if (!tmp_skb) - goto err; - - skb = tmp_skb; + skb = skb_share_check(skb, GFP_ATOMIC); + if (!skb) + return -1; if (unlikely(eth_hdr(skb)->h_proto != htons(ETH_P_FCOE))) { printk(KERN_ERR PFX "bnx2fc_rcv: Wrong FC type frame\n"); -- cgit v1.2.3 From b9ccf18e315f736c2117619b34a4463a13414ec0 Mon Sep 17 00:00:00 2001 From: Javier Carrasco Date: Thu, 26 Oct 2023 17:44:49 +0200 Subject: iio: common: ms_sensors: ms_sensors_i2c: fix humidity conversion time table commit 54cf39ec16335dadbe1ba008d8e5e98dae3e26f8 upstream. The HTU21 offers 4 sampling frequencies: 20, 40, 70 and 120, which are associated to an index that is used to select the right measurement resolution and its corresponding measurement time. The current implementation selects the measurement resolution and the temperature measurement time properly, but it does not select the right humidity measurement time in all cases. In summary, the 40 and 70 humidity measurement times are swapped. The reason for that is probably the unusual coding for the measurement resolution. According to the datasheet, the bits [7,0] of the "user register" are used as follows to select the bit resolution: -------------------------------------------------- | Bit 7 | Bit 0 | RH | Temp | Trh (us) | Tt (us) | -------------------------------------------------- | 0 | 0 | 12 | 14 | 16000 | 50000 | -------------------------------------------------- | 0 | 1 | 8 | 12 | 3000 | 13000 | -------------------------------------------------- | 1 | 0 | 10 | 13 | 5000 | 25000 | -------------------------------------------------- | 1 | 1 | 11 | 11 | 8000 | 7000 | -------------------------------------------------- *This table is available in the official datasheet, page 13/21. I have just appended the times provided in the humidity/temperature tables, pages 3/21, 5/21. Note that always a pair of resolutions is selected. The sampling frequencies [20, 40, 70, 120] are assigned to a linear index [0..3] which is then coded as follows [1]: Index [7,0] -------------- idx 0 0,0 idx 1 1,0 idx 2 0,1 idx 3 1,1 That is done that way because the temperature measurements are being used as the reference for the sampling frequency (the frequencies and the temperature measurement times are correlated), so increasing the index always reduces the temperature measurement time and its resolution. Therefore, the temperature measurement time array is as simple as [50000, 25000, 13000, 7000] On the other hand, the humidity resolution cannot follow the same pattern because of the way it is coded in the "user register", where both resolutions are selected at the same time. The humidity measurement time array is the following: [16000, 3000, 5000, 8000], which defines the following assignments: Index [7,0] Trh ----------------------- idx 0 0,0 16000 -> right, [0,0] selects 12 bits (Trh = 16000) idx 1 1,0 3000 -> wrong! [1,0] selects 10 bits (Trh = 5000) idx 2 0,1 5000 -> wrong! [0,1] selects 8 bits (Trh = 3000) idx 3 1,1 8000 -> right, [1,1] selects 11 bits (Trh = 8000) The times have been ordered as if idx = 1 -> [0,1] and idx = 2 -> [1,0], which is not the case for the reason explained above. So a simple modification is required to obtain the right humidity measurement time array, swapping the values in the positions 1 and 2. The right table should be the following: [16000, 5000, 3000, 8000] Fix the humidity measurement time array with the right idex/value coding. [1] The actual code that makes this coding and assigns it to the current value of the "user register" is the following: config_reg &= 0x7E; config_reg |= ((i & 1) << 7) + ((i & 2) >> 1); Fixes: d574a87cc311 ("Add meas-spec sensors common part") Signed-off-by: Javier Carrasco Link: https://lore.kernel.org/r/20231026-topic-htu21_conversion_time-v1-1-bd257dc44209@gmail.com Cc: Signed-off-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/iio/common/ms_sensors/ms_sensors_i2c.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/iio/common/ms_sensors/ms_sensors_i2c.c b/drivers/iio/common/ms_sensors/ms_sensors_i2c.c index 16ea697e945c..79809646708a 100644 --- a/drivers/iio/common/ms_sensors/ms_sensors_i2c.c +++ b/drivers/iio/common/ms_sensors/ms_sensors_i2c.c @@ -15,8 +15,8 @@ /* Conversion times in us */ static const u16 ms_sensors_ht_t_conversion_time[] = { 50000, 25000, 13000, 7000 }; -static const u16 ms_sensors_ht_h_conversion_time[] = { 16000, 3000, - 5000, 8000 }; +static const u16 ms_sensors_ht_h_conversion_time[] = { 16000, 5000, + 3000, 8000 }; static const u16 ms_sensors_tp_conversion_time[] = { 500, 1100, 2100, 4100, 8220, 16440 }; -- cgit v1.2.3 From 3becd9bc5af3580528b6d4f077f3553e79ca3dc6 Mon Sep 17 00:00:00 2001 From: Wadim Egorov Date: Mon, 25 Sep 2023 15:44:27 +0200 Subject: iio: adc: ti_am335x_adc: Fix return value check of tiadc_request_dma() commit 60576e84c187043cef11f11d015249e71151d35a upstream. Fix wrong handling of a DMA request where the probing only failed if -EPROPE_DEFER was returned. Instead, let us fail if a non -ENODEV value is returned. This makes DMAs explicitly optional. Even if the DMA request is unsuccessfully, the ADC can still work properly. We do also handle the defer probe case by making use of dev_err_probe(). Fixes: f438b9da75eb ("drivers: iio: ti_am335x_adc: add dma support") Signed-off-by: Wadim Egorov Reviewed-by: Bhavya Kapoor Link: https://lore.kernel.org/r/20230925134427.214556-1-w.egorov@phytec.de Cc: Signed-off-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/iio/adc/ti_am335x_adc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c index 855cc2d64ac8..084a18724f82 100644 --- a/drivers/iio/adc/ti_am335x_adc.c +++ b/drivers/iio/adc/ti_am335x_adc.c @@ -632,8 +632,10 @@ static int tiadc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, indio_dev); err = tiadc_request_dma(pdev, adc_dev); - if (err && err == -EPROBE_DEFER) + if (err && err != -ENODEV) { + dev_err_probe(&pdev->dev, err, "DMA request failed\n"); goto err_dma; + } return 0; -- cgit v1.2.3 From 5a16bb60b8cec4b428565eeb2d041bb3c395ef84 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Tue, 31 Oct 2023 16:05:19 -0500 Subject: iio: triggered-buffer: prevent possible freeing of wrong buffer commit bce61476dc82f114e24e9c2e11fb064781ec563c upstream. Commit ee708e6baacd ("iio: buffer: introduce support for attaching more IIO buffers") introduced support for multiple buffers per indio_dev but left indio_dev->buffer for a few legacy use cases. In the case of the triggered buffer, iio_triggered_buffer_cleanup() still assumes that indio_dev->buffer points to the buffer allocated by iio_triggered_buffer_setup_ext(). However, since iio_triggered_buffer_setup_ext() now calls iio_device_attach_buffer() to attach the buffer, indio_dev->buffer will only point to the buffer allocated by iio_device_attach_buffer() if it the first buffer attached. This adds a check to make sure that no other buffer has been attached yet to ensure that indio_dev->buffer will be assigned when iio_device_attach_buffer() is called. As per discussion in the review thread, we may want to deal with multiple triggers per device, but this is a fix for the issue in the meantime and any such support would be unlikely to be suitable for a backport. Fixes: ee708e6baacd ("iio: buffer: introduce support for attaching more IIO buffers") Signed-off-by: David Lechner Acked-by: Nuno Sa Link: https://lore.kernel.org/r/20231031210521.1661552-1-dlechner@baylibre.com Cc: Signed-off-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/iio/buffer/industrialio-triggered-buffer.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/iio/buffer/industrialio-triggered-buffer.c b/drivers/iio/buffer/industrialio-triggered-buffer.c index f77c4538141e..6dac1e83de9c 100644 --- a/drivers/iio/buffer/industrialio-triggered-buffer.c +++ b/drivers/iio/buffer/industrialio-triggered-buffer.c @@ -44,6 +44,16 @@ int iio_triggered_buffer_setup_ext(struct iio_dev *indio_dev, struct iio_buffer *buffer; int ret; + /* + * iio_triggered_buffer_cleanup() assumes that the buffer allocated here + * is assigned to indio_dev->buffer but this is only the case if this + * function is the first caller to iio_device_attach_buffer(). If + * indio_dev->buffer is already set then we can't proceed otherwise the + * cleanup function will try to free a buffer that was not allocated here. + */ + if (indio_dev->buffer) + return -EADDRINUSE; + buffer = iio_kfifo_allocate(); if (!buffer) { ret = -ENOMEM; -- cgit v1.2.3 From 498f212a774fae5f57a0de63ce0f910babef80af Mon Sep 17 00:00:00 2001 From: Jeremie Knuesel Date: Sun, 17 Dec 2023 12:22:43 +0100 Subject: ALSA: usb-audio: Increase delay in MOTU M quirk commit 48d6b91798a6694fdd6edb62799754b9d3fe0792 upstream. Increase the quirk delay from 2 seconds to 4 seconds. This reflects a change in the Windows driver in which the delay was increased to about 3.7 seconds. The larger delay fixes an issue where the device fails to work unless it was powered up early during boot. Also clarify in the quirk comment that the quirk is only applied to older devices (USB ID 07fd:0008). Signed-off-by: Jeremie Knuesel Suggested-by: Alexander Tsoy Cc: Link: https://bugzilla.kernel.org/show_bug.cgi?id=211975 Link: https://lore.kernel.org/r/20231217112243.33409-1-knuesel@gmail.com Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/usb/quirks.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index 6d87f58d1b00..9cdf0e05cf49 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -1125,7 +1125,7 @@ free_buf: static int snd_usb_motu_m_series_boot_quirk(struct usb_device *dev) { - msleep(2000); + msleep(4000); return 0; } @@ -1364,7 +1364,7 @@ int snd_usb_apply_boot_quirk_once(struct usb_device *dev, unsigned int id) { switch (id) { - case USB_ID(0x07fd, 0x0008): /* MOTU M Series */ + case USB_ID(0x07fd, 0x0008): /* MOTU M Series, 1st hardware version */ return snd_usb_motu_m_series_boot_quirk(dev); } -- cgit v1.2.3 From 69fab6dc374854fac0dfb92cf5d1099a758db21a Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Thu, 7 Dec 2023 21:20:50 +0800 Subject: wifi: cfg80211: Add my certificate commit fb768d3b13ffa325b7e84480d488ac799c9d2cd7 upstream. As announced [1][2], I have taken over maintainership of the wireless-regdb project. Add my certificate so that newer releases are valid to the kernel. Seth's certificate should be kept around for awhile, at least until a few new releases by me happen. This should also be applied to stable trees so that stable kernels can utilize newly released database binaries. [1] https://lore.kernel.org/linux-wireless/CAGb2v657baNMPKU3QADijx7hZa=GUcSv2LEDdn6N=QQaFX8r-g@mail.gmail.com/ [2] https://lore.kernel.org/linux-wireless/ZWmRR5ul7EDfxCan@wens.tw/ Cc: stable@vger.kernel.org Signed-off-by: Chen-Yu Tsai Acked-by: Seth Forshee Link: https://msgid.link/ZXHGsqs34qZyzZng@wens.tw Signed-off-by: Johannes Berg Signed-off-by: Greg Kroah-Hartman --- net/wireless/certs/wens.hex | 87 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 net/wireless/certs/wens.hex diff --git a/net/wireless/certs/wens.hex b/net/wireless/certs/wens.hex new file mode 100644 index 000000000000..ccd5b5dc3360 --- /dev/null +++ b/net/wireless/certs/wens.hex @@ -0,0 +1,87 @@ +/* Chen-Yu Tsai's regdb certificate */ +0x30, 0x82, 0x02, 0xa7, 0x30, 0x82, 0x01, 0x8f, +0x02, 0x14, 0x61, 0xc0, 0x38, 0x65, 0x1a, 0xab, +0xdc, 0xf9, 0x4b, 0xd0, 0xac, 0x7f, 0xf0, 0x6c, +0x72, 0x48, 0xdb, 0x18, 0xc6, 0x00, 0x30, 0x0d, +0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, +0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x0f, 0x31, +0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, 0x03, +0x0c, 0x04, 0x77, 0x65, 0x6e, 0x73, 0x30, 0x20, +0x17, 0x0d, 0x32, 0x33, 0x31, 0x32, 0x30, 0x31, +0x30, 0x37, 0x34, 0x31, 0x31, 0x34, 0x5a, 0x18, +0x0f, 0x32, 0x31, 0x32, 0x33, 0x31, 0x31, 0x30, +0x37, 0x30, 0x37, 0x34, 0x31, 0x31, 0x34, 0x5a, +0x30, 0x0f, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x03, +0x55, 0x04, 0x03, 0x0c, 0x04, 0x77, 0x65, 0x6e, +0x73, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, +0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, +0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, +0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, +0x01, 0x00, 0xa9, 0x7a, 0x2c, 0x78, 0x4d, 0xa7, +0x19, 0x2d, 0x32, 0x52, 0xa0, 0x2e, 0x6c, 0xef, +0x88, 0x7f, 0x15, 0xc5, 0xb6, 0x69, 0x54, 0x16, +0x43, 0x14, 0x79, 0x53, 0xb7, 0xae, 0x88, 0xfe, +0xc0, 0xb7, 0x5d, 0x47, 0x8e, 0x1a, 0xe1, 0xef, +0xb3, 0x90, 0x86, 0xda, 0xd3, 0x64, 0x81, 0x1f, +0xce, 0x5d, 0x9e, 0x4b, 0x6e, 0x58, 0x02, 0x3e, +0xb2, 0x6f, 0x5e, 0x42, 0x47, 0x41, 0xf4, 0x2c, +0xb8, 0xa8, 0xd4, 0xaa, 0xc0, 0x0e, 0xe6, 0x48, +0xf0, 0xa8, 0xce, 0xcb, 0x08, 0xae, 0x37, 0xaf, +0xf6, 0x40, 0x39, 0xcb, 0x55, 0x6f, 0x5b, 0x4f, +0x85, 0x34, 0xe6, 0x69, 0x10, 0x50, 0x72, 0x5e, +0x4e, 0x9d, 0x4c, 0xba, 0x38, 0x36, 0x0d, 0xce, +0x73, 0x38, 0xd7, 0x27, 0x02, 0x2a, 0x79, 0x03, +0xe1, 0xac, 0xcf, 0xb0, 0x27, 0x85, 0x86, 0x93, +0x17, 0xab, 0xec, 0x42, 0x77, 0x37, 0x65, 0x8a, +0x44, 0xcb, 0xd6, 0x42, 0x93, 0x92, 0x13, 0xe3, +0x39, 0x45, 0xc5, 0x6e, 0x00, 0x4a, 0x7f, 0xcb, +0x42, 0x17, 0x2b, 0x25, 0x8c, 0xb8, 0x17, 0x3b, +0x15, 0x36, 0x59, 0xde, 0x42, 0xce, 0x21, 0xe6, +0xb6, 0xc7, 0x6e, 0x5e, 0x26, 0x1f, 0xf7, 0x8a, +0x57, 0x9e, 0xa5, 0x96, 0x72, 0xb7, 0x02, 0x32, +0xeb, 0x07, 0x2b, 0x73, 0xe2, 0x4f, 0x66, 0x58, +0x9a, 0xeb, 0x0f, 0x07, 0xb6, 0xab, 0x50, 0x8b, +0xc3, 0x8f, 0x17, 0xfa, 0x0a, 0x99, 0xc2, 0x16, +0x25, 0xbf, 0x2d, 0x6b, 0x1a, 0xaa, 0xe6, 0x3e, +0x5f, 0xeb, 0x6d, 0x9b, 0x5d, 0x4d, 0x42, 0x83, +0x2d, 0x39, 0xb8, 0xc9, 0xac, 0xdb, 0x3a, 0x91, +0x50, 0xdf, 0xbb, 0xb1, 0x76, 0x6d, 0x15, 0x73, +0xfd, 0xc6, 0xe6, 0x6b, 0x71, 0x9e, 0x67, 0x36, +0x22, 0x83, 0x79, 0xb1, 0xd6, 0xb8, 0x84, 0x52, +0xaf, 0x96, 0x5b, 0xc3, 0x63, 0x02, 0x4e, 0x78, +0x70, 0x57, 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, +0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, +0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, +0x01, 0x01, 0x00, 0x24, 0x28, 0xee, 0x22, 0x74, +0x7f, 0x7c, 0xfa, 0x6c, 0x1f, 0xb3, 0x18, 0xd1, +0xc2, 0x3d, 0x7d, 0x29, 0x42, 0x88, 0xad, 0x82, +0xa5, 0xb1, 0x8a, 0x05, 0xd0, 0xec, 0x5c, 0x91, +0x20, 0xf6, 0x82, 0xfd, 0xd5, 0x67, 0x60, 0x5f, +0x31, 0xf5, 0xbd, 0x88, 0x91, 0x70, 0xbd, 0xb8, +0xb9, 0x8c, 0x88, 0xfe, 0x53, 0xc9, 0x54, 0x9b, +0x43, 0xc4, 0x7a, 0x43, 0x74, 0x6b, 0xdd, 0xb0, +0xb1, 0x3b, 0x33, 0x45, 0x46, 0x78, 0xa3, 0x1c, +0xef, 0x54, 0x68, 0xf7, 0x85, 0x9c, 0xe4, 0x51, +0x6f, 0x06, 0xaf, 0x81, 0xdb, 0x2a, 0x7b, 0x7b, +0x6f, 0xa8, 0x9c, 0x67, 0xd8, 0xcb, 0xc9, 0x91, +0x40, 0x00, 0xae, 0xd9, 0xa1, 0x9f, 0xdd, 0xa6, +0x43, 0x0e, 0x28, 0x7b, 0xaa, 0x1b, 0xe9, 0x84, +0xdb, 0x76, 0x64, 0x42, 0x70, 0xc9, 0xc0, 0xeb, +0xae, 0x84, 0x11, 0x16, 0x68, 0x4e, 0x84, 0x9e, +0x7e, 0x92, 0x36, 0xee, 0x1c, 0x3b, 0x08, 0x63, +0xeb, 0x79, 0x84, 0x15, 0x08, 0x9d, 0xaf, 0xc8, +0x9a, 0xc7, 0x34, 0xd3, 0x94, 0x4b, 0xd1, 0x28, +0x97, 0xbe, 0xd1, 0x45, 0x75, 0xdc, 0x35, 0x62, +0xac, 0x1d, 0x1f, 0xb7, 0xb7, 0x15, 0x87, 0xc8, +0x98, 0xc0, 0x24, 0x31, 0x56, 0x8d, 0xed, 0xdb, +0x06, 0xc6, 0x46, 0xbf, 0x4b, 0x6d, 0xa6, 0xd5, +0xab, 0xcc, 0x60, 0xfc, 0xe5, 0x37, 0xb6, 0x53, +0x7d, 0x58, 0x95, 0xa9, 0x56, 0xc7, 0xf7, 0xee, +0xc3, 0xa0, 0x76, 0xf7, 0x65, 0x4d, 0x53, 0xfa, +0xff, 0x5f, 0x76, 0x33, 0x5a, 0x08, 0xfa, 0x86, +0x92, 0x5a, 0x13, 0xfa, 0x1a, 0xfc, 0xf2, 0x1b, +0x8c, 0x7f, 0x42, 0x6d, 0xb7, 0x7e, 0xb7, 0xb4, +0xf0, 0xc7, 0x83, 0xbb, 0xa2, 0x81, 0x03, 0x2d, +0xd4, 0x2a, 0x63, 0x3f, 0xf7, 0x31, 0x2e, 0x40, +0x33, 0x5c, 0x46, 0xbc, 0x9b, 0xc1, 0x05, 0xa5, +0x45, 0x4e, 0xc3 -- cgit v1.2.3 From 433889344e8235c5ad0089d853aab78e91820343 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 14 Dec 2023 09:08:16 +0100 Subject: wifi: cfg80211: fix certs build to not depend on file order commit 3c2a8ebe3fe66a5f77d4c164a0bea8e2ff37b455 upstream. The file for the new certificate (Chen-Yu Tsai's) didn't end with a comma, so depending on the file order in the build rule, we'd end up with invalid C when concatenating the (now two) certificates. Fix that. Cc: stable@vger.kernel.org Reported-by: Biju Das Reported-by: Naresh Kamboju Fixes: fb768d3b13ff ("wifi: cfg80211: Add my certificate") Signed-off-by: Johannes Berg Signed-off-by: Greg Kroah-Hartman --- net/wireless/certs/wens.hex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/wireless/certs/wens.hex b/net/wireless/certs/wens.hex index ccd5b5dc3360..0d50369bede9 100644 --- a/net/wireless/certs/wens.hex +++ b/net/wireless/certs/wens.hex @@ -84,4 +84,4 @@ 0xf0, 0xc7, 0x83, 0xbb, 0xa2, 0x81, 0x03, 0x2d, 0xd4, 0x2a, 0x63, 0x3f, 0xf7, 0x31, 0x2e, 0x40, 0x33, 0x5c, 0x46, 0xbc, 0x9b, 0xc1, 0x05, 0xa5, -0x45, 0x4e, 0xc3 +0x45, 0x4e, 0xc3, -- cgit v1.2.3 From 0e285069fd2ace7ff629a22ea37b5e45d109f1dc Mon Sep 17 00:00:00 2001 From: Mark Glover Date: Wed, 20 Dec 2023 13:57:40 +0000 Subject: USB: serial: ftdi_sio: update Actisense PIDs constant names commit 513d88a88e0203188a38f4647dd08170aebd85df upstream. Update the constant names for unused USB PIDs (product identifiers) to reflect the new products now using the PIDs. Signed-off-by: Mark Glover Cc: stable@vger.kernel.org Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 6 +++--- drivers/usb/serial/ftdi_sio_ids.h | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 49448cdbe998..2345208b7221 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -1011,9 +1011,9 @@ static const struct usb_device_id id_table_combined[] = { { USB_DEVICE(FTDI_VID, ACTISENSE_USG_PID) }, { USB_DEVICE(FTDI_VID, ACTISENSE_NGT_PID) }, { USB_DEVICE(FTDI_VID, ACTISENSE_NGW_PID) }, - { USB_DEVICE(FTDI_VID, ACTISENSE_D9AC_PID) }, - { USB_DEVICE(FTDI_VID, ACTISENSE_D9AD_PID) }, - { USB_DEVICE(FTDI_VID, ACTISENSE_D9AE_PID) }, + { USB_DEVICE(FTDI_VID, ACTISENSE_UID_PID) }, + { USB_DEVICE(FTDI_VID, ACTISENSE_USA_PID) }, + { USB_DEVICE(FTDI_VID, ACTISENSE_NGX_PID) }, { USB_DEVICE(FTDI_VID, ACTISENSE_D9AF_PID) }, { USB_DEVICE(FTDI_VID, CHETCO_SEAGAUGE_PID) }, { USB_DEVICE(FTDI_VID, CHETCO_SEASWITCH_PID) }, diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 31c8ccabbbb7..9a0f9fc99124 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -1561,9 +1561,9 @@ #define ACTISENSE_USG_PID 0xD9A9 /* USG USB Serial Adapter */ #define ACTISENSE_NGT_PID 0xD9AA /* NGT NMEA2000 Interface */ #define ACTISENSE_NGW_PID 0xD9AB /* NGW NMEA2000 Gateway */ -#define ACTISENSE_D9AC_PID 0xD9AC /* Actisense Reserved */ -#define ACTISENSE_D9AD_PID 0xD9AD /* Actisense Reserved */ -#define ACTISENSE_D9AE_PID 0xD9AE /* Actisense Reserved */ +#define ACTISENSE_UID_PID 0xD9AC /* USB Isolating Device */ +#define ACTISENSE_USA_PID 0xD9AD /* USB to Serial Adapter */ +#define ACTISENSE_NGX_PID 0xD9AE /* NGX NMEA2000 Gateway */ #define ACTISENSE_D9AF_PID 0xD9AF /* Actisense Reserved */ #define CHETCO_SEAGAUGE_PID 0xA548 /* SeaGauge USB Adapter */ #define CHETCO_SEASWITCH_PID 0xA549 /* SeaSwitch USB Adapter */ -- cgit v1.2.3 From a67f0b5bc2faf4f69df64e1b209cebd071d3cc14 Mon Sep 17 00:00:00 2001 From: Alper Ak Date: Tue, 8 Aug 2023 13:51:58 +0300 Subject: USB: serial: option: add Quectel EG912Y module support commit 6d79d9434c69bb8ffa8a631050eb0ad6b83d3e90 upstream. Add Quectel EG912Y "DIAG, AT, MODEM" 0x6001: ECM / RNDIS + DIAG + AT + MODEM T: Bus=01 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#= 3 Spd=480 MxCh= 0 D: Ver= 2.00 Cls=ef(misc ) Sub=02 Prot=01 MxPS=64 #Cfgs= 1 P: Vendor=2c7c ProdID=6001 Rev= 3.18 S: Manufacturer=Android S: Product=Android S: SerialNumber=0000 C:* #Ifs= 5 Cfg#= 1 Atr=e0 MxPwr=500mA A: FirstIf#= 0 IfCount= 2 Cls=02(comm.) Sub=06 Prot=00 I:* If#= 0 Alt= 0 #EPs= 1 Cls=02(comm.) Sub=06 Prot=00 Driver=cdc_ether E: Ad=87(I) Atr=03(Int.) MxPS= 64 Ivl=4096ms I: If#= 1 Alt= 0 #EPs= 0 Cls=0a(data ) Sub=00 Prot=00 Driver=cdc_ether I:* If#= 1 Alt= 1 #EPs= 2 Cls=0a(data ) Sub=00 Prot=00 Driver=cdc_ether E: Ad=83(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=0c(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms I:* If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=00 Prot=00 Driver=option E: Ad=82(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=0b(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms I:* If#= 3 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option E: Ad=89(I) Atr=03(Int.) MxPS= 64 Ivl=4096ms E: Ad=86(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=0f(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms I:* If#= 4 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option E: Ad=88(I) Atr=03(Int.) MxPS= 64 Ivl=4096ms E: Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=0a(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms Signed-off-by: Alper Ak Cc: stable@vger.kernel.org Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 7f2aa72d52e6..cc6e9c7af09d 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -272,6 +272,7 @@ static void option_instat_callback(struct urb *urb); #define QUECTEL_PRODUCT_RM500Q 0x0800 #define QUECTEL_PRODUCT_RM520N 0x0801 #define QUECTEL_PRODUCT_EC200U 0x0901 +#define QUECTEL_PRODUCT_EG912Y 0x6001 #define QUECTEL_PRODUCT_EC200S_CN 0x6002 #define QUECTEL_PRODUCT_EC200A 0x6005 #define QUECTEL_PRODUCT_EM061K_LWW 0x6008 @@ -1244,6 +1245,7 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC200U, 0xff, 0, 0) }, { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC200S_CN, 0xff, 0, 0) }, { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC200T, 0xff, 0, 0) }, + { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EG912Y, 0xff, 0, 0) }, { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM500K, 0xff, 0x00, 0x00) }, { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6001) }, -- cgit v1.2.3 From d0adf8fe08b936d887d3ea32926cdc4139009190 Mon Sep 17 00:00:00 2001 From: Slark Xiao Date: Fri, 1 Dec 2023 10:09:50 +0800 Subject: USB: serial: option: add Foxconn T99W265 with new baseline commit 13fde9ac23ca8c6d1ac13cc9eefe1f1ac3ee30a4 upstream. This ID was added based on latest SDX12 code base line, and we made some changes with previous 0489:e0db. Test evidence as below: T: Bus=02 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 3 Spd=5000 MxCh= 0 D: Ver= 3.20 Cls=ef(misc ) Sub=02 Prot=01 MxPS= 9 #Cfgs= 2 P: Vendor=0489 ProdID=e0da Rev=05.04 S: Manufacturer=Qualcomm S: Product=Qualcomm Snapdragon X12 S: SerialNumber=2bda65fb C: #Ifs= 6 Cfg#= 2 Atr=a0 MxPwr=896mA I: If#=0x0 Alt= 0 #EPs= 1 Cls=02(commc) Sub=0e Prot=00 Driver=cdc_mbim I: If#=0x1 Alt= 1 #EPs= 2 Cls=0a(data ) Sub=00 Prot=02 Driver=cdc_mbim I: If#=0x2 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=40 Driver=option I: If#=0x3 Alt= 0 #EPs= 1 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none) I: If#=0x4 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=30 Driver=option I: If#=0x5 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=42 Prot=01 Driver=(none) 0&1: MBIM, 2: Modem, 3:GNSS, 4:Diag, 5:ADB Signed-off-by: Slark Xiao Cc: stable@vger.kernel.org Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index cc6e9c7af09d..b500be5eaa5a 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -2244,6 +2244,8 @@ static const struct usb_device_id option_ids[] = { .driver_info = RSVD(0) | RSVD(1) | RSVD(6) }, { USB_DEVICE(0x0489, 0xe0b5), /* Foxconn T77W968 ESIM */ .driver_info = RSVD(0) | RSVD(1) | RSVD(6) }, + { USB_DEVICE_INTERFACE_CLASS(0x0489, 0xe0da, 0xff), /* Foxconn T99W265 MBIM variant */ + .driver_info = RSVD(3) | RSVD(5) }, { USB_DEVICE_INTERFACE_CLASS(0x0489, 0xe0db, 0xff), /* Foxconn T99W265 MBIM */ .driver_info = RSVD(3) }, { USB_DEVICE_INTERFACE_CLASS(0x0489, 0xe0ee, 0xff), /* Foxconn T99W368 MBIM */ -- cgit v1.2.3 From 094ae245f7aa5d91be7247e101ee63089ec2c0de Mon Sep 17 00:00:00 2001 From: Reinhard Speyerer Date: Tue, 12 Dec 2023 18:15:38 +0100 Subject: USB: serial: option: add Quectel RM500Q R13 firmware support commit 06f22cd6635bdae7d73566fca9879b2026a08e00 upstream. Add support for Quectel RM500Q R13 firmware which uses Prot=40 for the NMEA port: T: Bus=02 Lev=01 Prnt=01 Port=01 Cnt=01 Dev#= 8 Spd=5000 MxCh= 0 D: Ver= 3.20 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 9 #Cfgs= 1 P: Vendor=2c7c ProdID=0800 Rev= 4.14 S: Manufacturer=Quectel S: Product=RM500Q-AE S: SerialNumber=xxxxxxxx C:* #Ifs= 5 Cfg#= 1 Atr=a0 MxPwr=896mA I:* If#= 0 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=30 Driver=option E: Ad=81(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms E: Ad=01(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms I:* If#= 1 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=40 Driver=option E: Ad=83(I) Atr=03(Int.) MxPS= 10 Ivl=32ms E: Ad=82(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms E: Ad=02(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms I:* If#= 2 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option E: Ad=85(I) Atr=03(Int.) MxPS= 10 Ivl=32ms E: Ad=84(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms E: Ad=03(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms I:* If#= 3 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option E: Ad=87(I) Atr=03(Int.) MxPS= 10 Ivl=32ms E: Ad=86(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms E: Ad=04(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms I:* If#= 4 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=ff Driver=qmi_wwan E: Ad=88(I) Atr=03(Int.) MxPS= 8 Ivl=32ms E: Ad=8e(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms E: Ad=0f(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms Signed-off-by: Reinhard Speyerer Cc: stable@vger.kernel.org Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index b500be5eaa5a..4adef9259870 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -1233,6 +1233,7 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_INTERFACE_CLASS(QUECTEL_VENDOR_ID, 0x0700, 0xff), /* BG95 */ .driver_info = RSVD(3) | ZLP }, { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM500Q, 0xff, 0xff, 0x30) }, + { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM500Q, 0xff, 0, 0x40) }, { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM500Q, 0xff, 0, 0) }, { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM500Q, 0xff, 0xff, 0x10), .driver_info = ZLP }, -- cgit v1.2.3 From 70db6466c029187d8f25e71dc39bcb8cbf92b9b1 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Mon, 20 Nov 2023 10:04:39 -0500 Subject: Bluetooth: hci_event: Fix not checking if HCI_OP_INQUIRY has been sent commit 99e67d46e5ff3c7c901af6009edec72d3d363be8 upstream. Before setting HCI_INQUIRY bit check if HCI_OP_INQUIRY was really sent otherwise the controller maybe be generating invalid events or, more likely, it is a result of fuzzing tools attempting to test the right behavior of the stack when unexpected events are generated. Cc: stable@vger.kernel.org Link: https://bugzilla.kernel.org/show_bug.cgi?id=218151 Signed-off-by: Luiz Augusto von Dentz Signed-off-by: Greg Kroah-Hartman --- net/bluetooth/hci_event.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 1dd65f13f893..edf5132b5dc9 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -1926,7 +1926,8 @@ static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status) return; } - set_bit(HCI_INQUIRY, &hdev->flags); + if (hci_sent_cmd_data(hdev, HCI_OP_INQUIRY)) + set_bit(HCI_INQUIRY, &hdev->flags); } static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status) -- cgit v1.2.3 From 916ca52a3e2825563523e0b267dace89ec5e10e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Danis?= Date: Fri, 8 Dec 2023 18:41:50 +0100 Subject: Bluetooth: L2CAP: Send reject on command corrupted request MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 78b99eb1faa7371bf9c534690f26a71b6996622d upstream. L2CAP/COS/CED/BI-02-C PTS test send a malformed L2CAP signaling packet with 2 commands in it (a connection request and an unknown command) and expect to get a connection response packet and a command reject packet. The second is currently not sent. Cc: stable@vger.kernel.org Signed-off-by: Frédéric Danis Signed-off-by: Luiz Augusto von Dentz Signed-off-by: Greg Kroah-Hartman --- net/bluetooth/l2cap_core.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 0770286ecf0b..9f3596de90a7 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -6493,6 +6493,14 @@ drop: kfree_skb(skb); } +static inline void l2cap_sig_send_rej(struct l2cap_conn *conn, u16 ident) +{ + struct l2cap_cmd_rej_unk rej; + + rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD); + l2cap_send_cmd(conn, ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej); +} + static inline void l2cap_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb) { @@ -6518,23 +6526,24 @@ static inline void l2cap_sig_channel(struct l2cap_conn *conn, if (len > skb->len || !cmd->ident) { BT_DBG("corrupted command"); + l2cap_sig_send_rej(conn, cmd->ident); break; } err = l2cap_bredr_sig_cmd(conn, cmd, len, skb->data); if (err) { - struct l2cap_cmd_rej_unk rej; - BT_ERR("Wrong link type (%d)", err); - - rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD); - l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ, - sizeof(rej), &rej); + l2cap_sig_send_rej(conn, cmd->ident); } skb_pull(skb, len); } + if (skb->len > 0) { + BT_DBG("corrupted command"); + l2cap_sig_send_rej(conn, 0); + } + drop: kfree_skb(skb); } -- cgit v1.2.3 From a346cfc6389ac36051292b20b91980e6fcc4aa51 Mon Sep 17 00:00:00 2001 From: Xiao Yao Date: Tue, 12 Dec 2023 00:27:18 +0800 Subject: Bluetooth: MGMT/SMP: Fix address type when using SMP over BREDR/LE commit 59b047bc98084f8af2c41483e4d68a5adf2fa7f7 upstream. If two Bluetooth devices both support BR/EDR and BLE, and also support Secure Connections, then they only need to pair once. The LTK generated during the LE pairing process may be converted into a BR/EDR link key for BR/EDR transport, and conversely, a link key generated during the BR/EDR SSP pairing process can be converted into an LTK for LE transport. Hence, the link type of the link key and LTK is not fixed, they can be either an LE LINK or an ACL LINK. Currently, in the mgmt_new_irk/ltk/crsk/link_key functions, the link type is fixed, which could lead to incorrect address types being reported to the application layer. Therefore, it is necessary to add link_type/addr_type to the smp_irk/ltk/crsk and link_key, to ensure the generation of the correct address type. SMP over BREDR: Before Fix: > ACL Data RX: Handle 11 flags 0x02 dlen 12 BR/EDR SMP: Identity Address Information (0x09) len 7 Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) @ MGMT Event: New Identity Resolving Key (0x0018) plen 30 Random address: 00:00:00:00:00:00 (Non-Resolvable) LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) @ MGMT Event: New Long Term Key (0x000a) plen 37 LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) Key type: Authenticated key from P-256 (0x03) After Fix: > ACL Data RX: Handle 11 flags 0x02 dlen 12 BR/EDR SMP: Identity Address Information (0x09) len 7 Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) @ MGMT Event: New Identity Resolving Key (0x0018) plen 30 Random address: 00:00:00:00:00:00 (Non-Resolvable) BR/EDR Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) @ MGMT Event: New Long Term Key (0x000a) plen 37 BR/EDR Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) Key type: Authenticated key from P-256 (0x03) SMP over LE: Before Fix: @ MGMT Event: New Identity Resolving Key (0x0018) plen 30 Random address: 5F:5C:07:37:47:D5 (Resolvable) LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) @ MGMT Event: New Long Term Key (0x000a) plen 37 LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) Key type: Authenticated key from P-256 (0x03) @ MGMT Event: New Link Key (0x0009) plen 26 BR/EDR Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) Key type: Authenticated Combination key from P-256 (0x08) After Fix: @ MGMT Event: New Identity Resolving Key (0x0018) plen 30 Random address: 5E:03:1C:00:38:21 (Resolvable) LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) @ MGMT Event: New Long Term Key (0x000a) plen 37 LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) Key type: Authenticated key from P-256 (0x03) @ MGMT Event: New Link Key (0x0009) plen 26 Store hint: Yes (0x01) LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) Key type: Authenticated Combination key from P-256 (0x08) Cc: stable@vger.kernel.org Signed-off-by: Xiao Yao Signed-off-by: Luiz Augusto von Dentz Signed-off-by: Greg Kroah-Hartman --- include/net/bluetooth/hci_core.h | 5 +++++ net/bluetooth/mgmt.c | 25 ++++++++++++++++++------- net/bluetooth/smp.c | 7 +++++++ 3 files changed, 30 insertions(+), 7 deletions(-) diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 1f718e91509f..9a21ccbb5b5c 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -176,6 +176,7 @@ struct blocked_key { struct smp_csrk { bdaddr_t bdaddr; u8 bdaddr_type; + u8 link_type; u8 type; u8 val[16]; }; @@ -185,6 +186,7 @@ struct smp_ltk { struct rcu_head rcu; bdaddr_t bdaddr; u8 bdaddr_type; + u8 link_type; u8 authenticated; u8 type; u8 enc_size; @@ -199,6 +201,7 @@ struct smp_irk { bdaddr_t rpa; bdaddr_t bdaddr; u8 addr_type; + u8 link_type; u8 val[16]; }; @@ -206,6 +209,8 @@ struct link_key { struct list_head list; struct rcu_head rcu; bdaddr_t bdaddr; + u8 bdaddr_type; + u8 link_type; u8 type; u8 val[HCI_LINK_KEY_SIZE]; u8 pin_len; diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 04000499f4a2..8f1162961836 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -2378,7 +2378,8 @@ static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data, for (i = 0; i < key_count; i++) { struct mgmt_link_key_info *key = &cp->keys[i]; - if (key->addr.type != BDADDR_BREDR || key->type > 0x08) + /* Considering SMP over BREDR/LE, there is no need to check addr_type */ + if (key->type > 0x08) return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, MGMT_STATUS_INVALID_PARAMS); @@ -6180,6 +6181,7 @@ static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data, for (i = 0; i < irk_count; i++) { struct mgmt_irk_info *irk = &cp->irks[i]; + u8 addr_type = le_addr_type(irk->addr.type); if (hci_is_blocked_key(hdev, HCI_BLOCKED_KEY_TYPE_IRK, @@ -6189,8 +6191,12 @@ static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data, continue; } + /* When using SMP over BR/EDR, the addr type should be set to BREDR */ + if (irk->addr.type == BDADDR_BREDR) + addr_type = BDADDR_BREDR; + hci_add_irk(hdev, &irk->addr.bdaddr, - le_addr_type(irk->addr.type), irk->val, + addr_type, irk->val, BDADDR_ANY); } @@ -6271,6 +6277,7 @@ static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev, for (i = 0; i < key_count; i++) { struct mgmt_ltk_info *key = &cp->keys[i]; u8 type, authenticated; + u8 addr_type = le_addr_type(key->addr.type); if (hci_is_blocked_key(hdev, HCI_BLOCKED_KEY_TYPE_LTK, @@ -6305,8 +6312,12 @@ static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev, continue; } + /* When using SMP over BR/EDR, the addr type should be set to BREDR */ + if (key->addr.type == BDADDR_BREDR) + addr_type = BDADDR_BREDR; + hci_add_ltk(hdev, &key->addr.bdaddr, - le_addr_type(key->addr.type), type, authenticated, + addr_type, type, authenticated, key->val, key->enc_size, key->ediv, key->rand); } @@ -8673,7 +8684,7 @@ void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key, ev.store_hint = persistent; bacpy(&ev.key.addr.bdaddr, &key->bdaddr); - ev.key.addr.type = BDADDR_BREDR; + ev.key.addr.type = link_to_bdaddr(key->link_type, key->bdaddr_type); ev.key.type = key->type; memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE); ev.key.pin_len = key->pin_len; @@ -8724,7 +8735,7 @@ void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent) ev.store_hint = persistent; bacpy(&ev.key.addr.bdaddr, &key->bdaddr); - ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type); + ev.key.addr.type = link_to_bdaddr(key->link_type, key->bdaddr_type); ev.key.type = mgmt_ltk_type(key); ev.key.enc_size = key->enc_size; ev.key.ediv = key->ediv; @@ -8753,7 +8764,7 @@ void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk, bool persistent) bacpy(&ev.rpa, &irk->rpa); bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr); - ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type); + ev.irk.addr.type = link_to_bdaddr(irk->link_type, irk->addr_type); memcpy(ev.irk.val, irk->val, sizeof(irk->val)); mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL); @@ -8782,7 +8793,7 @@ void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk, ev.store_hint = persistent; bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr); - ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type); + ev.key.addr.type = link_to_bdaddr(csrk->link_type, csrk->bdaddr_type); ev.key.type = csrk->type; memcpy(ev.key.val, csrk->val, sizeof(csrk->val)); diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index 11f853d0500f..f688f941c40c 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c @@ -1058,6 +1058,7 @@ static void smp_notify_keys(struct l2cap_conn *conn) } if (smp->remote_irk) { + smp->remote_irk->link_type = hcon->type; mgmt_new_irk(hdev, smp->remote_irk, persistent); /* Now that user space can be considered to know the @@ -1072,24 +1073,28 @@ static void smp_notify_keys(struct l2cap_conn *conn) } if (smp->csrk) { + smp->csrk->link_type = hcon->type; smp->csrk->bdaddr_type = hcon->dst_type; bacpy(&smp->csrk->bdaddr, &hcon->dst); mgmt_new_csrk(hdev, smp->csrk, persistent); } if (smp->responder_csrk) { + smp->responder_csrk->link_type = hcon->type; smp->responder_csrk->bdaddr_type = hcon->dst_type; bacpy(&smp->responder_csrk->bdaddr, &hcon->dst); mgmt_new_csrk(hdev, smp->responder_csrk, persistent); } if (smp->ltk) { + smp->ltk->link_type = hcon->type; smp->ltk->bdaddr_type = hcon->dst_type; bacpy(&smp->ltk->bdaddr, &hcon->dst); mgmt_new_ltk(hdev, smp->ltk, persistent); } if (smp->responder_ltk) { + smp->responder_ltk->link_type = hcon->type; smp->responder_ltk->bdaddr_type = hcon->dst_type; bacpy(&smp->responder_ltk->bdaddr, &hcon->dst); mgmt_new_ltk(hdev, smp->responder_ltk, persistent); @@ -1109,6 +1114,8 @@ static void smp_notify_keys(struct l2cap_conn *conn) key = hci_add_link_key(hdev, smp->conn->hcon, &hcon->dst, smp->link_key, type, 0, &persistent); if (key) { + key->link_type = hcon->type; + key->bdaddr_type = hcon->dst_type; mgmt_new_link_key(hdev, key, persistent); /* Don't keep debug keys around if the relevant -- cgit v1.2.3 From 85fd35ce5bc0422ec77522f44a63128645b135fe Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Fri, 22 Dec 2023 23:25:38 -0800 Subject: Input: soc_button_array - add mapping for airplane mode button commit ea3715941a9b7d816a1e9096ac0577900af2a69e upstream. This add a mapping for the airplane mode button on the TUXEDO Pulse Gen3. While it is physically a key it behaves more like a switch, sending a key down on first press and a key up on 2nd press. Therefor the switch event is used here. Besides this behaviour it uses the HID usage-id 0xc6 (Wireless Radio Button) and not 0xc8 (Wireless Radio Slider Switch), but since neither 0xc6 nor 0xc8 are currently implemented at all in soc_button_array this not to standard behaviour is not put behind a quirk for the moment. Signed-off-by: Christoffer Sandberg Signed-off-by: Werner Sembach Link: https://lore.kernel.org/r/20231215171718.80229-1-wse@tuxedocomputers.com Cc: stable@vger.kernel.org Signed-off-by: Dmitry Torokhov Signed-off-by: Greg Kroah-Hartman --- drivers/input/misc/soc_button_array.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/input/misc/soc_button_array.c b/drivers/input/misc/soc_button_array.c index 67a134c8448d..b9ef03af5263 100644 --- a/drivers/input/misc/soc_button_array.c +++ b/drivers/input/misc/soc_button_array.c @@ -299,6 +299,11 @@ static int soc_button_parse_btn_desc(struct device *dev, info->name = "power"; info->event_code = KEY_POWER; info->wakeup = true; + } else if (upage == 0x01 && usage == 0xc6) { + info->name = "airplane mode switch"; + info->event_type = EV_SW; + info->event_code = SW_RFKILL_ALL; + info->active_low = false; } else if (upage == 0x01 && usage == 0xca) { info->name = "rotation lock switch"; info->event_type = EV_SW; -- cgit v1.2.3 From 4431cf7c3310062f4b2bc4a64aa92f483848dfc7 Mon Sep 17 00:00:00 2001 From: Fedor Pchelkin Date: Wed, 6 Dec 2023 23:09:13 +0300 Subject: net: 9p: avoid freeing uninit memory in p9pdu_vreadf commit ff49bf1867578f23a5ffdd38f927f6e1e16796c4 upstream. If some of p9pdu_readf() calls inside case 'T' in p9pdu_vreadf() fails, the error path is not handled properly. *wnames or members of *wnames array may be left uninitialized and invalidly freed. Initialize *wnames to NULL in beginning of case 'T'. Initialize the first *wnames array element to NULL and nullify the failing *wnames element so that the error path freeing loop stops on the first NULL element and doesn't proceed further. Found by Linux Verification Center (linuxtesting.org). Fixes: ace51c4dd2f9 ("9p: add new protocol support code") Signed-off-by: Fedor Pchelkin Message-ID: <20231206200913.16135-1-pchelkin@ispras.ru> Cc: stable@vger.kernel.org Reviewed-by: Simon Horman Reviewed-by: Christian Schoenebeck Signed-off-by: Dominique Martinet Signed-off-by: Greg Kroah-Hartman --- net/9p/protocol.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/net/9p/protocol.c b/net/9p/protocol.c index 59eb71f357fa..d473e5eb29cc 100644 --- a/net/9p/protocol.c +++ b/net/9p/protocol.c @@ -230,6 +230,8 @@ p9pdu_vreadf(struct p9_fcall *pdu, int proto_version, const char *fmt, uint16_t *nwname = va_arg(ap, uint16_t *); char ***wnames = va_arg(ap, char ***); + *wnames = NULL; + errcode = p9pdu_readf(pdu, proto_version, "w", nwname); if (!errcode) { @@ -239,6 +241,8 @@ p9pdu_vreadf(struct p9_fcall *pdu, int proto_version, const char *fmt, GFP_NOFS); if (!*wnames) errcode = -ENOMEM; + else + (*wnames)[0] = NULL; } if (!errcode) { @@ -250,8 +254,10 @@ p9pdu_vreadf(struct p9_fcall *pdu, int proto_version, const char *fmt, proto_version, "s", &(*wnames)[i]); - if (errcode) + if (errcode) { + (*wnames)[i] = NULL; break; + } } } @@ -259,11 +265,14 @@ p9pdu_vreadf(struct p9_fcall *pdu, int proto_version, const char *fmt, if (*wnames) { int i; - for (i = 0; i < *nwname; i++) + for (i = 0; i < *nwname; i++) { + if (!(*wnames)[i]) + break; kfree((*wnames)[i]); + } + kfree(*wnames); + *wnames = NULL; } - kfree(*wnames); - *wnames = NULL; } } break; -- cgit v1.2.3 From 28855385bff10afb7c14631b01900ee965cd269a Mon Sep 17 00:00:00 2001 From: Rouven Czerwinski Date: Thu, 7 Dec 2023 08:58:36 +0100 Subject: net: rfkill: gpio: set GPIO direction commit 23484d817082c3005252d8edfc8292c8a1006b5b upstream. Fix the undefined usage of the GPIO consumer API after retrieving the GPIO description with GPIO_ASIS. The API documentation mentions that GPIO_ASIS won't set a GPIO direction and requires the user to set a direction before using the GPIO. This can be confirmed on i.MX6 hardware, where rfkill-gpio is no longer able to enabled/disable a device, presumably because the GPIO controller was never configured for the output direction. Fixes: b2f750c3a80b ("net: rfkill: gpio: prevent value glitch during probe") Cc: stable@vger.kernel.org Signed-off-by: Rouven Czerwinski Link: https://msgid.link/20231207075835.3091694-1-r.czerwinski@pengutronix.de Signed-off-by: Johannes Berg Signed-off-by: Greg Kroah-Hartman --- net/rfkill/rfkill-gpio.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/net/rfkill/rfkill-gpio.c b/net/rfkill/rfkill-gpio.c index 2cc95c8dc4c7..f74baefd855d 100644 --- a/net/rfkill/rfkill-gpio.c +++ b/net/rfkill/rfkill-gpio.c @@ -116,6 +116,14 @@ static int rfkill_gpio_probe(struct platform_device *pdev) return -EINVAL; } + ret = gpiod_direction_output(rfkill->reset_gpio, true); + if (ret) + return ret; + + ret = gpiod_direction_output(rfkill->shutdown_gpio, true); + if (ret) + return ret; + rfkill->rfkill_dev = rfkill_alloc(rfkill->name, &pdev->dev, rfkill->type, &rfkill_gpio_ops, rfkill); -- cgit v1.2.3 From 7c25c5d7274631b655f0f9098a16241fcd5db57b Mon Sep 17 00:00:00 2001 From: Ronald Wahl Date: Thu, 14 Dec 2023 19:11:12 +0100 Subject: net: ks8851: Fix TX stall caused by TX buffer overrun commit 3dc5d44545453de1de9c53cc529cc960a85933da upstream. There is a bug in the ks8851 Ethernet driver that more data is written to the hardware TX buffer than actually available. This is caused by wrong accounting of the free TX buffer space. The driver maintains a tx_space variable that represents the TX buffer space that is deemed to be free. The ks8851_start_xmit_spi() function adds an SKB to a queue if tx_space is large enough and reduces tx_space by the amount of buffer space it will later need in the TX buffer and then schedules a work item. If there is not enough space then the TX queue is stopped. The worker function ks8851_tx_work() dequeues all the SKBs and writes the data into the hardware TX buffer. The last packet will trigger an interrupt after it was send. Here it is assumed that all data fits into the TX buffer. In the interrupt routine (which runs asynchronously because it is a threaded interrupt) tx_space is updated with the current value from the hardware. Also the TX queue is woken up again. Now it could happen that after data was sent to the hardware and before handling the TX interrupt new data is queued in ks8851_start_xmit_spi() when the TX buffer space had still some space left. When the interrupt is actually handled tx_space is updated from the hardware but now we already have new SKBs queued that have not been written to the hardware TX buffer yet. Since tx_space has been overwritten by the value from the hardware the space is not accounted for. Now we have more data queued then buffer space available in the hardware and ks8851_tx_work() will potentially overrun the hardware TX buffer. In many cases it will still work because often the buffer is written out fast enough so that no overrun occurs but for example if the peer throttles us via flow control then an overrun may happen. This can be fixed in different ways. The most simple way would be to set tx_space to 0 before writing data to the hardware TX buffer preventing the queuing of more SKBs until the TX interrupt has been handled. I have chosen a slightly more efficient (and still rather simple) way and track the amount of data that is already queued and not yet written to the hardware. When new SKBs are to be queued the already queued amount of data is honoured when checking free TX buffer space. I tested this with a setup of two linked KS8851 running iperf3 between the two in bidirectional mode. Before the fix I got a stall after some minutes. With the fix I saw now issues anymore after hours. Fixes: 3ba81f3ece3c ("net: Micrel KS8851 SPI network driver") Cc: "David S. Miller" Cc: Eric Dumazet Cc: Jakub Kicinski Cc: Paolo Abeni Cc: Ben Dooks Cc: Tristram Ha Cc: netdev@vger.kernel.org Cc: stable@vger.kernel.org # 5.10+ Signed-off-by: Ronald Wahl Reviewed-by: Simon Horman Link: https://lore.kernel.org/r/20231214181112.76052-1-rwahl@gmx.de Signed-off-by: Paolo Abeni Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/micrel/ks8851.h | 3 +++ drivers/net/ethernet/micrel/ks8851_common.c | 20 +++++++------- drivers/net/ethernet/micrel/ks8851_spi.c | 42 ++++++++++++++++++----------- 3 files changed, 40 insertions(+), 25 deletions(-) diff --git a/drivers/net/ethernet/micrel/ks8851.h b/drivers/net/ethernet/micrel/ks8851.h index e2eb0caeac82..c0ab179541b2 100644 --- a/drivers/net/ethernet/micrel/ks8851.h +++ b/drivers/net/ethernet/micrel/ks8851.h @@ -350,6 +350,8 @@ union ks8851_tx_hdr { * @rxd: Space for receiving SPI data, in DMA-able space. * @txd: Space for transmitting SPI data, in DMA-able space. * @msg_enable: The message flags controlling driver output (see ethtool). + * @tx_space: Free space in the hardware TX buffer (cached copy of KS_TXMIR). + * @queued_len: Space required in hardware TX buffer for queued packets in txq. * @fid: Incrementing frame id tag. * @rc_ier: Cached copy of KS_IER. * @rc_ccr: Cached copy of KS_CCR. @@ -399,6 +401,7 @@ struct ks8851_net { struct work_struct rxctrl_work; struct sk_buff_head txq; + unsigned int queued_len; struct eeprom_93cx6 eeprom; struct regulator *vdd_reg; diff --git a/drivers/net/ethernet/micrel/ks8851_common.c b/drivers/net/ethernet/micrel/ks8851_common.c index 2c80dba2606c..fb3bed24d50f 100644 --- a/drivers/net/ethernet/micrel/ks8851_common.c +++ b/drivers/net/ethernet/micrel/ks8851_common.c @@ -361,16 +361,18 @@ static irqreturn_t ks8851_irq(int irq, void *_ks) handled |= IRQ_RXPSI; if (status & IRQ_TXI) { - handled |= IRQ_TXI; + unsigned short tx_space = ks8851_rdreg16(ks, KS_TXMIR); - /* no lock here, tx queue should have been stopped */ + netif_dbg(ks, intr, ks->netdev, + "%s: txspace %d\n", __func__, tx_space); - /* update our idea of how much tx space is available to the - * system */ - ks->tx_space = ks8851_rdreg16(ks, KS_TXMIR); + spin_lock(&ks->statelock); + ks->tx_space = tx_space; + if (netif_queue_stopped(ks->netdev)) + netif_wake_queue(ks->netdev); + spin_unlock(&ks->statelock); - netif_dbg(ks, intr, ks->netdev, - "%s: txspace %d\n", __func__, ks->tx_space); + handled |= IRQ_TXI; } if (status & IRQ_RXI) @@ -413,9 +415,6 @@ static irqreturn_t ks8851_irq(int irq, void *_ks) if (status & IRQ_LCI) mii_check_link(&ks->mii); - if (status & IRQ_TXI) - netif_wake_queue(ks->netdev); - return IRQ_HANDLED; } @@ -499,6 +498,7 @@ static int ks8851_net_open(struct net_device *dev) ks8851_wrreg16(ks, KS_ISR, ks->rc_ier); ks8851_wrreg16(ks, KS_IER, ks->rc_ier); + ks->queued_len = 0; netif_start_queue(ks->netdev); netif_dbg(ks, ifup, ks->netdev, "network device up\n"); diff --git a/drivers/net/ethernet/micrel/ks8851_spi.c b/drivers/net/ethernet/micrel/ks8851_spi.c index 479406ecbaa3..cd17eca77285 100644 --- a/drivers/net/ethernet/micrel/ks8851_spi.c +++ b/drivers/net/ethernet/micrel/ks8851_spi.c @@ -286,6 +286,18 @@ static void ks8851_wrfifo_spi(struct ks8851_net *ks, struct sk_buff *txp, netdev_err(ks->netdev, "%s: spi_sync() failed\n", __func__); } +/** + * calc_txlen - calculate size of message to send packet + * @len: Length of data + * + * Returns the size of the TXFIFO message needed to send + * this packet. + */ +static unsigned int calc_txlen(unsigned int len) +{ + return ALIGN(len + 4, 4); +} + /** * ks8851_rx_skb_spi - receive skbuff * @ks: The device state @@ -305,7 +317,9 @@ static void ks8851_rx_skb_spi(struct ks8851_net *ks, struct sk_buff *skb) */ static void ks8851_tx_work(struct work_struct *work) { + unsigned int dequeued_len = 0; struct ks8851_net_spi *kss; + unsigned short tx_space; struct ks8851_net *ks; unsigned long flags; struct sk_buff *txb; @@ -322,6 +336,8 @@ static void ks8851_tx_work(struct work_struct *work) last = skb_queue_empty(&ks->txq); if (txb) { + dequeued_len += calc_txlen(txb->len); + ks8851_wrreg16_spi(ks, KS_RXQCR, ks->rc_rxqcr | RXQCR_SDA); ks8851_wrfifo_spi(ks, txb, last); @@ -332,6 +348,13 @@ static void ks8851_tx_work(struct work_struct *work) } } + tx_space = ks8851_rdreg16_spi(ks, KS_TXMIR); + + spin_lock(&ks->statelock); + ks->queued_len -= dequeued_len; + ks->tx_space = tx_space; + spin_unlock(&ks->statelock); + ks8851_unlock_spi(ks, &flags); } @@ -346,18 +369,6 @@ static void ks8851_flush_tx_work_spi(struct ks8851_net *ks) flush_work(&kss->tx_work); } -/** - * calc_txlen - calculate size of message to send packet - * @len: Length of data - * - * Returns the size of the TXFIFO message needed to send - * this packet. - */ -static unsigned int calc_txlen(unsigned int len) -{ - return ALIGN(len + 4, 4); -} - /** * ks8851_start_xmit_spi - transmit packet using SPI * @skb: The buffer to transmit @@ -386,16 +397,17 @@ static netdev_tx_t ks8851_start_xmit_spi(struct sk_buff *skb, spin_lock(&ks->statelock); - if (needed > ks->tx_space) { + if (ks->queued_len + needed > ks->tx_space) { netif_stop_queue(dev); ret = NETDEV_TX_BUSY; } else { - ks->tx_space -= needed; + ks->queued_len += needed; skb_queue_tail(&ks->txq, skb); } spin_unlock(&ks->statelock); - schedule_work(&kss->tx_work); + if (ret == NETDEV_TX_OK) + schedule_work(&kss->tx_work); return ret; } -- cgit v1.2.3 From 686774523f8e37a3f264ebaf63be1adb9cf4c841 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Fri, 15 Dec 2023 11:13:57 +0000 Subject: dt-bindings: nvmem: mxs-ocotp: Document fsl,ocotp commit a2a8aefecbd0f87d6127951cef33b3def8439057 upstream. Both imx23.dtsi and imx28.dtsi describe the OCOTP nodes in the format: compatible = "fsl,imx28-ocotp", "fsl,ocotp"; Document the "fsl,ocotp" entry to fix the following schema warning: efuse@8002c000: compatible: ['fsl,imx23-ocotp', 'fsl,ocotp'] is too long from schema $id: http://devicetree.org/schemas/nvmem/mxs-ocotp.yaml# Fixes: 2c504460f502 ("dt-bindings: nvmem: Convert MXS OCOTP to json-schema") Cc: Signed-off-by: Fabio Estevam Acked-by: Conor Dooley Signed-off-by: Srinivas Kandagatla Link: https://lore.kernel.org/r/20231215111358.316727-2-srinivas.kandagatla@linaro.org Signed-off-by: Greg Kroah-Hartman Signed-off-by: Greg Kroah-Hartman --- Documentation/devicetree/bindings/nvmem/mxs-ocotp.yaml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Documentation/devicetree/bindings/nvmem/mxs-ocotp.yaml b/Documentation/devicetree/bindings/nvmem/mxs-ocotp.yaml index ff317fd7c15b..2e1fcff3c280 100644 --- a/Documentation/devicetree/bindings/nvmem/mxs-ocotp.yaml +++ b/Documentation/devicetree/bindings/nvmem/mxs-ocotp.yaml @@ -14,9 +14,11 @@ allOf: properties: compatible: - enum: - - fsl,imx23-ocotp - - fsl,imx28-ocotp + items: + - enum: + - fsl,imx23-ocotp + - fsl,imx28-ocotp + - const: fsl,ocotp "#address-cells": const: 1 @@ -40,7 +42,7 @@ additionalProperties: false examples: - | ocotp: efuse@8002c000 { - compatible = "fsl,imx28-ocotp"; + compatible = "fsl,imx28-ocotp", "fsl,ocotp"; #address-cells = <1>; #size-cells = <1>; reg = <0x8002c000 0x2000>; -- cgit v1.2.3 From da95f8b7bc6a4d0f4c2ded86e6c2fdb2897f09f3 Mon Sep 17 00:00:00 2001 From: Alexander Atanasov Date: Fri, 15 Dec 2023 14:10:08 +0200 Subject: scsi: core: Always send batch on reset or error handling command commit 066c5b46b6eaf2f13f80c19500dbb3b84baabb33 upstream. In commit 8930a6c20791 ("scsi: core: add support for request batching") the block layer bd->last flag was mapped to SCMD_LAST and used as an indicator to send the batch for the drivers that implement this feature. However, the error handling code was not updated accordingly. scsi_send_eh_cmnd() is used to send error handling commands and request sense. The problem is that request sense comes as a single command that gets into the batch queue and times out. As a result the device goes offline after several failed resets. This was observed on virtio_scsi during a device resize operation. [ 496.316946] sd 0:0:4:0: [sdd] tag#117 scsi_eh_0: requesting sense [ 506.786356] sd 0:0:4:0: [sdd] tag#117 scsi_send_eh_cmnd timeleft: 0 [ 506.787981] sd 0:0:4:0: [sdd] tag#117 abort To fix this always set SCMD_LAST flag in scsi_send_eh_cmnd() and scsi_reset_ioctl(). Fixes: 8930a6c20791 ("scsi: core: add support for request batching") Cc: Signed-off-by: Alexander Atanasov Link: https://lore.kernel.org/r/20231215121008.2881653-1-alexander.atanasov@virtuozzo.com Reviewed-by: Ming Lei Signed-off-by: Martin K. Petersen Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/scsi_error.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 18b99240a906..f79cfd1cb3e7 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -1104,6 +1104,7 @@ retry: scsi_log_send(scmd); scmd->submitter = SUBMITTED_BY_SCSI_ERROR_HANDLER; + scmd->flags |= SCMD_LAST; /* * Lock sdev->state_mutex to avoid that scsi_device_quiesce() can @@ -2397,6 +2398,7 @@ scsi_ioctl_reset(struct scsi_device *dev, int __user *arg) scmd->cmnd = scsi_req(rq)->cmd; scmd->submitter = SUBMITTED_BY_SCSI_RESET_IOCTL; + scmd->flags |= SCMD_LAST; memset(&scmd->sdb, 0, sizeof(scmd->sdb)); scmd->cmd_len = 0; -- cgit v1.2.3 From d47b2b6a087ad8f4efcfdbecf85e2b872509c636 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (Google)" Date: Wed, 20 Dec 2023 11:15:25 -0500 Subject: tracing / synthetic: Disable events after testing in synth_event_gen_test_init() commit 88b30c7f5d27e1594d70dc2bd7199b18f2b57fa9 upstream. The synth_event_gen_test module can be built in, if someone wants to run the tests at boot up and not have to load them. The synth_event_gen_test_init() function creates and enables the synthetic events and runs its tests. The synth_event_gen_test_exit() disables the events it created and destroys the events. If the module is builtin, the events are never disabled. The issue is, the events should be disable after the tests are run. This could be an issue if the rest of the boot up tests are enabled, as they expect the events to be in a known state before testing. That known state happens to be disabled. When CONFIG_SYNTH_EVENT_GEN_TEST=y and CONFIG_EVENT_TRACE_STARTUP_TEST=y a warning will trigger: Running tests on trace events: Testing event create_synth_test: Enabled event during self test! ------------[ cut here ]------------ WARNING: CPU: 2 PID: 1 at kernel/trace/trace_events.c:4150 event_trace_self_tests+0x1c2/0x480 Modules linked in: CPU: 2 PID: 1 Comm: swapper/0 Not tainted 6.7.0-rc2-test-00031-gb803d7c664d5-dirty #276 Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.2-debian-1.16.2-1 04/01/2014 RIP: 0010:event_trace_self_tests+0x1c2/0x480 Code: bb e8 a2 ab 5d fc 48 8d 7b 48 e8 f9 3d 99 fc 48 8b 73 48 40 f6 c6 01 0f 84 d6 fe ff ff 48 c7 c7 20 b6 ad bb e8 7f ab 5d fc 90 <0f> 0b 90 48 89 df e8 d3 3d 99 fc 48 8b 1b 4c 39 f3 0f 85 2c ff ff RSP: 0000:ffffc9000001fdc0 EFLAGS: 00010246 RAX: 0000000000000029 RBX: ffff88810399ca80 RCX: 0000000000000000 RDX: 0000000000000000 RSI: ffffffffb9f19478 RDI: ffff88823c734e64 RBP: ffff88810399f300 R08: 0000000000000000 R09: fffffbfff79eb32a R10: ffffffffbcf59957 R11: 0000000000000001 R12: ffff888104068090 R13: ffffffffbc89f0a0 R14: ffffffffbc8a0f08 R15: 0000000000000078 FS: 0000000000000000(0000) GS:ffff88823c700000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000000000000000 CR3: 00000001f6282001 CR4: 0000000000170ef0 Call Trace: ? __warn+0xa5/0x200 ? event_trace_self_tests+0x1c2/0x480 ? report_bug+0x1f6/0x220 ? handle_bug+0x6f/0x90 ? exc_invalid_op+0x17/0x50 ? asm_exc_invalid_op+0x1a/0x20 ? tracer_preempt_on+0x78/0x1c0 ? event_trace_self_tests+0x1c2/0x480 ? __pfx_event_trace_self_tests_init+0x10/0x10 event_trace_self_tests_init+0x27/0xe0 do_one_initcall+0xd6/0x3c0 ? __pfx_do_one_initcall+0x10/0x10 ? kasan_set_track+0x25/0x30 ? rcu_is_watching+0x38/0x60 kernel_init_freeable+0x324/0x450 ? __pfx_kernel_init+0x10/0x10 kernel_init+0x1f/0x1e0 ? _raw_spin_unlock_irq+0x33/0x50 ret_from_fork+0x34/0x60 ? __pfx_kernel_init+0x10/0x10 ret_from_fork_asm+0x1b/0x30 This is because the synth_event_gen_test_init() left the synthetic events that it created enabled. By having it disable them after testing, the other selftests will run fine. Link: https://lore.kernel.org/linux-trace-kernel/20231220111525.2f0f49b0@gandalf.local.home Cc: stable@vger.kernel.org Cc: Mathieu Desnoyers Cc: Tom Zanussi Fixes: 9fe41efaca084 ("tracing: Add synth event generation test module") Acked-by: Masami Hiramatsu (Google) Reported-by: Alexander Graf Tested-by: Alexander Graf Signed-off-by: Steven Rostedt (Google) Signed-off-by: Greg Kroah-Hartman --- kernel/trace/synth_event_gen_test.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/kernel/trace/synth_event_gen_test.c b/kernel/trace/synth_event_gen_test.c index 8d77526892f4..d944924cd1e1 100644 --- a/kernel/trace/synth_event_gen_test.c +++ b/kernel/trace/synth_event_gen_test.c @@ -477,6 +477,17 @@ static int __init synth_event_gen_test_init(void) ret = test_trace_synth_event(); WARN_ON(ret); + + /* Disable when done */ + trace_array_set_clr_event(gen_synth_test->tr, + "synthetic", + "gen_synth_test", false); + trace_array_set_clr_event(empty_synth_test->tr, + "synthetic", + "empty_synth_test", false); + trace_array_set_clr_event(create_synth_test->tr, + "synthetic", + "create_synth_test", false); out: return ret; } -- cgit v1.2.3 From e4d3534c6818ccdca1683de67537f19571ff7a66 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Fri, 24 Nov 2023 10:50:56 +0200 Subject: bus: ti-sysc: Flush posted write only after srst_udelay commit f71f6ff8c1f682a1cae4e8d7bdeed9d7f76b8f75 upstream. Commit 34539b442b3b ("bus: ti-sysc: Flush posted write on enable before reset") caused a regression reproducable on omap4 duovero where the ISS target module can produce interconnect errors on boot. Turns out the registers are not accessible until after a delay for devices needing a ti,sysc-delay-us value. Let's fix this by flushing the posted write only after the reset delay. We do flushing also for ti,sysc-delay-us using devices as that should trigger an interconnect error if the delay is not properly configured. Let's also add some comments while at it. Fixes: 34539b442b3b ("bus: ti-sysc: Flush posted write on enable before reset") Cc: stable@vger.kernel.org Signed-off-by: Tony Lindgren Signed-off-by: Greg Kroah-Hartman --- drivers/bus/ti-sysc.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c index 0a159989c899..05ae57775853 100644 --- a/drivers/bus/ti-sysc.c +++ b/drivers/bus/ti-sysc.c @@ -2104,13 +2104,23 @@ static int sysc_reset(struct sysc *ddata) sysc_val = sysc_read_sysconfig(ddata); sysc_val |= sysc_mask; sysc_write(ddata, sysc_offset, sysc_val); - /* Flush posted write */ + + /* + * Some devices need a delay before reading registers + * after reset. Presumably a srst_udelay is not needed + * for devices that use a rstctrl register reset. + */ + if (ddata->cfg.srst_udelay) + fsleep(ddata->cfg.srst_udelay); + + /* + * Flush posted write. For devices needing srst_udelay + * this should trigger an interconnect error if the + * srst_udelay value is needed but not configured. + */ sysc_val = sysc_read_sysconfig(ddata); } - if (ddata->cfg.srst_udelay) - fsleep(ddata->cfg.srst_udelay); - if (ddata->post_reset_quirk) ddata->post_reset_quirk(ddata); -- cgit v1.2.3 From f9dc6e0a0b02746c6d87b38cacfe6950d709df19 Mon Sep 17 00:00:00 2001 From: xiongxin Date: Wed, 20 Dec 2023 10:29:01 +0800 Subject: gpio: dwapb: mask/unmask IRQ when disable/enale it commit 1cc3542c76acb5f59001e3e562eba672f1983355 upstream. In the hardware implementation of the I2C HID driver based on DesignWare GPIO IRQ chip, when the user continues to use the I2C HID device in the suspend process, the I2C HID interrupt will be masked after the resume process is finished. This is because the disable_irq()/enable_irq() of the DesignWare GPIO driver does not synchronize the IRQ mask register state. In normal use of the I2C HID procedure, the GPIO IRQ irq_mask()/irq_unmask() functions are called in pairs. In case of an exception, i2c_hid_core_suspend() calls disable_irq() to disable the GPIO IRQ. With low probability, this causes irq_unmask() to not be called, which causes the GPIO IRQ to be masked and not unmasked in enable_irq(), raising an exception. Add synchronization to the masked register state in the dwapb_irq_enable()/dwapb_irq_disable() function. mask the GPIO IRQ before disabling it. After enabling the GPIO IRQ, unmask the IRQ. Fixes: 7779b3455697 ("gpio: add a driver for the Synopsys DesignWare APB GPIO block") Cc: stable@kernel.org Co-developed-by: Riwen Lu Signed-off-by: Riwen Lu Signed-off-by: xiongxin Acked-by: Serge Semin Reviewed-by: Andy Shevchenko Signed-off-by: Bartosz Golaszewski Signed-off-by: Greg Kroah-Hartman --- drivers/gpio/gpio-dwapb.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c index a503f37001eb..8773cbf6138f 100644 --- a/drivers/gpio/gpio-dwapb.c +++ b/drivers/gpio/gpio-dwapb.c @@ -277,13 +277,15 @@ static void dwapb_irq_enable(struct irq_data *d) { struct gpio_chip *gc = irq_data_get_irq_chip_data(d); struct dwapb_gpio *gpio = to_dwapb_gpio(gc); + irq_hw_number_t hwirq = irqd_to_hwirq(d); unsigned long flags; u32 val; raw_spin_lock_irqsave(&gc->bgpio_lock, flags); - val = dwapb_read(gpio, GPIO_INTEN); - val |= BIT(irqd_to_hwirq(d)); + val = dwapb_read(gpio, GPIO_INTEN) | BIT(hwirq); dwapb_write(gpio, GPIO_INTEN, val); + val = dwapb_read(gpio, GPIO_INTMASK) & ~BIT(hwirq); + dwapb_write(gpio, GPIO_INTMASK, val); raw_spin_unlock_irqrestore(&gc->bgpio_lock, flags); } @@ -291,12 +293,14 @@ static void dwapb_irq_disable(struct irq_data *d) { struct gpio_chip *gc = irq_data_get_irq_chip_data(d); struct dwapb_gpio *gpio = to_dwapb_gpio(gc); + irq_hw_number_t hwirq = irqd_to_hwirq(d); unsigned long flags; u32 val; raw_spin_lock_irqsave(&gc->bgpio_lock, flags); - val = dwapb_read(gpio, GPIO_INTEN); - val &= ~BIT(irqd_to_hwirq(d)); + val = dwapb_read(gpio, GPIO_INTMASK) | BIT(hwirq); + dwapb_write(gpio, GPIO_INTMASK, val); + val = dwapb_read(gpio, GPIO_INTEN) & ~BIT(hwirq); dwapb_write(gpio, GPIO_INTEN, val); raw_spin_unlock_irqrestore(&gc->bgpio_lock, flags); } -- cgit v1.2.3 From 46bc250b082c75754804ce821d6467daab09c099 Mon Sep 17 00:00:00 2001 From: Herve Codina Date: Tue, 14 Nov 2023 16:26:55 +0100 Subject: lib/vsprintf: Fix %pfwf when current node refcount == 0 commit 5c47251e8c4903111608ddcba2a77c0c425c247c upstream. A refcount issue can appeared in __fwnode_link_del() due to the pr_debug() call: WARNING: CPU: 0 PID: 901 at lib/refcount.c:25 refcount_warn_saturate+0xe5/0x110 Call Trace: ... of_node_get+0x1e/0x30 of_fwnode_get+0x28/0x40 fwnode_full_name_string+0x34/0x90 fwnode_string+0xdb/0x140 ... vsnprintf+0x17b/0x630 ... __fwnode_link_del+0x25/0xa0 fwnode_links_purge+0x39/0xb0 of_node_release+0xd9/0x180 ... Indeed, an fwnode (of_node) is being destroyed and so, of_node_release() is called because the of_node refcount reached 0. From of_node_release() several function calls are done and lead to a pr_debug() calls with %pfwf to print the fwnode full name. The issue is not present if we change %pfwf to %pfwP. To print the full name, %pfwf iterates over the current node and its parents and obtain/drop a reference to all nodes involved. In order to allow to print the full name (%pfwf) of a node while it is being destroyed, do not obtain/drop a reference to this current node. Fixes: a92eb7621b9f ("lib/vsprintf: Make use of fwnode API to obtain node names and separators") Cc: stable@vger.kernel.org Signed-off-by: Herve Codina Reviewed-by: Sakari Ailus Reviewed-by: Andy Shevchenko Signed-off-by: Petr Mladek Link: https://lore.kernel.org/r/20231114152655.409331-1-herve.codina@bootlin.com Signed-off-by: Greg Kroah-Hartman --- lib/vsprintf.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/lib/vsprintf.c b/lib/vsprintf.c index a60f0bb2ea90..d86abdc77c26 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -2111,15 +2111,20 @@ char *fwnode_full_name_string(struct fwnode_handle *fwnode, char *buf, /* Loop starting from the root node to the current node. */ for (depth = fwnode_count_parents(fwnode); depth >= 0; depth--) { - struct fwnode_handle *__fwnode = - fwnode_get_nth_parent(fwnode, depth); + /* + * Only get a reference for other nodes (i.e. parent nodes). + * fwnode refcount may be 0 here. + */ + struct fwnode_handle *__fwnode = depth ? + fwnode_get_nth_parent(fwnode, depth) : fwnode; buf = string(buf, end, fwnode_get_name_prefix(__fwnode), default_str_spec); buf = string(buf, end, fwnode_get_name(__fwnode), default_str_spec); - fwnode_handle_put(__fwnode); + if (depth) + fwnode_handle_put(__fwnode); } return buf; -- cgit v1.2.3 From ccda72aa73c791d51559acc95e1104a613d8dadd Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Thu, 7 Dec 2023 15:11:59 +0000 Subject: KVM: arm64: vgic: Force vcpu vgic teardown on vcpu destroy commit 02e3858f08faabab9503ae2911cf7c7e27702257 upstream. When failing to create a vcpu because (for example) it has a duplicate vcpu_id, we destroy the vcpu. Amusingly, this leaves the redistributor registered with the KVM_MMIO bus. This is no good, and we should properly clean the mess. Force a teardown of the vgic vcpu interface, including the RD device before returning to the caller. Cc: stable@vger.kernel.org Signed-off-by: Marc Zyngier Link: https://lore.kernel.org/r/20231207151201.3028710-4-maz@kernel.org Signed-off-by: Oliver Upton Signed-off-by: Greg Kroah-Hartman --- arch/arm64/kvm/arm.c | 2 +- arch/arm64/kvm/vgic/vgic-init.c | 5 ++++- arch/arm64/kvm/vgic/vgic-mmio-v3.c | 2 +- arch/arm64/kvm/vgic/vgic.h | 1 + 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c index 3fe816c244ce..47d737672aba 100644 --- a/arch/arm64/kvm/arm.c +++ b/arch/arm64/kvm/arm.c @@ -356,7 +356,7 @@ void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu) kvm_mmu_free_memory_cache(&vcpu->arch.mmu_page_cache); kvm_timer_vcpu_terminate(vcpu); kvm_pmu_vcpu_destroy(vcpu); - + kvm_vgic_vcpu_destroy(vcpu); kvm_arm_vcpu_destroy(vcpu); } diff --git a/arch/arm64/kvm/vgic/vgic-init.c b/arch/arm64/kvm/vgic/vgic-init.c index 340c51d87677..1ccbb19fad77 100644 --- a/arch/arm64/kvm/vgic/vgic-init.c +++ b/arch/arm64/kvm/vgic/vgic-init.c @@ -363,7 +363,10 @@ void kvm_vgic_vcpu_destroy(struct kvm_vcpu *vcpu) vgic_flush_pending_lpis(vcpu); INIT_LIST_HEAD(&vgic_cpu->ap_list_head); - vgic_cpu->rd_iodev.base_addr = VGIC_ADDR_UNDEF; + if (vcpu->kvm->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3) { + vgic_unregister_redist_iodev(vcpu); + vgic_cpu->rd_iodev.base_addr = VGIC_ADDR_UNDEF; + } } /* To be called with kvm->lock held */ diff --git a/arch/arm64/kvm/vgic/vgic-mmio-v3.c b/arch/arm64/kvm/vgic/vgic-mmio-v3.c index a09cdc0b953c..b94a6d1de35d 100644 --- a/arch/arm64/kvm/vgic/vgic-mmio-v3.c +++ b/arch/arm64/kvm/vgic/vgic-mmio-v3.c @@ -744,7 +744,7 @@ int vgic_register_redist_iodev(struct kvm_vcpu *vcpu) return 0; } -static void vgic_unregister_redist_iodev(struct kvm_vcpu *vcpu) +void vgic_unregister_redist_iodev(struct kvm_vcpu *vcpu) { struct vgic_io_device *rd_dev = &vcpu->arch.vgic_cpu.rd_iodev; diff --git a/arch/arm64/kvm/vgic/vgic.h b/arch/arm64/kvm/vgic/vgic.h index 36021c31a706..640249950acf 100644 --- a/arch/arm64/kvm/vgic/vgic.h +++ b/arch/arm64/kvm/vgic/vgic.h @@ -223,6 +223,7 @@ int vgic_v3_lpi_sync_pending_status(struct kvm *kvm, struct vgic_irq *irq); int vgic_v3_save_pending_tables(struct kvm *kvm); int vgic_v3_set_redist_base(struct kvm *kvm, u32 index, u64 addr, u32 count); int vgic_register_redist_iodev(struct kvm_vcpu *vcpu); +void vgic_unregister_redist_iodev(struct kvm_vcpu *vcpu); bool vgic_v3_check_base(struct kvm *kvm); void vgic_v3_load(struct kvm_vcpu *vcpu); -- cgit v1.2.3 From 1c811b7c83a4f7431c8e02f5a4f2942bf8b0fc99 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Thu, 7 Dec 2023 20:49:24 +0100 Subject: x86/alternatives: Sync core before enabling interrupts commit 3ea1704a92967834bf0e64ca1205db4680d04048 upstream. text_poke_early() does: local_irq_save(flags); memcpy(addr, opcode, len); local_irq_restore(flags); sync_core(); That's not really correct because the synchronization should happen before interrupts are re-enabled to ensure that a pending interrupt observes the complete update of the opcodes. It's not entirely clear whether the interrupt entry provides enough serialization already, but moving the sync_core() invocation into interrupt disabled region does no harm and is obviously correct. Fixes: 6fffacb30349 ("x86/alternatives, jumplabel: Use text_poke_early() before mm_init()") Signed-off-by: Thomas Gleixner Signed-off-by: Borislav Petkov (AMD) Acked-by: Peter Zijlstra (Intel) Cc: Link: https://lore.kernel.org/r/ZT6narvE%2BLxX%2B7Be@windriver.com Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/alternative.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c index c9e3246bf4f3..aea88d0d8352 100644 --- a/arch/x86/kernel/alternative.c +++ b/arch/x86/kernel/alternative.c @@ -963,8 +963,8 @@ void __init_or_module text_poke_early(void *addr, const void *opcode, } else { local_irq_save(flags); memcpy(addr, opcode, len); - local_irq_restore(flags); sync_core(); + local_irq_restore(flags); /* * Could also do a CLFLUSH here to speed up CPU recovery; but -- cgit v1.2.3 From b54b9fbc16a056793a9bb8f5fe80d048c4198662 Mon Sep 17 00:00:00 2001 From: Krister Johansen Date: Fri, 3 Nov 2023 10:39:47 -0700 Subject: fuse: share lookup state between submount and its parent commit c4d361f66ac91db8fc65061a9671682f61f4ca9d upstream. Fuse submounts do not perform a lookup for the nodeid that they inherit from their parent. Instead, the code decrements the nlookup on the submount's fuse_inode when it is instantiated, and no forget is performed when a submount root is evicted. Trouble arises when the submount's parent is evicted despite the submount itself being in use. In this author's case, the submount was in a container and deatched from the initial mount namespace via a MNT_DEATCH operation. When memory pressure triggered the shrinker, the inode from the parent was evicted, which triggered enough forgets to render the submount's nodeid invalid. Since submounts should still function, even if their parent goes away, solve this problem by sharing refcounted state between the parent and its submount. When all of the references on this shared state reach zero, it's safe to forget the final lookup of the fuse nodeid. Signed-off-by: Krister Johansen Cc: stable@vger.kernel.org Fixes: 1866d779d5d2 ("fuse: Allow fuse_fill_super_common() for submounts") Signed-off-by: Miklos Szeredi Signed-off-by: Krister Johansen Signed-off-by: Greg Kroah-Hartman --- fs/fuse/fuse_i.h | 15 ++++++++++++ fs/fuse/inode.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 87 insertions(+), 3 deletions(-) diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index c3a87586a15f..4b8f094345e1 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -63,6 +63,19 @@ struct fuse_forget_link { struct fuse_forget_link *next; }; +/* Submount lookup tracking */ +struct fuse_submount_lookup { + /** Refcount */ + refcount_t count; + + /** Unique ID, which identifies the inode between userspace + * and kernel */ + u64 nodeid; + + /** The request used for sending the FORGET message */ + struct fuse_forget_link *forget; +}; + /** FUSE inode */ struct fuse_inode { /** Inode data */ @@ -155,6 +168,8 @@ struct fuse_inode { */ struct fuse_inode_dax *dax; #endif + /** Submount specific lookup tracking */ + struct fuse_submount_lookup *submount_lookup; }; /** FUSE inode state bits */ diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 50365143f50e..97dc24557bf2 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -69,6 +69,24 @@ struct fuse_forget_link *fuse_alloc_forget(void) return kzalloc(sizeof(struct fuse_forget_link), GFP_KERNEL_ACCOUNT); } +static struct fuse_submount_lookup *fuse_alloc_submount_lookup(void) +{ + struct fuse_submount_lookup *sl; + + sl = kzalloc(sizeof(struct fuse_submount_lookup), GFP_KERNEL_ACCOUNT); + if (!sl) + return NULL; + sl->forget = fuse_alloc_forget(); + if (!sl->forget) + goto out_free; + + return sl; + +out_free: + kfree(sl); + return NULL; +} + static struct inode *fuse_alloc_inode(struct super_block *sb) { struct fuse_inode *fi; @@ -84,6 +102,7 @@ static struct inode *fuse_alloc_inode(struct super_block *sb) fi->attr_version = 0; fi->orig_ino = 0; fi->state = 0; + fi->submount_lookup = NULL; mutex_init(&fi->mutex); spin_lock_init(&fi->lock); fi->forget = fuse_alloc_forget(); @@ -114,6 +133,17 @@ static void fuse_free_inode(struct inode *inode) kmem_cache_free(fuse_inode_cachep, fi); } +static void fuse_cleanup_submount_lookup(struct fuse_conn *fc, + struct fuse_submount_lookup *sl) +{ + if (!refcount_dec_and_test(&sl->count)) + return; + + fuse_queue_forget(fc, sl->forget, sl->nodeid, 1); + sl->forget = NULL; + kfree(sl); +} + static void fuse_evict_inode(struct inode *inode) { struct fuse_inode *fi = get_fuse_inode(inode); @@ -133,6 +163,11 @@ static void fuse_evict_inode(struct inode *inode) fi->nlookup); fi->forget = NULL; } + + if (fi->submount_lookup) { + fuse_cleanup_submount_lookup(fc, fi->submount_lookup); + fi->submount_lookup = NULL; + } } if (S_ISREG(inode->i_mode) && !fuse_is_bad(inode)) { WARN_ON(!list_empty(&fi->write_files)); @@ -279,6 +314,13 @@ void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr, } } +static void fuse_init_submount_lookup(struct fuse_submount_lookup *sl, + u64 nodeid) +{ + sl->nodeid = nodeid; + refcount_set(&sl->count, 1); +} + static void fuse_init_inode(struct inode *inode, struct fuse_attr *attr) { inode->i_mode = attr->mode & S_IFMT; @@ -336,12 +378,22 @@ struct inode *fuse_iget(struct super_block *sb, u64 nodeid, */ if (fc->auto_submounts && (attr->flags & FUSE_ATTR_SUBMOUNT) && S_ISDIR(attr->mode)) { + struct fuse_inode *fi; + inode = new_inode(sb); if (!inode) return NULL; fuse_init_inode(inode, attr); - get_fuse_inode(inode)->nodeid = nodeid; + fi = get_fuse_inode(inode); + fi->nodeid = nodeid; + fi->submount_lookup = fuse_alloc_submount_lookup(); + if (!fi->submount_lookup) { + iput(inode); + return NULL; + } + /* Sets nlookup = 1 on fi->submount_lookup->nlookup */ + fuse_init_submount_lookup(fi->submount_lookup, nodeid); inode->i_flags |= S_AUTOMOUNT; goto done; } @@ -364,11 +416,11 @@ retry: iput(inode); goto retry; } -done: fi = get_fuse_inode(inode); spin_lock(&fi->lock); fi->nlookup++; spin_unlock(&fi->lock); +done: fuse_change_attributes(inode, attr, attr_valid, attr_version); return inode; @@ -1380,6 +1432,8 @@ static int fuse_fill_super_submount(struct super_block *sb, struct super_block *parent_sb = parent_fi->inode.i_sb; struct fuse_attr root_attr; struct inode *root; + struct fuse_submount_lookup *sl; + struct fuse_inode *fi; fuse_sb_defaults(sb); fm->sb = sb; @@ -1402,12 +1456,27 @@ static int fuse_fill_super_submount(struct super_block *sb, * its nlookup should not be incremented. fuse_iget() does * that, though, so undo it here. */ - get_fuse_inode(root)->nlookup--; + fi = get_fuse_inode(root); + fi->nlookup--; + sb->s_d_op = &fuse_dentry_operations; sb->s_root = d_make_root(root); if (!sb->s_root) return -ENOMEM; + /* + * Grab the parent's submount_lookup pointer and take a + * reference on the shared nlookup from the parent. This is to + * prevent the last forget for this nodeid from getting + * triggered until all users have finished with it. + */ + sl = parent_fi->submount_lookup; + WARN_ON(!sl); + if (sl) { + refcount_inc(&sl->count); + fi->submount_lookup = sl; + } + return 0; } -- cgit v1.2.3 From ac385518598f50dd1b9b41bd05f50ce9795481d5 Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Wed, 27 Dec 2023 19:25:58 +0900 Subject: ksmbd: have a dependency on cifs ARC4 Omitted the change that has a dependency on cifs ARC4 from backporting commit f9929ef6a2a5("ksmbd: add support for key exchange"). This patch make ksmbd have a dependeny on cifs ARC4. Fixes: c5049d2d73b2 ("ksmbd: add support for key exchange") Signed-off-by: Namjae Jeon Signed-off-by: Sasha Levin --- fs/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/Kconfig b/fs/Kconfig index a6313a969bc5..971339ecc1a2 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -369,8 +369,8 @@ source "fs/ksmbd/Kconfig" config SMBFS_COMMON tristate - default y if CIFS=y - default m if CIFS=m + default y if CIFS=y || SMB_SERVER=y + default m if CIFS=m || SMB_SERVER=m source "fs/coda/Kconfig" source "fs/afs/Kconfig" -- cgit v1.2.3 From 1bf476d8a89a2c4f5159085f5a2b84dd73026e62 Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Wed, 27 Dec 2023 19:25:59 +0900 Subject: ksmbd: set epoch in create context v2 lease [ Upstream commit d045850b628aaf931fc776c90feaf824dca5a1cf ] To support v2 lease(directory lease), ksmbd set epoch in create context v2 lease response. Signed-off-by: Namjae Jeon Signed-off-by: Steve French Signed-off-by: Sasha Levin --- fs/ksmbd/oplock.c | 5 ++++- fs/ksmbd/oplock.h | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/fs/ksmbd/oplock.c b/fs/ksmbd/oplock.c index 1cf2d2a3746a..ed639b7b6509 100644 --- a/fs/ksmbd/oplock.c +++ b/fs/ksmbd/oplock.c @@ -104,7 +104,7 @@ static int alloc_lease(struct oplock_info *opinfo, struct lease_ctx_info *lctx) lease->duration = lctx->duration; memcpy(lease->parent_lease_key, lctx->parent_lease_key, SMB2_LEASE_KEY_SIZE); lease->version = lctx->version; - lease->epoch = 0; + lease->epoch = le16_to_cpu(lctx->epoch); INIT_LIST_HEAD(&opinfo->lease_entry); opinfo->o_lease = lease; @@ -1032,6 +1032,7 @@ static void copy_lease(struct oplock_info *op1, struct oplock_info *op2) SMB2_LEASE_KEY_SIZE); lease2->duration = lease1->duration; lease2->flags = lease1->flags; + lease2->epoch = lease1->epoch++; } static int add_lease_global_list(struct oplock_info *opinfo) @@ -1364,6 +1365,7 @@ void create_lease_buf(u8 *rbuf, struct lease *lease) memcpy(buf->lcontext.LeaseKey, lease->lease_key, SMB2_LEASE_KEY_SIZE); buf->lcontext.LeaseFlags = lease->flags; + buf->lcontext.Epoch = cpu_to_le16(++lease->epoch); buf->lcontext.LeaseState = lease->state; memcpy(buf->lcontext.ParentLeaseKey, lease->parent_lease_key, SMB2_LEASE_KEY_SIZE); @@ -1423,6 +1425,7 @@ struct lease_ctx_info *parse_lease_state(void *open_req) memcpy(lreq->lease_key, lc->lcontext.LeaseKey, SMB2_LEASE_KEY_SIZE); lreq->req_state = lc->lcontext.LeaseState; lreq->flags = lc->lcontext.LeaseFlags; + lreq->epoch = lc->lcontext.Epoch; lreq->duration = lc->lcontext.LeaseDuration; memcpy(lreq->parent_lease_key, lc->lcontext.ParentLeaseKey, SMB2_LEASE_KEY_SIZE); diff --git a/fs/ksmbd/oplock.h b/fs/ksmbd/oplock.h index 4b0fe6da7694..ad31439c61fe 100644 --- a/fs/ksmbd/oplock.h +++ b/fs/ksmbd/oplock.h @@ -34,6 +34,7 @@ struct lease_ctx_info { __le32 flags; __le64 duration; __u8 parent_lease_key[SMB2_LEASE_KEY_SIZE]; + __le16 epoch; int version; }; -- cgit v1.2.3 From f7c8270be3cb57ba00ca30ad1655e20c1f4872eb Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Wed, 27 Dec 2023 19:26:00 +0900 Subject: ksmbd: set v2 lease capability [ Upstream commit 18dd1c367c31d0a060f737d48345747662369b64 ] Set SMB2_GLOBAL_CAP_DIRECTORY_LEASING to ->capabilities to inform server support directory lease to client. Signed-off-by: Namjae Jeon Signed-off-by: Steve French Signed-off-by: Sasha Levin --- fs/ksmbd/oplock.c | 4 ---- fs/ksmbd/smb2ops.c | 9 ++++++--- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/fs/ksmbd/oplock.c b/fs/ksmbd/oplock.c index ed639b7b6509..24716dbe7108 100644 --- a/fs/ksmbd/oplock.c +++ b/fs/ksmbd/oplock.c @@ -1105,10 +1105,6 @@ int smb_grant_oplock(struct ksmbd_work *work, int req_op_level, u64 pid, bool prev_op_has_lease; __le32 prev_op_state = 0; - /* not support directory lease */ - if (S_ISDIR(file_inode(fp->filp)->i_mode)) - return 0; - opinfo = alloc_opinfo(work, pid, tid); if (!opinfo) return -ENOMEM; diff --git a/fs/ksmbd/smb2ops.c b/fs/ksmbd/smb2ops.c index 9138e1c29b22..c69943d96565 100644 --- a/fs/ksmbd/smb2ops.c +++ b/fs/ksmbd/smb2ops.c @@ -222,7 +222,8 @@ void init_smb3_0_server(struct ksmbd_conn *conn) conn->signing_algorithm = SIGNING_ALG_AES_CMAC; if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_LEASES) - conn->vals->capabilities |= SMB2_GLOBAL_CAP_LEASING; + conn->vals->capabilities |= SMB2_GLOBAL_CAP_LEASING | + SMB2_GLOBAL_CAP_DIRECTORY_LEASING; if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION && conn->cli_cap & SMB2_GLOBAL_CAP_ENCRYPTION) @@ -246,7 +247,8 @@ void init_smb3_02_server(struct ksmbd_conn *conn) conn->signing_algorithm = SIGNING_ALG_AES_CMAC; if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_LEASES) - conn->vals->capabilities |= SMB2_GLOBAL_CAP_LEASING; + conn->vals->capabilities |= SMB2_GLOBAL_CAP_LEASING | + SMB2_GLOBAL_CAP_DIRECTORY_LEASING; if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION || (!(server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION_OFF) && @@ -271,7 +273,8 @@ int init_smb3_11_server(struct ksmbd_conn *conn) conn->signing_algorithm = SIGNING_ALG_AES_CMAC; if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_LEASES) - conn->vals->capabilities |= SMB2_GLOBAL_CAP_LEASING; + conn->vals->capabilities |= SMB2_GLOBAL_CAP_LEASING | + SMB2_GLOBAL_CAP_DIRECTORY_LEASING; if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION || (!(server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION_OFF) && -- cgit v1.2.3 From 86967f696586e40fd49a66b35ba7e27fe8ac0b21 Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Wed, 27 Dec 2023 19:26:01 +0900 Subject: ksmbd: downgrade RWH lease caching state to RH for directory [ Upstream commit eb547407f3572d2110cb1194ecd8865b3371a7a4 ] RWH(Read + Write + Handle) caching state is not supported for directory. ksmbd downgrade it to RH for directory if client send RWH caching lease state. Signed-off-by: Namjae Jeon Signed-off-by: Steve French Signed-off-by: Sasha Levin --- fs/ksmbd/oplock.c | 9 +++++++-- fs/ksmbd/oplock.h | 2 +- fs/ksmbd/smb2pdu.c | 8 ++++---- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/fs/ksmbd/oplock.c b/fs/ksmbd/oplock.c index 24716dbe7108..600312e2c6c2 100644 --- a/fs/ksmbd/oplock.c +++ b/fs/ksmbd/oplock.c @@ -1398,10 +1398,11 @@ void create_lease_buf(u8 *rbuf, struct lease *lease) /** * parse_lease_state() - parse lease context containted in file open request * @open_req: buffer containing smb2 file open(create) request + * @is_dir: whether leasing file is directory * * Return: oplock state, -ENOENT if create lease context not found */ -struct lease_ctx_info *parse_lease_state(void *open_req) +struct lease_ctx_info *parse_lease_state(void *open_req, bool is_dir) { struct create_context *cc; struct smb2_create_req *req = (struct smb2_create_req *)open_req; @@ -1419,7 +1420,11 @@ struct lease_ctx_info *parse_lease_state(void *open_req) struct create_lease_v2 *lc = (struct create_lease_v2 *)cc; memcpy(lreq->lease_key, lc->lcontext.LeaseKey, SMB2_LEASE_KEY_SIZE); - lreq->req_state = lc->lcontext.LeaseState; + if (is_dir) + lreq->req_state = lc->lcontext.LeaseState & + ~SMB2_LEASE_WRITE_CACHING_LE; + else + lreq->req_state = lc->lcontext.LeaseState; lreq->flags = lc->lcontext.LeaseFlags; lreq->epoch = lc->lcontext.Epoch; lreq->duration = lc->lcontext.LeaseDuration; diff --git a/fs/ksmbd/oplock.h b/fs/ksmbd/oplock.h index ad31439c61fe..672127318c75 100644 --- a/fs/ksmbd/oplock.h +++ b/fs/ksmbd/oplock.h @@ -109,7 +109,7 @@ void opinfo_put(struct oplock_info *opinfo); /* Lease related functions */ void create_lease_buf(u8 *rbuf, struct lease *lease); -struct lease_ctx_info *parse_lease_state(void *open_req); +struct lease_ctx_info *parse_lease_state(void *open_req, bool is_dir); __u8 smb2_map_lease_to_oplock(__le32 lease_state); int lease_read_to_write(struct oplock_info *opinfo); diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c index 7ce5746f9167..6a3cd6ea3af1 100644 --- a/fs/ksmbd/smb2pdu.c +++ b/fs/ksmbd/smb2pdu.c @@ -2729,10 +2729,6 @@ int smb2_open(struct ksmbd_work *work) } } - req_op_level = req->RequestedOplockLevel; - if (req_op_level == SMB2_OPLOCK_LEVEL_LEASE) - lc = parse_lease_state(req); - if (le32_to_cpu(req->ImpersonationLevel) > le32_to_cpu(IL_DELEGATE_LE)) { pr_err("Invalid impersonationlevel : 0x%x\n", le32_to_cpu(req->ImpersonationLevel)); @@ -3212,6 +3208,10 @@ int smb2_open(struct ksmbd_work *work) need_truncate = 1; } + req_op_level = req->RequestedOplockLevel; + if (req_op_level == SMB2_OPLOCK_LEVEL_LEASE) + lc = parse_lease_state(req, S_ISDIR(file_inode(filp)->i_mode)); + share_ret = ksmbd_smb_check_shared_mode(fp->filp, fp); if (!test_share_config_flag(work->tcon->share_conf, KSMBD_SHARE_FLAG_OPLOCKS) || (req_op_level == SMB2_OPLOCK_LEVEL_LEASE && -- cgit v1.2.3 From f58afd8c70111b253d0f2d3cde0e38108c22baa9 Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Wed, 27 Dec 2023 19:26:02 +0900 Subject: ksmbd: send v2 lease break notification for directory [ Upstream commit d47d9886aeef79feba7adac701a510d65f3682b5 ] If client send different parent key, different client guid, or there is no parent lease key flags in create context v2 lease, ksmbd send lease break to client. Signed-off-by: Namjae Jeon Signed-off-by: Steve French Signed-off-by: Sasha Levin --- fs/ksmbd/oplock.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++----- fs/ksmbd/oplock.h | 4 ++++ fs/ksmbd/smb2pdu.c | 7 +++++++ fs/ksmbd/smb2pdu.h | 1 + fs/ksmbd/vfs_cache.c | 13 +++++++++++- fs/ksmbd/vfs_cache.h | 2 ++ 6 files changed, 77 insertions(+), 6 deletions(-) diff --git a/fs/ksmbd/oplock.c b/fs/ksmbd/oplock.c index 600312e2c6c2..df6f00f58f19 100644 --- a/fs/ksmbd/oplock.c +++ b/fs/ksmbd/oplock.c @@ -102,6 +102,7 @@ static int alloc_lease(struct oplock_info *opinfo, struct lease_ctx_info *lctx) lease->new_state = 0; lease->flags = lctx->flags; lease->duration = lctx->duration; + lease->is_dir = lctx->is_dir; memcpy(lease->parent_lease_key, lctx->parent_lease_key, SMB2_LEASE_KEY_SIZE); lease->version = lctx->version; lease->epoch = le16_to_cpu(lctx->epoch); @@ -543,12 +544,13 @@ static struct oplock_info *same_client_has_lease(struct ksmbd_inode *ci, /* upgrading lease */ if ((atomic_read(&ci->op_count) + atomic_read(&ci->sop_count)) == 1) { - if (lease->state == - (lctx->req_state & lease->state)) { + if (lease->state != SMB2_LEASE_NONE_LE && + lease->state == (lctx->req_state & lease->state)) { lease->state |= lctx->req_state; if (lctx->req_state & SMB2_LEASE_WRITE_CACHING_LE) lease_read_to_write(opinfo); + } } else if ((atomic_read(&ci->op_count) + atomic_read(&ci->sop_count)) > 1) { @@ -900,7 +902,8 @@ static int oplock_break(struct oplock_info *brk_opinfo, int req_op_level) lease->new_state = SMB2_LEASE_READ_CACHING_LE; } else { - if (lease->state & SMB2_LEASE_HANDLE_CACHING_LE) + if (lease->state & SMB2_LEASE_HANDLE_CACHING_LE && + !lease->is_dir) lease->new_state = SMB2_LEASE_READ_CACHING_LE; else @@ -1082,6 +1085,48 @@ static void set_oplock_level(struct oplock_info *opinfo, int level, } } +void smb_send_parent_lease_break_noti(struct ksmbd_file *fp, + struct lease_ctx_info *lctx) +{ + struct oplock_info *opinfo; + struct ksmbd_inode *p_ci = NULL; + + if (lctx->version != 2) + return; + + p_ci = ksmbd_inode_lookup_lock(fp->filp->f_path.dentry->d_parent); + if (!p_ci) + return; + + read_lock(&p_ci->m_lock); + list_for_each_entry(opinfo, &p_ci->m_op_list, op_entry) { + if (!opinfo->is_lease) + continue; + + if (opinfo->o_lease->state != SMB2_OPLOCK_LEVEL_NONE && + (!(lctx->flags & SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET_LE) || + !compare_guid_key(opinfo, fp->conn->ClientGUID, + lctx->parent_lease_key))) { + if (!atomic_inc_not_zero(&opinfo->refcount)) + continue; + + atomic_inc(&opinfo->conn->r_count); + if (ksmbd_conn_releasing(opinfo->conn)) { + atomic_dec(&opinfo->conn->r_count); + continue; + } + + read_unlock(&p_ci->m_lock); + oplock_break(opinfo, SMB2_OPLOCK_LEVEL_NONE); + opinfo_conn_put(opinfo); + read_lock(&p_ci->m_lock); + } + } + read_unlock(&p_ci->m_lock); + + ksmbd_inode_put(p_ci); +} + /** * smb_grant_oplock() - handle oplock/lease request on file open * @work: smb work @@ -1420,10 +1465,11 @@ struct lease_ctx_info *parse_lease_state(void *open_req, bool is_dir) struct create_lease_v2 *lc = (struct create_lease_v2 *)cc; memcpy(lreq->lease_key, lc->lcontext.LeaseKey, SMB2_LEASE_KEY_SIZE); - if (is_dir) + if (is_dir) { lreq->req_state = lc->lcontext.LeaseState & ~SMB2_LEASE_WRITE_CACHING_LE; - else + lreq->is_dir = true; + } else lreq->req_state = lc->lcontext.LeaseState; lreq->flags = lc->lcontext.LeaseFlags; lreq->epoch = lc->lcontext.Epoch; diff --git a/fs/ksmbd/oplock.h b/fs/ksmbd/oplock.h index 672127318c75..b64d1536882a 100644 --- a/fs/ksmbd/oplock.h +++ b/fs/ksmbd/oplock.h @@ -36,6 +36,7 @@ struct lease_ctx_info { __u8 parent_lease_key[SMB2_LEASE_KEY_SIZE]; __le16 epoch; int version; + bool is_dir; }; struct lease_table { @@ -54,6 +55,7 @@ struct lease { __u8 parent_lease_key[SMB2_LEASE_KEY_SIZE]; int version; unsigned short epoch; + bool is_dir; struct lease_table *l_lb; }; @@ -125,4 +127,6 @@ struct oplock_info *lookup_lease_in_table(struct ksmbd_conn *conn, int find_same_lease_key(struct ksmbd_session *sess, struct ksmbd_inode *ci, struct lease_ctx_info *lctx); void destroy_lease_table(struct ksmbd_conn *conn); +void smb_send_parent_lease_break_noti(struct ksmbd_file *fp, + struct lease_ctx_info *lctx); #endif /* __KSMBD_OPLOCK_H */ diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c index 6a3cd6ea3af1..c1dde4204366 100644 --- a/fs/ksmbd/smb2pdu.c +++ b/fs/ksmbd/smb2pdu.c @@ -3222,6 +3222,13 @@ int smb2_open(struct ksmbd_work *work) } } else { if (req_op_level == SMB2_OPLOCK_LEVEL_LEASE) { + /* + * Compare parent lease using parent key. If there is no + * a lease that has same parent key, Send lease break + * notification. + */ + smb_send_parent_lease_break_noti(fp, lc); + req_op_level = smb2_map_lease_to_oplock(lc->req_state); ksmbd_debug(SMB, "lease req for(%s) req oplock state 0x%x, lease state 0x%x\n", diff --git a/fs/ksmbd/smb2pdu.h b/fs/ksmbd/smb2pdu.h index e1d0849ee68f..912bd94257ec 100644 --- a/fs/ksmbd/smb2pdu.h +++ b/fs/ksmbd/smb2pdu.h @@ -737,6 +737,7 @@ struct create_posix_rsp { #define SMB2_LEASE_WRITE_CACHING_LE cpu_to_le32(0x04) #define SMB2_LEASE_FLAG_BREAK_IN_PROGRESS_LE cpu_to_le32(0x02) +#define SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET_LE cpu_to_le32(0x04) #define SMB2_LEASE_KEY_SIZE 16 diff --git a/fs/ksmbd/vfs_cache.c b/fs/ksmbd/vfs_cache.c index 774a387fccce..2528ce8aeebb 100644 --- a/fs/ksmbd/vfs_cache.c +++ b/fs/ksmbd/vfs_cache.c @@ -86,6 +86,17 @@ static struct ksmbd_inode *ksmbd_inode_lookup(struct ksmbd_file *fp) return __ksmbd_inode_lookup(fp->filp->f_path.dentry); } +struct ksmbd_inode *ksmbd_inode_lookup_lock(struct dentry *d) +{ + struct ksmbd_inode *ci; + + read_lock(&inode_hash_lock); + ci = __ksmbd_inode_lookup(d); + read_unlock(&inode_hash_lock); + + return ci; +} + int ksmbd_query_inode_status(struct dentry *dentry) { struct ksmbd_inode *ci; @@ -198,7 +209,7 @@ static void ksmbd_inode_free(struct ksmbd_inode *ci) kfree(ci); } -static void ksmbd_inode_put(struct ksmbd_inode *ci) +void ksmbd_inode_put(struct ksmbd_inode *ci) { if (atomic_dec_and_test(&ci->m_count)) ksmbd_inode_free(ci); diff --git a/fs/ksmbd/vfs_cache.h b/fs/ksmbd/vfs_cache.h index 8325cf4527c4..4d4938d6029b 100644 --- a/fs/ksmbd/vfs_cache.h +++ b/fs/ksmbd/vfs_cache.h @@ -138,6 +138,8 @@ struct ksmbd_file *ksmbd_lookup_foreign_fd(struct ksmbd_work *work, u64 id); struct ksmbd_file *ksmbd_lookup_fd_slow(struct ksmbd_work *work, u64 id, u64 pid); void ksmbd_fd_put(struct ksmbd_work *work, struct ksmbd_file *fp); +struct ksmbd_inode *ksmbd_inode_lookup_lock(struct dentry *d); +void ksmbd_inode_put(struct ksmbd_inode *ci); struct ksmbd_file *ksmbd_lookup_durable_fd(unsigned long long id); struct ksmbd_file *ksmbd_lookup_fd_cguid(char *cguid); struct ksmbd_file *ksmbd_lookup_fd_inode(struct dentry *dentry); -- cgit v1.2.3 From 9444c47d2c3b3ee5761585157aa60af572a672de Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Wed, 27 Dec 2023 19:26:03 +0900 Subject: ksmbd: lazy v2 lease break on smb2_write() [ Upstream commit c2a721eead71202a0d8ddd9b56ec8dce652c71d1 ] Don't immediately send directory lease break notification on smb2_write(). Instead, It postpones it until smb2_close(). Signed-off-by: Namjae Jeon Signed-off-by: Steve French Signed-off-by: Sasha Levin --- fs/ksmbd/oplock.c | 45 +++++++++++++++++++++++++++++++++++++++++++-- fs/ksmbd/oplock.h | 1 + fs/ksmbd/vfs.c | 3 +++ fs/ksmbd/vfs_cache.h | 1 + 4 files changed, 48 insertions(+), 2 deletions(-) diff --git a/fs/ksmbd/oplock.c b/fs/ksmbd/oplock.c index df6f00f58f19..2da256259722 100644 --- a/fs/ksmbd/oplock.c +++ b/fs/ksmbd/oplock.c @@ -396,8 +396,8 @@ void close_id_del_oplock(struct ksmbd_file *fp) { struct oplock_info *opinfo; - if (S_ISDIR(file_inode(fp->filp)->i_mode)) - return; + if (fp->reserve_lease_break) + smb_lazy_parent_lease_break_close(fp); opinfo = opinfo_get(fp); if (!opinfo) @@ -1127,6 +1127,47 @@ void smb_send_parent_lease_break_noti(struct ksmbd_file *fp, ksmbd_inode_put(p_ci); } +void smb_lazy_parent_lease_break_close(struct ksmbd_file *fp) +{ + struct oplock_info *opinfo; + struct ksmbd_inode *p_ci = NULL; + + rcu_read_lock(); + opinfo = rcu_dereference(fp->f_opinfo); + rcu_read_unlock(); + + if (!opinfo->is_lease || opinfo->o_lease->version != 2) + return; + + p_ci = ksmbd_inode_lookup_lock(fp->filp->f_path.dentry->d_parent); + if (!p_ci) + return; + + read_lock(&p_ci->m_lock); + list_for_each_entry(opinfo, &p_ci->m_op_list, op_entry) { + if (!opinfo->is_lease) + continue; + + if (opinfo->o_lease->state != SMB2_OPLOCK_LEVEL_NONE) { + if (!atomic_inc_not_zero(&opinfo->refcount)) + continue; + + atomic_inc(&opinfo->conn->r_count); + if (ksmbd_conn_releasing(opinfo->conn)) { + atomic_dec(&opinfo->conn->r_count); + continue; + } + read_unlock(&p_ci->m_lock); + oplock_break(opinfo, SMB2_OPLOCK_LEVEL_NONE); + opinfo_conn_put(opinfo); + read_lock(&p_ci->m_lock); + } + } + read_unlock(&p_ci->m_lock); + + ksmbd_inode_put(p_ci); +} + /** * smb_grant_oplock() - handle oplock/lease request on file open * @work: smb work diff --git a/fs/ksmbd/oplock.h b/fs/ksmbd/oplock.h index b64d1536882a..5b93ea9196c0 100644 --- a/fs/ksmbd/oplock.h +++ b/fs/ksmbd/oplock.h @@ -129,4 +129,5 @@ int find_same_lease_key(struct ksmbd_session *sess, struct ksmbd_inode *ci, void destroy_lease_table(struct ksmbd_conn *conn); void smb_send_parent_lease_break_noti(struct ksmbd_file *fp, struct lease_ctx_info *lctx); +void smb_lazy_parent_lease_break_close(struct ksmbd_file *fp); #endif /* __KSMBD_OPLOCK_H */ diff --git a/fs/ksmbd/vfs.c b/fs/ksmbd/vfs.c index a89529b21c86..173a488bfeee 100644 --- a/fs/ksmbd/vfs.c +++ b/fs/ksmbd/vfs.c @@ -517,6 +517,9 @@ int ksmbd_vfs_write(struct ksmbd_work *work, struct ksmbd_file *fp, } } + /* Reserve lease break for parent dir at closing time */ + fp->reserve_lease_break = true; + /* Do we need to break any of a levelII oplock? */ smb_break_all_levII_oplock(work, fp, 1); diff --git a/fs/ksmbd/vfs_cache.h b/fs/ksmbd/vfs_cache.h index 4d4938d6029b..a528f0cc775a 100644 --- a/fs/ksmbd/vfs_cache.h +++ b/fs/ksmbd/vfs_cache.h @@ -105,6 +105,7 @@ struct ksmbd_file { struct ksmbd_readdir_data readdir_data; int dot_dotdot[2]; unsigned int f_state; + bool reserve_lease_break; }; static inline void set_ctx_actor(struct dir_context *ctx, -- cgit v1.2.3 From 06208a04a7bd6ac3a359de2fa047e71f474f24b9 Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Wed, 27 Dec 2023 19:26:04 +0900 Subject: ksmbd: avoid duplicate opinfo_put() call on error of smb21_lease_break_ack() [ Upstream commit 658609d9a618d8881bf549b5893c0ba8fcff4526 ] opinfo_put() could be called twice on error of smb21_lease_break_ack(). It will cause UAF issue if opinfo is referenced on other places. Signed-off-by: Namjae Jeon Signed-off-by: Steve French Signed-off-by: Sasha Levin --- fs/ksmbd/smb2pdu.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c index c1dde4204366..e1c640ed7acc 100644 --- a/fs/ksmbd/smb2pdu.c +++ b/fs/ksmbd/smb2pdu.c @@ -8221,6 +8221,11 @@ static void smb21_lease_break_ack(struct ksmbd_work *work) le32_to_cpu(req->LeaseState)); } + if (ret < 0) { + rsp->hdr.Status = err; + goto err_out; + } + lease_state = lease->state; opinfo->op_state = OPLOCK_STATE_NONE; wake_up_interruptible_all(&opinfo->oplock_q); @@ -8228,11 +8233,6 @@ static void smb21_lease_break_ack(struct ksmbd_work *work) wake_up_interruptible_all(&opinfo->oplock_brk); opinfo_put(opinfo); - if (ret < 0) { - rsp->hdr.Status = err; - goto err_out; - } - rsp->StructureSize = cpu_to_le16(36); rsp->Reserved = 0; rsp->Flags = 0; -- cgit v1.2.3 From 8bf06286d740719ce0d7012a9c860447491b8c00 Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Wed, 27 Dec 2023 19:26:05 +0900 Subject: ksmbd: fix wrong allocation size update in smb2_open() [ Upstream commit a9f106c765c12d2f58aa33431bd8ce8e9d8a404a ] When client send SMB2_CREATE_ALLOCATION_SIZE create context, ksmbd update old size to ->AllocationSize in smb2 create response. ksmbd_vfs_getattr() should be called after it to get updated stat result. Signed-off-by: Namjae Jeon Signed-off-by: Steve French Signed-off-by: Sasha Levin --- fs/ksmbd/smb2pdu.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c index e1c640ed7acc..8875c04e8382 100644 --- a/fs/ksmbd/smb2pdu.c +++ b/fs/ksmbd/smb2pdu.c @@ -2516,7 +2516,7 @@ static void smb2_new_xattrs(struct ksmbd_tree_connect *tcon, const struct path * da.flags = XATTR_DOSINFO_ATTRIB | XATTR_DOSINFO_CREATE_TIME | XATTR_DOSINFO_ITIME; - rc = ksmbd_vfs_set_dos_attrib_xattr(mnt_user_ns(path->mnt), path, &da, false); + rc = ksmbd_vfs_set_dos_attrib_xattr(mnt_user_ns(path->mnt), path, &da, true); if (rc) ksmbd_debug(SMB, "failed to store file attribute into xattr\n"); } @@ -3182,23 +3182,6 @@ int smb2_open(struct ksmbd_work *work) goto err_out; } - rc = ksmbd_vfs_getattr(&path, &stat); - if (rc) - goto err_out; - - if (stat.result_mask & STATX_BTIME) - fp->create_time = ksmbd_UnixTimeToNT(stat.btime); - else - fp->create_time = ksmbd_UnixTimeToNT(stat.ctime); - if (req->FileAttributes || fp->f_ci->m_fattr == 0) - fp->f_ci->m_fattr = - cpu_to_le32(smb2_get_dos_mode(&stat, le32_to_cpu(req->FileAttributes))); - - if (!created) - smb2_update_xattrs(tcon, &path, fp); - else - smb2_new_xattrs(tcon, &path, fp); - if (file_present || created) ksmbd_vfs_kern_path_unlock(&parent_path, &path); @@ -3299,6 +3282,23 @@ int smb2_open(struct ksmbd_work *work) } } + rc = ksmbd_vfs_getattr(&path, &stat); + if (rc) + goto err_out1; + + if (stat.result_mask & STATX_BTIME) + fp->create_time = ksmbd_UnixTimeToNT(stat.btime); + else + fp->create_time = ksmbd_UnixTimeToNT(stat.ctime); + if (req->FileAttributes || fp->f_ci->m_fattr == 0) + fp->f_ci->m_fattr = + cpu_to_le32(smb2_get_dos_mode(&stat, le32_to_cpu(req->FileAttributes))); + + if (!created) + smb2_update_xattrs(tcon, &path, fp); + else + smb2_new_xattrs(tcon, &path, fp); + memcpy(fp->client_guid, conn->ClientGUID, SMB2_CLIENT_GUID_SIZE); rsp->StructureSize = cpu_to_le16(89); -- cgit v1.2.3 From d529cc22789746f078fae573f11ec0288a4c4844 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Tue, 12 Dec 2023 15:50:35 +0200 Subject: ARM: dts: Fix occasional boot hang for am3 usb [ Upstream commit 9b6a51aab5f5f9f71d2fa16e8b4d530e1643dfcb ] With subtle timings changes, we can now sometimes get an external abort on non-linefetch error booting am3 devices at sysc_reset(). This is because of a missing reset delay needed for the usb target module. Looks like we never enabled the delay earlier for am3, although a similar issue was seen earlier with a similar usb setup for dm814x as described in commit ebf244148092 ("ARM: OMAP2+: Use srst_udelay for USB on dm814x"). Cc: stable@vger.kernel.org Fixes: 0782e8572ce4 ("ARM: dts: Probe am335x musb with ti-sysc") Signed-off-by: Tony Lindgren Signed-off-by: Sasha Levin --- arch/arm/boot/dts/am33xx.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi index f53695ecbb78..7daf6ae2cd9a 100644 --- a/arch/arm/boot/dts/am33xx.dtsi +++ b/arch/arm/boot/dts/am33xx.dtsi @@ -349,6 +349,7 @@ , , ; + ti,sysc-delay-us = <2>; clocks = <&l3s_clkctrl AM3_L3S_USB_OTG_HS_CLKCTRL 0>; clock-names = "fck"; #address-cells = <1>; -- cgit v1.2.3 From 32d9a4ce5240bbf7c8923301be845bf020239e3f Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 13 Dec 2023 16:22:43 +0300 Subject: usb: fotg210-hcd: delete an incorrect bounds test [ Upstream commit 7fbcd195e2b8cc952e4aeaeb50867b798040314c ] Here "temp" is the number of characters that we have written and "size" is the size of the buffer. The intent was clearly to say that if we have written to the end of the buffer then stop. However, for that to work the comparison should have been done on the original "size" value instead of the "size -= temp" value. Not only will that not trigger when we want to, but there is a small chance that it will trigger incorrectly before we want it to and we break from the loop slightly earlier than intended. This code was recently changed from using snprintf() to scnprintf(). With snprintf() we likely would have continued looping and passed a negative size parameter to snprintf(). This would have triggered an annoying WARN(). Now that we have converted to scnprintf() "size" will never drop below 1 and there is no real need for this test. We could change the condition to "if (temp <= 1) goto done;" but just deleting the test is cleanest. Fixes: 7d50195f6c50 ("usb: host: Faraday fotg210-hcd driver") Cc: stable Signed-off-by: Dan Carpenter Reviewed-by: Linus Walleij Reviewed-by: Lee Jones Link: https://lore.kernel.org/r/ZXmwIwHe35wGfgzu@suswa Signed-off-by: Greg Kroah-Hartman Signed-off-by: Sasha Levin --- drivers/usb/host/fotg210-hcd.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/usb/host/fotg210-hcd.c b/drivers/usb/host/fotg210-hcd.c index d9a3fd8af7a0..b0b6caaa29bd 100644 --- a/drivers/usb/host/fotg210-hcd.c +++ b/drivers/usb/host/fotg210-hcd.c @@ -429,8 +429,6 @@ static void qh_lines(struct fotg210_hcd *fotg210, struct fotg210_qh *qh, temp = size; size -= temp; next += temp; - if (temp == size) - goto done; } temp = snprintf(next, size, "\n"); @@ -440,7 +438,6 @@ static void qh_lines(struct fotg210_hcd *fotg210, struct fotg210_qh *qh, size -= temp; next += temp; -done: *sizep = size; *nextp = next; } -- cgit v1.2.3 From 597305fd770870fbfd12ed981b095e073ae1aafe Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Thu, 14 Oct 2021 07:24:31 -0700 Subject: ethernet: constify references to netdev->dev_addr in drivers [ Upstream commit 766607570becbd26cab6d66a544dd8d0d964df5a ] This big patch sprinkles const on local variables and function arguments which may refer to netdev->dev_addr. Commit 406f42fa0d3c ("net-next: When a bond have a massive amount of VLANs...") introduced a rbtree for faster Ethernet address look up. To maintain netdev->dev_addr in this tree we need to make all the writes to it got through appropriate helpers. Some of the changes here are not strictly required - const is sometimes cast off but pointer is not used for writing. It seems like it's still better to add the const in case the code changes later or relevant -W flags get enabled for the build. No functional changes. Link: https://lore.kernel.org/r/20211014142432.449314-1-kuba@kernel.org Signed-off-by: Jakub Kicinski Stable-dep-of: aef05e349bfd ("net: usb: ax88179_178a: avoid failed operations when device is disconnected") Signed-off-by: Sasha Levin --- drivers/net/ethernet/actions/owl-emac.c | 2 +- drivers/net/ethernet/adaptec/starfire.c | 10 +++++----- drivers/net/ethernet/alacritech/slicoss.c | 2 +- drivers/net/ethernet/alteon/acenic.c | 4 ++-- drivers/net/ethernet/altera/altera_tse_main.c | 2 +- drivers/net/ethernet/amd/nmclan_cs.c | 3 ++- drivers/net/ethernet/amd/xgbe/xgbe-dev.c | 2 +- drivers/net/ethernet/amd/xgbe/xgbe.h | 2 +- drivers/net/ethernet/apm/xgene-v2/mac.c | 2 +- drivers/net/ethernet/apm/xgene/xgene_enet_hw.c | 2 +- drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c | 2 +- drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c | 2 +- drivers/net/ethernet/apple/bmac.c | 8 ++++---- drivers/net/ethernet/aquantia/atlantic/aq_hw.h | 6 +++--- drivers/net/ethernet/aquantia/atlantic/aq_macsec.c | 2 +- drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c | 4 ++-- drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c | 4 ++-- drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.h | 2 +- drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c | 4 ++-- .../ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c | 4 ++-- drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c | 2 +- drivers/net/ethernet/broadcom/b44.c | 6 ++++-- drivers/net/ethernet/broadcom/bcmsysport.c | 2 +- drivers/net/ethernet/broadcom/bgmac.c | 2 +- drivers/net/ethernet/broadcom/bnx2.c | 2 +- drivers/net/ethernet/broadcom/bnx2x/bnx2x.h | 2 +- drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | 4 ++-- drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h | 3 ++- drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c | 2 +- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 2 +- drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c | 4 ++-- drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.h | 2 +- drivers/net/ethernet/broadcom/genet/bcmgenet.c | 4 ++-- drivers/net/ethernet/calxeda/xgmac.c | 2 +- drivers/net/ethernet/chelsio/cxgb/gmac.h | 2 +- drivers/net/ethernet/chelsio/cxgb/pm3393.c | 2 +- drivers/net/ethernet/chelsio/cxgb/vsc7326.c | 2 +- drivers/net/ethernet/chelsio/cxgb3/common.h | 2 +- drivers/net/ethernet/chelsio/cxgb3/xgmac.c | 2 +- drivers/net/ethernet/cisco/enic/enic_pp.c | 2 +- drivers/net/ethernet/dlink/dl2k.c | 2 +- drivers/net/ethernet/dnet.c | 6 +++--- drivers/net/ethernet/emulex/benet/be_cmds.c | 2 +- drivers/net/ethernet/emulex/benet/be_cmds.h | 2 +- drivers/net/ethernet/emulex/benet/be_main.c | 2 +- drivers/net/ethernet/ethoc.c | 2 +- drivers/net/ethernet/fealnx.c | 2 +- drivers/net/ethernet/freescale/dpaa/dpaa_eth.c | 4 ++-- drivers/net/ethernet/freescale/fman/fman_dtsec.c | 8 ++++---- drivers/net/ethernet/freescale/fman/fman_dtsec.h | 2 +- drivers/net/ethernet/freescale/fman/fman_memac.c | 8 ++++---- drivers/net/ethernet/freescale/fman/fman_memac.h | 2 +- drivers/net/ethernet/freescale/fman/fman_tgec.c | 8 ++++---- drivers/net/ethernet/freescale/fman/fman_tgec.h | 2 +- drivers/net/ethernet/freescale/fman/mac.h | 2 +- drivers/net/ethernet/hisilicon/hisi_femac.c | 2 +- drivers/net/ethernet/hisilicon/hix5hd2_gmac.c | 2 +- drivers/net/ethernet/hisilicon/hns/hnae.h | 2 +- drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c | 2 +- drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c | 2 +- drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c | 2 +- drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h | 5 +++-- drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c | 2 +- drivers/net/ethernet/hisilicon/hns3/hnae3.h | 2 +- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 2 +- drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c | 2 +- drivers/net/ethernet/i825xx/sun3_82586.c | 2 +- drivers/net/ethernet/intel/i40e/i40e.h | 2 +- drivers/net/ethernet/intel/ixgb/ixgb_hw.c | 2 +- drivers/net/ethernet/intel/ixgb/ixgb_hw.h | 2 +- drivers/net/ethernet/marvell/mv643xx_eth.c | 2 +- drivers/net/ethernet/marvell/mvneta.c | 4 ++-- drivers/net/ethernet/marvell/pxa168_eth.c | 6 +++--- drivers/net/ethernet/mediatek/mtk_star_emac.c | 2 +- drivers/net/ethernet/mellanox/mlx5/core/en_fs.c | 4 ++-- drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c | 2 +- drivers/net/ethernet/micrel/ks8842.c | 2 +- drivers/net/ethernet/micrel/ksz884x.c | 4 ++-- drivers/net/ethernet/myricom/myri10ge/myri10ge.c | 3 ++- drivers/net/ethernet/neterion/s2io.c | 2 +- drivers/net/ethernet/neterion/s2io.h | 2 +- drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c | 6 +++--- drivers/net/ethernet/nxp/lpc_eth.c | 2 +- drivers/net/ethernet/qlogic/qed/qed_dev.c | 2 +- drivers/net/ethernet/qlogic/qed/qed_dev_api.h | 2 +- drivers/net/ethernet/qlogic/qed/qed_l2.c | 2 +- drivers/net/ethernet/qlogic/qed/qed_main.c | 2 +- drivers/net/ethernet/qlogic/qed/qed_mcp.c | 2 +- drivers/net/ethernet/qlogic/qed/qed_mcp.h | 2 +- drivers/net/ethernet/qlogic/qed/qed_rdma.c | 2 +- drivers/net/ethernet/qlogic/qed/qed_vf.c | 2 +- drivers/net/ethernet/qlogic/qed/qed_vf.h | 4 ++-- drivers/net/ethernet/qlogic/qede/qede_filter.c | 2 +- drivers/net/ethernet/qualcomm/emac/emac-mac.c | 2 +- drivers/net/ethernet/rdc/r6040.c | 12 ++++++------ drivers/net/ethernet/samsung/sxgbe/sxgbe_common.h | 2 +- drivers/net/ethernet/samsung/sxgbe/sxgbe_core.c | 3 ++- drivers/net/ethernet/sfc/ef10.c | 4 ++-- drivers/net/ethernet/sfc/ef10_sriov.c | 2 +- drivers/net/ethernet/sfc/ef10_sriov.h | 6 +++--- drivers/net/ethernet/sfc/net_driver.h | 2 +- drivers/net/ethernet/sfc/siena_sriov.c | 2 +- drivers/net/ethernet/sfc/siena_sriov.h | 2 +- drivers/net/ethernet/sis/sis900.c | 2 +- drivers/net/ethernet/smsc/smsc911x.c | 2 +- drivers/net/ethernet/smsc/smsc9420.c | 2 +- drivers/net/ethernet/stmicro/stmmac/common.h | 4 ++-- drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 2 +- drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c | 2 +- drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c | 2 +- drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c | 2 +- drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c | 2 +- drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c | 2 +- drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c | 3 ++- drivers/net/ethernet/stmicro/stmmac/hwif.h | 3 ++- drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c | 4 ++-- drivers/net/ethernet/sun/sunbmac.c | 2 +- drivers/net/ethernet/sun/sunqe.c | 2 +- drivers/net/ethernet/synopsys/dwc-xlgmac-hw.c | 2 +- drivers/net/ethernet/synopsys/dwc-xlgmac.h | 2 +- drivers/net/ethernet/ti/tlan.c | 4 ++-- drivers/net/ethernet/toshiba/tc35815.c | 3 ++- drivers/net/ethernet/xilinx/xilinx_emaclite.c | 7 ++++--- drivers/net/ethernet/xircom/xirc2ps_cs.c | 2 +- drivers/net/phy/mscc/mscc_main.c | 2 +- drivers/net/usb/aqc111.c | 2 +- drivers/net/usb/ax88179_178a.c | 8 ++++---- drivers/net/usb/catc.c | 2 +- drivers/net/usb/dm9601.c | 3 ++- drivers/net/usb/mcs7830.c | 3 ++- drivers/net/usb/sr9700.c | 3 ++- include/linux/qed/qed_eth_if.h | 2 +- include/linux/qed/qed_if.h | 2 +- include/linux/qed/qed_rdma_if.h | 3 ++- 134 files changed, 204 insertions(+), 189 deletions(-) diff --git a/drivers/net/ethernet/actions/owl-emac.c b/drivers/net/ethernet/actions/owl-emac.c index c4ecf4fcadf8..add3480c6c56 100644 --- a/drivers/net/ethernet/actions/owl-emac.c +++ b/drivers/net/ethernet/actions/owl-emac.c @@ -342,7 +342,7 @@ static u32 owl_emac_dma_cmd_stop(struct owl_emac_priv *priv) static void owl_emac_set_hw_mac_addr(struct net_device *netdev) { struct owl_emac_priv *priv = netdev_priv(netdev); - u8 *mac_addr = netdev->dev_addr; + const u8 *mac_addr = netdev->dev_addr; u32 addr_high, addr_low; addr_high = mac_addr[0] << 8 | mac_addr[1]; diff --git a/drivers/net/ethernet/adaptec/starfire.c b/drivers/net/ethernet/adaptec/starfire.c index e0f6cc910bd2..16b6b83f670b 100644 --- a/drivers/net/ethernet/adaptec/starfire.c +++ b/drivers/net/ethernet/adaptec/starfire.c @@ -955,7 +955,7 @@ static int netdev_open(struct net_device *dev) writew(0, ioaddr + PerfFilterTable + 4); writew(0, ioaddr + PerfFilterTable + 8); for (i = 1; i < 16; i++) { - __be16 *eaddrs = (__be16 *)dev->dev_addr; + const __be16 *eaddrs = (const __be16 *)dev->dev_addr; void __iomem *setup_frm = ioaddr + PerfFilterTable + i * 16; writew(be16_to_cpu(eaddrs[2]), setup_frm); setup_frm += 4; writew(be16_to_cpu(eaddrs[1]), setup_frm); setup_frm += 4; @@ -1787,14 +1787,14 @@ static void set_rx_mode(struct net_device *dev) } else if (netdev_mc_count(dev) <= 14) { /* Use the 16 element perfect filter, skip first two entries. */ void __iomem *filter_addr = ioaddr + PerfFilterTable + 2 * 16; - __be16 *eaddrs; + const __be16 *eaddrs; netdev_for_each_mc_addr(ha, dev) { eaddrs = (__be16 *) ha->addr; writew(be16_to_cpu(eaddrs[2]), filter_addr); filter_addr += 4; writew(be16_to_cpu(eaddrs[1]), filter_addr); filter_addr += 4; writew(be16_to_cpu(eaddrs[0]), filter_addr); filter_addr += 8; } - eaddrs = (__be16 *)dev->dev_addr; + eaddrs = (const __be16 *)dev->dev_addr; i = netdev_mc_count(dev) + 2; while (i++ < 16) { writew(be16_to_cpu(eaddrs[0]), filter_addr); filter_addr += 4; @@ -1805,7 +1805,7 @@ static void set_rx_mode(struct net_device *dev) } else { /* Must use a multicast hash table. */ void __iomem *filter_addr; - __be16 *eaddrs; + const __be16 *eaddrs; __le16 mc_filter[32] __attribute__ ((aligned(sizeof(long)))); /* Multicast hash filter */ memset(mc_filter, 0, sizeof(mc_filter)); @@ -1819,7 +1819,7 @@ static void set_rx_mode(struct net_device *dev) } /* Clear the perfect filter list, skip first two entries. */ filter_addr = ioaddr + PerfFilterTable + 2 * 16; - eaddrs = (__be16 *)dev->dev_addr; + eaddrs = (const __be16 *)dev->dev_addr; for (i = 2; i < 16; i++) { writew(be16_to_cpu(eaddrs[0]), filter_addr); filter_addr += 4; writew(be16_to_cpu(eaddrs[1]), filter_addr); filter_addr += 4; diff --git a/drivers/net/ethernet/alacritech/slicoss.c b/drivers/net/ethernet/alacritech/slicoss.c index 82f4f2608102..1fc9a1cd3ef8 100644 --- a/drivers/net/ethernet/alacritech/slicoss.c +++ b/drivers/net/ethernet/alacritech/slicoss.c @@ -1008,7 +1008,7 @@ static void slic_set_link_autoneg(struct slic_device *sdev) static void slic_set_mac_address(struct slic_device *sdev) { - u8 *addr = sdev->netdev->dev_addr; + const u8 *addr = sdev->netdev->dev_addr; u32 val; val = addr[5] | addr[4] << 8 | addr[3] << 16 | addr[2] << 24; diff --git a/drivers/net/ethernet/alteon/acenic.c b/drivers/net/ethernet/alteon/acenic.c index 9dc12b13061f..afa383355265 100644 --- a/drivers/net/ethernet/alteon/acenic.c +++ b/drivers/net/ethernet/alteon/acenic.c @@ -2712,7 +2712,7 @@ static int ace_set_mac_addr(struct net_device *dev, void *p) struct ace_private *ap = netdev_priv(dev); struct ace_regs __iomem *regs = ap->regs; struct sockaddr *addr=p; - u8 *da; + const u8 *da; struct cmd cmd; if(netif_running(dev)) @@ -2720,7 +2720,7 @@ static int ace_set_mac_addr(struct net_device *dev, void *p) memcpy(dev->dev_addr, addr->sa_data,dev->addr_len); - da = (u8 *)dev->dev_addr; + da = (const u8 *)dev->dev_addr; writel(da[0] << 8 | da[1], ®s->MacAddrHi); writel((da[2] << 24) | (da[3] << 16) | (da[4] << 8) | da[5], diff --git a/drivers/net/ethernet/altera/altera_tse_main.c b/drivers/net/ethernet/altera/altera_tse_main.c index 9e721436f06f..36bf3ce545c9 100644 --- a/drivers/net/ethernet/altera/altera_tse_main.c +++ b/drivers/net/ethernet/altera/altera_tse_main.c @@ -853,7 +853,7 @@ static int init_phy(struct net_device *dev) return 0; } -static void tse_update_mac_addr(struct altera_tse_private *priv, u8 *addr) +static void tse_update_mac_addr(struct altera_tse_private *priv, const u8 *addr) { u32 msb; u32 lsb; diff --git a/drivers/net/ethernet/amd/nmclan_cs.c b/drivers/net/ethernet/amd/nmclan_cs.c index 8bd063e54ac3..0f961d7e7196 100644 --- a/drivers/net/ethernet/amd/nmclan_cs.c +++ b/drivers/net/ethernet/amd/nmclan_cs.c @@ -529,7 +529,8 @@ static void mace_write(mace_private *lp, unsigned int ioaddr, int reg, mace_init Resets the MACE chip. ---------------------------------------------------------------------------- */ -static int mace_init(mace_private *lp, unsigned int ioaddr, char *enet_addr) +static int mace_init(mace_private *lp, unsigned int ioaddr, + const char *enet_addr) { int i; int ct = 0; diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c index decc1c09a031..4030d619e84f 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c @@ -1087,7 +1087,7 @@ static int xgbe_add_mac_addresses(struct xgbe_prv_data *pdata) return 0; } -static int xgbe_set_mac_address(struct xgbe_prv_data *pdata, u8 *addr) +static int xgbe_set_mac_address(struct xgbe_prv_data *pdata, const u8 *addr) { unsigned int mac_addr_hi, mac_addr_lo; diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h b/drivers/net/ethernet/amd/xgbe/xgbe.h index e0b8f3c4cc0b..497c4ec6089a 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe.h +++ b/drivers/net/ethernet/amd/xgbe/xgbe.h @@ -730,7 +730,7 @@ struct xgbe_ext_stats { struct xgbe_hw_if { int (*tx_complete)(struct xgbe_ring_desc *); - int (*set_mac_address)(struct xgbe_prv_data *, u8 *addr); + int (*set_mac_address)(struct xgbe_prv_data *, const u8 *addr); int (*config_rx_mode)(struct xgbe_prv_data *); int (*enable_rx_csum)(struct xgbe_prv_data *); diff --git a/drivers/net/ethernet/apm/xgene-v2/mac.c b/drivers/net/ethernet/apm/xgene-v2/mac.c index 2da979e4fad1..6423e22e05b2 100644 --- a/drivers/net/ethernet/apm/xgene-v2/mac.c +++ b/drivers/net/ethernet/apm/xgene-v2/mac.c @@ -65,7 +65,7 @@ void xge_mac_set_speed(struct xge_pdata *pdata) void xge_mac_set_station_addr(struct xge_pdata *pdata) { - u8 *dev_addr = pdata->ndev->dev_addr; + const u8 *dev_addr = pdata->ndev->dev_addr; u32 addr0, addr1; addr0 = (dev_addr[3] << 24) | (dev_addr[2] << 16) | diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c index 5f657879134e..e641dbbea1e2 100644 --- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c @@ -378,8 +378,8 @@ u32 xgene_enet_rd_stat(struct xgene_enet_pdata *pdata, u32 rd_addr) static void xgene_gmac_set_mac_addr(struct xgene_enet_pdata *pdata) { + const u8 *dev_addr = pdata->ndev->dev_addr; u32 addr0, addr1; - u8 *dev_addr = pdata->ndev->dev_addr; addr0 = (dev_addr[3] << 24) | (dev_addr[2] << 16) | (dev_addr[1] << 8) | dev_addr[0]; diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c b/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c index f482ced2cadd..72b5e8eb0ec7 100644 --- a/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c @@ -165,8 +165,8 @@ static void xgene_sgmac_reset(struct xgene_enet_pdata *p) static void xgene_sgmac_set_mac_addr(struct xgene_enet_pdata *p) { + const u8 *dev_addr = p->ndev->dev_addr; u32 addr0, addr1; - u8 *dev_addr = p->ndev->dev_addr; addr0 = (dev_addr[3] << 24) | (dev_addr[2] << 16) | (dev_addr[1] << 8) | dev_addr[0]; diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c index 304b5d43f236..86607b79c09f 100644 --- a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c @@ -207,8 +207,8 @@ static void xgene_pcs_reset(struct xgene_enet_pdata *pdata) static void xgene_xgmac_set_mac_addr(struct xgene_enet_pdata *pdata) { + const u8 *dev_addr = pdata->ndev->dev_addr; u32 addr0, addr1; - u8 *dev_addr = pdata->ndev->dev_addr; addr0 = (dev_addr[3] << 24) | (dev_addr[2] << 16) | (dev_addr[1] << 8) | dev_addr[0]; diff --git a/drivers/net/ethernet/apple/bmac.c b/drivers/net/ethernet/apple/bmac.c index 7a966361d83f..4c513f7a36a8 100644 --- a/drivers/net/ethernet/apple/bmac.c +++ b/drivers/net/ethernet/apple/bmac.c @@ -308,7 +308,7 @@ bmac_init_registers(struct net_device *dev) { struct bmac_data *bp = netdev_priv(dev); volatile unsigned short regValue; - unsigned short *pWord16; + const unsigned short *pWord16; int i; /* XXDEBUG(("bmac: enter init_registers\n")); */ @@ -371,7 +371,7 @@ bmac_init_registers(struct net_device *dev) bmwrite(dev, BHASH1, bp->hash_table_mask[2]); /* bits 47 - 32 */ bmwrite(dev, BHASH0, bp->hash_table_mask[3]); /* bits 63 - 48 */ - pWord16 = (unsigned short *)dev->dev_addr; + pWord16 = (const unsigned short *)dev->dev_addr; bmwrite(dev, MADD0, *pWord16++); bmwrite(dev, MADD1, *pWord16++); bmwrite(dev, MADD2, *pWord16); @@ -522,7 +522,7 @@ static int bmac_set_address(struct net_device *dev, void *addr) { struct bmac_data *bp = netdev_priv(dev); unsigned char *p = addr; - unsigned short *pWord16; + const unsigned short *pWord16; unsigned long flags; int i; @@ -533,7 +533,7 @@ static int bmac_set_address(struct net_device *dev, void *addr) dev->dev_addr[i] = p[i]; } /* load up the hardware address */ - pWord16 = (unsigned short *)dev->dev_addr; + pWord16 = (const unsigned short *)dev->dev_addr; bmwrite(dev, MADD0, *pWord16++); bmwrite(dev, MADD1, *pWord16++); bmwrite(dev, MADD2, *pWord16); diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h index 7442850ca95f..dbd284660135 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h +++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h @@ -219,7 +219,7 @@ struct aq_hw_ops { int (*hw_ring_tx_head_update)(struct aq_hw_s *self, struct aq_ring_s *aq_ring); - int (*hw_set_mac_address)(struct aq_hw_s *self, u8 *mac_addr); + int (*hw_set_mac_address)(struct aq_hw_s *self, const u8 *mac_addr); int (*hw_soft_reset)(struct aq_hw_s *self); @@ -228,7 +228,7 @@ struct aq_hw_ops { int (*hw_reset)(struct aq_hw_s *self); - int (*hw_init)(struct aq_hw_s *self, u8 *mac_addr); + int (*hw_init)(struct aq_hw_s *self, const u8 *mac_addr); int (*hw_start)(struct aq_hw_s *self); @@ -375,7 +375,7 @@ struct aq_fw_ops { int (*set_phyloopback)(struct aq_hw_s *self, u32 mode, bool enable); int (*set_power)(struct aq_hw_s *self, unsigned int power_state, - u8 *mac); + const u8 *mac); int (*send_fw_request)(struct aq_hw_s *self, const struct hw_fw_request_iface *fw_req, diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_macsec.c b/drivers/net/ethernet/aquantia/atlantic/aq_macsec.c index ee823a18294c..958b7f8c77d9 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_macsec.c +++ b/drivers/net/ethernet/aquantia/atlantic/aq_macsec.c @@ -35,7 +35,7 @@ static int aq_apply_macsec_cfg(struct aq_nic_s *nic); static int aq_apply_secy_cfg(struct aq_nic_s *nic, const struct macsec_secy *secy); -static void aq_ether_addr_to_mac(u32 mac[2], unsigned char *emac) +static void aq_ether_addr_to_mac(u32 mac[2], const unsigned char *emac) { u32 tmp[2] = { 0 }; diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c index 611875ef2cd1..4625ccb79499 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c @@ -322,7 +322,7 @@ static int hw_atl_a0_hw_init_rx_path(struct aq_hw_s *self) return aq_hw_err_from_flags(self); } -static int hw_atl_a0_hw_mac_addr_set(struct aq_hw_s *self, u8 *mac_addr) +static int hw_atl_a0_hw_mac_addr_set(struct aq_hw_s *self, const u8 *mac_addr) { unsigned int h = 0U; unsigned int l = 0U; @@ -348,7 +348,7 @@ err_exit: return err; } -static int hw_atl_a0_hw_init(struct aq_hw_s *self, u8 *mac_addr) +static int hw_atl_a0_hw_init(struct aq_hw_s *self, const u8 *mac_addr) { static u32 aq_hw_atl_igcr_table_[4][2] = { [AQ_HW_IRQ_INVALID] = { 0x20000000U, 0x20000000U }, diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c index 45c17c585d74..15ede7285fb5 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c @@ -533,7 +533,7 @@ static int hw_atl_b0_hw_init_rx_path(struct aq_hw_s *self) return aq_hw_err_from_flags(self); } -int hw_atl_b0_hw_mac_addr_set(struct aq_hw_s *self, u8 *mac_addr) +int hw_atl_b0_hw_mac_addr_set(struct aq_hw_s *self, const u8 *mac_addr) { unsigned int h = 0U; unsigned int l = 0U; @@ -558,7 +558,7 @@ err_exit: return err; } -static int hw_atl_b0_hw_init(struct aq_hw_s *self, u8 *mac_addr) +static int hw_atl_b0_hw_init(struct aq_hw_s *self, const u8 *mac_addr) { static u32 aq_hw_atl_igcr_table_[4][2] = { [AQ_HW_IRQ_INVALID] = { 0x20000000U, 0x20000000U }, diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.h index d8db972113ec..5298846dd9f7 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.h +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.h @@ -58,7 +58,7 @@ int hw_atl_b0_hw_ring_rx_stop(struct aq_hw_s *self, struct aq_ring_s *ring); void hw_atl_b0_hw_init_rx_rss_ctrl1(struct aq_hw_s *self); -int hw_atl_b0_hw_mac_addr_set(struct aq_hw_s *self, u8 *mac_addr); +int hw_atl_b0_hw_mac_addr_set(struct aq_hw_s *self, const u8 *mac_addr); int hw_atl_b0_set_fc(struct aq_hw_s *self, u32 fc, u32 tc); int hw_atl_b0_set_loopback(struct aq_hw_s *self, u32 mode, bool enable); diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c index 65b9e5846be4..7e88d7234b14 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c @@ -965,7 +965,7 @@ u32 hw_atl_utils_get_fw_version(struct aq_hw_s *self) } static int aq_fw1x_set_wake_magic(struct aq_hw_s *self, bool wol_enabled, - u8 *mac) + const u8 *mac) { struct hw_atl_utils_fw_rpc *prpc = NULL; unsigned int rpc_size = 0U; @@ -1008,7 +1008,7 @@ err_exit: } static int aq_fw1x_set_power(struct aq_hw_s *self, unsigned int power_state, - u8 *mac) + const u8 *mac) { struct hw_atl_utils_fw_rpc *prpc = NULL; unsigned int rpc_size = 0U; diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c index 05086f0040fd..4d4cfbc91e19 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c @@ -355,7 +355,7 @@ static int aq_fw2x_get_phy_temp(struct aq_hw_s *self, int *temp) return 0; } -static int aq_fw2x_set_wol(struct aq_hw_s *self, u8 *mac) +static int aq_fw2x_set_wol(struct aq_hw_s *self, const u8 *mac) { struct hw_atl_utils_fw_rpc *rpc = NULL; struct offload_info *info = NULL; @@ -401,7 +401,7 @@ err_exit: } static int aq_fw2x_set_power(struct aq_hw_s *self, unsigned int power_state, - u8 *mac) + const u8 *mac) { int err = 0; diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c index c76ccdc77ba6..5dfc751572ed 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c @@ -530,7 +530,7 @@ static int hw_atl2_hw_init_rx_path(struct aq_hw_s *self) return aq_hw_err_from_flags(self); } -static int hw_atl2_hw_init(struct aq_hw_s *self, u8 *mac_addr) +static int hw_atl2_hw_init(struct aq_hw_s *self, const u8 *mac_addr) { static u32 aq_hw_atl2_igcr_table_[4][2] = { [AQ_HW_IRQ_INVALID] = { 0x20000000U, 0x20000000U }, diff --git a/drivers/net/ethernet/broadcom/b44.c b/drivers/net/ethernet/broadcom/b44.c index fa784953c601..485d32dda56f 100644 --- a/drivers/net/ethernet/broadcom/b44.c +++ b/drivers/net/ethernet/broadcom/b44.c @@ -218,7 +218,8 @@ static inline void __b44_cam_read(struct b44 *bp, unsigned char *data, int index data[1] = (val >> 0) & 0xFF; } -static inline void __b44_cam_write(struct b44 *bp, unsigned char *data, int index) +static inline void __b44_cam_write(struct b44 *bp, + const unsigned char *data, int index) { u32 val; @@ -1507,7 +1508,8 @@ static void bwfilter_table(struct b44 *bp, u8 *pp, u32 bytes, u32 table_offset) } } -static int b44_magic_pattern(u8 *macaddr, u8 *ppattern, u8 *pmask, int offset) +static int b44_magic_pattern(const u8 *macaddr, u8 *ppattern, u8 *pmask, + int offset) { int magicsync = 6; int k, j, len = offset; diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c index 25466d73b432..93c965bcdb6c 100644 --- a/drivers/net/ethernet/broadcom/bcmsysport.c +++ b/drivers/net/ethernet/broadcom/bcmsysport.c @@ -1820,7 +1820,7 @@ static inline void umac_reset(struct bcm_sysport_priv *priv) } static void umac_set_hw_addr(struct bcm_sysport_priv *priv, - unsigned char *addr) + const unsigned char *addr) { u32 mac0 = (addr[0] << 24) | (addr[1] << 16) | (addr[2] << 8) | addr[3]; diff --git a/drivers/net/ethernet/broadcom/bgmac.c b/drivers/net/ethernet/broadcom/bgmac.c index c691635cf4eb..3b42674b9df6 100644 --- a/drivers/net/ethernet/broadcom/bgmac.c +++ b/drivers/net/ethernet/broadcom/bgmac.c @@ -768,7 +768,7 @@ static void bgmac_umac_cmd_maskset(struct bgmac *bgmac, u32 mask, u32 set, udelay(2); } -static void bgmac_write_mac_address(struct bgmac *bgmac, u8 *addr) +static void bgmac_write_mac_address(struct bgmac *bgmac, const u8 *addr) { u32 tmp; diff --git a/drivers/net/ethernet/broadcom/bnx2.c b/drivers/net/ethernet/broadcom/bnx2.c index 9d70d908c064..cf4535f8b344 100644 --- a/drivers/net/ethernet/broadcom/bnx2.c +++ b/drivers/net/ethernet/broadcom/bnx2.c @@ -2704,7 +2704,7 @@ bnx2_alloc_bad_rbuf(struct bnx2 *bp) } static void -bnx2_set_mac_addr(struct bnx2 *bp, u8 *mac_addr, u32 pos) +bnx2_set_mac_addr(struct bnx2 *bp, const u8 *mac_addr, u32 pos) { u32 val; diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h index 9e79bcfb365f..2209d99b3404 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h @@ -2002,7 +2002,7 @@ int bnx2x_idle_chk(struct bnx2x *bp); * operation has been successfully scheduled and a negative - if a requested * operations has failed. */ -int bnx2x_set_mac_one(struct bnx2x *bp, u8 *mac, +int bnx2x_set_mac_one(struct bnx2x *bp, const u8 *mac, struct bnx2x_vlan_mac_obj *obj, bool set, int mac_type, unsigned long *ramrod_flags); diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index 9c26c46771f5..ed20a5945885 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -8428,7 +8428,7 @@ alloc_mem_err: * Init service functions */ -int bnx2x_set_mac_one(struct bnx2x *bp, u8 *mac, +int bnx2x_set_mac_one(struct bnx2x *bp, const u8 *mac, struct bnx2x_vlan_mac_obj *obj, bool set, int mac_type, unsigned long *ramrod_flags) { @@ -9157,7 +9157,7 @@ u32 bnx2x_send_unload_req(struct bnx2x *bp, int unload_mode) else if (bp->wol) { u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0; - u8 *mac_addr = bp->dev->dev_addr; + const u8 *mac_addr = bp->dev->dev_addr; struct pci_dev *pdev = bp->pdev; u32 val; u16 pmc; diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h index 966d5722c5e2..8c2cf5519787 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h @@ -508,7 +508,8 @@ int bnx2x_vfpf_init(struct bnx2x *bp); void bnx2x_vfpf_close_vf(struct bnx2x *bp); int bnx2x_vfpf_setup_q(struct bnx2x *bp, struct bnx2x_fastpath *fp, bool is_leading); -int bnx2x_vfpf_config_mac(struct bnx2x *bp, u8 *addr, u8 vf_qid, bool set); +int bnx2x_vfpf_config_mac(struct bnx2x *bp, const u8 *addr, u8 vf_qid, + bool set); int bnx2x_vfpf_config_rss(struct bnx2x *bp, struct bnx2x_config_rss_params *params); int bnx2x_vfpf_set_mcast(struct net_device *dev); diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c index ea0e9394f898..05d861679a02 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c @@ -722,7 +722,7 @@ out: } /* request pf to add a mac for the vf */ -int bnx2x_vfpf_config_mac(struct bnx2x *bp, u8 *addr, u8 vf_qid, bool set) +int bnx2x_vfpf_config_mac(struct bnx2x *bp, const u8 *addr, u8 vf_qid, bool set) { struct vfpf_set_q_filters_tlv *req = &bp->vf2pf_mbox->req.set_q_filters; struct pfvf_general_resp_tlv *resp = &bp->vf2pf_mbox->resp.general_resp; diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 4cb22e406052..42fa21829529 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -4882,7 +4882,7 @@ static int bnxt_hwrm_cfa_ntuple_filter_alloc(struct bnxt *bp, #endif static int bnxt_hwrm_set_vnic_filter(struct bnxt *bp, u16 vnic_id, u16 idx, - u8 *mac_addr) + const u8 *mac_addr) { struct hwrm_cfa_l2_filter_alloc_output *resp; struct hwrm_cfa_l2_filter_alloc_input *req; diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c index 78763f5027d1..7de7101d5389 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c @@ -1151,7 +1151,7 @@ void bnxt_hwrm_exec_fwd_req(struct bnxt *bp) } } -int bnxt_approve_mac(struct bnxt *bp, u8 *mac, bool strict) +int bnxt_approve_mac(struct bnxt *bp, const u8 *mac, bool strict) { struct hwrm_func_vf_cfg_input *req; int rc = 0; @@ -1246,7 +1246,7 @@ void bnxt_update_vf_mac(struct bnxt *bp) { } -int bnxt_approve_mac(struct bnxt *bp, u8 *mac, bool strict) +int bnxt_approve_mac(struct bnxt *bp, const u8 *mac, bool strict) { return 0; } diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.h index 995535e4c11b..9a4bacba477b 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.h @@ -41,5 +41,5 @@ int bnxt_cfg_hw_sriov(struct bnxt *bp, int *num_vfs, bool reset); void bnxt_sriov_disable(struct bnxt *); void bnxt_hwrm_exec_fwd_req(struct bnxt *); void bnxt_update_vf_mac(struct bnxt *); -int bnxt_approve_mac(struct bnxt *, u8 *, bool); +int bnxt_approve_mac(struct bnxt *, const u8 *, bool); #endif diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c index e036a244b78b..f6a553e5df25 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c @@ -3239,7 +3239,7 @@ static void bcmgenet_umac_reset(struct bcmgenet_priv *priv) } static void bcmgenet_set_hw_addr(struct bcmgenet_priv *priv, - unsigned char *addr) + const unsigned char *addr) { bcmgenet_umac_writel(priv, get_unaligned_be32(&addr[0]), UMAC_MAC0); bcmgenet_umac_writel(priv, get_unaligned_be16(&addr[4]), UMAC_MAC1); @@ -3537,7 +3537,7 @@ static void bcmgenet_timeout(struct net_device *dev, unsigned int txqueue) #define MAX_MDF_FILTER 17 static inline void bcmgenet_set_mdf_addr(struct bcmgenet_priv *priv, - unsigned char *addr, + const unsigned char *addr, int *i) { bcmgenet_umac_writel(priv, addr[0] << 8 | addr[1], diff --git a/drivers/net/ethernet/calxeda/xgmac.c b/drivers/net/ethernet/calxeda/xgmac.c index b6a066404f4b..9695c261d18f 100644 --- a/drivers/net/ethernet/calxeda/xgmac.c +++ b/drivers/net/ethernet/calxeda/xgmac.c @@ -607,7 +607,7 @@ static inline void xgmac_mac_disable(void __iomem *ioaddr) writel(value, ioaddr + XGMAC_CONTROL); } -static void xgmac_set_mac_addr(void __iomem *ioaddr, unsigned char *addr, +static void xgmac_set_mac_addr(void __iomem *ioaddr, const unsigned char *addr, int num) { u32 data; diff --git a/drivers/net/ethernet/chelsio/cxgb/gmac.h b/drivers/net/ethernet/chelsio/cxgb/gmac.h index dfa77491a910..5913eaf442b5 100644 --- a/drivers/net/ethernet/chelsio/cxgb/gmac.h +++ b/drivers/net/ethernet/chelsio/cxgb/gmac.h @@ -117,7 +117,7 @@ struct cmac_ops { const struct cmac_statistics *(*statistics_update)(struct cmac *, int); int (*macaddress_get)(struct cmac *, u8 mac_addr[6]); - int (*macaddress_set)(struct cmac *, u8 mac_addr[6]); + int (*macaddress_set)(struct cmac *, const u8 mac_addr[6]); }; typedef struct _cmac_instance cmac_instance; diff --git a/drivers/net/ethernet/chelsio/cxgb/pm3393.c b/drivers/net/ethernet/chelsio/cxgb/pm3393.c index c27908e66f5e..0bb37e4680c7 100644 --- a/drivers/net/ethernet/chelsio/cxgb/pm3393.c +++ b/drivers/net/ethernet/chelsio/cxgb/pm3393.c @@ -496,7 +496,7 @@ static int pm3393_macaddress_get(struct cmac *cmac, u8 mac_addr[6]) return 0; } -static int pm3393_macaddress_set(struct cmac *cmac, u8 ma[6]) +static int pm3393_macaddress_set(struct cmac *cmac, const u8 ma[6]) { u32 val, lo, mid, hi, enabled = cmac->instance->enabled; diff --git a/drivers/net/ethernet/chelsio/cxgb/vsc7326.c b/drivers/net/ethernet/chelsio/cxgb/vsc7326.c index 873c1c7b4ca0..81317a9baf1a 100644 --- a/drivers/net/ethernet/chelsio/cxgb/vsc7326.c +++ b/drivers/net/ethernet/chelsio/cxgb/vsc7326.c @@ -379,7 +379,7 @@ static int mac_intr_clear(struct cmac *mac) } /* Expect MAC address to be in network byte order. */ -static int mac_set_address(struct cmac* mac, u8 addr[6]) +static int mac_set_address(struct cmac* mac, const u8 addr[6]) { u32 val; int port = mac->instance->index; diff --git a/drivers/net/ethernet/chelsio/cxgb3/common.h b/drivers/net/ethernet/chelsio/cxgb3/common.h index b706f2fbe4f4..a309016f7f8c 100644 --- a/drivers/net/ethernet/chelsio/cxgb3/common.h +++ b/drivers/net/ethernet/chelsio/cxgb3/common.h @@ -710,7 +710,7 @@ int t3_mac_enable(struct cmac *mac, int which); int t3_mac_disable(struct cmac *mac, int which); int t3_mac_set_mtu(struct cmac *mac, unsigned int mtu); int t3_mac_set_rx_mode(struct cmac *mac, struct net_device *dev); -int t3_mac_set_address(struct cmac *mac, unsigned int idx, u8 addr[6]); +int t3_mac_set_address(struct cmac *mac, unsigned int idx, const u8 addr[6]); int t3_mac_set_num_ucast(struct cmac *mac, int n); const struct mac_stats *t3_mac_update_stats(struct cmac *mac); int t3_mac_set_speed_duplex_fc(struct cmac *mac, int speed, int duplex, int fc); diff --git a/drivers/net/ethernet/chelsio/cxgb3/xgmac.c b/drivers/net/ethernet/chelsio/cxgb3/xgmac.c index 3af19a550372..1bdc6cad1e49 100644 --- a/drivers/net/ethernet/chelsio/cxgb3/xgmac.c +++ b/drivers/net/ethernet/chelsio/cxgb3/xgmac.c @@ -240,7 +240,7 @@ static void set_addr_filter(struct cmac *mac, int idx, const u8 * addr) } /* Set one of the station's unicast MAC addresses. */ -int t3_mac_set_address(struct cmac *mac, unsigned int idx, u8 addr[6]) +int t3_mac_set_address(struct cmac *mac, unsigned int idx, const u8 addr[6]) { if (idx >= mac->nucast) return -EINVAL; diff --git a/drivers/net/ethernet/cisco/enic/enic_pp.c b/drivers/net/ethernet/cisco/enic/enic_pp.c index e6a83198c3dd..80f46dbd5117 100644 --- a/drivers/net/ethernet/cisco/enic/enic_pp.c +++ b/drivers/net/ethernet/cisco/enic/enic_pp.c @@ -73,9 +73,9 @@ static int enic_set_port_profile(struct enic *enic, int vf) struct vic_provinfo *vp; const u8 oui[3] = VIC_PROVINFO_CISCO_OUI; const __be16 os_type = htons(VIC_GENERIC_PROV_OS_TYPE_LINUX); + const u8 *client_mac; char uuid_str[38]; char client_mac_str[18]; - u8 *client_mac; int err; ENIC_PP_BY_INDEX(enic, vf, pp, &err); diff --git a/drivers/net/ethernet/dlink/dl2k.c b/drivers/net/ethernet/dlink/dl2k.c index 202ecb132053..993bba0ffb16 100644 --- a/drivers/net/ethernet/dlink/dl2k.c +++ b/drivers/net/ethernet/dlink/dl2k.c @@ -567,7 +567,7 @@ static void rio_hw_init(struct net_device *dev) */ for (i = 0; i < 3; i++) dw16(StationAddr0 + 2 * i, - cpu_to_le16(((u16 *)dev->dev_addr)[i])); + cpu_to_le16(((const u16 *)dev->dev_addr)[i])); set_multicast (dev); if (np->coalesce) { diff --git a/drivers/net/ethernet/dnet.c b/drivers/net/ethernet/dnet.c index 14dc2e13bf03..667ef2b18047 100644 --- a/drivers/net/ethernet/dnet.c +++ b/drivers/net/ethernet/dnet.c @@ -60,11 +60,11 @@ static void __dnet_set_hwaddr(struct dnet *bp) { u16 tmp; - tmp = be16_to_cpup((__be16 *)bp->dev->dev_addr); + tmp = be16_to_cpup((const __be16 *)bp->dev->dev_addr); dnet_writew_mac(bp, DNET_INTERNAL_MAC_ADDR_0_REG, tmp); - tmp = be16_to_cpup((__be16 *)(bp->dev->dev_addr + 2)); + tmp = be16_to_cpup((const __be16 *)(bp->dev->dev_addr + 2)); dnet_writew_mac(bp, DNET_INTERNAL_MAC_ADDR_1_REG, tmp); - tmp = be16_to_cpup((__be16 *)(bp->dev->dev_addr + 4)); + tmp = be16_to_cpup((const __be16 *)(bp->dev->dev_addr + 4)); dnet_writew_mac(bp, DNET_INTERNAL_MAC_ADDR_2_REG, tmp); } diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c index 1288b5e3d220..b4f5e57d0285 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.c +++ b/drivers/net/ethernet/emulex/benet/be_cmds.c @@ -1080,7 +1080,7 @@ err: } /* Uses synchronous MCCQ */ -int be_cmd_pmac_add(struct be_adapter *adapter, u8 *mac_addr, +int be_cmd_pmac_add(struct be_adapter *adapter, const u8 *mac_addr, u32 if_id, u32 *pmac_id, u32 domain) { struct be_mcc_wrb *wrb; diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h index 9e17d6a7ab8c..e2085c68c0ee 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.h +++ b/drivers/net/ethernet/emulex/benet/be_cmds.h @@ -2385,7 +2385,7 @@ int be_pci_fnum_get(struct be_adapter *adapter); int be_fw_wait_ready(struct be_adapter *adapter); int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr, bool permanent, u32 if_handle, u32 pmac_id); -int be_cmd_pmac_add(struct be_adapter *adapter, u8 *mac_addr, u32 if_id, +int be_cmd_pmac_add(struct be_adapter *adapter, const u8 *mac_addr, u32 if_id, u32 *pmac_id, u32 domain); int be_cmd_pmac_del(struct be_adapter *adapter, u32 if_id, int pmac_id, u32 domain); diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index a61b368286e0..b91029db1f21 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -272,7 +272,7 @@ void be_cq_notify(struct be_adapter *adapter, u16 qid, bool arm, u16 num_popped) iowrite32(val, adapter->db + DB_CQ_OFFSET); } -static int be_dev_mac_add(struct be_adapter *adapter, u8 *mac) +static int be_dev_mac_add(struct be_adapter *adapter, const u8 *mac) { int i; diff --git a/drivers/net/ethernet/ethoc.c b/drivers/net/ethernet/ethoc.c index 7f456297fc45..b6c3c562107c 100644 --- a/drivers/net/ethernet/ethoc.c +++ b/drivers/net/ethernet/ethoc.c @@ -806,8 +806,8 @@ static int ethoc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) static void ethoc_do_set_mac_address(struct net_device *dev) { + const unsigned char *mac = dev->dev_addr; struct ethoc *priv = netdev_priv(dev); - unsigned char *mac = dev->dev_addr; ethoc_write(priv, MAC_ADDR0, (mac[2] << 24) | (mac[3] << 16) | (mac[4] << 8) | (mac[5] << 0)); diff --git a/drivers/net/ethernet/fealnx.c b/drivers/net/ethernet/fealnx.c index 819266d463b0..ab194c9b0691 100644 --- a/drivers/net/ethernet/fealnx.c +++ b/drivers/net/ethernet/fealnx.c @@ -827,7 +827,7 @@ static int netdev_open(struct net_device *dev) return -EAGAIN; for (i = 0; i < 3; i++) - iowrite16(((unsigned short*)dev->dev_addr)[i], + iowrite16(((const unsigned short *)dev->dev_addr)[i], ioaddr + PAR0 + i*2); init_ring(dev); diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c index fe5fc2b3406f..1766b7d94ffa 100644 --- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c +++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c @@ -272,7 +272,7 @@ static int dpaa_netdev_init(struct net_device *net_dev, } else { eth_hw_addr_random(net_dev); err = priv->mac_dev->change_addr(priv->mac_dev->fman_mac, - (enet_addr_t *)net_dev->dev_addr); + (const enet_addr_t *)net_dev->dev_addr); if (err) { dev_err(dev, "Failed to set random MAC address\n"); return -EINVAL; @@ -452,7 +452,7 @@ static int dpaa_set_mac_address(struct net_device *net_dev, void *addr) mac_dev = priv->mac_dev; err = mac_dev->change_addr(mac_dev->fman_mac, - (enet_addr_t *)net_dev->dev_addr); + (const enet_addr_t *)net_dev->dev_addr); if (err < 0) { netif_err(priv, drv, net_dev, "mac_dev->change_addr() = %d\n", err); diff --git a/drivers/net/ethernet/freescale/fman/fman_dtsec.c b/drivers/net/ethernet/freescale/fman/fman_dtsec.c index bce3c9398887..1950a8936bc0 100644 --- a/drivers/net/ethernet/freescale/fman/fman_dtsec.c +++ b/drivers/net/ethernet/freescale/fman/fman_dtsec.c @@ -366,7 +366,7 @@ static void set_dflts(struct dtsec_cfg *cfg) cfg->maximum_frame = DEFAULT_MAXIMUM_FRAME; } -static void set_mac_address(struct dtsec_regs __iomem *regs, u8 *adr) +static void set_mac_address(struct dtsec_regs __iomem *regs, const u8 *adr) { u32 tmp; @@ -516,7 +516,7 @@ static int init(struct dtsec_regs __iomem *regs, struct dtsec_cfg *cfg, if (addr) { MAKE_ENET_ADDR_FROM_UINT64(addr, eth_addr); - set_mac_address(regs, (u8 *)eth_addr); + set_mac_address(regs, (const u8 *)eth_addr); } /* HASH */ @@ -1022,7 +1022,7 @@ int dtsec_accept_rx_pause_frames(struct fman_mac *dtsec, bool en) return 0; } -int dtsec_modify_mac_address(struct fman_mac *dtsec, enet_addr_t *enet_addr) +int dtsec_modify_mac_address(struct fman_mac *dtsec, const enet_addr_t *enet_addr) { struct dtsec_regs __iomem *regs = dtsec->regs; enum comm_mode mode = COMM_MODE_NONE; @@ -1041,7 +1041,7 @@ int dtsec_modify_mac_address(struct fman_mac *dtsec, enet_addr_t *enet_addr) * Station address have to be swapped (big endian to little endian */ dtsec->addr = ENET_ADDR_TO_UINT64(*enet_addr); - set_mac_address(dtsec->regs, (u8 *)(*enet_addr)); + set_mac_address(dtsec->regs, (const u8 *)(*enet_addr)); graceful_start(dtsec, mode); diff --git a/drivers/net/ethernet/freescale/fman/fman_dtsec.h b/drivers/net/ethernet/freescale/fman/fman_dtsec.h index 5149d96ec2c1..68512c3bd6e5 100644 --- a/drivers/net/ethernet/freescale/fman/fman_dtsec.h +++ b/drivers/net/ethernet/freescale/fman/fman_dtsec.h @@ -37,7 +37,7 @@ struct fman_mac *dtsec_config(struct fman_mac_params *params); int dtsec_set_promiscuous(struct fman_mac *dtsec, bool new_val); -int dtsec_modify_mac_address(struct fman_mac *dtsec, enet_addr_t *enet_addr); +int dtsec_modify_mac_address(struct fman_mac *dtsec, const enet_addr_t *enet_addr); int dtsec_adjust_link(struct fman_mac *dtsec, u16 speed); int dtsec_restart_autoneg(struct fman_mac *dtsec); diff --git a/drivers/net/ethernet/freescale/fman/fman_memac.c b/drivers/net/ethernet/freescale/fman/fman_memac.c index 62f42921933d..2216b7f51d26 100644 --- a/drivers/net/ethernet/freescale/fman/fman_memac.c +++ b/drivers/net/ethernet/freescale/fman/fman_memac.c @@ -354,7 +354,7 @@ struct fman_mac { bool allmulti_enabled; }; -static void add_addr_in_paddr(struct memac_regs __iomem *regs, u8 *adr, +static void add_addr_in_paddr(struct memac_regs __iomem *regs, const u8 *adr, u8 paddr_num) { u32 tmp0, tmp1; @@ -897,12 +897,12 @@ int memac_accept_rx_pause_frames(struct fman_mac *memac, bool en) return 0; } -int memac_modify_mac_address(struct fman_mac *memac, enet_addr_t *enet_addr) +int memac_modify_mac_address(struct fman_mac *memac, const enet_addr_t *enet_addr) { if (!is_init_done(memac->memac_drv_param)) return -EINVAL; - add_addr_in_paddr(memac->regs, (u8 *)(*enet_addr), 0); + add_addr_in_paddr(memac->regs, (const u8 *)(*enet_addr), 0); return 0; } @@ -1058,7 +1058,7 @@ int memac_init(struct fman_mac *memac) /* MAC Address */ if (memac->addr != 0) { MAKE_ENET_ADDR_FROM_UINT64(memac->addr, eth_addr); - add_addr_in_paddr(memac->regs, (u8 *)eth_addr, 0); + add_addr_in_paddr(memac->regs, (const u8 *)eth_addr, 0); } fixed_link = memac_drv_param->fixed_link; diff --git a/drivers/net/ethernet/freescale/fman/fman_memac.h b/drivers/net/ethernet/freescale/fman/fman_memac.h index b2c671ec0ce7..3820f7a22983 100644 --- a/drivers/net/ethernet/freescale/fman/fman_memac.h +++ b/drivers/net/ethernet/freescale/fman/fman_memac.h @@ -40,7 +40,7 @@ struct fman_mac *memac_config(struct fman_mac_params *params); int memac_set_promiscuous(struct fman_mac *memac, bool new_val); -int memac_modify_mac_address(struct fman_mac *memac, enet_addr_t *enet_addr); +int memac_modify_mac_address(struct fman_mac *memac, const enet_addr_t *enet_addr); int memac_adjust_link(struct fman_mac *memac, u16 speed); int memac_cfg_max_frame_len(struct fman_mac *memac, u16 new_val); int memac_cfg_reset_on_init(struct fman_mac *memac, bool enable); diff --git a/drivers/net/ethernet/freescale/fman/fman_tgec.c b/drivers/net/ethernet/freescale/fman/fman_tgec.c index 41946b16f6c7..311c1906e044 100644 --- a/drivers/net/ethernet/freescale/fman/fman_tgec.c +++ b/drivers/net/ethernet/freescale/fman/fman_tgec.c @@ -221,7 +221,7 @@ struct fman_mac { bool allmulti_enabled; }; -static void set_mac_address(struct tgec_regs __iomem *regs, u8 *adr) +static void set_mac_address(struct tgec_regs __iomem *regs, const u8 *adr) { u32 tmp0, tmp1; @@ -514,13 +514,13 @@ int tgec_accept_rx_pause_frames(struct fman_mac *tgec, bool en) return 0; } -int tgec_modify_mac_address(struct fman_mac *tgec, enet_addr_t *p_enet_addr) +int tgec_modify_mac_address(struct fman_mac *tgec, const enet_addr_t *p_enet_addr) { if (!is_init_done(tgec->cfg)) return -EINVAL; tgec->addr = ENET_ADDR_TO_UINT64(*p_enet_addr); - set_mac_address(tgec->regs, (u8 *)(*p_enet_addr)); + set_mac_address(tgec->regs, (const u8 *)(*p_enet_addr)); return 0; } @@ -704,7 +704,7 @@ int tgec_init(struct fman_mac *tgec) if (tgec->addr) { MAKE_ENET_ADDR_FROM_UINT64(tgec->addr, eth_addr); - set_mac_address(tgec->regs, (u8 *)eth_addr); + set_mac_address(tgec->regs, (const u8 *)eth_addr); } /* interrupts */ diff --git a/drivers/net/ethernet/freescale/fman/fman_tgec.h b/drivers/net/ethernet/freescale/fman/fman_tgec.h index 3bfd1062b386..b28b20b26148 100644 --- a/drivers/net/ethernet/freescale/fman/fman_tgec.h +++ b/drivers/net/ethernet/freescale/fman/fman_tgec.h @@ -37,7 +37,7 @@ struct fman_mac *tgec_config(struct fman_mac_params *params); int tgec_set_promiscuous(struct fman_mac *tgec, bool new_val); -int tgec_modify_mac_address(struct fman_mac *tgec, enet_addr_t *enet_addr); +int tgec_modify_mac_address(struct fman_mac *tgec, const enet_addr_t *enet_addr); int tgec_cfg_max_frame_len(struct fman_mac *tgec, u16 new_val); int tgec_enable(struct fman_mac *tgec, enum comm_mode mode); int tgec_disable(struct fman_mac *tgec, enum comm_mode mode); diff --git a/drivers/net/ethernet/freescale/fman/mac.h b/drivers/net/ethernet/freescale/fman/mac.h index 824a81a9f350..daa285a9b8b2 100644 --- a/drivers/net/ethernet/freescale/fman/mac.h +++ b/drivers/net/ethernet/freescale/fman/mac.h @@ -66,7 +66,7 @@ struct mac_device { int (*stop)(struct mac_device *mac_dev); void (*adjust_link)(struct mac_device *mac_dev); int (*set_promisc)(struct fman_mac *mac_dev, bool enable); - int (*change_addr)(struct fman_mac *mac_dev, enet_addr_t *enet_addr); + int (*change_addr)(struct fman_mac *mac_dev, const enet_addr_t *enet_addr); int (*set_allmulti)(struct fman_mac *mac_dev, bool enable); int (*set_tstamp)(struct fman_mac *mac_dev, bool enable); int (*set_multi)(struct net_device *net_dev, diff --git a/drivers/net/ethernet/hisilicon/hisi_femac.c b/drivers/net/ethernet/hisilicon/hisi_femac.c index 05cb4582a58d..d881f8de74fc 100644 --- a/drivers/net/ethernet/hisilicon/hisi_femac.c +++ b/drivers/net/ethernet/hisilicon/hisi_femac.c @@ -427,7 +427,7 @@ static void hisi_femac_free_skb_rings(struct hisi_femac_priv *priv) } static int hisi_femac_set_hw_mac_addr(struct hisi_femac_priv *priv, - unsigned char *mac) + const unsigned char *mac) { u32 reg; diff --git a/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c b/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c index 923191b9a87d..b981b6cbe6ff 100644 --- a/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c +++ b/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c @@ -429,7 +429,7 @@ static void hix5hd2_port_disable(struct hix5hd2_priv *priv) static void hix5hd2_hw_set_mac_addr(struct net_device *dev) { struct hix5hd2_priv *priv = netdev_priv(dev); - unsigned char *mac = dev->dev_addr; + const unsigned char *mac = dev->dev_addr; u32 val; val = mac[1] | (mac[0] << 8); diff --git a/drivers/net/ethernet/hisilicon/hns/hnae.h b/drivers/net/ethernet/hisilicon/hns/hnae.h index 2b7db1c22321..3d6de4cfa9f7 100644 --- a/drivers/net/ethernet/hisilicon/hns/hnae.h +++ b/drivers/net/ethernet/hisilicon/hns/hnae.h @@ -499,7 +499,7 @@ struct hnae_ae_ops { u32 *tx_usecs_high, u32 *rx_usecs_high); void (*set_promisc_mode)(struct hnae_handle *handle, u32 en); int (*get_mac_addr)(struct hnae_handle *handle, void **p); - int (*set_mac_addr)(struct hnae_handle *handle, void *p); + int (*set_mac_addr)(struct hnae_handle *handle, const void *p); int (*add_uc_addr)(struct hnae_handle *handle, const unsigned char *addr); int (*rm_uc_addr)(struct hnae_handle *handle, diff --git a/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c b/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c index 75e4ec569da8..b13ee48b458c 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c @@ -207,7 +207,7 @@ static void hns_ae_fini_queue(struct hnae_queue *q) hns_rcb_reset_ring_hw(q); } -static int hns_ae_set_mac_address(struct hnae_handle *handle, void *p) +static int hns_ae_set_mac_address(struct hnae_handle *handle, const void *p) { int ret; struct hns_mac_cb *mac_cb = hns_get_mac_cb(handle); diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c index f387a859a201..8f391e2adcc0 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c @@ -450,7 +450,7 @@ static void hns_gmac_update_stats(void *mac_drv) += dsaf_read_dev(drv, GMAC_TX_PAUSE_FRAMES_REG); } -static void hns_gmac_set_mac_addr(void *mac_drv, char *mac_addr) +static void hns_gmac_set_mac_addr(void *mac_drv, const char *mac_addr) { struct mac_driver *drv = (struct mac_driver *)mac_drv; diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c index ec9a02495df4..236ee9b9d1e6 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c @@ -269,7 +269,7 @@ int hns_mac_get_inner_port_num(struct hns_mac_cb *mac_cb, u8 vmid, u8 *port_num) *@addr:mac address */ int hns_mac_change_vf_addr(struct hns_mac_cb *mac_cb, - u32 vmid, char *addr) + u32 vmid, const char *addr) { int ret; struct mac_driver *mac_ctrl_drv = hns_mac_get_drv(mac_cb); diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h index 8943ffab4418..e3bb05959ba9 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h @@ -348,7 +348,7 @@ struct mac_driver { /*disable mac when disable nic or dsaf*/ void (*mac_disable)(void *mac_drv, enum mac_commom_mode mode); /* config mac address*/ - void (*set_mac_addr)(void *mac_drv, char *mac_addr); + void (*set_mac_addr)(void *mac_drv, const char *mac_addr); /*adjust mac mode of port,include speed and duplex*/ int (*adjust_link)(void *mac_drv, enum mac_speed speed, u32 full_duplex); @@ -425,7 +425,8 @@ int hns_mac_init(struct dsaf_device *dsaf_dev); void mac_adjust_link(struct net_device *net_dev); bool hns_mac_need_adjust_link(struct hns_mac_cb *mac_cb, int speed, int duplex); void hns_mac_get_link_status(struct hns_mac_cb *mac_cb, u32 *link_status); -int hns_mac_change_vf_addr(struct hns_mac_cb *mac_cb, u32 vmid, char *addr); +int hns_mac_change_vf_addr(struct hns_mac_cb *mac_cb, u32 vmid, + const char *addr); int hns_mac_set_multi(struct hns_mac_cb *mac_cb, u32 port_num, char *addr, bool enable); int hns_mac_vm_config_bc_en(struct hns_mac_cb *mac_cb, u32 vm, bool enable); diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c index 401fef5f1d07..fc26ffaae620 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c @@ -255,7 +255,7 @@ static void hns_xgmac_pausefrm_cfg(void *mac_drv, u32 rx_en, u32 tx_en) dsaf_write_dev(drv, XGMAC_MAC_PAUSE_CTRL_REG, origin); } -static void hns_xgmac_set_pausefrm_mac_addr(void *mac_drv, char *mac_addr) +static void hns_xgmac_set_pausefrm_mac_addr(void *mac_drv, const char *mac_addr) { struct mac_driver *drv = (struct mac_driver *)mac_drv; diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index 695e299f534d..b51afb83d023 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -590,7 +590,7 @@ struct hnae3_ae_ops { u32 *tx_usecs_high, u32 *rx_usecs_high); void (*get_mac_addr)(struct hnae3_handle *handle, u8 *p); - int (*set_mac_addr)(struct hnae3_handle *handle, void *p, + int (*set_mac_addr)(struct hnae3_handle *handle, const void *p, bool is_first); int (*do_ioctl)(struct hnae3_handle *handle, struct ifreq *ifr, int cmd); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 9e33f0f0b75d..12274c2b9fea 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -9444,7 +9444,7 @@ int hclge_update_mac_node_for_dev_addr(struct hclge_vport *vport, return 0; } -static int hclge_set_mac_addr(struct hnae3_handle *handle, void *p, +static int hclge_set_mac_addr(struct hnae3_handle *handle, const void *p, bool is_first) { const unsigned char *new_addr = (const unsigned char *)p; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c index 880feeac0637..bd8468c2d9a6 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c @@ -1349,7 +1349,7 @@ static void hclgevf_get_mac_addr(struct hnae3_handle *handle, u8 *p) ether_addr_copy(p, hdev->hw.mac.mac_addr); } -static int hclgevf_set_mac_addr(struct hnae3_handle *handle, void *p, +static int hclgevf_set_mac_addr(struct hnae3_handle *handle, const void *p, bool is_first) { struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle); diff --git a/drivers/net/ethernet/i825xx/sun3_82586.c b/drivers/net/ethernet/i825xx/sun3_82586.c index 0696f723228a..18d32302c3c7 100644 --- a/drivers/net/ethernet/i825xx/sun3_82586.c +++ b/drivers/net/ethernet/i825xx/sun3_82586.c @@ -461,7 +461,7 @@ static int init586(struct net_device *dev) ias_cmd->cmd_cmd = swab16(CMD_IASETUP | CMD_LAST); ias_cmd->cmd_link = 0xffff; - memcpy((char *)&ias_cmd->iaddr,(char *) dev->dev_addr,ETH_ALEN); + memcpy((char *)&ias_cmd->iaddr,(const char *) dev->dev_addr,ETH_ALEN); p->scb->cbl_offset = make16(ias_cmd); diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index 22802222d34d..453a85410634 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -437,7 +437,7 @@ static inline bool i40e_is_channel_macvlan(struct i40e_channel *ch) return !!ch->fwd; } -static inline u8 *i40e_channel_mac(struct i40e_channel *ch) +static inline const u8 *i40e_channel_mac(struct i40e_channel *ch) { if (i40e_is_channel_macvlan(ch)) return ch->fwd->netdev->dev_addr; diff --git a/drivers/net/ethernet/intel/ixgb/ixgb_hw.c b/drivers/net/ethernet/intel/ixgb/ixgb_hw.c index a430871d1c27..c8d1e815ec6b 100644 --- a/drivers/net/ethernet/intel/ixgb/ixgb_hw.c +++ b/drivers/net/ethernet/intel/ixgb/ixgb_hw.c @@ -549,7 +549,7 @@ ixgb_mta_set(struct ixgb_hw *hw, *****************************************************************************/ void ixgb_rar_set(struct ixgb_hw *hw, - u8 *addr, + const u8 *addr, u32 index) { u32 rar_low, rar_high; diff --git a/drivers/net/ethernet/intel/ixgb/ixgb_hw.h b/drivers/net/ethernet/intel/ixgb/ixgb_hw.h index 6064583095da..70bcff5fb3db 100644 --- a/drivers/net/ethernet/intel/ixgb/ixgb_hw.h +++ b/drivers/net/ethernet/intel/ixgb/ixgb_hw.h @@ -740,7 +740,7 @@ bool ixgb_adapter_start(struct ixgb_hw *hw); void ixgb_check_for_link(struct ixgb_hw *hw); bool ixgb_check_for_bad_link(struct ixgb_hw *hw); -void ixgb_rar_set(struct ixgb_hw *hw, u8 *addr, u32 index); +void ixgb_rar_set(struct ixgb_hw *hw, const u8 *addr, u32 index); /* Filters (multicast, vlan, receive) */ void ixgb_mc_addr_list_update(struct ixgb_hw *hw, u8 *mc_addr_list, diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c index fc67e9d31f6d..d37a0fba3d16 100644 --- a/drivers/net/ethernet/marvell/mv643xx_eth.c +++ b/drivers/net/ethernet/marvell/mv643xx_eth.c @@ -1770,7 +1770,7 @@ static void uc_addr_get(struct mv643xx_eth_private *mp, unsigned char *addr) addr[5] = mac_l & 0xff; } -static void uc_addr_set(struct mv643xx_eth_private *mp, unsigned char *addr) +static void uc_addr_set(struct mv643xx_eth_private *mp, const u8 *addr) { wrlp(mp, MAC_ADDR_HIGH, (addr[0] << 24) | (addr[1] << 16) | (addr[2] << 8) | addr[3]); diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c index 5fa81322a44b..3f124268bd4d 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c @@ -1623,8 +1623,8 @@ static void mvneta_set_ucast_addr(struct mvneta_port *pp, u8 last_nibble, } /* Set mac address */ -static void mvneta_mac_addr_set(struct mvneta_port *pp, unsigned char *addr, - int queue) +static void mvneta_mac_addr_set(struct mvneta_port *pp, + const unsigned char *addr, int queue) { unsigned int mac_h; unsigned int mac_l; diff --git a/drivers/net/ethernet/marvell/pxa168_eth.c b/drivers/net/ethernet/marvell/pxa168_eth.c index 8ebd13f089db..11ef1d8dea15 100644 --- a/drivers/net/ethernet/marvell/pxa168_eth.c +++ b/drivers/net/ethernet/marvell/pxa168_eth.c @@ -389,7 +389,7 @@ static void inverse_every_nibble(unsigned char *mac_addr) * Outputs * return the calculated entry. */ -static u32 hash_function(unsigned char *mac_addr_orig) +static u32 hash_function(const unsigned char *mac_addr_orig) { u32 hash_result; u32 addr0; @@ -434,7 +434,7 @@ static u32 hash_function(unsigned char *mac_addr_orig) * -ENOSPC if table full */ static int add_del_hash_entry(struct pxa168_eth_private *pep, - unsigned char *mac_addr, + const unsigned char *mac_addr, u32 rd, u32 skip, int del) { struct addr_table_entry *entry, *start; @@ -521,7 +521,7 @@ static int add_del_hash_entry(struct pxa168_eth_private *pep, */ static void update_hash_table_mac_address(struct pxa168_eth_private *pep, unsigned char *oaddr, - unsigned char *addr) + const unsigned char *addr) { /* Delete old entry */ if (oaddr) diff --git a/drivers/net/ethernet/mediatek/mtk_star_emac.c b/drivers/net/ethernet/mediatek/mtk_star_emac.c index 8f3493e146e5..67f9e4415ae9 100644 --- a/drivers/net/ethernet/mediatek/mtk_star_emac.c +++ b/drivers/net/ethernet/mediatek/mtk_star_emac.c @@ -522,7 +522,7 @@ static void mtk_star_dma_resume_tx(struct mtk_star_priv *priv) static void mtk_star_set_mac_addr(struct net_device *ndev) { struct mtk_star_priv *priv = netdev_priv(ndev); - u8 *mac_addr = ndev->dev_addr; + const u8 *mac_addr = ndev->dev_addr; unsigned int high, low; high = mac_addr[0] << 8 | mac_addr[1] << 0; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c index d226cc5ab1d1..aeff1d972a46 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c @@ -71,12 +71,12 @@ struct mlx5e_l2_hash_node { bool mpfs; }; -static inline int mlx5e_hash_l2(u8 *addr) +static inline int mlx5e_hash_l2(const u8 *addr) { return addr[5]; } -static void mlx5e_add_l2_to_hash(struct hlist_head *hash, u8 *addr) +static void mlx5e_add_l2_to_hash(struct hlist_head *hash, const u8 *addr) { struct mlx5e_l2_hash_node *hn; int ix = mlx5e_hash_l2(addr); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c index 10940b8dc83e..8ffc69e57dc6 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c @@ -223,7 +223,7 @@ void mlx5i_uninit_underlay_qp(struct mlx5e_priv *priv) int mlx5i_create_underlay_qp(struct mlx5e_priv *priv) { - unsigned char *dev_addr = priv->netdev->dev_addr; + const unsigned char *dev_addr = priv->netdev->dev_addr; u32 out[MLX5_ST_SZ_DW(create_qp_out)] = {}; u32 in[MLX5_ST_SZ_DW(create_qp_in)] = {}; struct mlx5i_priv *ipriv = priv->ppriv; diff --git a/drivers/net/ethernet/micrel/ks8842.c b/drivers/net/ethernet/micrel/ks8842.c index b27713906d3a..b639557dbdc6 100644 --- a/drivers/net/ethernet/micrel/ks8842.c +++ b/drivers/net/ethernet/micrel/ks8842.c @@ -380,7 +380,7 @@ static void ks8842_read_mac_addr(struct ks8842_adapter *adapter, u8 *dest) } } -static void ks8842_write_mac_addr(struct ks8842_adapter *adapter, u8 *mac) +static void ks8842_write_mac_addr(struct ks8842_adapter *adapter, const u8 *mac) { unsigned long flags; unsigned i; diff --git a/drivers/net/ethernet/micrel/ksz884x.c b/drivers/net/ethernet/micrel/ksz884x.c index f56bcd3e36d2..4de7ac046265 100644 --- a/drivers/net/ethernet/micrel/ksz884x.c +++ b/drivers/net/ethernet/micrel/ksz884x.c @@ -4033,7 +4033,7 @@ static void hw_set_add_addr(struct ksz_hw *hw) } } -static int hw_add_addr(struct ksz_hw *hw, u8 *mac_addr) +static int hw_add_addr(struct ksz_hw *hw, const u8 *mac_addr) { int i; int j = ADDITIONAL_ENTRIES; @@ -4054,7 +4054,7 @@ static int hw_add_addr(struct ksz_hw *hw, u8 *mac_addr) return -1; } -static int hw_del_addr(struct ksz_hw *hw, u8 *mac_addr) +static int hw_del_addr(struct ksz_hw *hw, const u8 *mac_addr) { int i; diff --git a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c index 97c2604df019..e6f18e004036 100644 --- a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c +++ b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c @@ -796,7 +796,8 @@ static int myri10ge_load_firmware(struct myri10ge_priv *mgp, int adopt) return status; } -static int myri10ge_update_mac_address(struct myri10ge_priv *mgp, u8 * addr) +static int myri10ge_update_mac_address(struct myri10ge_priv *mgp, + const u8 * addr) { struct myri10ge_cmd cmd; int status; diff --git a/drivers/net/ethernet/neterion/s2io.c b/drivers/net/ethernet/neterion/s2io.c index 65ccdbe665e5..7b50c5135bfa 100644 --- a/drivers/net/ethernet/neterion/s2io.c +++ b/drivers/net/ethernet/neterion/s2io.c @@ -5217,7 +5217,7 @@ static int s2io_set_mac_addr(struct net_device *dev, void *p) * as defined in errno.h file on failure. */ -static int do_s2io_prog_unicast(struct net_device *dev, u8 *addr) +static int do_s2io_prog_unicast(struct net_device *dev, const u8 *addr) { struct s2io_nic *sp = netdev_priv(dev); register u64 mac_addr = 0, perm_addr = 0; diff --git a/drivers/net/ethernet/neterion/s2io.h b/drivers/net/ethernet/neterion/s2io.h index 5a6032212c19..a4266d1544ab 100644 --- a/drivers/net/ethernet/neterion/s2io.h +++ b/drivers/net/ethernet/neterion/s2io.h @@ -1073,7 +1073,7 @@ static void s2io_reset(struct s2io_nic * sp); static int s2io_poll_msix(struct napi_struct *napi, int budget); static int s2io_poll_inta(struct napi_struct *napi, int budget); static void s2io_init_pci(struct s2io_nic * sp); -static int do_s2io_prog_unicast(struct net_device *dev, u8 *addr); +static int do_s2io_prog_unicast(struct net_device *dev, const u8 *addr); static void s2io_alarm_handle(struct timer_list *t); static irqreturn_t s2io_msix_ring_handle(int irq, void *dev_id); diff --git a/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c b/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c index babd374333f3..cb43651ea9ba 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c +++ b/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c @@ -837,7 +837,7 @@ nfp_tunnel_put_ipv6_off(struct nfp_app *app, struct nfp_ipv6_addr_entry *entry) } static int -__nfp_tunnel_offload_mac(struct nfp_app *app, u8 *mac, u16 idx, bool del) +__nfp_tunnel_offload_mac(struct nfp_app *app, const u8 *mac, u16 idx, bool del) { struct nfp_tun_mac_addr_offload payload; @@ -886,7 +886,7 @@ static bool nfp_tunnel_is_mac_idx_global(u16 nfp_mac_idx) } static struct nfp_tun_offloaded_mac * -nfp_tunnel_lookup_offloaded_macs(struct nfp_app *app, u8 *mac) +nfp_tunnel_lookup_offloaded_macs(struct nfp_app *app, const u8 *mac) { struct nfp_flower_priv *priv = app->priv; @@ -1005,7 +1005,7 @@ err_free_ida: static int nfp_tunnel_del_shared_mac(struct nfp_app *app, struct net_device *netdev, - u8 *mac, bool mod) + const u8 *mac, bool mod) { struct nfp_flower_priv *priv = app->priv; struct nfp_flower_repr_priv *repr_priv; diff --git a/drivers/net/ethernet/nxp/lpc_eth.c b/drivers/net/ethernet/nxp/lpc_eth.c index b42b65fb034e..0b8d605f5ad9 100644 --- a/drivers/net/ethernet/nxp/lpc_eth.c +++ b/drivers/net/ethernet/nxp/lpc_eth.c @@ -419,7 +419,7 @@ struct netdata_local { /* * MAC support functions */ -static void __lpc_set_mac(struct netdata_local *pldat, u8 *mac) +static void __lpc_set_mac(struct netdata_local *pldat, const u8 *mac) { u32 tmp; diff --git a/drivers/net/ethernet/qlogic/qed/qed_dev.c b/drivers/net/ethernet/qlogic/qed/qed_dev.c index ba445724ee65..3478f6fba826 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_dev.c +++ b/drivers/net/ethernet/qlogic/qed/qed_dev.c @@ -951,7 +951,7 @@ qed_llh_remove_filter(struct qed_hwfn *p_hwfn, } int qed_llh_add_mac_filter(struct qed_dev *cdev, - u8 ppfid, u8 mac_addr[ETH_ALEN]) + u8 ppfid, const u8 mac_addr[ETH_ALEN]) { struct qed_hwfn *p_hwfn = QED_LEADING_HWFN(cdev); struct qed_ptt *p_ptt = qed_ptt_acquire(p_hwfn); diff --git a/drivers/net/ethernet/qlogic/qed/qed_dev_api.h b/drivers/net/ethernet/qlogic/qed/qed_dev_api.h index a0a766a1723c..2475058e7caa 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_dev_api.h +++ b/drivers/net/ethernet/qlogic/qed/qed_dev_api.h @@ -381,7 +381,7 @@ int qed_llh_set_roce_affinity(struct qed_dev *cdev, enum qed_eng eng); * Return: Int. */ int qed_llh_add_mac_filter(struct qed_dev *cdev, - u8 ppfid, u8 mac_addr[ETH_ALEN]); + u8 ppfid, const u8 mac_addr[ETH_ALEN]); /** * qed_llh_remove_mac_filter(): Remove a LLH MAC filter from the given diff --git a/drivers/net/ethernet/qlogic/qed/qed_l2.c b/drivers/net/ethernet/qlogic/qed/qed_l2.c index 6ffa6425a75a..0872b6c85ab8 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_l2.c +++ b/drivers/net/ethernet/qlogic/qed/qed_l2.c @@ -2857,7 +2857,7 @@ static int qed_fp_cqe_completion(struct qed_dev *dev, cqe); } -static int qed_req_bulletin_update_mac(struct qed_dev *cdev, u8 *mac) +static int qed_req_bulletin_update_mac(struct qed_dev *cdev, const u8 *mac) { int i, ret; diff --git a/drivers/net/ethernet/qlogic/qed/qed_main.c b/drivers/net/ethernet/qlogic/qed/qed_main.c index 26700b0b4b37..6e902d57c793 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_main.c +++ b/drivers/net/ethernet/qlogic/qed/qed_main.c @@ -2892,7 +2892,7 @@ static int qed_update_drv_state(struct qed_dev *cdev, bool active) return status; } -static int qed_update_mac(struct qed_dev *cdev, u8 *mac) +static int qed_update_mac(struct qed_dev *cdev, const u8 *mac) { struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev); struct qed_ptt *ptt; diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.c b/drivers/net/ethernet/qlogic/qed/qed_mcp.c index 24cd41567775..b734c120d508 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_mcp.c +++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.c @@ -2854,7 +2854,7 @@ int qed_mcp_ov_update_mtu(struct qed_hwfn *p_hwfn, } int qed_mcp_ov_update_mac(struct qed_hwfn *p_hwfn, - struct qed_ptt *p_ptt, u8 *mac) + struct qed_ptt *p_ptt, const u8 *mac) { struct qed_mcp_mb_params mb_params; u32 mfw_mac[2]; diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.h b/drivers/net/ethernet/qlogic/qed/qed_mcp.h index 352b757183e8..526cfdf7ffcc 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_mcp.h +++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.h @@ -536,7 +536,7 @@ int qed_mcp_ov_update_mtu(struct qed_hwfn *p_hwfn, * Return: Int - 0 - Operation was successul. */ int qed_mcp_ov_update_mac(struct qed_hwfn *p_hwfn, - struct qed_ptt *p_ptt, u8 *mac); + struct qed_ptt *p_ptt, const u8 *mac); /** * qed_mcp_ov_update_wol(): Send WOL mode to MFW. diff --git a/drivers/net/ethernet/qlogic/qed/qed_rdma.c b/drivers/net/ethernet/qlogic/qed/qed_rdma.c index 4f4b79250a2b..725ace88272e 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_rdma.c +++ b/drivers/net/ethernet/qlogic/qed/qed_rdma.c @@ -1966,7 +1966,7 @@ static void qed_rdma_remove_user(void *rdma_cxt, u16 dpi) static int qed_roce_ll2_set_mac_filter(struct qed_dev *cdev, u8 *old_mac_address, - u8 *new_mac_address) + const u8 *new_mac_address) { int rc = 0; diff --git a/drivers/net/ethernet/qlogic/qed/qed_vf.c b/drivers/net/ethernet/qlogic/qed/qed_vf.c index e2a5a6a373cb..f25d9676e572 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_vf.c +++ b/drivers/net/ethernet/qlogic/qed/qed_vf.c @@ -1379,7 +1379,7 @@ exit: int qed_vf_pf_bulletin_update_mac(struct qed_hwfn *p_hwfn, - u8 *p_mac) + const u8 *p_mac) { struct qed_vf_iov *p_iov = p_hwfn->vf_iov_info; struct vfpf_bulletin_update_mac_tlv *p_req; diff --git a/drivers/net/ethernet/qlogic/qed/qed_vf.h b/drivers/net/ethernet/qlogic/qed/qed_vf.h index 976201fc7d4a..a6492f265487 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_vf.h +++ b/drivers/net/ethernet/qlogic/qed/qed_vf.h @@ -1070,7 +1070,7 @@ u32 qed_vf_hw_bar_size(struct qed_hwfn *p_hwfn, enum BAR_ID bar_id); * * Return: Int. */ -int qed_vf_pf_bulletin_update_mac(struct qed_hwfn *p_hwfn, u8 *p_mac); +int qed_vf_pf_bulletin_update_mac(struct qed_hwfn *p_hwfn, const u8 *p_mac); #else static inline void qed_vf_get_link_params(struct qed_hwfn *p_hwfn, @@ -1259,7 +1259,7 @@ static inline int qed_vf_pf_tunnel_param_update(struct qed_hwfn *p_hwfn, } static inline int qed_vf_pf_bulletin_update_mac(struct qed_hwfn *p_hwfn, - u8 *p_mac) + const u8 *p_mac) { return -EINVAL; } diff --git a/drivers/net/ethernet/qlogic/qede/qede_filter.c b/drivers/net/ethernet/qlogic/qede/qede_filter.c index 03c51dd37e1f..3010833ddde3 100644 --- a/drivers/net/ethernet/qlogic/qede/qede_filter.c +++ b/drivers/net/ethernet/qlogic/qede/qede_filter.c @@ -617,7 +617,7 @@ void qede_fill_rss_params(struct qede_dev *edev, static int qede_set_ucast_rx_mac(struct qede_dev *edev, enum qed_filter_xcast_params_type opcode, - unsigned char mac[ETH_ALEN]) + const unsigned char mac[ETH_ALEN]) { struct qed_filter_ucast_params ucast; diff --git a/drivers/net/ethernet/qualcomm/emac/emac-mac.c b/drivers/net/ethernet/qualcomm/emac/emac-mac.c index 87b8c032195d..06104d2ff5b3 100644 --- a/drivers/net/ethernet/qualcomm/emac/emac-mac.c +++ b/drivers/net/ethernet/qualcomm/emac/emac-mac.c @@ -420,7 +420,7 @@ static void emac_mac_dma_config(struct emac_adapter *adpt) } /* set MAC address */ -static void emac_set_mac_address(struct emac_adapter *adpt, u8 *addr) +static void emac_set_mac_address(struct emac_adapter *adpt, const u8 *addr) { u32 sta; diff --git a/drivers/net/ethernet/rdc/r6040.c b/drivers/net/ethernet/rdc/r6040.c index 5a8a6977ec9a..91e136bc2c67 100644 --- a/drivers/net/ethernet/rdc/r6040.c +++ b/drivers/net/ethernet/rdc/r6040.c @@ -453,7 +453,7 @@ static void r6040_down(struct net_device *dev) { struct r6040_private *lp = netdev_priv(dev); void __iomem *ioaddr = lp->base; - u16 *adrp; + const u16 *adrp; /* Stop MAC */ iowrite16(MSK_INT, ioaddr + MIER); /* Mask Off Interrupt */ @@ -462,7 +462,7 @@ static void r6040_down(struct net_device *dev) r6040_reset_mac(lp); /* Restore MAC Address to MIDx */ - adrp = (u16 *) dev->dev_addr; + adrp = (const u16 *) dev->dev_addr; iowrite16(adrp[0], ioaddr + MID_0L); iowrite16(adrp[1], ioaddr + MID_0M); iowrite16(adrp[2], ioaddr + MID_0H); @@ -731,13 +731,13 @@ static void r6040_mac_address(struct net_device *dev) { struct r6040_private *lp = netdev_priv(dev); void __iomem *ioaddr = lp->base; - u16 *adrp; + const u16 *adrp; /* Reset MAC */ r6040_reset_mac(lp); /* Restore MAC Address */ - adrp = (u16 *) dev->dev_addr; + adrp = (const u16 *) dev->dev_addr; iowrite16(adrp[0], ioaddr + MID_0L); iowrite16(adrp[1], ioaddr + MID_0M); iowrite16(adrp[2], ioaddr + MID_0H); @@ -849,13 +849,13 @@ static void r6040_multicast_list(struct net_device *dev) unsigned long flags; struct netdev_hw_addr *ha; int i; - u16 *adrp; + const u16 *adrp; u16 hash_table[4] = { 0 }; spin_lock_irqsave(&lp->lock, flags); /* Keep our MAC Address */ - adrp = (u16 *)dev->dev_addr; + adrp = (const u16 *)dev->dev_addr; iowrite16(adrp[0], ioaddr + MID_0L); iowrite16(adrp[1], ioaddr + MID_0M); iowrite16(adrp[2], ioaddr + MID_0H); diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_common.h b/drivers/net/ethernet/samsung/sxgbe/sxgbe_common.h index 049dc6cf4611..0f45107db8dd 100644 --- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_common.h +++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_common.h @@ -329,7 +329,7 @@ struct sxgbe_core_ops { /* Set power management mode (e.g. magic frame) */ void (*pmt)(void __iomem *ioaddr, unsigned long mode); /* Set/Get Unicast MAC addresses */ - void (*set_umac_addr)(void __iomem *ioaddr, unsigned char *addr, + void (*set_umac_addr)(void __iomem *ioaddr, const unsigned char *addr, unsigned int reg_n); void (*get_umac_addr)(void __iomem *ioaddr, unsigned char *addr, unsigned int reg_n); diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_core.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_core.c index e96e2bd295ef..7d9f257de92a 100644 --- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_core.c +++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_core.c @@ -85,7 +85,8 @@ static void sxgbe_core_pmt(void __iomem *ioaddr, unsigned long mode) } /* Set/Get Unicast MAC addresses */ -static void sxgbe_core_set_umac_addr(void __iomem *ioaddr, unsigned char *addr, +static void sxgbe_core_set_umac_addr(void __iomem *ioaddr, + const unsigned char *addr, unsigned int reg_n) { u32 high_word, low_word; diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c index b20dbda37c7e..d8b3b339a8df 100644 --- a/drivers/net/ethernet/sfc/ef10.c +++ b/drivers/net/ethernet/sfc/ef10.c @@ -1038,7 +1038,7 @@ int efx_ef10_vadaptor_free(struct efx_nic *efx, unsigned int port_id) } int efx_ef10_vport_add_mac(struct efx_nic *efx, - unsigned int port_id, u8 *mac) + unsigned int port_id, const u8 *mac) { MCDI_DECLARE_BUF(inbuf, MC_CMD_VPORT_ADD_MAC_ADDRESS_IN_LEN); @@ -1050,7 +1050,7 @@ int efx_ef10_vport_add_mac(struct efx_nic *efx, } int efx_ef10_vport_del_mac(struct efx_nic *efx, - unsigned int port_id, u8 *mac) + unsigned int port_id, const u8 *mac) { MCDI_DECLARE_BUF(inbuf, MC_CMD_VPORT_DEL_MAC_ADDRESS_IN_LEN); diff --git a/drivers/net/ethernet/sfc/ef10_sriov.c b/drivers/net/ethernet/sfc/ef10_sriov.c index eeaecea77cb8..92550c7e85ce 100644 --- a/drivers/net/ethernet/sfc/ef10_sriov.c +++ b/drivers/net/ethernet/sfc/ef10_sriov.c @@ -484,7 +484,7 @@ static int efx_ef10_vport_del_vf_mac(struct efx_nic *efx, unsigned int port_id, return rc; } -int efx_ef10_sriov_set_vf_mac(struct efx_nic *efx, int vf_i, u8 *mac) +int efx_ef10_sriov_set_vf_mac(struct efx_nic *efx, int vf_i, const u8 *mac) { struct efx_ef10_nic_data *nic_data = efx->nic_data; struct ef10_vf *vf; diff --git a/drivers/net/ethernet/sfc/ef10_sriov.h b/drivers/net/ethernet/sfc/ef10_sriov.h index cfe556d17313..3c703ca878b0 100644 --- a/drivers/net/ethernet/sfc/ef10_sriov.h +++ b/drivers/net/ethernet/sfc/ef10_sriov.h @@ -39,7 +39,7 @@ static inline void efx_ef10_sriov_reset(struct efx_nic *efx) {} void efx_ef10_sriov_fini(struct efx_nic *efx); static inline void efx_ef10_sriov_flr(struct efx_nic *efx, unsigned vf_i) {} -int efx_ef10_sriov_set_vf_mac(struct efx_nic *efx, int vf, u8 *mac); +int efx_ef10_sriov_set_vf_mac(struct efx_nic *efx, int vf, const u8 *mac); int efx_ef10_sriov_set_vf_vlan(struct efx_nic *efx, int vf_i, u16 vlan, u8 qos); @@ -60,9 +60,9 @@ int efx_ef10_vswitching_restore_vf(struct efx_nic *efx); void efx_ef10_vswitching_remove_pf(struct efx_nic *efx); void efx_ef10_vswitching_remove_vf(struct efx_nic *efx); int efx_ef10_vport_add_mac(struct efx_nic *efx, - unsigned int port_id, u8 *mac); + unsigned int port_id, const u8 *mac); int efx_ef10_vport_del_mac(struct efx_nic *efx, - unsigned int port_id, u8 *mac); + unsigned int port_id, const u8 *mac); int efx_ef10_vadaptor_alloc(struct efx_nic *efx, unsigned int port_id); int efx_ef10_vadaptor_query(struct efx_nic *efx, unsigned int port_id, u32 *port_flags, u32 *vadaptor_flags, diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h index 6df500dbb6b7..67a9758467b1 100644 --- a/drivers/net/ethernet/sfc/net_driver.h +++ b/drivers/net/ethernet/sfc/net_driver.h @@ -1482,7 +1482,7 @@ struct efx_nic_type { bool (*sriov_wanted)(struct efx_nic *efx); void (*sriov_reset)(struct efx_nic *efx); void (*sriov_flr)(struct efx_nic *efx, unsigned vf_i); - int (*sriov_set_vf_mac)(struct efx_nic *efx, int vf_i, u8 *mac); + int (*sriov_set_vf_mac)(struct efx_nic *efx, int vf_i, const u8 *mac); int (*sriov_set_vf_vlan)(struct efx_nic *efx, int vf_i, u16 vlan, u8 qos); int (*sriov_set_vf_spoofchk)(struct efx_nic *efx, int vf_i, diff --git a/drivers/net/ethernet/sfc/siena_sriov.c b/drivers/net/ethernet/sfc/siena_sriov.c index 441e7f3e5375..f12851a527d9 100644 --- a/drivers/net/ethernet/sfc/siena_sriov.c +++ b/drivers/net/ethernet/sfc/siena_sriov.c @@ -1591,7 +1591,7 @@ void efx_fini_sriov(void) destroy_workqueue(vfdi_workqueue); } -int efx_siena_sriov_set_vf_mac(struct efx_nic *efx, int vf_i, u8 *mac) +int efx_siena_sriov_set_vf_mac(struct efx_nic *efx, int vf_i, const u8 *mac) { struct siena_nic_data *nic_data = efx->nic_data; struct siena_vf *vf; diff --git a/drivers/net/ethernet/sfc/siena_sriov.h b/drivers/net/ethernet/sfc/siena_sriov.h index e441c89c25ce..e548c4daf189 100644 --- a/drivers/net/ethernet/sfc/siena_sriov.h +++ b/drivers/net/ethernet/sfc/siena_sriov.h @@ -46,7 +46,7 @@ bool efx_siena_sriov_wanted(struct efx_nic *efx); void efx_siena_sriov_reset(struct efx_nic *efx); void efx_siena_sriov_flr(struct efx_nic *efx, unsigned flr); -int efx_siena_sriov_set_vf_mac(struct efx_nic *efx, int vf, u8 *mac); +int efx_siena_sriov_set_vf_mac(struct efx_nic *efx, int vf, const u8 *mac); int efx_siena_sriov_set_vf_vlan(struct efx_nic *efx, int vf, u16 vlan, u8 qos); int efx_siena_sriov_set_vf_spoofchk(struct efx_nic *efx, int vf, diff --git a/drivers/net/ethernet/sis/sis900.c b/drivers/net/ethernet/sis/sis900.c index 60a0c0e9ded2..d105779ba3b2 100644 --- a/drivers/net/ethernet/sis/sis900.c +++ b/drivers/net/ethernet/sis/sis900.c @@ -1098,7 +1098,7 @@ sis900_init_rxfilter (struct net_device * net_dev) /* load MAC addr to filter data register */ for (i = 0 ; i < 3 ; i++) { - u32 w = (u32) *((u16 *)(net_dev->dev_addr)+i); + u32 w = (u32) *((const u16 *)(net_dev->dev_addr)+i); sw32(rfcr, i << RFADDR_shift); sw32(rfdr, w); diff --git a/drivers/net/ethernet/smsc/smsc911x.c b/drivers/net/ethernet/smsc/smsc911x.c index b330dcbe949d..42f79147739b 100644 --- a/drivers/net/ethernet/smsc/smsc911x.c +++ b/drivers/net/ethernet/smsc/smsc911x.c @@ -1508,7 +1508,7 @@ static int smsc911x_soft_reset(struct smsc911x_data *pdata) /* Sets the device MAC address to dev_addr, called with mac_lock held */ static void -smsc911x_set_hw_mac_address(struct smsc911x_data *pdata, u8 dev_addr[6]) +smsc911x_set_hw_mac_address(struct smsc911x_data *pdata, const u8 dev_addr[6]) { u32 mac_high16 = (dev_addr[5] << 8) | dev_addr[4]; u32 mac_low32 = (dev_addr[3] << 24) | (dev_addr[2] << 16) | diff --git a/drivers/net/ethernet/smsc/smsc9420.c b/drivers/net/ethernet/smsc/smsc9420.c index fdbd2a43e267..2bded7313600 100644 --- a/drivers/net/ethernet/smsc/smsc9420.c +++ b/drivers/net/ethernet/smsc/smsc9420.c @@ -404,7 +404,7 @@ static const struct ethtool_ops smsc9420_ethtool_ops = { static void smsc9420_set_mac_address(struct net_device *dev) { struct smsc9420_pdata *pd = netdev_priv(dev); - u8 *dev_addr = dev->dev_addr; + const u8 *dev_addr = dev->dev_addr; u32 mac_high16 = (dev_addr[5] << 8) | dev_addr[4]; u32 mac_low32 = (dev_addr[3] << 24) | (dev_addr[2] << 16) | (dev_addr[1] << 8) | dev_addr[0]; diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h index c113ec56f5b0..c03ac229e936 100644 --- a/drivers/net/ethernet/stmicro/stmmac/common.h +++ b/drivers/net/ethernet/stmicro/stmmac/common.h @@ -545,13 +545,13 @@ int dwmac4_setup(struct stmmac_priv *priv); int dwxgmac2_setup(struct stmmac_priv *priv); int dwxlgmac2_setup(struct stmmac_priv *priv); -void stmmac_set_mac_addr(void __iomem *ioaddr, u8 addr[6], +void stmmac_set_mac_addr(void __iomem *ioaddr, const u8 addr[6], unsigned int high, unsigned int low); void stmmac_get_mac_addr(void __iomem *ioaddr, unsigned char *addr, unsigned int high, unsigned int low); void stmmac_set_mac(void __iomem *ioaddr, bool enable); -void stmmac_dwmac4_set_mac_addr(void __iomem *ioaddr, u8 addr[6], +void stmmac_dwmac4_set_mac_addr(void __iomem *ioaddr, const u8 addr[6], unsigned int high, unsigned int low); void stmmac_dwmac4_get_mac_addr(void __iomem *ioaddr, unsigned char *addr, unsigned int high, unsigned int low); diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c index 06e2af9387d7..fda53b4b9406 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c @@ -634,7 +634,7 @@ static void sun8i_dwmac_set_mac(void __iomem *ioaddr, bool enable) * If addr is NULL, clear the slot */ static void sun8i_dwmac_set_umac_addr(struct mac_device_info *hw, - unsigned char *addr, + const unsigned char *addr, unsigned int reg_n) { void __iomem *ioaddr = hw->pcsr; diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c index fc8759f146c7..76edb9b72675 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c @@ -104,7 +104,7 @@ static void dwmac1000_dump_regs(struct mac_device_info *hw, u32 *reg_space) } static void dwmac1000_set_umac_addr(struct mac_device_info *hw, - unsigned char *addr, + const unsigned char *addr, unsigned int reg_n) { void __iomem *ioaddr = hw->pcsr; diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c index ebcad8dd99db..75071a7d551a 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c @@ -68,7 +68,7 @@ static int dwmac100_irq_status(struct mac_device_info *hw, } static void dwmac100_set_umac_addr(struct mac_device_info *hw, - unsigned char *addr, + const unsigned char *addr, unsigned int reg_n) { void __iomem *ioaddr = hw->pcsr; diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c index 29480314a486..f6d6a6d9c555 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c @@ -334,7 +334,7 @@ static void dwmac4_pmt(struct mac_device_info *hw, unsigned long mode) } static void dwmac4_set_umac_addr(struct mac_device_info *hw, - unsigned char *addr, unsigned int reg_n) + const unsigned char *addr, unsigned int reg_n) { void __iomem *ioaddr = hw->pcsr; diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c index 7011c08d2e01..7c26394f665e 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c @@ -187,7 +187,7 @@ int dwmac4_dma_interrupt(void __iomem *ioaddr, return ret; } -void stmmac_dwmac4_set_mac_addr(void __iomem *ioaddr, u8 addr[6], +void stmmac_dwmac4_set_mac_addr(void __iomem *ioaddr, const u8 addr[6], unsigned int high, unsigned int low) { unsigned long data; diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c index 01d0a14f6752..9b6138b11776 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c @@ -239,7 +239,7 @@ void dwmac_dma_flush_tx_fifo(void __iomem *ioaddr) do {} while ((readl(ioaddr + DMA_CONTROL) & DMA_CONTROL_FTF)); } -void stmmac_set_mac_addr(void __iomem *ioaddr, u8 addr[6], +void stmmac_set_mac_addr(void __iomem *ioaddr, const u8 addr[6], unsigned int high, unsigned int low) { unsigned long data; diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c index 3568bf3ccfbe..c2181c277291 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c @@ -335,7 +335,8 @@ static void dwxgmac2_pmt(struct mac_device_info *hw, unsigned long mode) } static void dwxgmac2_set_umac_addr(struct mac_device_info *hw, - unsigned char *addr, unsigned int reg_n) + const unsigned char *addr, + unsigned int reg_n) { void __iomem *ioaddr = hw->pcsr; u32 value; diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h index cc229ccd5d81..58e5c6c428dc 100644 --- a/drivers/net/ethernet/stmicro/stmmac/hwif.h +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h @@ -330,7 +330,8 @@ struct stmmac_ops { /* Set power management mode (e.g. magic frame) */ void (*pmt)(struct mac_device_info *hw, unsigned long mode); /* Set/Get Unicast MAC addresses */ - void (*set_umac_addr)(struct mac_device_info *hw, unsigned char *addr, + void (*set_umac_addr)(struct mac_device_info *hw, + const unsigned char *addr, unsigned int reg_n); void (*get_umac_addr)(struct mac_device_info *hw, unsigned char *addr, unsigned int reg_n); diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c index ea7200b7b647..4705344077b6 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c @@ -36,7 +36,7 @@ struct stmmac_packet_attrs { int vlan_id_in; int vlan_id_out; unsigned char *src; - unsigned char *dst; + const unsigned char *dst; u32 ip_src; u32 ip_dst; int tcp; @@ -249,8 +249,8 @@ static int stmmac_test_loopback_validate(struct sk_buff *skb, struct net_device *orig_ndev) { struct stmmac_test_priv *tpriv = pt->af_packet_priv; + const unsigned char *dst = tpriv->packet->dst; unsigned char *src = tpriv->packet->src; - unsigned char *dst = tpriv->packet->dst; struct stmmachdr *shdr; struct ethhdr *ehdr; struct udphdr *uhdr; diff --git a/drivers/net/ethernet/sun/sunbmac.c b/drivers/net/ethernet/sun/sunbmac.c index c646575e79d5..d70426670c37 100644 --- a/drivers/net/ethernet/sun/sunbmac.c +++ b/drivers/net/ethernet/sun/sunbmac.c @@ -623,7 +623,7 @@ static int bigmac_init_hw(struct bigmac *bp, bool non_blocking) void __iomem *cregs = bp->creg; void __iomem *bregs = bp->bregs; __u32 bblk_dvma = (__u32)bp->bblock_dvma; - unsigned char *e = &bp->dev->dev_addr[0]; + const unsigned char *e = &bp->dev->dev_addr[0]; /* Latch current counters into statistics. */ bigmac_get_counters(bp, bregs); diff --git a/drivers/net/ethernet/sun/sunqe.c b/drivers/net/ethernet/sun/sunqe.c index 577cd9753d8e..7591d2d77eb6 100644 --- a/drivers/net/ethernet/sun/sunqe.c +++ b/drivers/net/ethernet/sun/sunqe.c @@ -144,7 +144,7 @@ static int qe_init(struct sunqe *qep, int from_irq) void __iomem *cregs = qep->qcregs; void __iomem *mregs = qep->mregs; void __iomem *gregs = qecp->gregs; - unsigned char *e = &qep->dev->dev_addr[0]; + const unsigned char *e = &qep->dev->dev_addr[0]; __u32 qblk_dvma = (__u32)qep->qblock_dvma; u32 tmp; int i; diff --git a/drivers/net/ethernet/synopsys/dwc-xlgmac-hw.c b/drivers/net/ethernet/synopsys/dwc-xlgmac-hw.c index bf6c1c6779ff..76eb7db80f13 100644 --- a/drivers/net/ethernet/synopsys/dwc-xlgmac-hw.c +++ b/drivers/net/ethernet/synopsys/dwc-xlgmac-hw.c @@ -57,7 +57,7 @@ static int xlgmac_enable_rx_csum(struct xlgmac_pdata *pdata) return 0; } -static int xlgmac_set_mac_address(struct xlgmac_pdata *pdata, u8 *addr) +static int xlgmac_set_mac_address(struct xlgmac_pdata *pdata, const u8 *addr) { unsigned int mac_addr_hi, mac_addr_lo; diff --git a/drivers/net/ethernet/synopsys/dwc-xlgmac.h b/drivers/net/ethernet/synopsys/dwc-xlgmac.h index 8598aaf3ec99..98e3a271e017 100644 --- a/drivers/net/ethernet/synopsys/dwc-xlgmac.h +++ b/drivers/net/ethernet/synopsys/dwc-xlgmac.h @@ -410,7 +410,7 @@ struct xlgmac_hw_ops { void (*dev_xmit)(struct xlgmac_channel *channel); int (*dev_read)(struct xlgmac_channel *channel); - int (*set_mac_address)(struct xlgmac_pdata *pdata, u8 *addr); + int (*set_mac_address)(struct xlgmac_pdata *pdata, const u8 *addr); int (*config_rx_mode)(struct xlgmac_pdata *pdata); int (*enable_rx_csum)(struct xlgmac_pdata *pdata); int (*disable_rx_csum)(struct xlgmac_pdata *pdata); diff --git a/drivers/net/ethernet/ti/tlan.c b/drivers/net/ethernet/ti/tlan.c index 77c448ad67ce..eab7d78d7c72 100644 --- a/drivers/net/ethernet/ti/tlan.c +++ b/drivers/net/ethernet/ti/tlan.c @@ -184,7 +184,7 @@ static void tlan_print_list(struct tlan_list *, char *, int); static void tlan_read_and_clear_stats(struct net_device *, int); static void tlan_reset_adapter(struct net_device *); static void tlan_finish_reset(struct net_device *); -static void tlan_set_mac(struct net_device *, int areg, char *mac); +static void tlan_set_mac(struct net_device *, int areg, const char *mac); static void __tlan_phy_print(struct net_device *); static void tlan_phy_print(struct net_device *); @@ -2346,7 +2346,7 @@ tlan_finish_reset(struct net_device *dev) * **************************************************************/ -static void tlan_set_mac(struct net_device *dev, int areg, char *mac) +static void tlan_set_mac(struct net_device *dev, int areg, const char *mac) { int i; diff --git a/drivers/net/ethernet/toshiba/tc35815.c b/drivers/net/ethernet/toshiba/tc35815.c index 52245ac60fc7..07f9f8e19890 100644 --- a/drivers/net/ethernet/toshiba/tc35815.c +++ b/drivers/net/ethernet/toshiba/tc35815.c @@ -1859,7 +1859,8 @@ static struct net_device_stats *tc35815_get_stats(struct net_device *dev) return &dev->stats; } -static void tc35815_set_cam_entry(struct net_device *dev, int index, unsigned char *addr) +static void tc35815_set_cam_entry(struct net_device *dev, int index, + const unsigned char *addr) { struct tc35815_local *lp = netdev_priv(dev); struct tc35815_regs __iomem *tr = diff --git a/drivers/net/ethernet/xilinx/xilinx_emaclite.c b/drivers/net/ethernet/xilinx/xilinx_emaclite.c index 093c75da38c4..84e459358b05 100644 --- a/drivers/net/ethernet/xilinx/xilinx_emaclite.c +++ b/drivers/net/ethernet/xilinx/xilinx_emaclite.c @@ -206,12 +206,13 @@ static void xemaclite_disable_interrupts(struct net_local *drvdata) * This function writes data from a 16-bit aligned buffer to a 32-bit aligned * address in the EmacLite device. */ -static void xemaclite_aligned_write(void *src_ptr, u32 *dest_ptr, +static void xemaclite_aligned_write(const void *src_ptr, u32 *dest_ptr, unsigned length) { + const u16 *from_u16_ptr; u32 align_buffer; u32 *to_u32_ptr; - u16 *from_u16_ptr, *to_u16_ptr; + u16 *to_u16_ptr; to_u32_ptr = dest_ptr; from_u16_ptr = src_ptr; @@ -470,7 +471,7 @@ static u16 xemaclite_recv_data(struct net_local *drvdata, u8 *data, int maxlen) * buffers (if configured). */ static void xemaclite_update_address(struct net_local *drvdata, - u8 *address_ptr) + const u8 *address_ptr) { void __iomem *addr; u32 reg_data; diff --git a/drivers/net/ethernet/xircom/xirc2ps_cs.c b/drivers/net/ethernet/xircom/xirc2ps_cs.c index f8bbd1489af1..10f42b7df8b3 100644 --- a/drivers/net/ethernet/xircom/xirc2ps_cs.c +++ b/drivers/net/ethernet/xircom/xirc2ps_cs.c @@ -1276,7 +1276,7 @@ struct set_address_info { unsigned int ioaddr; }; -static void set_address(struct set_address_info *sa_info, char *addr) +static void set_address(struct set_address_info *sa_info, const char *addr) { unsigned int ioaddr = sa_info->ioaddr; int i; diff --git a/drivers/net/phy/mscc/mscc_main.c b/drivers/net/phy/mscc/mscc_main.c index cef43b1344a9..b349c359089e 100644 --- a/drivers/net/phy/mscc/mscc_main.c +++ b/drivers/net/phy/mscc/mscc_main.c @@ -273,12 +273,12 @@ static int vsc85xx_downshift_set(struct phy_device *phydev, u8 count) static int vsc85xx_wol_set(struct phy_device *phydev, struct ethtool_wolinfo *wol) { + const u8 *mac_addr = phydev->attached_dev->dev_addr; int rc; u16 reg_val; u8 i; u16 pwd[3] = {0, 0, 0}; struct ethtool_wolinfo *wol_conf = wol; - u8 *mac_addr = phydev->attached_dev->dev_addr; mutex_lock(&phydev->lock); rc = phy_select_page(phydev, MSCC_PHY_PAGE_EXTENDED_2); diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c index bc5e3f45c499..6db37eb6c5cc 100644 --- a/drivers/net/usb/aqc111.c +++ b/drivers/net/usb/aqc111.c @@ -119,7 +119,7 @@ static int aqc111_write_cmd_nopm(struct usbnet *dev, u8 cmd, u16 value, } static int aqc111_write_cmd(struct usbnet *dev, u8 cmd, u16 value, - u16 index, u16 size, void *data) + u16 index, u16 size, const void *data) { int ret; diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c index c419baf47813..7f5680c0b230 100644 --- a/drivers/net/usb/ax88179_178a.c +++ b/drivers/net/usb/ax88179_178a.c @@ -209,7 +209,7 @@ static int __ax88179_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, } static int __ax88179_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, - u16 size, void *data, int in_pm) + u16 size, const void *data, int in_pm) { int ret; int (*fn)(struct usbnet *, u8, u8, u16, u16, const void *, u16); @@ -272,7 +272,7 @@ static int ax88179_read_cmd_nopm(struct usbnet *dev, u8 cmd, u16 value, } static int ax88179_write_cmd_nopm(struct usbnet *dev, u8 cmd, u16 value, - u16 index, u16 size, void *data) + u16 index, u16 size, const void *data) { int ret; @@ -313,7 +313,7 @@ static int ax88179_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, } static int ax88179_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, - u16 size, void *data) + u16 size, const void *data) { int ret; @@ -463,7 +463,7 @@ static int ax88179_auto_detach(struct usbnet *dev, int in_pm) u16 tmp16; u8 tmp8; int (*fnr)(struct usbnet *, u8, u16, u16, u16, void *); - int (*fnw)(struct usbnet *, u8, u16, u16, u16, void *); + int (*fnw)(struct usbnet *, u8, u16, u16, u16, const void *); if (!in_pm) { fnr = ax88179_read_cmd; diff --git a/drivers/net/usb/catc.c b/drivers/net/usb/catc.c index 97ba67042d12..24db5768a3c0 100644 --- a/drivers/net/usb/catc.c +++ b/drivers/net/usb/catc.c @@ -615,7 +615,7 @@ static void catc_stats_timer(struct timer_list *t) * Receive modes. Broadcast, Multicast, Promisc. */ -static void catc_multicast(unsigned char *addr, u8 *multicast) +static void catc_multicast(const unsigned char *addr, u8 *multicast) { u32 crc; diff --git a/drivers/net/usb/dm9601.c b/drivers/net/usb/dm9601.c index 56f1c334cdd2..1959e12a3ff8 100644 --- a/drivers/net/usb/dm9601.c +++ b/drivers/net/usb/dm9601.c @@ -93,7 +93,8 @@ static int dm_write_reg(struct usbnet *dev, u8 reg, u8 value) value, reg, NULL, 0); } -static void dm_write_async(struct usbnet *dev, u8 reg, u16 length, void *data) +static void dm_write_async(struct usbnet *dev, u8 reg, u16 length, + const void *data) { usbnet_write_cmd_async(dev, DM_WRITE_REGS, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, diff --git a/drivers/net/usb/mcs7830.c b/drivers/net/usb/mcs7830.c index a31a3b9cbd58..8f484c4949d9 100644 --- a/drivers/net/usb/mcs7830.c +++ b/drivers/net/usb/mcs7830.c @@ -140,7 +140,8 @@ static int mcs7830_hif_get_mac_address(struct usbnet *dev, unsigned char *addr) return 0; } -static int mcs7830_hif_set_mac_address(struct usbnet *dev, unsigned char *addr) +static int mcs7830_hif_set_mac_address(struct usbnet *dev, + const unsigned char *addr) { int ret = mcs7830_set_reg(dev, HIF_REG_ETHERNET_ADDR, ETH_ALEN, addr); diff --git a/drivers/net/usb/sr9700.c b/drivers/net/usb/sr9700.c index 1fac6ee273c4..279a540aef10 100644 --- a/drivers/net/usb/sr9700.c +++ b/drivers/net/usb/sr9700.c @@ -56,7 +56,8 @@ static int sr_write_reg(struct usbnet *dev, u8 reg, u8 value) value, reg, NULL, 0); } -static void sr_write_async(struct usbnet *dev, u8 reg, u16 length, void *data) +static void sr_write_async(struct usbnet *dev, u8 reg, u16 length, + const void *data) { usbnet_write_cmd_async(dev, SR_WR_REGS, SR_REQ_WR_REG, 0, reg, data, length); diff --git a/include/linux/qed/qed_eth_if.h b/include/linux/qed/qed_eth_if.h index 4df0bf0a0864..e1bf3219b4e6 100644 --- a/include/linux/qed/qed_eth_if.h +++ b/include/linux/qed/qed_eth_if.h @@ -331,7 +331,7 @@ struct qed_eth_ops { int (*configure_arfs_searcher)(struct qed_dev *cdev, enum qed_filter_config_mode mode); int (*get_coalesce)(struct qed_dev *cdev, u16 *coal, void *handle); - int (*req_bulletin_update_mac)(struct qed_dev *cdev, u8 *mac); + int (*req_bulletin_update_mac)(struct qed_dev *cdev, const u8 *mac); }; const struct qed_eth_ops *qed_get_eth_ops(void); diff --git a/include/linux/qed/qed_if.h b/include/linux/qed/qed_if.h index f39451aaaeec..905de11cc209 100644 --- a/include/linux/qed/qed_if.h +++ b/include/linux/qed/qed_if.h @@ -1111,7 +1111,7 @@ struct qed_common_ops { * * Return: Int. */ - int (*update_mac)(struct qed_dev *cdev, u8 *mac); + int (*update_mac)(struct qed_dev *cdev, const u8 *mac); /** * update_mtu(): API to inform the change in the mtu. diff --git a/include/linux/qed/qed_rdma_if.h b/include/linux/qed/qed_rdma_if.h index aeb242cefebf..3b76c07fbcf8 100644 --- a/include/linux/qed/qed_rdma_if.h +++ b/include/linux/qed/qed_rdma_if.h @@ -662,7 +662,8 @@ struct qed_rdma_ops { u8 connection_handle, struct qed_ll2_stats *p_stats); int (*ll2_set_mac_filter)(struct qed_dev *cdev, - u8 *old_mac_address, u8 *new_mac_address); + u8 *old_mac_address, + const u8 *new_mac_address); int (*iwarp_set_engine_affin)(struct qed_dev *cdev, bool b_reset); -- cgit v1.2.3 From 2964a0de752695b02d3d7089cece3e98f1c103cb Mon Sep 17 00:00:00 2001 From: Justin Chen Date: Wed, 20 Jul 2022 17:28:13 -0700 Subject: net: usb: ax88179_178a: clean up pm calls [ Upstream commit 843f92052da7694e846e8e12bbe2342845d2033e ] Instead of passing in_pm flags all over the place, use the private struct to handle in_pm mode. Signed-off-by: Justin Chen Signed-off-by: Jakub Kicinski Stable-dep-of: aef05e349bfd ("net: usb: ax88179_178a: avoid failed operations when device is disconnected") Signed-off-by: Sasha Levin --- drivers/net/usb/ax88179_178a.c | 147 +++++++++++++++++------------------------ 1 file changed, 59 insertions(+), 88 deletions(-) diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c index 7f5680c0b230..bd258c4e1394 100644 --- a/drivers/net/usb/ax88179_178a.c +++ b/drivers/net/usb/ax88179_178a.c @@ -169,6 +169,7 @@ struct ax88179_data { u8 eee_active; u16 rxctl; u16 reserved; + u8 in_pm; }; struct ax88179_int_data { @@ -185,15 +186,29 @@ static const struct { {7, 0xcc, 0x4c, 0x18, 8}, }; +static void ax88179_set_pm_mode(struct usbnet *dev, bool pm_mode) +{ + struct ax88179_data *ax179_data = (struct ax88179_data *)dev->data; + + ax179_data->in_pm = pm_mode; +} + +static int ax88179_in_pm(struct usbnet *dev) +{ + struct ax88179_data *ax179_data = (struct ax88179_data *)dev->data; + + return ax179_data->in_pm; +} + static int __ax88179_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, - u16 size, void *data, int in_pm) + u16 size, void *data) { int ret; int (*fn)(struct usbnet *, u8, u8, u16, u16, void *, u16); BUG_ON(!dev); - if (!in_pm) + if (!ax88179_in_pm(dev)) fn = usbnet_read_cmd; else fn = usbnet_read_cmd_nopm; @@ -209,14 +224,14 @@ static int __ax88179_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, } static int __ax88179_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, - u16 size, const void *data, int in_pm) + u16 size, const void *data) { int ret; int (*fn)(struct usbnet *, u8, u8, u16, u16, const void *, u16); BUG_ON(!dev); - if (!in_pm) + if (!ax88179_in_pm(dev)) fn = usbnet_write_cmd; else fn = usbnet_write_cmd_nopm; @@ -249,47 +264,6 @@ static void ax88179_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, } } -static int ax88179_read_cmd_nopm(struct usbnet *dev, u8 cmd, u16 value, - u16 index, u16 size, void *data) -{ - int ret; - - if (2 == size) { - u16 buf; - ret = __ax88179_read_cmd(dev, cmd, value, index, size, &buf, 1); - le16_to_cpus(&buf); - *((u16 *)data) = buf; - } else if (4 == size) { - u32 buf; - ret = __ax88179_read_cmd(dev, cmd, value, index, size, &buf, 1); - le32_to_cpus(&buf); - *((u32 *)data) = buf; - } else { - ret = __ax88179_read_cmd(dev, cmd, value, index, size, data, 1); - } - - return ret; -} - -static int ax88179_write_cmd_nopm(struct usbnet *dev, u8 cmd, u16 value, - u16 index, u16 size, const void *data) -{ - int ret; - - if (2 == size) { - u16 buf; - buf = *((u16 *)data); - cpu_to_le16s(&buf); - ret = __ax88179_write_cmd(dev, cmd, value, index, - size, &buf, 1); - } else { - ret = __ax88179_write_cmd(dev, cmd, value, index, - size, data, 1); - } - - return ret; -} - static int ax88179_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, u16 size, void *data) { @@ -297,16 +271,16 @@ static int ax88179_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, if (2 == size) { u16 buf = 0; - ret = __ax88179_read_cmd(dev, cmd, value, index, size, &buf, 0); + ret = __ax88179_read_cmd(dev, cmd, value, index, size, &buf); le16_to_cpus(&buf); *((u16 *)data) = buf; } else if (4 == size) { u32 buf = 0; - ret = __ax88179_read_cmd(dev, cmd, value, index, size, &buf, 0); + ret = __ax88179_read_cmd(dev, cmd, value, index, size, &buf); le32_to_cpus(&buf); *((u32 *)data) = buf; } else { - ret = __ax88179_read_cmd(dev, cmd, value, index, size, data, 0); + ret = __ax88179_read_cmd(dev, cmd, value, index, size, data); } return ret; @@ -322,10 +296,10 @@ static int ax88179_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, buf = *((u16 *)data); cpu_to_le16s(&buf); ret = __ax88179_write_cmd(dev, cmd, value, index, - size, &buf, 0); + size, &buf); } else { ret = __ax88179_write_cmd(dev, cmd, value, index, - size, data, 0); + size, data); } return ret; @@ -428,52 +402,46 @@ static int ax88179_suspend(struct usb_interface *intf, pm_message_t message) u16 tmp16; u8 tmp8; + ax88179_set_pm_mode(dev, true); + usbnet_suspend(intf, message); /* Disable RX path */ - ax88179_read_cmd_nopm(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, - 2, 2, &tmp16); + ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, + 2, 2, &tmp16); tmp16 &= ~AX_MEDIUM_RECEIVE_EN; - ax88179_write_cmd_nopm(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, - 2, 2, &tmp16); + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, + 2, 2, &tmp16); /* Force bulk-in zero length */ - ax88179_read_cmd_nopm(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, - 2, 2, &tmp16); + ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, + 2, 2, &tmp16); tmp16 |= AX_PHYPWR_RSTCTL_BZ | AX_PHYPWR_RSTCTL_IPRL; - ax88179_write_cmd_nopm(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, - 2, 2, &tmp16); + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, + 2, 2, &tmp16); /* change clock */ tmp8 = 0; - ax88179_write_cmd_nopm(dev, AX_ACCESS_MAC, AX_CLK_SELECT, 1, 1, &tmp8); + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_CLK_SELECT, 1, 1, &tmp8); /* Configure RX control register => stop operation */ tmp16 = AX_RX_CTL_STOP; - ax88179_write_cmd_nopm(dev, AX_ACCESS_MAC, AX_RX_CTL, 2, 2, &tmp16); + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RX_CTL, 2, 2, &tmp16); + + ax88179_set_pm_mode(dev, false); return 0; } /* This function is used to enable the autodetach function. */ /* This function is determined by offset 0x43 of EEPROM */ -static int ax88179_auto_detach(struct usbnet *dev, int in_pm) +static int ax88179_auto_detach(struct usbnet *dev) { u16 tmp16; u8 tmp8; - int (*fnr)(struct usbnet *, u8, u16, u16, u16, void *); - int (*fnw)(struct usbnet *, u8, u16, u16, u16, const void *); - - if (!in_pm) { - fnr = ax88179_read_cmd; - fnw = ax88179_write_cmd; - } else { - fnr = ax88179_read_cmd_nopm; - fnw = ax88179_write_cmd_nopm; - } - if (fnr(dev, AX_ACCESS_EEPROM, 0x43, 1, 2, &tmp16) < 0) + if (ax88179_read_cmd(dev, AX_ACCESS_EEPROM, 0x43, 1, 2, &tmp16) < 0) return 0; if ((tmp16 == 0xFFFF) || (!(tmp16 & 0x0100))) @@ -481,13 +449,13 @@ static int ax88179_auto_detach(struct usbnet *dev, int in_pm) /* Enable Auto Detach bit */ tmp8 = 0; - fnr(dev, AX_ACCESS_MAC, AX_CLK_SELECT, 1, 1, &tmp8); + ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_CLK_SELECT, 1, 1, &tmp8); tmp8 |= AX_CLK_SELECT_ULR; - fnw(dev, AX_ACCESS_MAC, AX_CLK_SELECT, 1, 1, &tmp8); + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_CLK_SELECT, 1, 1, &tmp8); - fnr(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, 2, 2, &tmp16); + ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, 2, 2, &tmp16); tmp16 |= AX_PHYPWR_RSTCTL_AT; - fnw(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, 2, 2, &tmp16); + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, 2, 2, &tmp16); return 0; } @@ -498,32 +466,36 @@ static int ax88179_resume(struct usb_interface *intf) u16 tmp16; u8 tmp8; + ax88179_set_pm_mode(dev, true); + usbnet_link_change(dev, 0, 0); /* Power up ethernet PHY */ tmp16 = 0; - ax88179_write_cmd_nopm(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, - 2, 2, &tmp16); + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, + 2, 2, &tmp16); udelay(1000); tmp16 = AX_PHYPWR_RSTCTL_IPRL; - ax88179_write_cmd_nopm(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, - 2, 2, &tmp16); + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, + 2, 2, &tmp16); msleep(200); /* Ethernet PHY Auto Detach*/ - ax88179_auto_detach(dev, 1); + ax88179_auto_detach(dev); /* Enable clock */ - ax88179_read_cmd_nopm(dev, AX_ACCESS_MAC, AX_CLK_SELECT, 1, 1, &tmp8); + ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_CLK_SELECT, 1, 1, &tmp8); tmp8 |= AX_CLK_SELECT_ACS | AX_CLK_SELECT_BCS; - ax88179_write_cmd_nopm(dev, AX_ACCESS_MAC, AX_CLK_SELECT, 1, 1, &tmp8); + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_CLK_SELECT, 1, 1, &tmp8); msleep(100); /* Configure RX control register => start operation */ tmp16 = AX_RX_CTL_DROPCRCERR | AX_RX_CTL_IPE | AX_RX_CTL_START | AX_RX_CTL_AP | AX_RX_CTL_AMALL | AX_RX_CTL_AB; - ax88179_write_cmd_nopm(dev, AX_ACCESS_MAC, AX_RX_CTL, 2, 2, &tmp16); + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RX_CTL, 2, 2, &tmp16); + + ax88179_set_pm_mode(dev, false); return usbnet_resume(intf); } @@ -599,8 +571,7 @@ ax88179_get_eeprom(struct net_device *net, struct ethtool_eeprom *eeprom, /* ax88179/178A returns 2 bytes from eeprom on read */ for (i = first_word; i <= last_word; i++) { ret = __ax88179_read_cmd(dev, AX_ACCESS_EEPROM, i, 1, 2, - &eeprom_buff[i - first_word], - 0); + &eeprom_buff[i - first_word]); if (ret < 0) { kfree(eeprom_buff); return -EIO; @@ -1069,7 +1040,7 @@ static int ax88179_check_eeprom(struct usbnet *dev) } while (buf & EEP_BUSY); __ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_SROM_DATA_LOW, - 2, 2, &eeprom[i * 2], 0); + 2, 2, &eeprom[i * 2]); if ((i == 0) && (eeprom[0] == 0xFF)) return -EINVAL; @@ -1707,7 +1678,7 @@ static int ax88179_reset(struct usbnet *dev) msleep(200); /* Ethernet PHY Auto Detach*/ - ax88179_auto_detach(dev, 0); + ax88179_auto_detach(dev); /* Read MAC address from DTB or asix chip */ ax88179_get_mac_addr(dev); -- cgit v1.2.3 From f860413aa00c4e1fbdf3508ea3131e602457c73b Mon Sep 17 00:00:00 2001 From: Justin Chen Date: Wed, 20 Jul 2022 17:28:16 -0700 Subject: net: usb: ax88179_178a: wol optimizations [ Upstream commit 5050531610a64f08461e0c309db80ca51b779fd5 ] - Check if wol is supported on reset instead of everytime get_wol is called. - Save wolopts in private data instead of relying on the HW to save it. - Defer enabling WoL until suspend instead of enabling it everytime set_wol is called. Signed-off-by: Justin Chen Signed-off-by: Jakub Kicinski Stable-dep-of: aef05e349bfd ("net: usb: ax88179_178a: avoid failed operations when device is disconnected") Signed-off-by: Sasha Levin --- drivers/net/usb/ax88179_178a.c | 52 +++++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c index bd258c4e1394..49d97ad37665 100644 --- a/drivers/net/usb/ax88179_178a.c +++ b/drivers/net/usb/ax88179_178a.c @@ -170,6 +170,8 @@ struct ax88179_data { u16 rxctl; u16 reserved; u8 in_pm; + u32 wol_supported; + u32 wolopts; }; struct ax88179_int_data { @@ -399,6 +401,7 @@ ax88179_phy_write_mmd_indirect(struct usbnet *dev, u16 prtad, u16 devad, static int ax88179_suspend(struct usb_interface *intf, pm_message_t message) { struct usbnet *dev = usb_get_intfdata(intf); + struct ax88179_data *priv = dev->driver_priv; u16 tmp16; u8 tmp8; @@ -406,6 +409,19 @@ static int ax88179_suspend(struct usb_interface *intf, pm_message_t message) usbnet_suspend(intf, message); + /* Enable WoL */ + if (priv->wolopts) { + ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_MONITOR_MOD, + 1, 1, &tmp8); + if (priv->wolopts & WAKE_PHY) + tmp8 |= AX_MONITOR_MODE_RWLC; + if (priv->wolopts & WAKE_MAGIC) + tmp8 |= AX_MONITOR_MODE_RWMP; + + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MONITOR_MOD, + 1, 1, &tmp8); + } + /* Disable RX path */ ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, 2, 2, &tmp16); @@ -504,40 +520,22 @@ static void ax88179_get_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo) { struct usbnet *dev = netdev_priv(net); - u8 opt; - - if (ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_MONITOR_MOD, - 1, 1, &opt) < 0) { - wolinfo->supported = 0; - wolinfo->wolopts = 0; - return; - } + struct ax88179_data *priv = dev->driver_priv; - wolinfo->supported = WAKE_PHY | WAKE_MAGIC; - wolinfo->wolopts = 0; - if (opt & AX_MONITOR_MODE_RWLC) - wolinfo->wolopts |= WAKE_PHY; - if (opt & AX_MONITOR_MODE_RWMP) - wolinfo->wolopts |= WAKE_MAGIC; + wolinfo->supported = priv->wol_supported; + wolinfo->wolopts = priv->wolopts; } static int ax88179_set_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo) { struct usbnet *dev = netdev_priv(net); - u8 opt = 0; + struct ax88179_data *priv = dev->driver_priv; - if (wolinfo->wolopts & ~(WAKE_PHY | WAKE_MAGIC)) + if (wolinfo->wolopts & ~(priv->wol_supported)) return -EINVAL; - if (wolinfo->wolopts & WAKE_PHY) - opt |= AX_MONITOR_MODE_RWLC; - if (wolinfo->wolopts & WAKE_MAGIC) - opt |= AX_MONITOR_MODE_RWMP; - - if (ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MONITOR_MOD, - 1, 1, &opt) < 0) - return -EINVAL; + priv->wolopts = wolinfo->wolopts; return 0; } @@ -1727,6 +1725,12 @@ static int ax88179_reset(struct usbnet *dev) ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, 2, 2, tmp16); + /* Check if WoL is supported */ + ax179_data->wol_supported = 0; + if (ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_MONITOR_MOD, + 1, 1, &tmp) > 0) + ax179_data->wol_supported = WAKE_MAGIC | WAKE_PHY; + ax88179_led_setting(dev); ax179_data->eee_enabled = 0; -- cgit v1.2.3 From d63fafd6cc28840a947fe02f367ec277347c4832 Mon Sep 17 00:00:00 2001 From: Jose Ignacio Tornos Martinez Date: Thu, 7 Dec 2023 18:50:07 +0100 Subject: net: usb: ax88179_178a: avoid failed operations when device is disconnected [ Upstream commit aef05e349bfd81c95adb4489639413fadbb74a83 ] When the device is disconnected we get the following messages showing failed operations: Nov 28 20:22:11 localhost kernel: usb 2-3: USB disconnect, device number 2 Nov 28 20:22:11 localhost kernel: ax88179_178a 2-3:1.0 enp2s0u3: unregister 'ax88179_178a' usb-0000:02:00.0-3, ASIX AX88179 USB 3.0 Gigabit Ethernet Nov 28 20:22:11 localhost kernel: ax88179_178a 2-3:1.0 enp2s0u3: Failed to read reg index 0x0002: -19 Nov 28 20:22:11 localhost kernel: ax88179_178a 2-3:1.0 enp2s0u3: Failed to write reg index 0x0002: -19 Nov 28 20:22:11 localhost kernel: ax88179_178a 2-3:1.0 enp2s0u3 (unregistered): Failed to write reg index 0x0002: -19 Nov 28 20:22:11 localhost kernel: ax88179_178a 2-3:1.0 enp2s0u3 (unregistered): Failed to write reg index 0x0001: -19 Nov 28 20:22:11 localhost kernel: ax88179_178a 2-3:1.0 enp2s0u3 (unregistered): Failed to write reg index 0x0002: -19 The reason is that although the device is detached, normal stop and unbind operations are commanded from the driver. These operations are not necessary in this situation, so avoid these logs when the device is detached if the result of the operation is -ENODEV and if the new flag informing about the disconnecting status is enabled. cc: Fixes: e2ca90c276e1f ("ax88179_178a: ASIX AX88179_178A USB 3.0/2.0 to gigabit ethernet adapter driver") Signed-off-by: Jose Ignacio Tornos Martinez Acked-by: Alan Stern Link: https://lore.kernel.org/r/20231207175007.263907-1-jtornosm@redhat.com Signed-off-by: Greg Kroah-Hartman Signed-off-by: Sasha Levin --- drivers/net/usb/ax88179_178a.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c index 49d97ad37665..a2b1f9a0c6d9 100644 --- a/drivers/net/usb/ax88179_178a.c +++ b/drivers/net/usb/ax88179_178a.c @@ -172,6 +172,7 @@ struct ax88179_data { u8 in_pm; u32 wol_supported; u32 wolopts; + u8 disconnecting; }; struct ax88179_int_data { @@ -207,6 +208,7 @@ static int __ax88179_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, { int ret; int (*fn)(struct usbnet *, u8, u8, u16, u16, void *, u16); + struct ax88179_data *ax179_data = dev->driver_priv; BUG_ON(!dev); @@ -218,7 +220,7 @@ static int __ax88179_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, ret = fn(dev, cmd, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, value, index, data, size); - if (unlikely(ret < 0)) + if (unlikely((ret < 0) && !(ret == -ENODEV && ax179_data->disconnecting))) netdev_warn(dev->net, "Failed to read reg index 0x%04x: %d\n", index, ret); @@ -230,6 +232,7 @@ static int __ax88179_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, { int ret; int (*fn)(struct usbnet *, u8, u8, u16, u16, const void *, u16); + struct ax88179_data *ax179_data = dev->driver_priv; BUG_ON(!dev); @@ -241,7 +244,7 @@ static int __ax88179_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, ret = fn(dev, cmd, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, value, index, data, size); - if (unlikely(ret < 0)) + if (unlikely((ret < 0) && !(ret == -ENODEV && ax179_data->disconnecting))) netdev_warn(dev->net, "Failed to write reg index 0x%04x: %d\n", index, ret); @@ -516,6 +519,20 @@ static int ax88179_resume(struct usb_interface *intf) return usbnet_resume(intf); } +static void ax88179_disconnect(struct usb_interface *intf) +{ + struct usbnet *dev = usb_get_intfdata(intf); + struct ax88179_data *ax179_data; + + if (!dev) + return; + + ax179_data = dev->driver_priv; + ax179_data->disconnecting = 1; + + usbnet_disconnect(intf); +} + static void ax88179_get_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo) { @@ -1946,7 +1963,7 @@ static struct usb_driver ax88179_178a_driver = { .suspend = ax88179_suspend, .resume = ax88179_resume, .reset_resume = ax88179_resume, - .disconnect = usbnet_disconnect, + .disconnect = ax88179_disconnect, .supports_autosuspend = 1, .disable_hub_initiated_lpm = 1, }; -- cgit v1.2.3 From fcf6fce2f147431a8423df382b3c9b7d7c3f34f7 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 22 Sep 2022 16:54:10 +0300 Subject: device property: Add const qualifier to device_get_match_data() parameter [ Upstream commit aade55c86033bee868a93e4bf3843c9c99e84526 ] Add const qualifier to the device_get_match_data() parameter. Some of the future users may utilize this function without forcing the type. All the same, dev_fwnode() may be used with a const qualifier. Reported-by: kernel test robot Acked-by: Heikki Krogerus Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20220922135410.49694-1-andriy.shevchenko@linux.intel.com Signed-off-by: Greg Kroah-Hartman Signed-off-by: Sasha Levin --- drivers/base/property.c | 4 ++-- include/linux/property.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/base/property.c b/drivers/base/property.c index 17a648d64356..2ed844650328 100644 --- a/drivers/base/property.c +++ b/drivers/base/property.c @@ -18,7 +18,7 @@ #include #include -struct fwnode_handle *dev_fwnode(struct device *dev) +struct fwnode_handle *dev_fwnode(const struct device *dev) { return IS_ENABLED(CONFIG_OF) && dev->of_node ? of_fwnode_handle(dev->of_node) : dev->fwnode; @@ -1281,7 +1281,7 @@ int fwnode_graph_parse_endpoint(const struct fwnode_handle *fwnode, } EXPORT_SYMBOL(fwnode_graph_parse_endpoint); -const void *device_get_match_data(struct device *dev) +const void *device_get_match_data(const struct device *dev) { return fwnode_call_ptr_op(dev_fwnode(dev), device_get_match_data, dev); } diff --git a/include/linux/property.h b/include/linux/property.h index 357513a977e5..1bd1e4ada7e3 100644 --- a/include/linux/property.h +++ b/include/linux/property.h @@ -31,7 +31,7 @@ enum dev_dma_attr { DEV_DMA_COHERENT, }; -struct fwnode_handle *dev_fwnode(struct device *dev); +struct fwnode_handle *dev_fwnode(const struct device *dev); bool device_property_present(struct device *dev, const char *propname); int device_property_read_u8_array(struct device *dev, const char *propname, @@ -385,7 +385,7 @@ bool device_dma_supported(struct device *dev); enum dev_dma_attr device_get_dma_attr(struct device *dev); -const void *device_get_match_data(struct device *dev); +const void *device_get_match_data(const struct device *dev); int device_get_phy_mode(struct device *dev); -- cgit v1.2.3 From bd1be85dbbbd4076e8dbdceefc3c4d2c673e0075 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 20 Oct 2022 22:54:21 +0300 Subject: spi: Introduce spi_get_device_match_data() helper [ Upstream commit aea672d054a21782ed8450c75febb6ba3c208ca4 ] The proposed spi_get_device_match_data() helper is for retrieving a driver data associated with the ID in an ID table. First, it tries to get driver data of the device enumerated by firmware interface (usually Device Tree or ACPI). If none is found it falls back to the SPI ID table matching. Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20221020195421.10482-1-andriy.shevchenko@linux.intel.com Signed-off-by: Mark Brown Stable-dep-of: ee4d79055aee ("iio: imu: adis16475: add spi_device_id table") Signed-off-by: Sasha Levin --- drivers/spi/spi.c | 12 ++++++++++++ include/linux/spi/spi.h | 3 +++ 2 files changed, 15 insertions(+) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 06dd1be54925..d4b186a35bb2 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -335,6 +335,18 @@ const struct spi_device_id *spi_get_device_id(const struct spi_device *sdev) } EXPORT_SYMBOL_GPL(spi_get_device_id); +const void *spi_get_device_match_data(const struct spi_device *sdev) +{ + const void *match; + + match = device_get_match_data(&sdev->dev); + if (match) + return match; + + return (const void *)spi_get_device_id(sdev)->driver_data; +} +EXPORT_SYMBOL_GPL(spi_get_device_match_data); + static int spi_match_device(struct device *dev, struct device_driver *drv) { const struct spi_device *spi = to_spi_device(dev); diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 6b0b686f6f90..9ab3dab9568a 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -1499,6 +1499,9 @@ extern void spi_unregister_device(struct spi_device *spi); extern const struct spi_device_id * spi_get_device_id(const struct spi_device *sdev); +extern const void * +spi_get_device_match_data(const struct spi_device *sdev); + static inline bool spi_transfer_is_last(struct spi_controller *ctlr, struct spi_transfer *xfer) { -- cgit v1.2.3 From 1228354a98893cc1b7531edc34fdd7f6aca753b7 Mon Sep 17 00:00:00 2001 From: Nuno Sa Date: Thu, 2 Nov 2023 13:52:58 +0100 Subject: iio: imu: adis16475: add spi_device_id table [ Upstream commit ee4d79055aeea27f1b8c42233cc0c90d0a8b5355 ] This prevents the warning message "SPI driver has no spi_device_id for..." when registering the driver. More importantly, it makes sure that module autoloading works as spi relies on spi: modaliases and not of. While at it, move the of_device_id table to it's natural place. Fixes: fff7352bf7a3c ("iio: imu: Add support for adis16475") Signed-off-by: Nuno Sa Link: https://lore.kernel.org/r/20231102125258.3284830-1-nuno.sa@analog.com Cc: Signed-off-by: Jonathan Cameron Signed-off-by: Sasha Levin --- drivers/iio/imu/adis16475.c | 117 +++++++++++++++++++++++++++----------------- 1 file changed, 72 insertions(+), 45 deletions(-) diff --git a/drivers/iio/imu/adis16475.c b/drivers/iio/imu/adis16475.c index 9d28534db3b0..a3b9745dd176 100644 --- a/drivers/iio/imu/adis16475.c +++ b/drivers/iio/imu/adis16475.c @@ -1273,50 +1273,6 @@ static int adis16475_config_irq_pin(struct adis16475 *st) return 0; } -static const struct of_device_id adis16475_of_match[] = { - { .compatible = "adi,adis16470", - .data = &adis16475_chip_info[ADIS16470] }, - { .compatible = "adi,adis16475-1", - .data = &adis16475_chip_info[ADIS16475_1] }, - { .compatible = "adi,adis16475-2", - .data = &adis16475_chip_info[ADIS16475_2] }, - { .compatible = "adi,adis16475-3", - .data = &adis16475_chip_info[ADIS16475_3] }, - { .compatible = "adi,adis16477-1", - .data = &adis16475_chip_info[ADIS16477_1] }, - { .compatible = "adi,adis16477-2", - .data = &adis16475_chip_info[ADIS16477_2] }, - { .compatible = "adi,adis16477-3", - .data = &adis16475_chip_info[ADIS16477_3] }, - { .compatible = "adi,adis16465-1", - .data = &adis16475_chip_info[ADIS16465_1] }, - { .compatible = "adi,adis16465-2", - .data = &adis16475_chip_info[ADIS16465_2] }, - { .compatible = "adi,adis16465-3", - .data = &adis16475_chip_info[ADIS16465_3] }, - { .compatible = "adi,adis16467-1", - .data = &adis16475_chip_info[ADIS16467_1] }, - { .compatible = "adi,adis16467-2", - .data = &adis16475_chip_info[ADIS16467_2] }, - { .compatible = "adi,adis16467-3", - .data = &adis16475_chip_info[ADIS16467_3] }, - { .compatible = "adi,adis16500", - .data = &adis16475_chip_info[ADIS16500] }, - { .compatible = "adi,adis16505-1", - .data = &adis16475_chip_info[ADIS16505_1] }, - { .compatible = "adi,adis16505-2", - .data = &adis16475_chip_info[ADIS16505_2] }, - { .compatible = "adi,adis16505-3", - .data = &adis16475_chip_info[ADIS16505_3] }, - { .compatible = "adi,adis16507-1", - .data = &adis16475_chip_info[ADIS16507_1] }, - { .compatible = "adi,adis16507-2", - .data = &adis16475_chip_info[ADIS16507_2] }, - { .compatible = "adi,adis16507-3", - .data = &adis16475_chip_info[ADIS16507_3] }, - { }, -}; -MODULE_DEVICE_TABLE(of, adis16475_of_match); static int adis16475_probe(struct spi_device *spi) { @@ -1330,7 +1286,7 @@ static int adis16475_probe(struct spi_device *spi) st = iio_priv(indio_dev); - st->info = device_get_match_data(&spi->dev); + st->info = spi_get_device_match_data(spi); if (!st->info) return -EINVAL; @@ -1370,12 +1326,83 @@ static int adis16475_probe(struct spi_device *spi) return 0; } +static const struct of_device_id adis16475_of_match[] = { + { .compatible = "adi,adis16470", + .data = &adis16475_chip_info[ADIS16470] }, + { .compatible = "adi,adis16475-1", + .data = &adis16475_chip_info[ADIS16475_1] }, + { .compatible = "adi,adis16475-2", + .data = &adis16475_chip_info[ADIS16475_2] }, + { .compatible = "adi,adis16475-3", + .data = &adis16475_chip_info[ADIS16475_3] }, + { .compatible = "adi,adis16477-1", + .data = &adis16475_chip_info[ADIS16477_1] }, + { .compatible = "adi,adis16477-2", + .data = &adis16475_chip_info[ADIS16477_2] }, + { .compatible = "adi,adis16477-3", + .data = &adis16475_chip_info[ADIS16477_3] }, + { .compatible = "adi,adis16465-1", + .data = &adis16475_chip_info[ADIS16465_1] }, + { .compatible = "adi,adis16465-2", + .data = &adis16475_chip_info[ADIS16465_2] }, + { .compatible = "adi,adis16465-3", + .data = &adis16475_chip_info[ADIS16465_3] }, + { .compatible = "adi,adis16467-1", + .data = &adis16475_chip_info[ADIS16467_1] }, + { .compatible = "adi,adis16467-2", + .data = &adis16475_chip_info[ADIS16467_2] }, + { .compatible = "adi,adis16467-3", + .data = &adis16475_chip_info[ADIS16467_3] }, + { .compatible = "adi,adis16500", + .data = &adis16475_chip_info[ADIS16500] }, + { .compatible = "adi,adis16505-1", + .data = &adis16475_chip_info[ADIS16505_1] }, + { .compatible = "adi,adis16505-2", + .data = &adis16475_chip_info[ADIS16505_2] }, + { .compatible = "adi,adis16505-3", + .data = &adis16475_chip_info[ADIS16505_3] }, + { .compatible = "adi,adis16507-1", + .data = &adis16475_chip_info[ADIS16507_1] }, + { .compatible = "adi,adis16507-2", + .data = &adis16475_chip_info[ADIS16507_2] }, + { .compatible = "adi,adis16507-3", + .data = &adis16475_chip_info[ADIS16507_3] }, + { }, +}; +MODULE_DEVICE_TABLE(of, adis16475_of_match); + +static const struct spi_device_id adis16475_ids[] = { + { "adis16470", (kernel_ulong_t)&adis16475_chip_info[ADIS16470] }, + { "adis16475-1", (kernel_ulong_t)&adis16475_chip_info[ADIS16475_1] }, + { "adis16475-2", (kernel_ulong_t)&adis16475_chip_info[ADIS16475_2] }, + { "adis16475-3", (kernel_ulong_t)&adis16475_chip_info[ADIS16475_3] }, + { "adis16477-1", (kernel_ulong_t)&adis16475_chip_info[ADIS16477_1] }, + { "adis16477-2", (kernel_ulong_t)&adis16475_chip_info[ADIS16477_2] }, + { "adis16477-3", (kernel_ulong_t)&adis16475_chip_info[ADIS16477_3] }, + { "adis16465-1", (kernel_ulong_t)&adis16475_chip_info[ADIS16465_1] }, + { "adis16465-2", (kernel_ulong_t)&adis16475_chip_info[ADIS16465_2] }, + { "adis16465-3", (kernel_ulong_t)&adis16475_chip_info[ADIS16465_3] }, + { "adis16467-1", (kernel_ulong_t)&adis16475_chip_info[ADIS16467_1] }, + { "adis16467-2", (kernel_ulong_t)&adis16475_chip_info[ADIS16467_2] }, + { "adis16467-3", (kernel_ulong_t)&adis16475_chip_info[ADIS16467_3] }, + { "adis16500", (kernel_ulong_t)&adis16475_chip_info[ADIS16500] }, + { "adis16505-1", (kernel_ulong_t)&adis16475_chip_info[ADIS16505_1] }, + { "adis16505-2", (kernel_ulong_t)&adis16475_chip_info[ADIS16505_2] }, + { "adis16505-3", (kernel_ulong_t)&adis16475_chip_info[ADIS16505_3] }, + { "adis16507-1", (kernel_ulong_t)&adis16475_chip_info[ADIS16507_1] }, + { "adis16507-2", (kernel_ulong_t)&adis16475_chip_info[ADIS16507_2] }, + { "adis16507-3", (kernel_ulong_t)&adis16475_chip_info[ADIS16507_3] }, + { } +}; +MODULE_DEVICE_TABLE(spi, adis16475_ids); + static struct spi_driver adis16475_driver = { .driver = { .name = "adis16475", .of_match_table = adis16475_of_match, }, .probe = adis16475_probe, + .id_table = adis16475_ids, }; module_spi_driver(adis16475_driver); -- cgit v1.2.3 From bfd18c0f570e4779cf2a36f6ebc462437348fbd4 Mon Sep 17 00:00:00 2001 From: Paulo Alcantara Date: Wed, 13 Dec 2023 12:25:57 -0300 Subject: smb: client: fix OOB in SMB2_query_info_init() [ Upstream commit 33eae65c6f49770fec7a662935d4eb4a6406d24b ] A small CIFS buffer (448 bytes) isn't big enough to hold SMB2_QUERY_INFO request along with user's input data from CIFS_QUERY_INFO ioctl. That is, if the user passed an input buffer > 344 bytes, the client will memcpy() off the end of @req->Buffer in SMB2_query_info_init() thus causing the following KASAN splat: BUG: KASAN: slab-out-of-bounds in SMB2_query_info_init+0x242/0x250 [cifs] Write of size 1023 at addr ffff88801308c5a8 by task a.out/1240 CPU: 1 PID: 1240 Comm: a.out Not tainted 6.7.0-rc4 #5 Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.16.2-3-gd478f380-rebuilt.opensuse.org 04/01/2014 Call Trace: dump_stack_lvl+0x4a/0x80 print_report+0xcf/0x650 ? srso_alias_return_thunk+0x5/0xfbef5 ? srso_alias_return_thunk+0x5/0xfbef5 ? srso_alias_return_thunk+0x5/0xfbef5 ? __phys_addr+0x46/0x90 kasan_report+0xd8/0x110 ? SMB2_query_info_init+0x242/0x250 [cifs] ? SMB2_query_info_init+0x242/0x250 [cifs] kasan_check_range+0x105/0x1b0 __asan_memcpy+0x3c/0x60 SMB2_query_info_init+0x242/0x250 [cifs] ? __pfx_SMB2_query_info_init+0x10/0x10 [cifs] ? srso_alias_return_thunk+0x5/0xfbef5 ? smb_rqst_len+0xa6/0xc0 [cifs] smb2_ioctl_query_info+0x4f4/0x9a0 [cifs] ? __pfx_smb2_ioctl_query_info+0x10/0x10 [cifs] ? __pfx_cifsConvertToUTF16+0x10/0x10 [cifs] ? kasan_set_track+0x25/0x30 ? srso_alias_return_thunk+0x5/0xfbef5 ? __kasan_kmalloc+0x8f/0xa0 ? srso_alias_return_thunk+0x5/0xfbef5 ? cifs_strndup_to_utf16+0x12d/0x1a0 [cifs] ? __build_path_from_dentry_optional_prefix+0x19d/0x2d0 [cifs] ? __pfx_smb2_ioctl_query_info+0x10/0x10 [cifs] cifs_ioctl+0x11c7/0x1de0 [cifs] ? __pfx_cifs_ioctl+0x10/0x10 [cifs] ? srso_alias_return_thunk+0x5/0xfbef5 ? rcu_is_watching+0x23/0x50 ? srso_alias_return_thunk+0x5/0xfbef5 ? __rseq_handle_notify_resume+0x6cd/0x850 ? __pfx___schedule+0x10/0x10 ? blkcg_iostat_update+0x250/0x290 ? srso_alias_return_thunk+0x5/0xfbef5 ? ksys_write+0xe9/0x170 __x64_sys_ioctl+0xc9/0x100 do_syscall_64+0x47/0xf0 entry_SYSCALL_64_after_hwframe+0x6f/0x77 RIP: 0033:0x7f893dde49cf Code: 00 48 89 44 24 18 31 c0 48 8d 44 24 60 c7 04 24 10 00 00 00 48 89 44 24 08 48 8d 44 24 20 48 89 44 24 10 b8 10 00 00 00 0f 05 <89> c2 3d 00 f0 ff ff 77 18 48 8b 44 24 18 64 48 2b 04 25 28 00 00 RSP: 002b:00007ffc03ff4160 EFLAGS: 00000246 ORIG_RAX: 0000000000000010 RAX: ffffffffffffffda RBX: 00007ffc03ff4378 RCX: 00007f893dde49cf RDX: 00007ffc03ff41d0 RSI: 00000000c018cf07 RDI: 0000000000000003 RBP: 00007ffc03ff4260 R08: 0000000000000410 R09: 0000000000000001 R10: 00007f893dce7300 R11: 0000000000000246 R12: 0000000000000000 R13: 00007ffc03ff4388 R14: 00007f893df15000 R15: 0000000000406de0 Fix this by increasing size of SMB2_QUERY_INFO request buffers and validating input length to prevent other callers from overflowing @req in SMB2_query_info_init() as well. Fixes: f5b05d622a3e ("cifs: add IOCTL for QUERY_INFO passthrough to userspace") Cc: stable@vger.kernel.org Reported-by: Robert Morris Signed-off-by: Paulo Alcantara Signed-off-by: Steve French Signed-off-by: Sasha Levin --- fs/cifs/smb2pdu.c | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index f51fea2e808d..6714e9db0ee8 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c @@ -364,10 +364,15 @@ static int __smb2_plain_req_init(__le16 smb2_command, struct cifs_tcon *tcon, void **request_buf, unsigned int *total_len) { /* BB eventually switch this to SMB2 specific small buf size */ - if (smb2_command == SMB2_SET_INFO) + switch (smb2_command) { + case SMB2_SET_INFO: + case SMB2_QUERY_INFO: *request_buf = cifs_buf_get(); - else + break; + default: *request_buf = cifs_small_buf_get(); + break; + } if (*request_buf == NULL) { /* BB should we add a retry in here if not a writepage? */ return -ENOMEM; @@ -3415,8 +3420,13 @@ SMB2_query_info_init(struct cifs_tcon *tcon, struct TCP_Server_Info *server, struct smb2_query_info_req *req; struct kvec *iov = rqst->rq_iov; unsigned int total_len; + size_t len; int rc; + if (unlikely(check_add_overflow(input_len, sizeof(*req), &len) || + len > CIFSMaxBufSize)) + return -EINVAL; + rc = smb2_plain_req_init(SMB2_QUERY_INFO, tcon, server, (void **) &req, &total_len); if (rc) @@ -3438,7 +3448,7 @@ SMB2_query_info_init(struct cifs_tcon *tcon, struct TCP_Server_Info *server, iov[0].iov_base = (char *)req; /* 1 for Buffer */ - iov[0].iov_len = total_len - 1 + input_len; + iov[0].iov_len = len; return 0; } @@ -3446,7 +3456,7 @@ void SMB2_query_info_free(struct smb_rqst *rqst) { if (rqst && rqst->rq_iov) - cifs_small_buf_release(rqst->rq_iov[0].iov_base); /* request */ + cifs_buf_release(rqst->rq_iov[0].iov_base); /* request */ } static int @@ -5176,6 +5186,11 @@ build_qfs_info_req(struct kvec *iov, struct cifs_tcon *tcon, return 0; } +static inline void free_qfs_info_req(struct kvec *iov) +{ + cifs_buf_release(iov->iov_base); +} + int SMB311_posix_qfs_info(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, u64 volatile_fid, struct kstatfs *fsdata) @@ -5207,7 +5222,7 @@ SMB311_posix_qfs_info(const unsigned int xid, struct cifs_tcon *tcon, rc = cifs_send_recv(xid, ses, server, &rqst, &resp_buftype, flags, &rsp_iov); - cifs_small_buf_release(iov.iov_base); + free_qfs_info_req(&iov); if (rc) { cifs_stats_fail_inc(tcon, SMB2_QUERY_INFO_HE); goto posix_qfsinf_exit; @@ -5258,7 +5273,7 @@ SMB2_QFS_info(const unsigned int xid, struct cifs_tcon *tcon, rc = cifs_send_recv(xid, ses, server, &rqst, &resp_buftype, flags, &rsp_iov); - cifs_small_buf_release(iov.iov_base); + free_qfs_info_req(&iov); if (rc) { cifs_stats_fail_inc(tcon, SMB2_QUERY_INFO_HE); goto qfsinf_exit; @@ -5325,7 +5340,7 @@ SMB2_QFS_attr(const unsigned int xid, struct cifs_tcon *tcon, rc = cifs_send_recv(xid, ses, server, &rqst, &resp_buftype, flags, &rsp_iov); - cifs_small_buf_release(iov.iov_base); + free_qfs_info_req(&iov); if (rc) { cifs_stats_fail_inc(tcon, SMB2_QUERY_INFO_HE); goto qfsattr_exit; -- cgit v1.2.3 From ded3cfdefec8b2accc767f176419316b61c157c3 Mon Sep 17 00:00:00 2001 From: Paulo Alcantara Date: Fri, 15 Dec 2023 19:59:14 -0300 Subject: smb: client: fix OOB in smbCalcSize() [ Upstream commit b35858b3786ddbb56e1c35138ba25d6adf8d0bef ] Validate @smb->WordCount to avoid reading off the end of @smb and thus causing the following KASAN splat: BUG: KASAN: slab-out-of-bounds in smbCalcSize+0x32/0x40 [cifs] Read of size 2 at addr ffff88801c024ec5 by task cifsd/1328 CPU: 1 PID: 1328 Comm: cifsd Not tainted 6.7.0-rc5 #9 Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.16.2-3-gd478f380-rebuilt.opensuse.org 04/01/2014 Call Trace: dump_stack_lvl+0x4a/0x80 print_report+0xcf/0x650 ? srso_alias_return_thunk+0x5/0xfbef5 ? srso_alias_return_thunk+0x5/0xfbef5 ? __phys_addr+0x46/0x90 kasan_report+0xd8/0x110 ? smbCalcSize+0x32/0x40 [cifs] ? smbCalcSize+0x32/0x40 [cifs] kasan_check_range+0x105/0x1b0 smbCalcSize+0x32/0x40 [cifs] checkSMB+0x162/0x370 [cifs] ? __pfx_checkSMB+0x10/0x10 [cifs] cifs_handle_standard+0xbc/0x2f0 [cifs] ? srso_alias_return_thunk+0x5/0xfbef5 cifs_demultiplex_thread+0xed1/0x1360 [cifs] ? __pfx_cifs_demultiplex_thread+0x10/0x10 [cifs] ? srso_alias_return_thunk+0x5/0xfbef5 ? lockdep_hardirqs_on_prepare+0x136/0x210 ? __pfx_lock_release+0x10/0x10 ? srso_alias_return_thunk+0x5/0xfbef5 ? mark_held_locks+0x1a/0x90 ? lockdep_hardirqs_on_prepare+0x136/0x210 ? srso_alias_return_thunk+0x5/0xfbef5 ? srso_alias_return_thunk+0x5/0xfbef5 ? __kthread_parkme+0xce/0xf0 ? __pfx_cifs_demultiplex_thread+0x10/0x10 [cifs] kthread+0x18d/0x1d0 ? kthread+0xdb/0x1d0 ? __pfx_kthread+0x10/0x10 ret_from_fork+0x34/0x60 ? __pfx_kthread+0x10/0x10 ret_from_fork_asm+0x1b/0x30 This fixes CVE-2023-6606. Reported-by: j51569436@gmail.com Closes: https://bugzilla.kernel.org/show_bug.cgi?id=218218 Cc: stable@vger.kernel.org Signed-off-by: Paulo Alcantara (SUSE) Signed-off-by: Steve French Signed-off-by: Sasha Levin --- fs/cifs/misc.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index 5e4dab5dfb7a..33328eae03d7 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c @@ -340,6 +340,10 @@ checkSMB(char *buf, unsigned int total_read, struct TCP_Server_Info *server) cifs_dbg(VFS, "Length less than smb header size\n"); } return -EIO; + } else if (total_read < sizeof(*smb) + 2 * smb->WordCount) { + cifs_dbg(VFS, "%s: can't read BCC due to invalid WordCount(%u)\n", + __func__, smb->WordCount); + return -EIO; } /* otherwise, there is enough to get to the BCC */ -- cgit v1.2.3 From 2b16d960c79abc397f102c3d23d30005b68cb036 Mon Sep 17 00:00:00 2001 From: Hyunwoo Kim Date: Sat, 9 Dec 2023 05:55:18 -0500 Subject: Bluetooth: af_bluetooth: Fix Use-After-Free in bt_sock_recvmsg [ Upstream commit 2e07e8348ea454615e268222ae3fc240421be768 ] This can cause a race with bt_sock_ioctl() because bt_sock_recvmsg() gets the skb from sk->sk_receive_queue and then frees it without holding lock_sock. A use-after-free for a skb occurs with the following flow. ``` bt_sock_recvmsg() -> skb_recv_datagram() -> skb_free_datagram() bt_sock_ioctl() -> skb_peek() ``` Add lock_sock to bt_sock_recvmsg() to fix this issue. Cc: stable@vger.kernel.org Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Signed-off-by: Hyunwoo Kim Signed-off-by: Luiz Augusto von Dentz Signed-off-by: Sasha Levin --- net/bluetooth/af_bluetooth.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index ce744b14d1a9..b7498e890f0b 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c @@ -263,11 +263,14 @@ int bt_sock_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, if (flags & MSG_OOB) return -EOPNOTSUPP; + lock_sock(sk); + skb = skb_recv_datagram(sk, flags, noblock, &err); if (!skb) { if (sk->sk_shutdown & RCV_SHUTDOWN) - return 0; + err = 0; + release_sock(sk); return err; } @@ -293,6 +296,8 @@ int bt_sock_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, skb_free_datagram(sk, skb); + release_sock(sk); + if (flags & MSG_TRUNC) copied = skblen; -- cgit v1.2.3 From c0be52181f35448eaf5f9d0045c7543d6c1c7fbe Mon Sep 17 00:00:00 2001 From: Baokun Li Date: Wed, 13 Dec 2023 14:23:24 +0800 Subject: mm/filemap: avoid buffered read/write race to read inconsistent data commit e2c27b803bb664748e090d99042ac128b3f88d92 upstream. The following concurrency may cause the data read to be inconsistent with the data on disk: cpu1 cpu2 ------------------------------|------------------------------ // Buffered write 2048 from 0 ext4_buffered_write_iter generic_perform_write copy_page_from_iter_atomic ext4_da_write_end ext4_da_do_write_end block_write_end __block_commit_write folio_mark_uptodate // Buffered read 4096 from 0 smp_wmb() ext4_file_read_iter set_bit(PG_uptodate, folio_flags) generic_file_read_iter i_size_write // 2048 filemap_read unlock_page(page) filemap_get_pages filemap_get_read_batch folio_test_uptodate(folio) ret = test_bit(PG_uptodate, folio_flags) if (ret) smp_rmb(); // Ensure that the data in page 0-2048 is up-to-date. // New buffered write 2048 from 2048 ext4_buffered_write_iter generic_perform_write copy_page_from_iter_atomic ext4_da_write_end ext4_da_do_write_end block_write_end __block_commit_write folio_mark_uptodate smp_wmb() set_bit(PG_uptodate, folio_flags) i_size_write // 4096 unlock_page(page) isize = i_size_read(inode) // 4096 // Read the latest isize 4096, but without smp_rmb(), there may be // Load-Load disorder resulting in the data in the 2048-4096 range // in the page is not up-to-date. copy_page_to_iter // copyout 4096 In the concurrency above, we read the updated i_size, but there is no read barrier to ensure that the data in the page is the same as the i_size at this point, so we may copy the unsynchronized page out. Hence adding the missing read memory barrier to fix this. This is a Load-Load reordering issue, which only occurs on some weak mem-ordering architectures (e.g. ARM64, ALPHA), but not on strong mem-ordering architectures (e.g. X86). And theoretically the problem doesn't only happen on ext4, filesystems that call filemap_read() but don't hold inode lock (e.g. btrfs, f2fs, ubifs ...) will have this problem, while filesystems with inode lock (e.g. xfs, nfs) won't have this problem. Link: https://lkml.kernel.org/r/20231213062324.739009-1-libaokun1@huawei.com Signed-off-by: Baokun Li Reviewed-by: Jan Kara Cc: Andreas Dilger Cc: Christoph Hellwig Cc: Dave Chinner Cc: Matthew Wilcox (Oracle) Cc: Ritesh Harjani (IBM) Cc: Theodore Ts'o Cc: yangerkun Cc: Yu Kuai Cc: Zhang Yi Cc: Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- mm/filemap.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/mm/filemap.c b/mm/filemap.c index 84a5b0213e0e..b76deb24aeea 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -2648,6 +2648,15 @@ ssize_t filemap_read(struct kiocb *iocb, struct iov_iter *iter, goto put_pages; end_offset = min_t(loff_t, isize, iocb->ki_pos + iter->count); + /* + * Pairs with a barrier in + * block_write_end()->mark_buffer_dirty() or other page + * dirtying routines like iomap_write_end() to ensure + * changes to page contents are visible before we see + * increased inode size. + */ + smp_rmb(); + /* * Once we start copying data, we don't want to be touching any * cachelines that might be contended: -- cgit v1.2.3 From c73cb01af11f34086dc1e9588130eaa618a59259 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (Google)" Date: Tue, 26 Dec 2023 12:59:02 -0500 Subject: ring-buffer: Fix wake ups when buffer_percent is set to 100 commit 623b1f896fa8a669a277ee5a258307a16c7377a3 upstream. The tracefs file "buffer_percent" is to allow user space to set a water-mark on how much of the tracing ring buffer needs to be filled in order to wake up a blocked reader. 0 - is to wait until any data is in the buffer 1 - is to wait for 1% of the sub buffers to be filled 50 - would be half of the sub buffers are filled with data 100 - is not to wake the waiter until the ring buffer is completely full Unfortunately the test for being full was: dirty = ring_buffer_nr_dirty_pages(buffer, cpu); return (dirty * 100) > (full * nr_pages); Where "full" is the value for "buffer_percent". There is two issues with the above when full == 100. 1. dirty * 100 > 100 * nr_pages will never be true That is, the above is basically saying that if the user sets buffer_percent to 100, more pages need to be dirty than exist in the ring buffer! 2. The page that the writer is on is never considered dirty, as dirty pages are only those that are full. When the writer goes to a new sub-buffer, it clears the contents of that sub-buffer. That is, even if the check was ">=" it would still not be equal as the most pages that can be considered "dirty" is nr_pages - 1. To fix this, add one to dirty and use ">=" in the compare. Link: https://lore.kernel.org/linux-trace-kernel/20231226125902.4a057f1d@gandalf.local.home Cc: stable@vger.kernel.org Cc: Mark Rutland Cc: Mathieu Desnoyers Acked-by: Masami Hiramatsu (Google) Fixes: 03329f9939781 ("tracing: Add tracefs file buffer_percentage") Signed-off-by: Steven Rostedt (Google) Signed-off-by: Greg Kroah-Hartman --- kernel/trace/ring_buffer.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index 5fb88b5519dd..e5935a5524bb 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c @@ -897,9 +897,14 @@ static __always_inline bool full_hit(struct trace_buffer *buffer, int cpu, int f if (!nr_pages || !full) return true; - dirty = ring_buffer_nr_dirty_pages(buffer, cpu); + /* + * Add one as dirty will never equal nr_pages, as the sub-buffer + * that the writer is on is not counted as dirty. + * This is needed if "buffer_percent" is set to 100. + */ + dirty = ring_buffer_nr_dirty_pages(buffer, cpu) + 1; - return (dirty * 100) > (full * nr_pages); + return (dirty * 100) >= (full * nr_pages); } /* -- cgit v1.2.3 From 7fb264aedec94d6ed0b90d59687ed31651225cda Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (Google)" Date: Thu, 28 Dec 2023 09:51:49 -0500 Subject: tracing: Fix blocked reader of snapshot buffer commit 39a7dc23a1ed0fe81141792a09449d124c5953bd upstream. If an application blocks on the snapshot or snapshot_raw files, expecting to be woken up when a snapshot occurs, it will not happen. Or it may happen with an unexpected result. That result is that the application will be reading the main buffer instead of the snapshot buffer. That is because when the snapshot occurs, the main and snapshot buffers are swapped. But the reader has a descriptor still pointing to the buffer that it originally connected to. This is fine for the main buffer readers, as they may be blocked waiting for a watermark to be hit, and when a snapshot occurs, the data that the main readers want is now on the snapshot buffer. But for waiters of the snapshot buffer, they are waiting for an event to occur that will trigger the snapshot and they can then consume it quickly to save the snapshot before the next snapshot occurs. But to do this, they need to read the new snapshot buffer, not the old one that is now receiving new data. Also, it does not make sense to have a watermark "buffer_percent" on the snapshot buffer, as the snapshot buffer is static and does not receive new data except all at once. Link: https://lore.kernel.org/linux-trace-kernel/20231228095149.77f5b45d@gandalf.local.home Cc: stable@vger.kernel.org Cc: Mathieu Desnoyers Cc: Mark Rutland Acked-by: Masami Hiramatsu (Google) Fixes: debdd57f5145f ("tracing: Make a snapshot feature available from userspace") Signed-off-by: Steven Rostedt (Google) Signed-off-by: Greg Kroah-Hartman --- kernel/trace/ring_buffer.c | 3 ++- kernel/trace/trace.c | 20 +++++++++++++++++--- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index e5935a5524bb..305978256825 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c @@ -964,7 +964,8 @@ void ring_buffer_wake_waiters(struct trace_buffer *buffer, int cpu) /* make sure the waiters see the new index */ smp_wmb(); - rb_wake_up_waiters(&rbwork->work); + /* This can be called in any context */ + irq_work_queue(&rbwork->work); } /** diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index d1b7dbffbfe4..91ff118138c8 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -1837,6 +1837,9 @@ update_max_tr(struct trace_array *tr, struct task_struct *tsk, int cpu, __update_max_tr(tr, tsk, cpu); arch_spin_unlock(&tr->max_lock); + + /* Any waiters on the old snapshot buffer need to wake up */ + ring_buffer_wake_waiters(tr->array_buffer.buffer, RING_BUFFER_ALL_CPUS); } /** @@ -1888,12 +1891,23 @@ update_max_tr_single(struct trace_array *tr, struct task_struct *tsk, int cpu) static int wait_on_pipe(struct trace_iterator *iter, int full) { + int ret; + /* Iterators are static, they should be filled or empty */ if (trace_buffer_iter(iter, iter->cpu_file)) return 0; - return ring_buffer_wait(iter->array_buffer->buffer, iter->cpu_file, - full); + ret = ring_buffer_wait(iter->array_buffer->buffer, iter->cpu_file, full); + +#ifdef CONFIG_TRACER_MAX_TRACE + /* + * Make sure this is still the snapshot buffer, as if a snapshot were + * to happen, this would now be the main buffer. + */ + if (iter->snapshot) + iter->array_buffer = &iter->tr->max_buffer; +#endif + return ret; } #ifdef CONFIG_FTRACE_STARTUP_TEST @@ -8383,7 +8397,7 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos, wait_index = READ_ONCE(iter->wait_index); - ret = wait_on_pipe(iter, iter->tr->buffer_percent); + ret = wait_on_pipe(iter, iter->snapshot ? 0 : iter->tr->buffer_percent); if (ret) goto out; -- cgit v1.2.3 From 53bed9b9f43100e5e98af3cd21fcbb9a7f9b2d2a Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (Google)" Date: Fri, 15 Dec 2023 08:18:10 -0500 Subject: ring-buffer: Remove useless update to write_stamp in rb_try_to_discard() commit 083e9f65bd215582bf8f6a920db729fadf16704f upstream. When filtering is enabled, a temporary buffer is created to place the content of the trace event output so that the filter logic can decide from the trace event output if the trace event should be filtered out or not. If it is to be filtered out, the content in the temporary buffer is simply discarded, otherwise it is written into the trace buffer. But if an interrupt were to come in while a previous event was using that temporary buffer, the event written by the interrupt would actually go into the ring buffer itself to prevent corrupting the data on the temporary buffer. If the event is to be filtered out, the event in the ring buffer is discarded, or if it fails to discard because another event were to have already come in, it is turned into padding. The update to the write_stamp in the rb_try_to_discard() happens after a fix was made to force the next event after the discard to use an absolute timestamp by setting the before_stamp to zero so it does not match the write_stamp (which causes an event to use the absolute timestamp). But there's an effort in rb_try_to_discard() to put back the write_stamp to what it was before the event was added. But this is useless and wasteful because nothing is going to be using that write_stamp for calculations as it still will not match the before_stamp. Remove this useless update, and in doing so, we remove another cmpxchg64()! Also update the comments to reflect this change as well as remove some extra white space in another comment. Link: https://lore.kernel.org/linux-trace-kernel/20231215081810.1f4f38fe@rorschach.local.home Cc: Masami Hiramatsu Cc: Mark Rutland Cc: Mathieu Desnoyers Cc: Joel Fernandes Cc: Vincent Donnefort Fixes: b2dd797543cf ("ring-buffer: Force absolute timestamp on discard of event") Signed-off-by: Steven Rostedt (Google) Signed-off-by: Greg Kroah-Hartman --- kernel/trace/ring_buffer.c | 47 +++++++++++----------------------------------- 1 file changed, 11 insertions(+), 36 deletions(-) diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index 305978256825..f7e79344657d 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c @@ -2942,25 +2942,6 @@ static unsigned rb_calculate_event_length(unsigned length) return length; } -static u64 rb_time_delta(struct ring_buffer_event *event) -{ - switch (event->type_len) { - case RINGBUF_TYPE_PADDING: - return 0; - - case RINGBUF_TYPE_TIME_EXTEND: - return rb_event_time_stamp(event); - - case RINGBUF_TYPE_TIME_STAMP: - return 0; - - case RINGBUF_TYPE_DATA: - return event->time_delta; - default: - return 0; - } -} - static inline int rb_try_to_discard(struct ring_buffer_per_cpu *cpu_buffer, struct ring_buffer_event *event) @@ -2969,8 +2950,6 @@ rb_try_to_discard(struct ring_buffer_per_cpu *cpu_buffer, struct buffer_page *bpage; unsigned long index; unsigned long addr; - u64 write_stamp; - u64 delta; new_index = rb_event_index(event); old_index = new_index + rb_event_ts_length(event); @@ -2979,14 +2958,10 @@ rb_try_to_discard(struct ring_buffer_per_cpu *cpu_buffer, bpage = READ_ONCE(cpu_buffer->tail_page); - delta = rb_time_delta(event); - - if (!rb_time_read(&cpu_buffer->write_stamp, &write_stamp)) - return 0; - - /* Make sure the write stamp is read before testing the location */ - barrier(); - + /* + * Make sure the tail_page is still the same and + * the next write location is the end of this event + */ if (bpage->page == (void *)addr && rb_page_write(bpage) == old_index) { unsigned long write_mask = local_read(&bpage->write) & ~RB_WRITE_MASK; @@ -2997,20 +2972,20 @@ rb_try_to_discard(struct ring_buffer_per_cpu *cpu_buffer, * to make sure that the next event adds an absolute * value and does not rely on the saved write stamp, which * is now going to be bogus. + * + * By setting the before_stamp to zero, the next event + * is not going to use the write_stamp and will instead + * create an absolute timestamp. This means there's no + * reason to update the wirte_stamp! */ rb_time_set(&cpu_buffer->before_stamp, 0); - /* Something came in, can't discard */ - if (!rb_time_cmpxchg(&cpu_buffer->write_stamp, - write_stamp, write_stamp - delta)) - return 0; - /* * If an event were to come in now, it would see that the * write_stamp and the before_stamp are different, and assume * that this event just added itself before updating * the write stamp. The interrupting event will fix the - * write stamp for us, and use the before stamp as its delta. + * write stamp for us, and use an absolute timestamp. */ /* @@ -3449,7 +3424,7 @@ static void check_buffer(struct ring_buffer_per_cpu *cpu_buffer, return; /* - * If this interrupted another event, + * If this interrupted another event, */ if (atomic_inc_return(this_cpu_ptr(&checking)) != 1) goto out; -- cgit v1.2.3 From d739f2b6d8f57aa9377362cd8c0b1152a4dd6bd5 Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Wed, 20 Dec 2023 15:52:11 +0900 Subject: ksmbd: fix slab-out-of-bounds in smb_strndup_from_utf16() commit d10c77873ba1e9e6b91905018e29e196fd5f863d upstream. If ->NameOffset/Length is bigger than ->CreateContextsOffset/Length, ksmbd_check_message doesn't validate request buffer it correctly. So slab-out-of-bounds warning from calling smb_strndup_from_utf16() in smb2_open() could happen. If ->NameLength is non-zero, Set the larger of the two sums (Name and CreateContext size) as the offset and length of the data area. Reported-by: Yang Chaoming Cc: stable@vger.kernel.org Signed-off-by: Namjae Jeon Signed-off-by: Steve French Signed-off-by: Greg Kroah-Hartman --- fs/ksmbd/smb2misc.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/fs/ksmbd/smb2misc.c b/fs/ksmbd/smb2misc.c index 39e523f115d2..4d1211bde190 100644 --- a/fs/ksmbd/smb2misc.c +++ b/fs/ksmbd/smb2misc.c @@ -107,16 +107,25 @@ static int smb2_get_data_area_len(unsigned int *off, unsigned int *len, break; case SMB2_CREATE: { + unsigned short int name_off = + le16_to_cpu(((struct smb2_create_req *)hdr)->NameOffset); + unsigned short int name_len = + le16_to_cpu(((struct smb2_create_req *)hdr)->NameLength); + if (((struct smb2_create_req *)hdr)->CreateContextsLength) { *off = le32_to_cpu(((struct smb2_create_req *) hdr)->CreateContextsOffset); *len = le32_to_cpu(((struct smb2_create_req *) hdr)->CreateContextsLength); - break; + if (!name_len) + break; + + if (name_off + name_len < (u64)*off + *len) + break; } - *off = le16_to_cpu(((struct smb2_create_req *)hdr)->NameOffset); - *len = le16_to_cpu(((struct smb2_create_req *)hdr)->NameLength); + *off = name_off; + *len = name_len; break; } case SMB2_QUERY_INFO: -- cgit v1.2.3 From d10f7540c5541ad9f4fe2a02a73153d25d4a540d Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Tue, 19 Dec 2023 19:44:49 +0100 Subject: netfilter: nf_tables: skip set commit for deleted/destroyed sets commit 7315dc1e122c85ffdfc8defffbb8f8b616c2eb1a upstream. NFT_MSG_DELSET deactivates all elements in the set, skip set->ops->commit() to avoid the unnecessary clone (for the pipapo case) as well as the sync GC cycle, which could deactivate again expired elements in such set. Fixes: 5f68718b34a5 ("netfilter: nf_tables: GC transaction API to avoid race with control plane") Reported-by: Kevin Rich Signed-off-by: Pablo Neira Ayuso Signed-off-by: Greg Kroah-Hartman --- net/netfilter/nf_tables_api.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 20c2b4f5e893..3ee0f632a942 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -9256,7 +9256,7 @@ static void nft_set_commit_update(struct list_head *set_update_list) list_for_each_entry_safe(set, next, set_update_list, pending_update) { list_del_init(&set->pending_update); - if (!set->ops->commit) + if (!set->ops->commit || set->dead) continue; set->ops->commit(set); -- cgit v1.2.3 From a033bb82a10cfc312a4d9655fc878ef501c96b95 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (Google)" Date: Mon, 18 Dec 2023 23:07:12 -0500 Subject: ring-buffer: Fix slowpath of interrupted event commit b803d7c664d55705831729d2f2e29c874bcd62ea upstream. To synchronize the timestamps with the ring buffer reservation, there are two timestamps that are saved in the buffer meta data. 1. before_stamp 2. write_stamp When the two are equal, the write_stamp is considered valid, as in, it may be used to calculate the delta of the next event as the write_stamp is the timestamp of the previous reserved event on the buffer. This is done by the following: /*A*/ w = current position on the ring buffer before = before_stamp after = write_stamp ts = read current timestamp if (before != after) { write_stamp is not valid, force adding an absolute timestamp. } /*B*/ before_stamp = ts /*C*/ write = local_add_return(event length, position on ring buffer) if (w == write - event length) { /* Nothing interrupted between A and C */ /*E*/ write_stamp = ts; delta = ts - after /* * If nothing interrupted again, * before_stamp == write_stamp and write_stamp * can be used to calculate the delta for * events that come in after this one. */ } else { /* * The slow path! * Was interrupted between A and C. */ This is the place that there's a bug. We currently have: after = write_stamp ts = read current timestamp /*F*/ if (write == current position on the ring buffer && after < ts && cmpxchg(write_stamp, after, ts)) { delta = ts - after; } else { delta = 0; } The assumption is that if the current position on the ring buffer hasn't moved between C and F, then it also was not interrupted, and that the last event written has a timestamp that matches the write_stamp. That is the write_stamp is valid. But this may not be the case: If a task context event was interrupted by softirq between B and C. And the softirq wrote an event that got interrupted by a hard irq between C and E. and the hard irq wrote an event (does not need to be interrupted) We have: /*B*/ before_stamp = ts of normal context ---> interrupted by softirq /*B*/ before_stamp = ts of softirq context ---> interrupted by hardirq /*B*/ before_stamp = ts of hard irq context /*E*/ write_stamp = ts of hard irq context /* matches and write_stamp valid */ <---- /*E*/ write_stamp = ts of softirq context /* No longer matches before_stamp, write_stamp is not valid! */ <--- w != write - length, go to slow path // Right now the order of events in the ring buffer is: // // |-- softirq event --|-- hard irq event --|-- normal context event --| // after = write_stamp (this is the ts of softirq) ts = read current timestamp if (write == current position on the ring buffer [true] && after < ts [true] && cmpxchg(write_stamp, after, ts) [true]) { delta = ts - after [Wrong!] The delta is to be between the hard irq event and the normal context event, but the above logic made the delta between the softirq event and the normal context event, where the hard irq event is between the two. This will shift all the remaining event timestamps on the sub-buffer incorrectly. The write_stamp is only valid if it matches the before_stamp. The cmpxchg does nothing to help this. Instead, the following logic can be done to fix this: before = before_stamp ts = read current timestamp before_stamp = ts after = write_stamp if (write == current position on the ring buffer && after == before && after < ts) { delta = ts - after } else { delta = 0; } The above will only use the write_stamp if it still matches before_stamp and was tested to not have changed since C. As a bonus, with this logic we do not need any 64-bit cmpxchg() at all! This means the 32-bit rb_time_t workaround can finally be removed. But that's for a later time. Link: https://lore.kernel.org/linux-trace-kernel/20231218175229.58ec3daf@gandalf.local.home/ Link: https://lore.kernel.org/linux-trace-kernel/20231218230712.3a76b081@gandalf.local.home Cc: stable@vger.kernel.org Cc: Masami Hiramatsu Cc: Mark Rutland Cc: Mathieu Desnoyers Cc: Linus Torvalds Fixes: dd93942570789 ("ring-buffer: Do not try to put back write_stamp") Signed-off-by: Steven Rostedt (Google) Signed-off-by: Greg Kroah-Hartman --- kernel/trace/ring_buffer.c | 77 +++++++++++++++------------------------------- 1 file changed, 24 insertions(+), 53 deletions(-) diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index f7e79344657d..65a728b89574 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c @@ -691,44 +691,6 @@ rb_time_read_cmpxchg(local_t *l, unsigned long expect, unsigned long set) return ret == expect; } -static int rb_time_cmpxchg(rb_time_t *t, u64 expect, u64 set) -{ - unsigned long cnt, top, bottom; - unsigned long cnt2, top2, bottom2; - u64 val; - - /* Any interruptions in this function should cause a failure */ - cnt = local_read(&t->cnt); - - /* The cmpxchg always fails if it interrupted an update */ - if (!__rb_time_read(t, &val, &cnt2)) - return false; - - if (val != expect) - return false; - - if ((cnt & 3) != cnt2) - return false; - - cnt2 = cnt + 1; - - rb_time_split(val, &top, &bottom); - top = rb_time_val_cnt(top, cnt); - bottom = rb_time_val_cnt(bottom, cnt); - - rb_time_split(set, &top2, &bottom2); - top2 = rb_time_val_cnt(top2, cnt2); - bottom2 = rb_time_val_cnt(bottom2, cnt2); - - if (!rb_time_read_cmpxchg(&t->cnt, cnt, cnt2)) - return false; - if (!rb_time_read_cmpxchg(&t->top, top, top2)) - return false; - if (!rb_time_read_cmpxchg(&t->bottom, bottom, bottom2)) - return false; - return true; -} - #else /* 64 bits */ /* local64_t always succeeds */ @@ -742,13 +704,6 @@ static void rb_time_set(rb_time_t *t, u64 val) { local64_set(&t->time, val); } - -static bool rb_time_cmpxchg(rb_time_t *t, u64 expect, u64 set) -{ - u64 val; - val = local64_cmpxchg(&t->time, expect, set); - return val == expect; -} #endif /* @@ -3568,20 +3523,36 @@ __rb_reserve_next(struct ring_buffer_per_cpu *cpu_buffer, } else { u64 ts; /* SLOW PATH - Interrupted between A and C */ - a_ok = rb_time_read(&cpu_buffer->write_stamp, &info->after); - /* Was interrupted before here, write_stamp must be valid */ + + /* Save the old before_stamp */ + a_ok = rb_time_read(&cpu_buffer->before_stamp, &info->before); RB_WARN_ON(cpu_buffer, !a_ok); + + /* + * Read a new timestamp and update the before_stamp to make + * the next event after this one force using an absolute + * timestamp. This is in case an interrupt were to come in + * between E and F. + */ ts = rb_time_stamp(cpu_buffer->buffer); + rb_time_set(&cpu_buffer->before_stamp, ts); + + barrier(); + /*E*/ a_ok = rb_time_read(&cpu_buffer->write_stamp, &info->after); + /* Was interrupted before here, write_stamp must be valid */ + RB_WARN_ON(cpu_buffer, !a_ok); barrier(); - /*E*/ if (write == (local_read(&tail_page->write) & RB_WRITE_MASK) && - info->after < ts && - rb_time_cmpxchg(&cpu_buffer->write_stamp, - info->after, ts)) { - /* Nothing came after this event between C and E */ + /*F*/ if (write == (local_read(&tail_page->write) & RB_WRITE_MASK) && + info->after == info->before && info->after < ts) { + /* + * Nothing came after this event between C and F, it is + * safe to use info->after for the delta as it + * matched info->before and is still valid. + */ info->delta = ts - info->after; } else { /* - * Interrupted between C and E: + * Interrupted between C and F: * Lost the previous events time stamp. Just set the * delta to zero, and this will be the same time as * the event this event interrupted. And the events that -- cgit v1.2.3 From 4d9dcdb333ca637e7c7c66119a16e83b5a25c74f Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Tue, 5 Dec 2023 16:39:16 +0100 Subject: dm-integrity: don't modify bio's immutable bio_vec in integrity_metadata() commit b86f4b790c998afdbc88fe1aa55cfe89c4068726 upstream. __bio_for_each_segment assumes that the first struct bio_vec argument doesn't change - it calls "bio_advance_iter_single((bio), &(iter), (bvl).bv_len)" to advance the iterator. Unfortunately, the dm-integrity code changes the bio_vec with "bv.bv_len -= pos". When this code path is taken, the iterator would be out of sync and dm-integrity would report errors. This happens if the machine is out of memory and "kmalloc" fails. Fix this bug by making a copy of "bv" and changing the copy instead. Fixes: 7eada909bfd7 ("dm: add integrity target") Cc: stable@vger.kernel.org # v4.12+ Signed-off-by: Mikulas Patocka Signed-off-by: Mike Snitzer Signed-off-by: Greg Kroah-Hartman --- drivers/md/dm-integrity.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/md/dm-integrity.c b/drivers/md/dm-integrity.c index 455788b6e5a1..df743650d8a9 100644 --- a/drivers/md/dm-integrity.c +++ b/drivers/md/dm-integrity.c @@ -1762,11 +1762,12 @@ static void integrity_metadata(struct work_struct *w) sectors_to_process = dio->range.n_sectors; __bio_for_each_segment(bv, bio, iter, dio->bio_details.bi_iter) { + struct bio_vec bv_copy = bv; unsigned pos; char *mem, *checksums_ptr; again: - mem = (char *)kmap_atomic(bv.bv_page) + bv.bv_offset; + mem = (char *)kmap_atomic(bv_copy.bv_page) + bv_copy.bv_offset; pos = 0; checksums_ptr = checksums; do { @@ -1775,7 +1776,7 @@ again: sectors_to_process -= ic->sectors_per_block; pos += ic->sectors_per_block << SECTOR_SHIFT; sector += ic->sectors_per_block; - } while (pos < bv.bv_len && sectors_to_process && checksums != checksums_onstack); + } while (pos < bv_copy.bv_len && sectors_to_process && checksums != checksums_onstack); kunmap_atomic(mem); r = dm_integrity_rw_tag(ic, checksums, &dio->metadata_block, &dio->metadata_offset, @@ -1796,9 +1797,9 @@ again: if (!sectors_to_process) break; - if (unlikely(pos < bv.bv_len)) { - bv.bv_offset += pos; - bv.bv_len -= pos; + if (unlikely(pos < bv_copy.bv_len)) { + bv_copy.bv_offset += pos; + bv_copy.bv_len -= pos; goto again; } } -- cgit v1.2.3 From 339add0430e7cc94a483179ed2b2cc8d2eec0b4f Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 4 Oct 2022 12:21:25 +0300 Subject: device property: Allow const parameter to dev_fwnode() commit b295d484b97081feba72b071ffcb72fb4638ccfd upstream. It's not fully correct to take a const parameter pointer to a struct and return a non-const pointer to a member of that struct. Instead, introduce a const version of the dev_fwnode() API which takes and returns const pointers and use it where it's applicable. With this, convert dev_fwnode() to be a macro wrapper on top of const and non-const APIs that chooses one based on the type. Suggested-by: Sakari Ailus Fixes: aade55c86033 ("device property: Add const qualifier to device_get_match_data() parameter") Signed-off-by: Andy Shevchenko Acked-by: Heikki Krogerus Reviewed-by: Sakari Ailus Link: https://lore.kernel.org/r/20221004092129.19412-2-andriy.shevchenko@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/base/property.c | 11 +++++++++-- include/linux/property.h | 7 ++++++- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/drivers/base/property.c b/drivers/base/property.c index 2ed844650328..21f4184db42f 100644 --- a/drivers/base/property.c +++ b/drivers/base/property.c @@ -18,12 +18,19 @@ #include #include -struct fwnode_handle *dev_fwnode(const struct device *dev) +struct fwnode_handle *__dev_fwnode(struct device *dev) { return IS_ENABLED(CONFIG_OF) && dev->of_node ? of_fwnode_handle(dev->of_node) : dev->fwnode; } -EXPORT_SYMBOL_GPL(dev_fwnode); +EXPORT_SYMBOL_GPL(__dev_fwnode); + +const struct fwnode_handle *__dev_fwnode_const(const struct device *dev) +{ + return IS_ENABLED(CONFIG_OF) && dev->of_node ? + of_fwnode_handle(dev->of_node) : dev->fwnode; +} +EXPORT_SYMBOL_GPL(__dev_fwnode_const); /** * device_property_present - check if a property of a device is present diff --git a/include/linux/property.h b/include/linux/property.h index 1bd1e4ada7e3..fe2092e39aed 100644 --- a/include/linux/property.h +++ b/include/linux/property.h @@ -31,7 +31,12 @@ enum dev_dma_attr { DEV_DMA_COHERENT, }; -struct fwnode_handle *dev_fwnode(const struct device *dev); +const struct fwnode_handle *__dev_fwnode_const(const struct device *dev); +struct fwnode_handle *__dev_fwnode(struct device *dev); +#define dev_fwnode(dev) \ + _Generic((dev), \ + const struct device *: __dev_fwnode_const, \ + struct device *: __dev_fwnode)(dev) bool device_property_present(struct device *dev, const char *propname); int device_property_read_u8_array(struct device *dev, const char *propname, -- cgit v1.2.3 From 13578b4ea461da333b863e7a2f732f0f8e0ffbd0 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Wed, 6 Dec 2023 09:30:40 +0100 Subject: bpf: Fix prog_array_map_poke_run map poke update commit 4b7de801606e504e69689df71475d27e35336fb3 upstream. Lee pointed out issue found by syscaller [0] hitting BUG in prog array map poke update in prog_array_map_poke_run function due to error value returned from bpf_arch_text_poke function. There's race window where bpf_arch_text_poke can fail due to missing bpf program kallsym symbols, which is accounted for with check for -EINVAL in that BUG_ON call. The problem is that in such case we won't update the tail call jump and cause imbalance for the next tail call update check which will fail with -EBUSY in bpf_arch_text_poke. I'm hitting following race during the program load: CPU 0 CPU 1 bpf_prog_load bpf_check do_misc_fixups prog_array_map_poke_track map_update_elem bpf_fd_array_map_update_elem prog_array_map_poke_run bpf_arch_text_poke returns -EINVAL bpf_prog_kallsyms_add After bpf_arch_text_poke (CPU 1) fails to update the tail call jump, the next poke update fails on expected jump instruction check in bpf_arch_text_poke with -EBUSY and triggers the BUG_ON in prog_array_map_poke_run. Similar race exists on the program unload. Fixing this by moving the update to bpf_arch_poke_desc_update function which makes sure we call __bpf_arch_text_poke that skips the bpf address check. Each architecture has slightly different approach wrt looking up bpf address in bpf_arch_text_poke, so instead of splitting the function or adding new 'checkip' argument in previous version, it seems best to move the whole map_poke_run update as arch specific code. [0] https://syzkaller.appspot.com/bug?extid=97a4fe20470e9bc30810 Fixes: ebf7d1f508a7 ("bpf, x64: rework pro/epilogue and tailcall handling in JIT") Reported-by: syzbot+97a4fe20470e9bc30810@syzkaller.appspotmail.com Signed-off-by: Jiri Olsa Signed-off-by: Daniel Borkmann Acked-by: Yonghong Song Cc: Lee Jones Cc: Maciej Fijalkowski Link: https://lore.kernel.org/bpf/20231206083041.1306660-2-jolsa@kernel.org Signed-off-by: Greg Kroah-Hartman --- arch/x86/net/bpf_jit_comp.c | 46 +++++++++++++++++++++++++++++++++++ include/linux/bpf.h | 3 +++ kernel/bpf/arraymap.c | 58 ++++++++------------------------------------- 3 files changed, 59 insertions(+), 48 deletions(-) diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c index dccaab2113f9..ee6e3cda1738 100644 --- a/arch/x86/net/bpf_jit_comp.c +++ b/arch/x86/net/bpf_jit_comp.c @@ -2403,3 +2403,49 @@ bool bpf_jit_supports_kfunc_call(void) { return true; } + +void bpf_arch_poke_desc_update(struct bpf_jit_poke_descriptor *poke, + struct bpf_prog *new, struct bpf_prog *old) +{ + u8 *old_addr, *new_addr, *old_bypass_addr; + int ret; + + old_bypass_addr = old ? NULL : poke->bypass_addr; + old_addr = old ? (u8 *)old->bpf_func + poke->adj_off : NULL; + new_addr = new ? (u8 *)new->bpf_func + poke->adj_off : NULL; + + /* + * On program loading or teardown, the program's kallsym entry + * might not be in place, so we use __bpf_arch_text_poke to skip + * the kallsyms check. + */ + if (new) { + ret = __bpf_arch_text_poke(poke->tailcall_target, + BPF_MOD_JUMP, + old_addr, new_addr, true); + BUG_ON(ret < 0); + if (!old) { + ret = __bpf_arch_text_poke(poke->tailcall_bypass, + BPF_MOD_JUMP, + poke->bypass_addr, + NULL, true); + BUG_ON(ret < 0); + } + } else { + ret = __bpf_arch_text_poke(poke->tailcall_bypass, + BPF_MOD_JUMP, + old_bypass_addr, + poke->bypass_addr, true); + BUG_ON(ret < 0); + /* let other CPUs finish the execution of program + * so that it will not possible to expose them + * to invalid nop, stack unwind, nop state + */ + if (!ret) + synchronize_rcu(); + ret = __bpf_arch_text_poke(poke->tailcall_target, + BPF_MOD_JUMP, + old_addr, NULL, true); + BUG_ON(ret < 0); + } +} diff --git a/include/linux/bpf.h b/include/linux/bpf.h index 9ab087d73ab3..00c615fc8ec3 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -2280,6 +2280,9 @@ enum bpf_text_poke_type { int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type t, void *addr1, void *addr2); +void bpf_arch_poke_desc_update(struct bpf_jit_poke_descriptor *poke, + struct bpf_prog *new, struct bpf_prog *old); + struct btf_id_set; bool btf_id_set_contains(const struct btf_id_set *set, u32 id); diff --git a/kernel/bpf/arraymap.c b/kernel/bpf/arraymap.c index 88014cd31b28..23ffb8f0b5d7 100644 --- a/kernel/bpf/arraymap.c +++ b/kernel/bpf/arraymap.c @@ -957,11 +957,16 @@ static void prog_array_map_poke_untrack(struct bpf_map *map, mutex_unlock(&aux->poke_mutex); } +void __weak bpf_arch_poke_desc_update(struct bpf_jit_poke_descriptor *poke, + struct bpf_prog *new, struct bpf_prog *old) +{ + WARN_ON_ONCE(1); +} + static void prog_array_map_poke_run(struct bpf_map *map, u32 key, struct bpf_prog *old, struct bpf_prog *new) { - u8 *old_addr, *new_addr, *old_bypass_addr; struct prog_poke_elem *elem; struct bpf_array_aux *aux; @@ -970,7 +975,7 @@ static void prog_array_map_poke_run(struct bpf_map *map, u32 key, list_for_each_entry(elem, &aux->poke_progs, list) { struct bpf_jit_poke_descriptor *poke; - int i, ret; + int i; for (i = 0; i < elem->aux->size_poke_tab; i++) { poke = &elem->aux->poke_tab[i]; @@ -989,21 +994,10 @@ static void prog_array_map_poke_run(struct bpf_map *map, u32 key, * activated, so tail call updates can arrive from here * while JIT is still finishing its final fixup for * non-activated poke entries. - * 3) On program teardown, the program's kallsym entry gets - * removed out of RCU callback, but we can only untrack - * from sleepable context, therefore bpf_arch_text_poke() - * might not see that this is in BPF text section and - * bails out with -EINVAL. As these are unreachable since - * RCU grace period already passed, we simply skip them. - * 4) Also programs reaching refcount of zero while patching + * 3) Also programs reaching refcount of zero while patching * is in progress is okay since we're protected under * poke_mutex and untrack the programs before the JIT - * buffer is freed. When we're still in the middle of - * patching and suddenly kallsyms entry of the program - * gets evicted, we just skip the rest which is fine due - * to point 3). - * 5) Any other error happening below from bpf_arch_text_poke() - * is a unexpected bug. + * buffer is freed. */ if (!READ_ONCE(poke->tailcall_target_stable)) continue; @@ -1013,39 +1007,7 @@ static void prog_array_map_poke_run(struct bpf_map *map, u32 key, poke->tail_call.key != key) continue; - old_bypass_addr = old ? NULL : poke->bypass_addr; - old_addr = old ? (u8 *)old->bpf_func + poke->adj_off : NULL; - new_addr = new ? (u8 *)new->bpf_func + poke->adj_off : NULL; - - if (new) { - ret = bpf_arch_text_poke(poke->tailcall_target, - BPF_MOD_JUMP, - old_addr, new_addr); - BUG_ON(ret < 0 && ret != -EINVAL); - if (!old) { - ret = bpf_arch_text_poke(poke->tailcall_bypass, - BPF_MOD_JUMP, - poke->bypass_addr, - NULL); - BUG_ON(ret < 0 && ret != -EINVAL); - } - } else { - ret = bpf_arch_text_poke(poke->tailcall_bypass, - BPF_MOD_JUMP, - old_bypass_addr, - poke->bypass_addr); - BUG_ON(ret < 0 && ret != -EINVAL); - /* let other CPUs finish the execution of program - * so that it will not possible to expose them - * to invalid nop, stack unwind, nop state - */ - if (!ret) - synchronize_rcu(); - ret = bpf_arch_text_poke(poke->tailcall_target, - BPF_MOD_JUMP, - old_addr, NULL); - BUG_ON(ret < 0 && ret != -EINVAL); - } + bpf_arch_poke_desc_update(poke, new, old); } } } -- cgit v1.2.3 From 26c690eff0a56293e0b6911a38e406c211b35547 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 5 Jan 2024 15:13:40 +0100 Subject: Linux 5.15.146 Link: https://lore.kernel.org/r/20240103164853.921194838@linuxfoundation.org Tested-by: SeongJae Park Tested-by: Florian Fainelli Tested-by: Kelsey Steele Tested-by: Shuah Khan Tested-by: Namjae Jeon Tested-by: Linux Kernel Functional Testing Tested-by: Harshit Mogalapalli Tested-by: Jon Hunter Tested-by: Guenter Roeck Tested-by: Ron Economos Tested-by: kernelci.org bot Signed-off-by: Greg Kroah-Hartman --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index d46825496e8e..bf3b4827b612 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 VERSION = 5 PATCHLEVEL = 15 -SUBLEVEL = 145 +SUBLEVEL = 146 EXTRAVERSION = NAME = Trick or Treat -- cgit v1.2.3