6.18.2-rc1 review
Subsystems (6)
Greg Kroah-Hartman
maintainerPATCH 401/614 wifi: mt76: mt7996: Add missing locking in mt7996_mac_sta_rc_work()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lorenzo Bianconi <[email protected]>
[ Upstream commit 7545551631fa63101f97974f49ac0b564814f703 ]
Grab the mt76 mutex running mt7996_mac_sta_rc_work() since it is required by mt7996_mcu_add_rate_ctrl routine.
--- drivers/net/wireless/mediatek/mt76/mt7996/mac.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/net/wireless/mediatek/mt76/mt7996/mac.c +4 -0
@@ -2860,6 +2860,8 @@ void mt7996_mac_sta_rc_work(struct work_struct *work)LIST_HEAD (list);u32 changed; +mutex_lock (&dev->mt76.mutex); +spin_lock_bh (&dev->mt76.sta_poll_lock);list_splice_init (&dev->sta_rc_list, &list);
@@ -2892,6 +2894,8 @@ void mt7996_mac_sta_rc_work(struct work_struct *work) }spin_unlock_bh (&dev->mt76.sta_poll_lock); + +mutex_unlock (&dev->mt76.mutex); }void mt7996_mac_work (struct work_struct *work)
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 402/614 mt76: mt7615: Fix memory leak in mt7615_mcu_wtbl_sta_add()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zilin Guan <[email protected]>
[ Upstream commit 53d1548612670aa8b5d89745116cc33d9d172863 ]
In mt7615_mcu_wtbl_sta_add(), an skb sskb is allocated. If the subsequent call to mt76_connac_mcu_alloc_wtbl_req() fails, the function returns an error without freeing sskb, leading to a memory leak.
Fix this by calling dev_kfree_skb() on sskb in the error handling path to ensure it is properly released.
--- drivers/net/wireless/mediatek/mt76/mt7615/mcu.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +3 -1
@@ -874,8 +874,10 @@ mt7615_mcu_wtbl_sta_add(struct mt7615_phy *phy, struct ieee80211_vif *vif, wtbl_hdr =mt76_connac_mcu_alloc_wtbl_req (&dev->mt76, &msta->wcid,WTBL_RESET_AND_SET ,NULL , &wskb); -if (IS_ERR (wtbl_hdr)) +if (IS_ERR (wtbl_hdr)) { +dev_kfree_skb (sskb);return PTR_ERR (wtbl_hdr); + }if (enable) { mt76_connac_mcu_wtbl_generic_tlv(&dev->mt76, wskb, vif, sta,
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 403/614 firmware: stratix10-svc: fix make htmldocs warning for stratix10_svc
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dinh Nguyen <[email protected]>
[ Upstream commit 377441d53a2df61b105e823b335010cd4f1a6e56 ]
Fix this warning that was generated from "make htmldocs":
WARNING: drivers/firmware/stratix10-svc.c:58 struct member 'intel_svc_fcs'
not described in 'stratix10_svc'
--- drivers/firmware/stratix10-svc.c | 1 + 1 file changed, 1 insertion(+)
drivers/firmware/stratix10-svc.c +1 -0
@@ -52,6 +52,7 @@ struct stratix10_svc_chan;/** * struct stratix10_svc - svc private data * @stratix10_svc_rsu: pointer to stratix10 RSU device +* @intel_svc_fcs: pointer to the FCS device */ struct stratix10_svc {struct platform_device *stratix10_svc_rsu;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 404/614 staging: fbtft: core: fix potential memory leak in fbtft_probe_common()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jianglei Nie <[email protected]>
[ Upstream commit 47d3949a9b04cbcb0e10abae30c2b53e98706e11 ]
fbtft_probe_common() allocates a memory chunk for "info" with fbtft_framebuffer_alloc(). When "display->buswidth == 0" is true, the function returns without releasing the "info", which will lead to a memory leak.
Fix it by calling fbtft_framebuffer_release() when "display->buswidth == 0" is true.
--- drivers/staging/fbtft/fbtft-core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/staging/fbtft/fbtft-core.c +2 -2
@@ -1171,8 +1171,8 @@ int fbtft_probe_common(struct fbtft_display *display, par->pdev = pdev;if (display->buswidth ==0 ) { -dev_err (dev,"buswidth is not set\n" ); -return -EINVAL ; + ret =dev_err_probe (dev, -EINVAL ,"buswidth is not set\n" ); + goto out_release; }/* write register functions */
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 405/614 iommu/arm-smmu-v3: Fix error check in arm_smmu_alloc_cd_tables
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ryan Huang <[email protected]>
[ Upstream commit 5941f0e0c1e0be03ebc15b461f64208f5250d3d9 ]
In arm_smmu_alloc_cd_tables(), the error check following the dma_alloc_coherent() for cd_table->l2.l1tab incorrectly tests cd_table->l2.l2ptrs.
This means an allocation failure for l1tab goes undetected, causing the function to return 0 (success) erroneously.
Correct the check to test cd_table->l2.l1tab.
--- drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c +1 -1
@@ -1464,7 +1464,7 @@ static int arm_smmu_alloc_cd_tables(struct arm_smmu_master *master) cd_table->l2.l1tab =dma_alloc_coherent (smmu->dev, l1size, &cd_table->cdtab_dma,GFP_KERNEL ); -if (!cd_table->l2.l2ptrs) { +if (!cd_table->l2.l1tab) { ret = -ENOMEM ; goto err_free_l2ptrs; }
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 406/614 bpftool: Allow bpftool to build with openssl < 3
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alan Maguire <[email protected]>
[ Upstream commit 90ae54b4c7eca42d5ce006dd0a8cb0b5bfbf80d0 ]
ERR_get_error_all()[1] is a openssl v3 API, so to make code compatible with openssl v1 utilize ERR_get_err_line_data instead. Since openssl is already a build requirement for the kernel (minimum requirement openssl 1.0.0), this will allow bpftool to compile where opensslv3 is not available. Signing-related BPF selftests pass with openssl v1.
[1] https://docs.openssl.org/3.4/man3/ERR_get_error/
--- tools/bpf/bpftool/sign.c | 6 ++++++ 1 file changed, 6 insertions(+)
tools/bpf/bpftool/sign.c +6 -0
@@ -28,6 +28,12 @@#define OPEN_SSL_ERR_BUF_LEN 256 +/* Use deprecated in 3.0 ERR_get_error_line_data for openssl < 3 */ +#if !defined(OPENSSL_VERSION_MAJOR ) || (OPENSSL_VERSION_MAJOR <3 ) +#define ERR_get_error_all (file, line, func, data, flags) \ + ERR_get_error_line_data(file, line, data, flags) +#endif +static void display_openssl_errors (int l) {char buf[OPEN_SSL_ERR_BUF_LEN ];
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 407/614 selftests/bpf: Allow selftests to build with older xxd
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alan Maguire <[email protected]>
[ Upstream commit ad93ba02678eda5fc8e259cf4b52997e6fa570cf ]
Currently selftests require xxd with the "-n <name>" option which allows the user to specify a name not derived from the input object path. Instead of relying on this newer feature, older xxd can be used if we link our desired name ("test_progs_verification_cert") to the input object.
Many distros ship xxd in vim-common package and do not have the latest xxd with -n support.
--- tools/testing/selftests/bpf/.gitignore | 1 + tools/testing/selftests/bpf/Makefile | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-)
tools/testing/selftests/bpf/.gitignore +1 -0
@@ -23,6 +23,7 @@ test_tcpnotify_user test_libbpf xdping test_cpp +test_progs_verification_cert *.d *.subskel.h *.skel.h
tools/testing/selftests/bpf/Makefile +4 -2
@@ -721,7 +721,8 @@ $(VERIFICATION_CERT) $(PRIVATE_KEY): $(VERIFY_SIG_SETUP) $(Q)$(VERIFY_SIG_SETUP) genkey $(BUILD_DIR) $(VERIFY_SIG_HDR): $(VERIFICATION_CERT) - $(Q)xxd -i -n test_progs_verification_cert $< > $@ + $(Q)ln -fs $< test_progs_verification_cert && \ + xxd -i test_progs_verification_cert > $@ # Define test_progs test runner. TRUNNER_TESTS_DIR := prog_tests
@@ -893,7 +894,8 @@ EXTRA_CLEAN := $(SCRATCH_DIR) $(HOST_SCRATCH_DIR) \ $(addprefix $(OUTPUT)/,*.o *.d *.skel.h *.lskel.h *.subskel.h \ no_alu32 cpuv4 bpf_gcc \ liburandom_read.so) \ - $(OUTPUT)/FEATURE-DUMP.selftests + $(OUTPUT)/FEATURE-DUMP.selftests \ + test_progs_verification_cert .PHONY: docs docs-clean
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 408/614 btrfs: fix double free of qgroup record after failure to add delayed ref head
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Miquel Sabaté Solà <[email protected]>
[ Upstream commit 725e46298876a2cc1f1c3fb22ba69d29102c3ddf ]
In the previous code it was possible to incur into a double kfree() scenario when calling add_delayed_ref_head(). This could happen if the record was reported to already exist in the btrfs_qgroup_trace_extent_nolock() call, but then there was an error later on add_delayed_ref_head(). In this case, since add_delayed_ref_head() returned an error, the caller went to free the record. Since add_delayed_ref_head() couldn't set this kfree'd pointer to NULL, then kfree() would have acted on a non-NULL 'record' object which was pointing to memory already freed by the callee.
The problem comes from the fact that the responsibility to kfree the object is on both the caller and the callee at the same time. Hence, the fix for this is to shift the ownership of the 'qrecord' object out of the add_delayed_ref_head(). That is, we will never attempt to kfree() the given object inside of this function, and will expect the caller to act on the 'qrecord' object on its own. The only exception where the 'qrecord' object cannot be kfree'd is if it was inserted into the tracing logic, for which we already have the 'qrecord_inserted_ret' boolean to account for this. Hence, the caller has to kfree the object only if add_delayed_ref_head() reports not to have inserted it on the tracing logic.
As a side-effect of the above, we must guarantee that 'qrecord_inserted_ret' is properly initialized at the start of the function, not at the end, and then set when an actual insert happens. This way we avoid 'qrecord_inserted_ret' having an invalid value on an early exit.
The documentation from the add_delayed_ref_head() has also been updated to reflect on the exact ownership of the 'qrecord' object.
--- fs/btrfs/delayed-ref.c | 43 ++++++++++++++++++++++++++++++++---------- 1 file changed, 33 insertions(+), 10 deletions(-)
fs/btrfs/delayed-ref.c +33 -10
@@ -798,9 +798,13 @@ static void init_delayed_ref_head(struct btrfs_delayed_ref_head *head_ref, }/* -* helper function to actually insert a head node into the rbtree. -* this does all the dirty work in terms of maintaining the correct -* overall modification count. +* Helper function to actually insert a head node into the xarray. This does all +* the dirty work in terms of maintaining the correct overall modification +* count. +* +* The caller is responsible for calling kfree() on @qrecord. More specifically, +* if this function reports that it did not insert it as noted in +* @qrecord_inserted_ret, then it's safe to call kfree() on it. * * Returns an error pointer in case of an error. */
@@ -814,7 +818,14 @@ add_delayed_ref_head(struct btrfs_trans_handle *trans,struct btrfs_delayed_ref_head *existing;struct btrfs_delayed_ref_root *delayed_refs;const unsigned long index = (head_ref->bytenr >> fs_info->sectorsize_bits); -bool qrecord_inserted = false; + +/* +* If 'qrecord_inserted_ret' is provided, then the first thing we need +* to do is to initialize it to false just in case we have an exit +* before trying to insert the record. +*/ +if (qrecord_inserted_ret) + *qrecord_inserted_ret = false; delayed_refs = &trans->transaction->delayed_refs;lockdep_assert_held (&delayed_refs->lock);
@@ -833,6 +844,12 @@ add_delayed_ref_head(struct btrfs_trans_handle *trans,/* Record qgroup extent info if provided */ if (qrecord) { +/* +* Setting 'qrecord' but not 'qrecord_inserted_ret' will likely +* result in a memory leakage. +*/ +ASSERT (qrecord_inserted_ret !=NULL ); +int ret; ret = btrfs_qgroup_trace_extent_nolock(fs_info, delayed_refs, qrecord,
@@ -840,12 +857,10 @@ add_delayed_ref_head(struct btrfs_trans_handle *trans,if (ret) {/* Clean up if insertion fails or item exists. */ xa_release (&delayed_refs->dirty_extents, index); -/* Caller responsible for freeing qrecord on error. */ if (ret <0 )return ERR_PTR (ret); -kfree (qrecord); - }else { - qrecord_inserted = true; + }else if (qrecord_inserted_ret) { + *qrecord_inserted_ret = true; } }
@@ -888,8 +903,6 @@ add_delayed_ref_head(struct btrfs_trans_handle *trans, delayed_refs->num_heads++; delayed_refs->num_heads_ready++; } -if (qrecord_inserted_ret) - *qrecord_inserted_ret = qrecord_inserted;return head_ref; }
@@ -1049,6 +1062,14 @@ static int add_delayed_ref(struct btrfs_trans_handle *trans,xa_release (&delayed_refs->head_refs, index);spin_unlock (&delayed_refs->lock); ret =PTR_ERR (new_head_ref); + +/* +* It's only safe to call kfree() on 'qrecord' if +* add_delayed_ref_head() has _not_ inserted it for +* tracing. Otherwise we need to handle this here. +*/ +if (!qrecord_reserved || qrecord_inserted) + goto free_head_ref; goto free_record; } head_ref = new_head_ref;
@@ -1071,6 +1092,8 @@ static int add_delayed_ref(struct btrfs_trans_handle *trans,if (qrecord_inserted)return btrfs_qgroup_trace_extent_post (trans, record, generic_ref->bytenr); + +kfree (record);return 0 ; free_record:
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 409/614 btrfs: fix racy bitfield write in btrfs_clear_space_info_full()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Boris Burkov <[email protected]>
[ Upstream commit 38e818718c5e04961eea0fa8feff3f100ce40408 ]
Quoted 1 line
From the memory-barriers.txt document regarding memory barrier ordering
guarantees:
(*) These guarantees do not apply to bitfields, because compilers often
generate code to modify these using non-atomic read-modify-write sequences. Do not attempt to use bitfields to synchronize parallel algorithms.
(*) Even in cases where bitfields are protected by locks, all fields
in a given bitfield must be protected by one lock. If two fields in a given bitfield are protected by different locks, the compiler's non-atomic read-modify-write sequences can cause an update to one field to corrupt the value of an adjacent field.
btrfs_space_info has a bitfield sharing an underlying word consisting of the fields full, chunk_alloc, and flush:
struct btrfs_space_info {
struct btrfs_fs_info * fs_info; /* 0 8 */
struct btrfs_space_info * parent; /* 8 8 */ ...
int clamp; /* 172 4 */
unsigned int full:1; /* 176: 0 4 */
unsigned int chunk_alloc:1; /* 176: 1 4 */
unsigned int flush:1; /* 176: 2 4 */
...
Therefore, to be safe from parallel read-modify-writes losing a write to one of the bitfield members protected by a lock, all writes to all the bitfields must use the lock. They almost universally do, except for btrfs_clear_space_info_full() which iterates over the space_infos and writes out found->full = 0 without a lock.
Imagine that we have one thread completing a transaction in which we finished deleting a block_group and are thus calling btrfs_clear_space_info_full() while simultaneously the data reclaim ticket infrastructure is running do_async_reclaim_data_space():
T1 T2btrfs_commit_transaction
btrfs_clear_space_info_full
data_sinfo->full = 0
READ: full:0, chunk_alloc:0, flush:1
do_async_reclaim_data_space(data_sinfo)
spin_lock(&space_info->lock);
if(list_empty(tickets))
space_info->flush = 0;
READ: full: 0, chunk_alloc:0, flush:1
MOD/WRITE: full: 0, chunk_alloc:0, flush:0
spin_unlock(&space_info->lock);
return;MOD/WRITE: full:0, chunk_alloc:0, flush:1
and now data_sinfo->flush is 1 but the reclaim worker has exited. This breaks the invariant that flush is 0 iff there is no work queued or running. Once this invariant is violated, future allocations that go into __reserve_bytes() will add tickets to space_info->tickets but will see space_info->flush is set to 1 and not queue the work. After this, they will block forever on the resulting ticket, as it is now impossible to kick the worker again.
I also confirmed by looking at the assembly of the affected kernel that it is doing RMW operations. For example, to set the flush (3rd) bit to 0, the assembly is:
andb $0xfb,0x60(%rbx)
and similarly for setting the full (1st) bit to 0:
andb $0xfe,-0x20(%rax)
So I think this is really a bug on practical systems. I have observed a number of systems in this exact state, but am currently unable to reproduce it.
Rather than leaving this footgun lying around for the future, take advantage of the fact that there is room in the struct anyway, and that it is already quite large and simply change the three bitfield members to bools. This avoids writes to space_info->full having any effect on writes to space_info->flush, regardless of locking.
--- fs/btrfs/block-group.c | 6 +++--- fs/btrfs/space-info.c | 22 +++++++++++----------- fs/btrfs/space-info.h | 6 +++--- 3 files changed, 17 insertions(+), 17 deletions(-)
fs/btrfs/block-group.c +3 -3
@@ -4215,7 +4215,7 @@ int btrfs_chunk_alloc(struct btrfs_trans_handle *trans,mutex_unlock (&fs_info->chunk_mutex); }else {/* Proceed with allocation */ - space_info->chunk_alloc =1 ; + space_info->chunk_alloc = true; wait_for_alloc = false;spin_unlock (&space_info->lock); }
@@ -4264,7 +4264,7 @@ int btrfs_chunk_alloc(struct btrfs_trans_handle *trans,spin_lock (&space_info->lock);if (ret <0 ) {if (ret == -ENOSPC ) - space_info->full =1 ; + space_info->full = true;else goto out; }else {
@@ -4274,7 +4274,7 @@ int btrfs_chunk_alloc(struct btrfs_trans_handle *trans, space_info->force_alloc =CHUNK_ALLOC_NO_FORCE ; out: - space_info->chunk_alloc =0 ; + space_info->chunk_alloc = false;spin_unlock (&space_info->lock);mutex_unlock (&fs_info->chunk_mutex);
fs/btrfs/space-info.c +11 -11
@@ -192,7 +192,7 @@ void btrfs_clear_space_info_full(struct btrfs_fs_info *info)struct btrfs_space_info *found;list_for_each_entry (found, head, list) - found->full =0 ; + found->full = false; }/*
@@ -372,7 +372,7 @@ void btrfs_add_bg_to_space_info(struct btrfs_fs_info *info, space_info->bytes_readonly += block_group->bytes_super;btrfs_space_info_update_bytes_zone_unusable (space_info, block_group->zone_unusable);if (block_group->length >0 ) - space_info->full =0 ; + space_info->full = false;btrfs_try_granting_tickets (info, space_info);spin_unlock (&space_info->lock);
@@ -1146,7 +1146,7 @@ static void do_async_reclaim_metadata_space(struct btrfs_space_info *space_info)spin_lock (&space_info->lock); to_reclaim =btrfs_calc_reclaim_metadata_size (fs_info, space_info);if (!to_reclaim) { - space_info->flush =0 ; + space_info->flush = false;spin_unlock (&space_info->lock);return ; }
@@ -1158,7 +1158,7 @@ static void do_async_reclaim_metadata_space(struct btrfs_space_info *space_info)flush_space (fs_info, space_info, to_reclaim, flush_state, false);spin_lock (&space_info->lock);if (list_empty (&space_info->tickets)) { - space_info->flush =0 ; + space_info->flush = false;spin_unlock (&space_info->lock);return ; }
@@ -1201,7 +1201,7 @@ static void do_async_reclaim_metadata_space(struct btrfs_space_info *space_info) flush_state =FLUSH_DELAYED_ITEMS_NR ; commit_cycles--; }else { - space_info->flush =0 ; + space_info->flush = false; } }else { flush_state =FLUSH_DELAYED_ITEMS_NR ;
@@ -1383,7 +1383,7 @@ static void do_async_reclaim_data_space(struct btrfs_space_info *space_info)spin_lock (&space_info->lock);if (list_empty (&space_info->tickets)) { - space_info->flush =0 ; + space_info->flush = false;spin_unlock (&space_info->lock);return ; }
@@ -1394,7 +1394,7 @@ static void do_async_reclaim_data_space(struct btrfs_space_info *space_info)flush_space (fs_info, space_info,U64_MAX ,ALLOC_CHUNK_FORCE , false);spin_lock (&space_info->lock);if (list_empty (&space_info->tickets)) { - space_info->flush =0 ; + space_info->flush = false;spin_unlock (&space_info->lock);return ; }
@@ -1411,7 +1411,7 @@ static void do_async_reclaim_data_space(struct btrfs_space_info *space_info) data_flush_states[flush_state], false);spin_lock (&space_info->lock);if (list_empty (&space_info->tickets)) { - space_info->flush =0 ; + space_info->flush = false;spin_unlock (&space_info->lock);return ; }
@@ -1428,7 +1428,7 @@ static void do_async_reclaim_data_space(struct btrfs_space_info *space_info)if (maybe_fail_all_tickets (fs_info, space_info)) flush_state =0 ;else - space_info->flush =0 ; + space_info->flush = false; }else { flush_state =0 ; }
@@ -1444,7 +1444,7 @@ static void do_async_reclaim_data_space(struct btrfs_space_info *space_info) aborted_fs:maybe_fail_all_tickets (fs_info, space_info); - space_info->flush =0 ; + space_info->flush = false;spin_unlock (&space_info->lock); }
@@ -1825,7 +1825,7 @@ static int __reserve_bytes(struct btrfs_fs_info *fs_info,*/ maybe_clamp_preempt (fs_info, space_info); - space_info->flush =1 ; + space_info->flush = true; trace_btrfs_trigger_flush(fs_info, space_info->flags, orig_bytes, flush,
fs/btrfs/space-info.h +3 -3
@@ -142,11 +142,11 @@ struct btrfs_space_info {flushing. The value is >> clamp, so turns out to be a 2^clamp divisor. */ - unsigned int full:1; /* indicates that we cannot allocate any more +bool full;/* indicates that we cannot allocate any more chunks for this space */ - unsigned int chunk_alloc:1; /* set if we are allocating a chunk */ +bool chunk_alloc;/* set if we are allocating a chunk */ - unsigned int flush:1; /* set if we are trying to make space */ +bool flush;/* set if we are trying to make space */ unsigned int force_alloc;/* set if we need to force a chunk alloc for this space */
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 410/614 btrfs: make sure extent and csum paths are always released in scrub_raid56_parity_stripe()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Qu Wenruo <[email protected]>
[ Upstream commit d435c513652e6a90a13c881986a2cc6420c99cab ]
Unlike queue_scrub_stripe() which uses the global sctx->extent_path and sctx->csum_path which are always released at the end of scrub_stripe(), scrub_raid56_parity_stripe() uses local extent_path and csum_path, as that function is going to handle the full stripe, whose bytenr may be smaller than the bytenr in the global sctx paths.
However the cleanup of local extent/csum paths is only happening after we have successfully submitted an rbio.
There are several error routes that we didn't release those two paths:
- scrub_find_fill_first_stripe() errored out at csum tree search In that case extent_path is still valid, and that function itself will not release the extent_path passed in.
And the function returns directly without releasing both paths.
- The full stripe is empty
- Some blocks failed to be recovered
- btrfs_map_block() failed
- raid56_parity_alloc_scrub_rbio() failed
The function returns directly without releasing both paths.
Fix it by covering btrfs_release_path() calls inside the out: tag.
This is just a hot fix, in the long run we will go scoped based auto freeing for both local paths.
--- fs/btrfs/scrub.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/btrfs/scrub.c +1 -1
@@ -2230,9 +2230,9 @@ static int scrub_raid56_parity_stripe(struct scrub_ctx *sctx,bio_put (bio);btrfs_bio_counter_dec (fs_info); +out:btrfs_release_path (&extent_path);btrfs_release_path (&csum_path); -out:return ret; }
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 411/614 btrfs: fix leaf leak in an error path in btrfs_del_items()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Filipe Manana <[email protected]>
[ Upstream commit e7dd1182fcedee7c6097c9f49eba8de94a4364e3 ]
If the call to btrfs_del_leaf() fails we return without decrementing the extra ref we took on the leaf, therefore leaking it. Fix this by ensuring we drop the ref count before returning the error.
--- fs/btrfs/ctree.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/btrfs/ctree.c +1 -1
@@ -4566,9 +4566,9 @@ int btrfs_del_items(struct btrfs_trans_handle *trans, struct btrfs_root *root,if (btrfs_header_nritems (leaf) ==0 ) { path->slots[1 ] = slot; ret =btrfs_del_leaf (trans, root, path, leaf); +free_extent_buffer (leaf);if (ret <0 )return ret; -free_extent_buffer (leaf); ret =0 ; }else {/* if we're still in the path, make sure
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 412/614 PCI: dwc: Fix wrong PORT_LOGIC_LTSSM_STATE_MASK definition
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Shawn Lin <[email protected]>
[ Upstream commit bcc9a4a0bca3aee4303fa4a20302e57b24ac8f68 ]
As per DesignWare Cores PCI Express Controller Databook, section 5.50,
SII: Debug Signals, cxpl_debug_info[63:0]:
[5:0] smlh_ltssm_state: LTSSM current state. Encoding is same as the dedicated smlh_ltssm_state output.
The mask should be 6 bits, from 0 to 5. Hence, fix the mask definition.
--- drivers/pci/controller/dwc/pcie-designware.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/pci/controller/dwc/pcie-designware.h +1 -1
@@ -97,7 +97,7 @@#define PORT_LANE_SKEW_INSERT_MASK GENMASK(23, 0)#define PCIE_PORT_DEBUG0 0x728 -#define PORT_LOGIC_LTSSM_STATE_MASK 0x1f +#define PORT_LOGIC_LTSSM_STATE_MASK 0x3f#define PORT_LOGIC_LTSSM_STATE_L0 0x11#define PCIE_PORT_DEBUG1 0x72C#define PCIE_PORT_DEBUG1_LINK_UP BIT(4)
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 413/614 drm/nouveau: restrict the flush page to a 32-bit address
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Timur Tabi <[email protected]>
[ Upstream commit 04d98b3452331fa53ec3b698b66273af6ef73288 ]
The flush page DMA address is stored in a special register that is not associated with the GPU's standard DMA range. For example, on Turing, the GPU's MMU can handle 47-bit addresses, but the flush page address register is limited to 40 bits.
At the point during device initialization when the flush page is allocated, the DMA mask is still at its default of 32 bits. So even though it's unlikely that the flush page could exist above a 40-bit address, the dma_map_page() call could fail, e.g. if IOMMU is disabled and the address is above 32 bits. The simplest way to achieve all constraints is to allocate the page in the DMA32 zone. Since the flush page is literally just a page, this is an acceptable limitation. The alternative is to temporarily set the DMA mask to 40 (or 52 for Hopper and later) bits, but that could have unforseen side effects.
In situations where the flush page is allocated above 32 bits and IOMMU is disabled, you will get an error like this:
nouveau 0000:65:00.0: DMA addr 0x0000000107c56000+4096 overflow (mask ffffffff, bus limit 0).
--- drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c +1 -1
@@ -279,7 +279,7 @@ nvkm_fb_ctor(const struct nvkm_fb_func *func, struct nvkm_device *device,mutex_init (&fb->tags.mutex);if (func->sysmem.flush_page_init) { - fb->sysmem.flush_page =alloc_page (GFP_KERNEL | __GFP_ZERO); + fb->sysmem.flush_page =alloc_page (GFP_KERNEL |GFP_DMA32 | __GFP_ZERO);if (!fb->sysmem.flush_page)return -ENOMEM ;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 414/614 um: Dont rename vmap to kernel_vmap
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Gow <[email protected]>
[ Upstream commit a74b6c0e53a6df8e8a096b50c06c4f872906368a ]
In order to work around the existence of a vmap symbol in libpcap, the UML makefile unconditionally redefines vmap to kernel_vmap. However, this not only affects the actual vmap symbol, but also anything else named vmap, including a number of struct members in DRM.
This would not be too much of a problem, since all uses are also updated, except we now have Rust DRM bindings, which expect the corresponding Rust structs to have 'vmap' names. Since the redefinition applies in bindgen, but not to Rust code, we end up with errors such as:
error[E0560]: struct drm_gem_object_funcs has no fields named vmap
--> rust/kernel/drm/gem/mod.rs:210:9
Since libpcap support was removed in commit 12b8e7e69aa7 ("um: Remove obsolete pcap driver"), remove the, now unnecessary, define as well.
We also take this opportunity to update the comment.
--- arch/um/Makefile | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-)
arch/um/Makefile +5 -7
@@ -46,19 +46,17 @@ ARCH_INCLUDE := -I$(srctree)/$(SHARED_HEADERS) ARCH_INCLUDE += -I$(srctree)/$(HOST_DIR)/um/shared KBUILD_CPPFLAGS += -I$(srctree)/$(HOST_DIR)/um -# -Dvmap=kernel_vmap prevents anything from referencing the libpcap.o symbol so -# named - it's a common symbol in libpcap, so we get a binary which crashes. -# -# Same things for in6addr_loopback and mktime - found in libc. For these two we -# only get link-time error, luckily. +# -Dstrrchr=kernel_strrchr (as well as the various in6addr symbols) prevents +# anything from referencing +# libc symbols with the same name, which can cause a linker error. # # -Dlongjmp=kernel_longjmp prevents anything from referencing the libpthread.a # embedded copy of longjmp, same thing for setjmp. # -# These apply to USER_CFLAGS to. +# These apply to USER_CFLAGS too. KBUILD_CFLAGS += $(CFLAGS) $(CFLAGS-y) -D__arch_um__ \ - $(ARCH_INCLUDE) $(MODE_INCLUDE) -Dvmap=kernel_vmap \ + $(ARCH_INCLUDE) $(MODE_INCLUDE) \ -Dlongjmp=kernel_longjmp -Dsetjmp=kernel_setjmp \ -Din6addr_loopback=kernel_in6addr_loopback \ -Din6addr_any=kernel_in6addr_any -Dstrrchr=kernel_strrchr \
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 415/614 iomap: always run error completions in user context
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christoph Hellwig <[email protected]>
[ Upstream commit ddb4873286e03e193c5a3bebb5fc6fa820e9ee3a ]
At least zonefs expects error completions to be able to sleep. Because error completions aren't performance critical, just defer them to workqueue context unconditionally.
--- fs/iomap/direct-io.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-)
fs/iomap/direct-io.c +12 -1
@@ -179,7 +179,18 @@ static void iomap_dio_done(struct iomap_dio *dio)WRITE_ONCE (dio->submit.waiter,NULL );blk_wake_io_task (waiter); - }else if (dio->flags &IOMAP_DIO_INLINE_COMP ) { +return ; + } + +/* +* Always run error completions in user context. These are not +* performance critical and some code relies on taking sleeping locks +* for error handling. +*/ +if (dio->error) + dio->flags &= ~IOMAP_DIO_INLINE_COMP ; + +if (dio->flags &IOMAP_DIO_INLINE_COMP ) {WRITE_ONCE (iocb->private,NULL );iomap_dio_complete_work (&dio->aio.work); }else if (dio->flags &IOMAP_DIO_CALLER_COMP ) {
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 416/614 iomap: allocate s_dio_done_wq for async reads as well
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christoph Hellwig <[email protected]>
[ Upstream commit 7fd8720dff2d9c70cf5a1a13b7513af01952ec02 ]
Since commit 222f2c7c6d14 ("iomap: always run error completions in user context"), read error completions are deferred to s_dio_done_wq. This means the workqueue also needs to be allocated for async reads.
--- fs/iomap/direct-io.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
fs/iomap/direct-io.c +5 -5
@@ -728,12 +728,12 @@ __iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter, } goto out_free_dio; } + } -if (!wait_for_completion && !inode->i_sb->s_dio_done_wq) { - ret =sb_init_dio_done_wq (inode->i_sb); -if (ret <0 ) - goto out_free_dio; - } +if (!wait_for_completion && !inode->i_sb->s_dio_done_wq) { + ret =sb_init_dio_done_wq (inode->i_sb); +if (ret <0 ) + goto out_free_dio; }inode_dio_begin (inode);
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 417/614 wifi: ieee80211: correct FILS status codes
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ria Thomas <[email protected]>
[ Upstream commit 24d4da5c2565313c2ad3c43449937a9351a64407 ]
The FILS status codes are set to 108/109, but the IEEE 802.11-2020 spec defines them as 112/113. Update the enum so it matches the specification and keeps the kernel consistent with standard values.
--- include/linux/ieee80211.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
include/linux/ieee80211.h +2 -2
@@ -3594,8 +3594,8 @@ enum ieee80211_statuscode {WLAN_STATUS_DENIED_WITH_SUGGESTED_BAND_AND_CHANNEL =99 ,WLAN_STATUS_DENIED_DUE_TO_SPECTRUM_MANAGEMENT =103 ,/* 802.11ai */ -WLAN_STATUS_FILS_AUTHENTICATION_FAILURE =108 , -WLAN_STATUS_UNKNOWN_AUTHENTICATION_SERVER =109 , +WLAN_STATUS_FILS_AUTHENTICATION_FAILURE =112 , +WLAN_STATUS_UNKNOWN_AUTHENTICATION_SERVER =113 ,WLAN_STATUS_SAE_HASH_TO_ELEMENT =126 ,WLAN_STATUS_SAE_PK =127 , WLAN_STATUS_DENIED_TID_TO_LINK_MAPPING = 133,
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 418/614 backlight: led-bl: Add devlink to supplier LEDs
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Luca Ceresoli <[email protected]>
[ Upstream commit 9341d6698f4cfdfc374fb6944158d111ebe16a9d ]
LED Backlight is a consumer of one or multiple LED class devices, but devlink is currently unable to create correct supplier-producer links when the supplier is a class device. It creates instead a link where the supplier is the parent of the expected device.
One consequence is that removal order is not correctly enforced.
Issues happen for example with the following sections in a device tree overlay:
// An LED driver chip
pca9632@62 {
compatible = "nxp,pca9632";
reg = <0x62>;
// ...
addon_led_pwm: led-pwm@3 {
reg = <3>;
label = "addon:led:pwm";
};
};
backlight-addon {
compatible = "led-backlight";
leds = <&addon_led_pwm>;
brightness-levels = <255>;
default-brightness-level = <255>;
};In this example, the devlink should be created between the backlight-addon (consumer) and the pca9632@62 (supplier). Instead it is created between the backlight-addon (consumer) and the parent of the pca9632@62, which is typically the I2C bus adapter.
On removal of the above overlay, the LED driver can be removed before the backlight device, resulting in:
Unable to handle kernel NULL pointer dereference at virtual address 0000000000000010
...
Call trace:
led_put+0xe0/0x140
devm_led_release+0x6c/0x98Another way to reproduce the bug without any device tree overlays is unbinding the LED class device (pca9632@62) before unbinding the consumer (backlight-addon):
echo 11-0062 >/sys/bus/i2c/drivers/leds-pca963x/unbind echo ...backlight-dock >/sys/bus/platform/drivers/led-backlight/unbind
Fix by adding a devlink between the consuming led-backlight device and the supplying LED device, as other drivers and subsystems do as well.
--- drivers/video/backlight/led_bl.c | 13 +++++++++++++ 1 file changed, 13 insertions(+)
drivers/video/backlight/led_bl.c +13 -0
@@ -210,6 +210,19 @@ static int led_bl_probe(struct platform_device *pdev)return PTR_ERR (priv->bl_dev); } +for (i =0 ; i < priv->nb_leds; i++) { +struct device_link *link; + + link =device_link_add (&pdev->dev, priv->leds[i]->dev->parent, +DL_FLAG_AUTOREMOVE_CONSUMER ); +if (!link) { +dev_err (&pdev->dev,"Failed to add devlink (consumer %s, supplier %s)\n" , +dev_name (&pdev->dev),dev_name (priv->leds[i]->dev->parent)); +backlight_device_unregister (priv->bl_dev); +return -EINVAL ; + } + } +for (i =0 ; i < priv->nb_leds; i++) {mutex_lock (&priv->leds[i]->led_access);led_sysfs_disable (priv->leds[i]);
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 419/614 backlight: lp855x: Fix lp855x.h kernel-doc warnings
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Randy Dunlap <[email protected]>
[ Upstream commit 2d45db63260c6ae3cf007361e04a1c41bd265084 ]
Add a missing struct short description and a missing leading " *" to lp855x.h to avoid kernel-doc warnings:
Warning: include/linux/platform_data/lp855x.h:126 missing initial short
description on line:
* struct lp855x_platform_data
Warning: include/linux/platform_data/lp855x.h:131 bad line:
Only valid when mode is PWM_BASED.
--- include/linux/platform_data/lp855x.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
include/linux/platform_data/lp855x.h +2 -2
@@ -124,12 +124,12 @@ struct lp855x_rom_data { };/** -* struct lp855x_platform_data +* struct lp855x_platform_data - lp855 platform-specific data * @name : Backlight driver name. If it is not defined, default name is set. * @device_control : value of DEVICE CONTROL register * @initial_brightness : initial value of backlight brightness * @period_ns : platform specific pwm period value. unit is nano. -Only valid when mode is PWM_BASED. +* Only valid when mode is PWM_BASED. * @size_program : total size of lp855x_rom_data * @rom_data : list of new eeprom/eprom registers */
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 420/614 iommu/arm-smmu-qcom: Enable use of all SMR groups when running bare-metal
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Stephan Gerhold <[email protected]>
[ Upstream commit 5583a55e074b33ccd88ac0542fd7cd656a7e2c8c ]
Some platforms (e.g. SC8280XP and X1E) support more than 128 stream matching groups. This is more than what is defined as maximum by the ARM SMMU architecture specification. Commit 122611347326 ("iommu/arm-smmu-qcom:
Limit the SMR groups to 128") disabled use of the additional groups because they don't exhibit the same behavior as the architecture supported ones.
It seems like this is just another quirk of the hypervisor: When running bare-metal without the hypervisor, the additional groups appear to behave just like all others. The boot firmware uses some of the additional groups, so ignoring them in this situation leads to stream match conflicts whenever we allocate a new SMR group for the same SID.
The workaround exists primarily because the bypass quirk detection fails when using a S2CR register from the additional matching groups, so let's perform the test with the last reliable S2CR (127) and then limit the number of SMR groups only if we detect that we are running below the hypervisor (because of the bypass quirk).
--- drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 27 ++++++++++++++-------- 1 file changed, 17 insertions(+), 10 deletions(-)
drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c +17 -10
@@ -431,17 +431,19 @@ static int qcom_smmu_cfg_probe(struct arm_smmu_device *smmu)/* * Some platforms support more than the Arm SMMU architected maximum of -* 128 stream matching groups. For unknown reasons, the additional -* groups don't exhibit the same behavior as the architected registers, -* so limit the groups to 128 until the behavior is fixed for the other -* groups. +* 128 stream matching groups. The additional registers appear to have +* the same behavior as the architected registers in the hardware. +* However, on some firmware versions, the hypervisor does not +* correctly trap and emulate accesses to the additional registers, +* resulting in unexpected behavior. +* +* If there are more than 128 groups, use the last reliable group to +* detect if we need to apply the bypass quirk. */ -if (smmu->num_mapping_groups >128 ) { -dev_notice (smmu->dev,"\tLimiting the stream matching groups to 128\n" ); - smmu->num_mapping_groups =128 ; - } - - last_s2cr =ARM_SMMU_GR0_S2CR (smmu->num_mapping_groups -1 ); +if (smmu->num_mapping_groups >128 ) + last_s2cr =ARM_SMMU_GR0_S2CR (127 ); +else + last_s2cr =ARM_SMMU_GR0_S2CR (smmu->num_mapping_groups -1 );/* * With some firmware versions writes to S2CR of type FAULT are
@@ -464,6 +466,11 @@ static int qcom_smmu_cfg_probe(struct arm_smmu_device *smmu) reg =FIELD_PREP (ARM_SMMU_CBAR_TYPE ,CBAR_TYPE_S1_TRANS_S2_BYPASS );arm_smmu_gr1_write (smmu,ARM_SMMU_GR1_CBAR (qsmmu->bypass_cbndx), reg); + +if (smmu->num_mapping_groups >128 ) { +dev_notice (smmu->dev,"\tLimiting the stream matching groups to 128\n" ); + smmu->num_mapping_groups =128 ; + } }for (i =0 ; i < smmu->num_mapping_groups; i++) {
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 421/614 RDMA/irdma: Fix data race in irdma_sc_ccq_arm
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Krzysztof Czurylo <[email protected]>
[ Upstream commit a521928164433de44fed5aaf5f49aeb3f1fb96f5 ]
Adds a lock around irdma_sc_ccq_arm body to prevent inter-thread data race. Fixes data race in irdma_sc_ccq_arm() reported by KCSAN:
BUG: KCSAN: data-race in irdma_sc_ccq_arm [irdma] / irdma_sc_ccq_arm [irdma]
read to 0xffff9d51b4034220 of 8 bytes by task 255 on cpu 11:
irdma_sc_ccq_arm+0x36/0xd0 [irdma] irdma_cqp_ce_handler+0x300/0x310 [irdma] cqp_compl_worker+0x2a/0x40 [irdma] process_one_work+0x402/0x7e0 worker_thread+0xb3/0x6d0 kthread+0x178/0x1a0 ret_from_fork+0x2c/0x50
write to 0xffff9d51b4034220 of 8 bytes by task 89 on cpu 3:
irdma_sc_ccq_arm+0x7e/0xd0 [irdma] irdma_cqp_ce_handler+0x300/0x310 [irdma] irdma_wait_event+0xd4/0x3e0 [irdma] irdma_handle_cqp_op+0xa5/0x220 [irdma] irdma_hw_flush_wqes+0xb1/0x300 [irdma] irdma_flush_wqes+0x22e/0x3a0 [irdma] irdma_cm_disconn_true+0x4c7/0x5d0 [irdma] irdma_disconnect_worker+0x35/0x50 [irdma] process_one_work+0x402/0x7e0 worker_thread+0xb3/0x6d0 kthread+0x178/0x1a0 ret_from_fork+0x2c/0x50
value changed: 0x0000000000024000 -> 0x0000000000034000
--- drivers/infiniband/hw/irdma/ctrl.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/infiniband/hw/irdma/ctrl.c +3 -0
@@ -3950,11 +3950,13 @@ int irdma_sc_cqp_destroy(struct irdma_sc_cqp *cqp)*/ void irdma_sc_ccq_arm (struct irdma_sc_cq *ccq) { +unsigned long flags;u64 temp_val;u16 sw_cq_sel;u8 arm_next_se;u8 arm_seq_num; +spin_lock_irqsave (&ccq->dev->cqp_lock, flags);get_64bit_val (ccq->cq_uk.shadow_area,32 , &temp_val); sw_cq_sel = (u16 )FIELD_GET (IRDMA_CQ_DBSA_SW_CQ_SELECT , temp_val); arm_next_se = (u8 )FIELD_GET (IRDMA_CQ_DBSA_ARM_NEXT_SE , temp_val);
@@ -3965,6 +3967,7 @@ void irdma_sc_ccq_arm(struct irdma_sc_cq *ccq)FIELD_PREP (IRDMA_CQ_DBSA_ARM_NEXT_SE , arm_next_se) |FIELD_PREP (IRDMA_CQ_DBSA_ARM_NEXT ,1 );set_64bit_val (ccq->cq_uk.shadow_area,32 , temp_val); +spin_unlock_irqrestore (&ccq->dev->cqp_lock, flags);dma_wmb ();/* make sure shadow area is updated before arming */
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 422/614 RDMA/irdma: Fix data race in irdma_free_pble
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Krzysztof Czurylo <[email protected]>
[ Upstream commit 81f44409fb4f027d1e6d54edbeba5156ad94b214 ]
Protects pble_rsrc counters with mutex to prevent data race. Fixes the following data race in irdma_free_pble reported by KCSAN:
BUG: KCSAN: data-race in irdma_free_pble [irdma] / irdma_free_pble [irdma]
write to 0xffff91430baa0078 of 8 bytes by task 16956 on cpu 5:
irdma_free_pble+0x3b/0xb0 [irdma] irdma_dereg_mr+0x108/0x110 [irdma] ib_dereg_mr_user+0x74/0x160 [ib_core] uverbs_free_mr+0x26/0x30 [ib_uverbs] destroy_hw_idr_uobject+0x4a/0x90 [ib_uverbs] uverbs_destroy_uobject+0x7b/0x330 [ib_uverbs] uobj_destroy+0x61/0xb0 [ib_uverbs] ib_uverbs_run_method+0x1f2/0x380 [ib_uverbs] ib_uverbs_cmd_verbs+0x365/0x440 [ib_uverbs] ib_uverbs_ioctl+0x111/0x190 [ib_uverbs] __x64_sys_ioctl+0xc9/0x100 do_syscall_64+0x44/0xa0 entry_SYSCALL_64_after_hwframe+0x6e/0xd8
read to 0xffff91430baa0078 of 8 bytes by task 16953 on cpu 2:
irdma_free_pble+0x23/0xb0 [irdma] irdma_dereg_mr+0x108/0x110 [irdma] ib_dereg_mr_user+0x74/0x160 [ib_core] uverbs_free_mr+0x26/0x30 [ib_uverbs] destroy_hw_idr_uobject+0x4a/0x90 [ib_uverbs] uverbs_destroy_uobject+0x7b/0x330 [ib_uverbs] uobj_destroy+0x61/0xb0 [ib_uverbs] ib_uverbs_run_method+0x1f2/0x380 [ib_uverbs] ib_uverbs_cmd_verbs+0x365/0x440 [ib_uverbs] ib_uverbs_ioctl+0x111/0x190 [ib_uverbs] __x64_sys_ioctl+0xc9/0x100 do_syscall_64+0x44/0xa0 entry_SYSCALL_64_after_hwframe+0x6e/0xd8
value changed: 0x0000000000005a62 -> 0x0000000000005a68
--- drivers/infiniband/hw/irdma/pble.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/infiniband/hw/irdma/pble.c +4 -2
@@ -506,12 +506,14 @@ int irdma_get_pble(struct irdma_hmc_pble_rsrc *pble_rsrc,void irdma_free_pble (struct irdma_hmc_pble_rsrc *pble_rsrc,struct irdma_pble_alloc *palloc) { - pble_rsrc->freedpbles += palloc->total_cnt; -if (palloc->level ==PBLE_LEVEL_2 )free_lvl2 (pble_rsrc, palloc);else irdma_prm_return_pbles (&pble_rsrc->pinfo, &palloc->level1.chunkinfo); + +mutex_lock (&pble_rsrc->pble_mutex_lock); + pble_rsrc->freedpbles += palloc->total_cnt; pble_rsrc->stats_alloc_freed++; +mutex_unlock (&pble_rsrc->pble_mutex_lock); }
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 423/614 RDMA/irdma: Add a missing kfree of struct irdma_pci_f for GEN2
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tatyana Nikolova <[email protected]>
[ Upstream commit 9e13d880ebae5da9b39ef2ed83a89737e927173f ]
During a refactor of the irdma GEN2 code, the kfree of the irdma_pci_f struct in icrdma_remove(), which was originally introduced upstream as part of commit 80f2ab46c2ee ("irdma: free iwdev->rf after removing MSI-X") was accidentally removed.
--- drivers/infiniband/hw/irdma/icrdma_if.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/infiniband/hw/irdma/icrdma_if.c +2 -0
@@ -320,6 +320,8 @@ static void icrdma_remove(struct auxiliary_device *aux_dev)irdma_ib_unregister_device (iwdev);icrdma_deinit_interrupts (iwdev->rf, cdev_info); +kfree (iwdev->rf); +pr_debug ("INIT: Gen[%d] func[%d] device remove success\n" , rdma_ver,PCI_FUNC (cdev_info->pdev->devfn)); }
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 424/614 RDMA/irdma: Fix SIGBUS in AEQ destroy
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Krzysztof Czurylo <[email protected]>
[ Upstream commit 5eff1ecce30143c3f8924d91770d81d44bd5abe5 ]
Removes write to IRDMA_PFINT_AEQCTL register prior to destroying AEQ, as this register does not exist in GEN3+ hardware and this kind of IRQ configuration is no longer required.
--- drivers/infiniband/hw/irdma/ctrl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/infiniband/hw/irdma/ctrl.c +2 -1
@@ -4734,7 +4734,8 @@ static int irdma_sc_aeq_destroy(struct irdma_sc_aeq *aeq, u64 scratch,u64 hdr; dev = aeq->dev; -if (dev->privileged) + +if (dev->hw_attrs.uk_attrs.hw_rev <=IRDMA_GEN_2 )writel (0 , dev->hw_regs[IRDMA_PFINT_AEQCTL ]); cqp = dev->cqp;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 425/614 RDMA/irdma: Add missing mutex destroy
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Anil Samal <[email protected]>
[ Upstream commit 35bd787babd1f5a42641d0b1513edbed5d4e1624 ]
Add missing destroy of ah_tbl_lock and vchnl_mutex.
--- drivers/infiniband/hw/irdma/icrdma_if.c | 4 +++- drivers/infiniband/hw/irdma/ig3rdma_if.c | 4 ++++ drivers/infiniband/hw/irdma/verbs.c | 4 +++- 3 files changed, 10 insertions(+), 2 deletions(-)
drivers/infiniband/hw/irdma/icrdma_if.c +3 -1
@@ -302,7 +302,8 @@ static int icrdma_probe(struct auxiliary_device *aux_dev, const struct auxiliary err_ctrl_init:icrdma_deinit_interrupts (rf, cdev_info); err_init_interrupts: -kfree (iwdev->rf); +mutex_destroy (&rf->ah_tbl_lock); +kfree (rf);ib_dealloc_device (&iwdev->ibdev);return err;
@@ -319,6 +320,7 @@ static void icrdma_remove(struct auxiliary_device *aux_dev)ice_rdma_update_vsi_filter (cdev_info, iwdev->vsi_num, false);irdma_ib_unregister_device (iwdev);icrdma_deinit_interrupts (iwdev->rf, cdev_info); +mutex_destroy (&iwdev->rf->ah_tbl_lock);kfree (iwdev->rf);
drivers/infiniband/hw/irdma/ig3rdma_if.c +4 -0
@@ -55,6 +55,7 @@ static int ig3rdma_vchnl_init(struct irdma_pci_f *rf, ret =irdma_sc_vchnl_init (&rf->sc_dev, &virt_info);if (ret) {destroy_workqueue (rf->vchnl_wq); +mutex_destroy (&rf->sc_dev.vchnl_mutex);return ret; }
@@ -124,7 +125,9 @@ static void ig3rdma_decfg_rf(struct irdma_pci_f *rf) {struct irdma_hw *hw = &rf->hw; +mutex_destroy (&rf->ah_tbl_lock);destroy_workqueue (rf->vchnl_wq); +mutex_destroy (&rf->sc_dev.vchnl_mutex);kfree (hw->io_regs);iounmap (hw->rdma_reg.addr); }
@@ -149,6 +152,7 @@ static int ig3rdma_cfg_rf(struct irdma_pci_f *rf, err =ig3rdma_cfg_regions (&rf->hw, cdev_info);if (err) {destroy_workqueue (rf->vchnl_wq); +mutex_destroy (&rf->sc_dev.vchnl_mutex);return err; }
drivers/infiniband/hw/irdma/verbs.c +3 -1
@@ -5500,7 +5500,9 @@ void irdma_ib_dealloc_device(struct ib_device *ibdev)irdma_rt_deinit_hw (iwdev);if (!iwdev->is_vport) {irdma_ctrl_deinit_hw (iwdev->rf); -if (iwdev->rf->vchnl_wq) +if (iwdev->rf->vchnl_wq) {destroy_workqueue (iwdev->rf->vchnl_wq); +mutex_destroy (&iwdev->rf->sc_dev.vchnl_mutex); + } } }
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 426/614 RDMA/irdma: Do not directly rely on IB_PD_UNSAFE_GLOBAL_RKEY
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jacob Moroni <[email protected]>
[ Upstream commit 71d3bdae5eab21cf8991a6f3cd914caa31d5a51f ]
The HW disables bounds checking for MRs with a length of zero, so the driver will only allow a zero length MR if the "all_memory" flag is set, and this flag is only set if IB_PD_UNSAFE_GLOBAL_RKEY is set for the PD.
This means that the "get_dma_mr" method will currently fail unless the IB_PD_UNSAFE_GLOBAL_RKEY flag is set. This has not been an issue because the "get_dma_mr" method is only ever invoked if the device does not support the local DMA key or if IB_PD_UNSAFE_GLOBAL_RKEY is set, and so far, all IRDMA HW supports the local DMA lkey.
However, some new HW does not support the local DMA lkey, so the "get_dma_mr" method needs to work without IB_PD_UNSAFE_GLOBAL_RKEY being set.
To support HW that does not allow the local DMA lkey, the logic has been changed to pass an explicit flag to indicate when a dma_mr is being created so that the zero length will be allowed.
Also, the "all_memory" flag has been forced to false for normal MR allocation since these MRs are never supposed to provide global unsafe rkey semantics anyway; only the MR created with "get_dma_mr" should support this.
--- drivers/infiniband/hw/irdma/cm.c | 2 +- drivers/infiniband/hw/irdma/main.h | 2 +- drivers/infiniband/hw/irdma/verbs.c | 15 ++++++++------- drivers/infiniband/hw/irdma/verbs.h | 3 ++- 4 files changed, 12 insertions(+), 10 deletions(-)
drivers/infiniband/hw/irdma/cm.c +1 -1
@@ -3710,7 +3710,7 @@ int irdma_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) iwpd = iwqp->iwpd; tagged_offset = (uintptr_t )iwqp->ietf_mem.va; ibmr =irdma_reg_phys_mr (&iwpd->ibpd, iwqp->ietf_mem.pa, buf_len, -IB_ACCESS_LOCAL_WRITE , &tagged_offset); +IB_ACCESS_LOCAL_WRITE , &tagged_offset, false);if (IS_ERR (ibmr)) { ret = -ENOMEM ; goto error;
drivers/infiniband/hw/irdma/main.h +1 -1
@@ -556,7 +556,7 @@ void irdma_copy_ip_htonl(__be32 *dst, u32 *src);u16 irdma_get_vlan_ipv4 (u32 *addr);void irdma_get_vlan_mac_ipv6 (u32 *addr,u16 *vlan_id,u8 *mac);struct ib_mr *irdma_reg_phys_mr (struct ib_pd *ib_pd,u64 addr,u64 size, -int acc,u64 *iova_start); +int acc,u64 *iova_start,bool dma_mr);int irdma_upload_qp_context (struct irdma_qp *iwqp,bool freeze,bool raw);void irdma_cqp_ce_handler (struct irdma_pci_f *rf,struct irdma_sc_cq *cq); int irdma_ah_cqp_op(struct irdma_pci_f *rf, struct irdma_sc_ah *sc_ah, u8 cmd,
drivers/infiniband/hw/irdma/verbs.c +8 -7
@@ -3108,7 +3108,6 @@ static int irdma_hw_alloc_stag(struct irdma_device *iwdev, info->stag_idx = iwmr->stag >>IRDMA_CQPSQ_STAG_IDX_S ; info->pd_id = iwpd->sc_pd.pd_id; info->total_len = iwmr->len; - info->all_memory = pd->flags &IB_PD_UNSAFE_GLOBAL_RKEY ; info->remote_access = true; cqp_info->cqp_cmd =IRDMA_OP_ALLOC_STAG ; cqp_info->post_sq =1 ;
@@ -3119,7 +3118,7 @@ static int irdma_hw_alloc_stag(struct irdma_device *iwdev,if (status)return status; - iwmr->is_hwreg =1 ; + iwmr->is_hwreg = true;return 0 ; }
@@ -3263,7 +3262,7 @@ static int irdma_hwreg_mr(struct irdma_device *iwdev, struct irdma_mr *iwmr,if (iwdev->rf->sc_dev.hw_attrs.uk_attrs.feature_flags &IRDMA_FEATURE_ATOMIC_OPS ) stag_info->remote_atomics_en = (access &IB_ACCESS_REMOTE_ATOMIC ) ?1 :0 ; stag_info->pd_id = iwpd->sc_pd.pd_id; - stag_info->all_memory = pd->flags &IB_PD_UNSAFE_GLOBAL_RKEY ; + stag_info->all_memory = iwmr->dma_mr;if (stag_info->access_rights &IRDMA_ACCESS_FLAGS_ZERO_BASED ) stag_info->addr_type =IRDMA_ADDR_TYPE_ZERO_BASED ;else
@@ -3290,7 +3289,7 @@ static int irdma_hwreg_mr(struct irdma_device *iwdev, struct irdma_mr *iwmr,irdma_put_cqp_request (&iwdev->rf->cqp, cqp_request);if (!ret) - iwmr->is_hwreg =1 ; + iwmr->is_hwreg = true;return ret; }
@@ -3663,7 +3662,7 @@ static int irdma_hwdereg_mr(struct ib_mr *ib_mr)if (status)return status; - iwmr->is_hwreg =0 ; + iwmr->is_hwreg = false;return 0 ; }
@@ -3786,9 +3785,10 @@ static struct ib_mr *irdma_rereg_user_mr(struct ib_mr *ib_mr, int flags,* @size: size of memory to register * @access: Access rights * @iova_start: start of virtual address for physical buffers +* @dma_mr: Flag indicating whether this region is a PD DMA MR */ struct ib_mr *irdma_reg_phys_mr (struct ib_pd *pd,u64 addr,u64 size,int access, -u64 *iova_start) +u64 *iova_start,bool dma_mr) {struct irdma_device *iwdev =to_iwdev (pd->device);struct irdma_pbl *iwpbl;
@@ -3805,6 +3805,7 @@ struct ib_mr *irdma_reg_phys_mr(struct ib_pd *pd, u64 addr, u64 size, int access iwpbl = &iwmr->iwpbl; iwpbl->iwmr = iwmr; iwmr->type =IRDMA_MEMREG_TYPE_MEM ; + iwmr->dma_mr = dma_mr; iwpbl->user_base = *iova_start; stag =irdma_create_stag (iwdev);if (!stag) {
@@ -3843,7 +3844,7 @@ static struct ib_mr *irdma_get_dma_mr(struct ib_pd *pd, int acc) {u64 kva =0 ; -return irdma_reg_phys_mr (pd,0 ,0 , acc, &kva); +return irdma_reg_phys_mr (pd,0 ,0 , acc, &kva, true); }/**
drivers/infiniband/hw/irdma/verbs.h +2 -1
@@ -111,7 +111,8 @@ struct irdma_mr { };struct ib_umem *region;int access; -u8 is_hwreg; + bool is_hwreg:1; + bool dma_mr:1;u16 type;u32 page_cnt;u64 page_size;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 427/614 RDMA/irdma: Do not set IBK_LOCAL_DMA_LKEY for GEN3+
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jacob Moroni <[email protected]>
[ Upstream commit eef3ad030b08c0f100cb18de7f604442a1adb8c7 ]
The GEN3 hardware does not appear to support IBK_LOCAL_DMA_LKEY. Attempts to use it will result in an AE.
--- drivers/infiniband/hw/irdma/verbs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/infiniband/hw/irdma/verbs.c +2 -1
@@ -27,7 +27,8 @@ static int irdma_query_device(struct ib_device *ibdev,irdma_fw_minor_ver (&rf->sc_dev); props->device_cap_flags =IB_DEVICE_MEM_WINDOW |IB_DEVICE_MEM_MGT_EXTENSIONS ; - props->kernel_cap_flags =IBK_LOCAL_DMA_LKEY ; +if (hw_attrs->uk_attrs.hw_rev <IRDMA_GEN_3 ) + props->kernel_cap_flags =IBK_LOCAL_DMA_LKEY ; props->vendor_id = pcidev->vendor; props->vendor_part_id = pcidev->device;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 428/614 RDMA/irdma: Remove doorbell elision logic
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jacob Moroni <[email protected]>
[ Upstream commit 62356fccb195f83d2ceafc787c5ba87ebbe5edfe ]
In some cases, this logic can result in doorbell writes being skipped when they should not have been (at least on GEN3 HW), so remove it. This also means that the mb() can be safely downgraded to dma_wmb().
--- drivers/infiniband/hw/irdma/puda.c | 1 - drivers/infiniband/hw/irdma/uk.c | 31 ++---------------------------- drivers/infiniband/hw/irdma/user.h | 1 - 3 files changed, 2 insertions(+), 31 deletions(-)
drivers/infiniband/hw/irdma/puda.c +0 -1
@@ -685,7 +685,6 @@ static int irdma_puda_qp_create(struct irdma_puda_rsrc *rsrc) ukqp->rq_size = rsrc->rq_size;IRDMA_RING_INIT (ukqp->sq_ring, ukqp->sq_size); -IRDMA_RING_INIT (ukqp->initial_ring, ukqp->sq_size);IRDMA_RING_INIT (ukqp->rq_ring, ukqp->rq_size); ukqp->wqe_alloc_db = qp->pd->dev->wqe_alloc_db;
drivers/infiniband/hw/irdma/uk.c +2 -29
@@ -114,33 +114,8 @@ void irdma_clr_wqes(struct irdma_qp_uk *qp, u32 qp_wqe_idx)*/ void irdma_uk_qp_post_wr (struct irdma_qp_uk *qp) { -u64 temp; -u32 hw_sq_tail; -u32 sw_sq_head; - -/* valid bit is written and loads completed before reading shadow */ -mb (); - -/* read the doorbell shadow area */ -get_64bit_val (qp->shadow_area,0 , &temp); - - hw_sq_tail = (u32 )FIELD_GET (IRDMA_QP_DBSA_HW_SQ_TAIL , temp); - sw_sq_head =IRDMA_RING_CURRENT_HEAD (qp->sq_ring); -if (sw_sq_head != qp->initial_ring.head) { -if (sw_sq_head != hw_sq_tail) { -if (sw_sq_head > qp->initial_ring.head) { -if (hw_sq_tail >= qp->initial_ring.head && - hw_sq_tail < sw_sq_head) -writel (qp->qp_id, qp->wqe_alloc_db); - }else { -if (hw_sq_tail >= qp->initial_ring.head || - hw_sq_tail < sw_sq_head) -writel (qp->qp_id, qp->wqe_alloc_db); - } - } - } - - qp->initial_ring.head = qp->sq_ring.head; +dma_wmb (); +writel (qp->qp_id, qp->wqe_alloc_db); }/**
@@ -1574,7 +1549,6 @@ static void irdma_setup_connection_wqes(struct irdma_qp_uk *qp, qp->conn_wqes = move_cnt;IRDMA_RING_MOVE_HEAD_BY_COUNT_NOCHECK (qp->sq_ring, move_cnt);IRDMA_RING_MOVE_TAIL_BY_COUNT (qp->sq_ring, move_cnt); -IRDMA_RING_MOVE_HEAD_BY_COUNT_NOCHECK (qp->initial_ring, move_cnt); }/**
@@ -1719,7 +1693,6 @@ int irdma_uk_qp_init(struct irdma_qp_uk *qp, struct irdma_qp_uk_init_info *info) qp->max_sq_frag_cnt = info->max_sq_frag_cnt; sq_ring_size = qp->sq_size << info->sq_shift;IRDMA_RING_INIT (qp->sq_ring, sq_ring_size); -IRDMA_RING_INIT (qp->initial_ring, sq_ring_size);if (info->first_sq_wq) {irdma_setup_connection_wqes (qp, info); qp->swqe_polarity =1 ;
drivers/infiniband/hw/irdma/user.h +0 -1
@@ -456,7 +456,6 @@ struct irdma_srq_uk {struct irdma_uk_attrs *uk_attrs;__le64 *shadow_area;struct irdma_ring srq_ring; -struct irdma_ring initial_ring;u32 srq_id;u32 srq_size;u32 max_srq_frag_cnt;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 429/614 RDMA/irdma: Fix SRQ shadow area address initialization
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jijun Wang <[email protected]>
[ Upstream commit 01dad9ca37c60d08f71e2ef639875ae895deede6 ]
Fix SRQ shadow area address initialization.
--- drivers/infiniband/hw/irdma/verbs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/infiniband/hw/irdma/verbs.c +1 -1
@@ -2307,8 +2307,8 @@ static int irdma_setup_kmode_srq(struct irdma_device *iwdev, ukinfo->srq_size = depth >> shift; ukinfo->shadow_area = mem->va + ring_size; - info->shadow_area_pa = info->srq_pa + ring_size; info->srq_pa = mem->pa; + info->shadow_area_pa = info->srq_pa + ring_size;return 0 ; }
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 430/614 arm64: dts: amlogic: meson-g12b: Fix L2 cache reference for S922X CPUs
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guillaume La Roque <[email protected]>
[ Upstream commit a7ab6f946683e065fa22db1cc2f2748d4584178a ]
The original addition of cache information for the Amlogic S922X SoC used the wrong next-level cache node for CPU cores 100 and 101, incorrectly referencing l2_cache_l. These cores actually belong to the big cluster and should reference l2_cache_b. Update the device tree accordingly.
--- arch/arm64/boot/dts/amlogic/meson-g12b.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
arch/arm64/boot/dts/amlogic/meson-g12b.dtsi +2 -2
@@ -87,7 +87,7 @@ cpu100: cpu@100 { i-cache-line-size = <32>; i-cache-size = <0x8000>; i-cache-sets = <32>; - next-level-cache = <&l2_cache_l>; + next-level-cache = <&l2_cache_b>; #cooling-cells = <2>; };
@@ -103,7 +103,7 @@ cpu101: cpu@101 { i-cache-line-size = <32>; i-cache-size = <0x8000>; i-cache-sets = <32>; - next-level-cache = <&l2_cache_l>; + next-level-cache = <&l2_cache_b>; #cooling-cells = <2>; };
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 431/614 drm/panthor: Avoid adding of kernel BOs to extobj list
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Akash Goel <[email protected]>
[ Upstream commit ce04ec03a9c2c4f3e60e26f21311b25d5a478208 ]
The kernel BOs unnecessarily got added to the external objects list of drm_gpuvm, when mapping to GPU, which would have resulted in few extra CPU cycles being spent at the time of job submission as drm_exec_until_all_locked() loop iterates over all external objects.
Kernel BOs are private to a VM and so they share the dma_resv object of the dummy GEM object created for a VM. Use of DRM_EXEC_IGNORE_DUPLICATES flag ensured the recursive locking of the dummy GEM object was ignored. Also no extra space got allocated to add fences to the dma_resv object of dummy GEM object. So no other impact apart from few extra CPU cycles.
This commit sets the pointer to dma_resv object of GEM object of kernel BOs before they are mapped to GPU, to prevent them from being added to external objects list.
v2: Add R-bs and fixes tags
--- drivers/gpu/drm/panthor/panthor_gem.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/gpu/drm/panthor/panthor_gem.c +3 -3
@@ -144,6 +144,9 @@ panthor_kernel_bo_create(struct panthor_device *ptdev, struct panthor_vm *vm, bo =to_panthor_bo (&obj->base); kbo->obj = &obj->base; bo->flags = bo_flags; + bo->exclusive_vm_root_gem =panthor_vm_root_gem (vm); +drm_gem_object_get (bo->exclusive_vm_root_gem); + bo->base.base.resv = bo->exclusive_vm_root_gem->resv;if (vm ==panthor_fw_vm (ptdev)) debug_flags |=PANTHOR_DEBUGFS_GEM_USAGE_FLAG_FW_MAPPED ;
@@ -167,9 +170,6 @@ panthor_kernel_bo_create(struct panthor_device *ptdev, struct panthor_vm *vm, goto err_free_va; kbo->vm =panthor_vm_get (vm); - bo->exclusive_vm_root_gem =panthor_vm_root_gem (vm); -drm_gem_object_get (bo->exclusive_vm_root_gem); - bo->base.base.resv = bo->exclusive_vm_root_gem->resv;return kbo; err_free_va:
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 432/614 clocksource/drivers/ralink: Fix resource leaks in init error path
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Haotian Zhang <[email protected]>
[ Upstream commit 2ba8e2aae1324704565a7d4d66f199d056c9e3c6 ]
The ralink_systick_init() function does not release all acquired resources on its error paths. If irq_of_parse_and_map() or a subsequent call fails, the previously created I/O memory mapping and IRQ mapping are leaked.
Add goto-based error handling labels to ensure that all allocated resources are correctly freed.
--- drivers/clocksource/timer-ralink.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-)
drivers/clocksource/timer-ralink.c +9 -2
@@ -130,14 +130,15 @@ static int __init ralink_systick_init(struct device_node *np) systick.dev.irq =irq_of_parse_and_map (np,0 );if (!systick.dev.irq) {pr_err ("%pOFn: request_irq failed" , np); -return -EINVAL ; + ret = -EINVAL ; + goto err_iounmap; } ret =clocksource_mmio_init (systick.membase +SYSTICK_COUNT , np->name,SYSTICK_FREQ ,301 ,16 , clocksource_mmio_readl_up);if (ret) -return ret; + goto err_free_irq;clockevents_register_device (&systick.dev);
@@ -145,6 +146,12 @@ static int __init ralink_systick_init(struct device_node *np) np, systick.dev.mult, systick.dev.shift);return 0 ; + +err_free_irq: +irq_dispose_mapping (systick.dev.irq); +err_iounmap: +iounmap (systick.membase); +return ret; }TIMER_OF_DECLARE (systick,"ralink,cevt-systick" , ralink_systick_init);
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 433/614 clocksource/drivers/stm: Fix double deregistration on probe failure
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
[ Upstream commit 6b38a8b31e2c5c2c3fd5f9848850788c190f216d ]
The purpose of the devm_add_action_or_reset() helper is to call the action function in case adding an action ever fails so drop the clock source deregistration from the error path to avoid deregistering twice.
--- drivers/clocksource/timer-nxp-stm.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
drivers/clocksource/timer-nxp-stm.c +1 -3
@@ -208,10 +208,8 @@ static int __init nxp_stm_clocksource_init(struct device *dev, struct stm_timerreturn ret; ret =devm_add_action_or_reset (dev, devm_clocksource_unregister, stm_timer); -if (ret) { -clocksource_unregister (&stm_timer->cs); +if (ret)return ret; - } stm_sched_clock = stm_timer;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 434/614 clocksource/drivers/arm_arch_timer_mmio: Prevent driver unbind
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
[ Upstream commit 6aa10f0e2ef9eba1955be6a9d0a8eaecf6bdb7ae ]
Clockevents cannot be deregistered so suppress the bind attributes to prevent the driver from being unbound and releasing the underlying resources after registration.
--- drivers/clocksource/arm_arch_timer_mmio.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/clocksource/arm_arch_timer_mmio.c +2 -0
@@ -426,6 +426,7 @@ static struct platform_driver arch_timer_mmio_drv = { .driver = { .name = "arch-timer-mmio", .of_match_table = arch_timer_mmio_of_table, + .suppress_bind_attrs = true, }, .probe = arch_timer_mmio_probe, };
@@ -434,6 +435,7 @@ builtin_platform_driver(arch_timer_mmio_drv);static struct platform_driver arch_timer_mmio_acpi_drv = { .driver = { .name ="gtdt-arm-mmio-timer" , + .suppress_bind_attrs = true, }, .probe = arch_timer_mmio_probe, };
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 435/614 clocksource/drivers/nxp-pit: Prevent driver unbind
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
[ Upstream commit e25f964cf414dafa6bee5c9c2c0b1d1fb041dc92 ]
The driver does not support unbinding (e.g. as clockevents cannot be deregistered) so suppress the bind attributes to prevent the driver from being unbound and rebound after registration (and disabling the timer when reprobing fails).
Even if the driver can currently only be built-in, also switch to builtin_platform_driver() to prevent it from being unloaded should modular builds ever be enabled.
--- drivers/clocksource/timer-nxp-pit.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/clocksource/timer-nxp-pit.c +2 -1
@@ -374,9 +374,10 @@ static struct platform_driver nxp_pit_driver = { .driver = { .name = "nxp-pit", .of_match_table = pit_timer_of_match, + .suppress_bind_attrs = true, }, .probe = pit_timer_probe, }; -module_platform_driver (nxp_pit_driver); +builtin_platform_driver (nxp_pit_driver);TIMER_OF_DECLARE (vf610,"fsl,vf610-pit" , pit_timer_init);
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 436/614 clocksource/drivers/nxp-stm: Fix section mismatches
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
[ Upstream commit b452d2c97eeccbf9c7ac5b3d2d9e80bf6d8a23db ]
Platform drivers can be probed after their init sections have been discarded (e.g. on probe deferral or manual rebind through sysfs) so the probe function must not live in init. Device managed resource actions similarly cannot be discarded.
The "_probe" suffix of the driver structure name prevents modpost from warning about this so replace it to catch any similar future issues.
Stable-dep-of: 6a2416892e89 ("clocksource/drivers/nxp-stm: Prevent driver unbind")
--- drivers/clocksource/timer-nxp-stm.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-)
drivers/clocksource/timer-nxp-stm.c +9 -9
@@ -177,15 +177,15 @@ static void nxp_stm_clocksource_resume(struct clocksource *cs)nxp_stm_clocksource_enable (cs); } -static void __init devm_clocksource_unregister (void *data) +static void devm_clocksource_unregister (void *data) {struct stm_timer *stm_timer = data;clocksource_unregister (&stm_timer->cs); } -static int __init nxp_stm_clocksource_init (struct device *dev,struct stm_timer *stm_timer, -const char *name,void __iomem *base,struct clk *clk) +static int nxp_stm_clocksource_init (struct device *dev,struct stm_timer *stm_timer, +const char *name,void __iomem *base,struct clk *clk) {int ret;
@@ -296,9 +296,9 @@ static void nxp_stm_clockevent_resume(struct clock_event_device *ced)nxp_stm_module_get (stm_timer); } -static int __init nxp_stm_clockevent_per_cpu_init (struct device *dev,struct stm_timer *stm_timer, -const char *name,void __iomem *base,int irq, -struct clk *clk,int cpu) +static int nxp_stm_clockevent_per_cpu_init (struct device *dev,struct stm_timer *stm_timer, +const char *name,void __iomem *base,int irq, +struct clk *clk,int cpu) { stm_timer->base = base; stm_timer->rate =clk_get_rate (clk);
@@ -386,7 +386,7 @@ static irqreturn_t nxp_stm_module_interrupt(int irq, void *dev_id)return IRQ_HANDLED ; } -static int __init nxp_stm_timer_probe (struct platform_device *pdev) +static int nxp_stm_timer_probe (struct platform_device *pdev) {struct stm_timer *stm_timer;struct device *dev = &pdev->dev;
@@ -482,14 +482,14 @@ static const struct of_device_id nxp_stm_of_match[] = { };MODULE_DEVICE_TABLE (of, nxp_stm_of_match); -static struct platform_driver nxp_stm_probe = { +static struct platform_driver nxp_stm_driver = { .probe = nxp_stm_timer_probe, .driver = { .name ="nxp-stm" , .of_match_table = nxp_stm_of_match, }, }; -module_platform_driver (nxp_stm_probe); +module_platform_driver (nxp_stm_driver);MODULE_DESCRIPTION ("NXP System Timer Module driver" );MODULE_LICENSE ("GPL" );
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 437/614 clocksource/drivers/nxp-stm: Prevent driver unbind
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
[ Upstream commit 6a2416892e8942f5e2bfe9b85c0164f410a53a2d ]
Clockevents cannot be deregistered so suppress the bind attributes to prevent the driver from being unbound and releasing the underlying resources after registration.
Even if the driver can currently only be built-in, also switch to builtin_platform_driver() to prevent it from being unloaded should modular builds ever be enabled.
--- drivers/clocksource/timer-nxp-stm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/clocksource/timer-nxp-stm.c +2 -1
@@ -487,9 +487,10 @@ static struct platform_driver nxp_stm_driver = { .driver = { .name = "nxp-stm", .of_match_table = nxp_stm_of_match, + .suppress_bind_attrs = true, }, }; -module_platform_driver (nxp_stm_driver); +builtin_platform_driver (nxp_stm_driver);MODULE_DESCRIPTION ("NXP System Timer Module driver" );MODULE_LICENSE ("GPL" );
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 438/614 ASoC: nau8325: use simple i2c probe function
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jaroslav Kysela <[email protected]>
[ Upstream commit b4d072c98e47c562834f2a050ca98a1c709ef4f9 ]
The i2c probe functions here don't use the id information provided in their second argument, so the single-parameter i2c probe function ("probe_new") can be used instead.
This avoids scanning the identifier tables during probes.
Stable-dep-of: cd41d3420ef6 ("ASoC: nau8325: add missing build config")
--- sound/soc/codecs/nau8325.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
sound/soc/codecs/nau8325.c +1 -2
@@ -829,8 +829,7 @@ static int nau8325_read_device_properties(struct device *dev,return 0 ; } -static int nau8325_i2c_probe (struct i2c_client *i2c, -const struct i2c_device_id *id) +static int nau8325_i2c_probe (struct i2c_client *i2c) {struct device *dev = &i2c->dev;struct nau8325 *nau8325 =dev_get_platdata (dev);
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 439/614 ASoC: nau8325: add missing build config
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jaroslav Kysela <[email protected]>
[ Upstream commit cd41d3420ef658b2ca902d7677536ec8e25b610a ]
This configuration was missing from the initial commit.
Found by Jiri Benc <[email protected]>
--- sound/soc/codecs/Kconfig | 5 +++++ sound/soc/codecs/Makefile | 2 ++ 2 files changed, 7 insertions(+)
sound/soc/codecs/Kconfig +5 -0
@@ -170,6 +170,7 @@ config SND_SOC_ALL_CODECS imply SND_SOC_MT6359 imply SND_SOC_MT6660 imply SND_SOC_NAU8315 + imply SND_SOC_NAU8325 imply SND_SOC_NAU8540 imply SND_SOC_NAU8810 imply SND_SOC_NAU8821
@@ -2715,6 +2716,10 @@ config SND_SOC_MT6660 config SND_SOC_NAU8315 tristate "Nuvoton Technology Corporation NAU8315 CODEC" +config SND_SOC_NAU8325 + tristate "Nuvoton Technology Corporation NAU8325 CODEC" + depends on I2C + config SND_SOC_NAU8540 tristate "Nuvoton Technology Corporation NAU85L40 CODEC" depends on I2C
sound/soc/codecs/Makefile +2 -0
@@ -192,6 +192,7 @@ snd-soc-mt6359-y := mt6359.o snd-soc-mt6359-accdet-y := mt6359-accdet.o snd-soc-mt6660-y := mt6660.o snd-soc-nau8315-y := nau8315.o +snd-soc-nau8325-y := nau8325.o snd-soc-nau8540-y := nau8540.o snd-soc-nau8810-y := nau8810.o snd-soc-nau8821-y := nau8821.o
@@ -618,6 +619,7 @@ obj-$(CONFIG_SND_SOC_MT6359) += snd-soc-mt6359.o obj-$(CONFIG_SND_SOC_MT6359_ACCDET) += mt6359-accdet.o obj-$(CONFIG_SND_SOC_MT6660) += snd-soc-mt6660.o obj-$(CONFIG_SND_SOC_NAU8315) += snd-soc-nau8315.o +obj-$(CONFIG_SND_SOC_NAU8325) += snd-soc-nau8325.o obj-$(CONFIG_SND_SOC_NAU8540) += snd-soc-nau8540.o obj-$(CONFIG_SND_SOC_NAU8810) += snd-soc-nau8810.o obj-$(CONFIG_SND_SOC_NAU8821) += snd-soc-nau8821.o
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 440/614 gfs2: Prevent recursive memory reclaim
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Andreas Gruenbacher <[email protected]>
[ Upstream commit 2c5f4a53476e3cab70adc77b38942c066bd2c17c ]
Function new_inode() returns a new inode with inode->i_mapping->gfp_mask set to GFP_HIGHUSER_MOVABLE. This value includes the __GFP_FS flag, so allocations in that address space can recurse into filesystem memory reclaim. We don't want that to happen because it can consume a significant amount of stack memory.
Worse than that is that it can also deadlock: for example, in several places, gfs2_unstuff_dinode() is called inside filesystem transactions. This calls filemap_grab_folio(), which can allocate a new folio, which can trigger memory reclaim. If memory reclaim recurses into the filesystem and starts another transaction, a deadlock will ensue.
To fix these kinds of problems, prevent memory reclaim from recursing into filesystem code by making sure that the gfp_mask of inode address spaces doesn't include __GFP_FS.
The "meta" and resource group address spaces were already using GFP_NOFS as their gfp_mask (which doesn't include __GFP_FS). The default value of GFP_HIGHUSER_MOVABLE is less restrictive than GFP_NOFS, though. To avoid being overly limiting, use the default value and only knock off the __GFP_FS flag. I'm not sure if this will actually make a difference, but it also shouldn't hurt.
This patch is loosely based on commit ad22c7a043c2 ("xfs: prevent stack overflows from page cache allocation").
Fixes xfstest generic/273.
--- fs/gfs2/glock.c | 5 ++++- fs/gfs2/inode.c | 15 +++++++++++++++ fs/gfs2/inode.h | 1 + fs/gfs2/ops_fstype.c | 2 +- 4 files changed, 21 insertions(+), 2 deletions(-)
fs/gfs2/glock.c +4 -1
@@ -1211,10 +1211,13 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number, mapping =gfs2_glock2aspace (gl);if (mapping) { +gfp_t gfp_mask; + mapping->a_ops = &gfs2_meta_aops; mapping->host = sdp->sd_inode; mapping->flags =0 ; -mapping_set_gfp_mask (mapping,GFP_NOFS ); + gfp_mask =mapping_gfp_mask (sdp->sd_inode->i_mapping); +mapping_set_gfp_mask (mapping, gfp_mask); mapping->i_private_data =NULL ; mapping->writeback_index =0 ; }
fs/gfs2/inode.c +15 -0
@@ -89,6 +89,19 @@ static int iget_set(struct inode *inode, void *opaque)return 0 ; } +void gfs2_setup_inode (struct inode *inode) +{ +gfp_t gfp_mask; + +/* +* Ensure all page cache allocations are done from GFP_NOFS context to +* prevent direct reclaim recursion back into the filesystem and blowing +* stacks or deadlocking. +*/ + gfp_mask =mapping_gfp_mask (inode->i_mapping); +mapping_set_gfp_mask (inode->i_mapping, gfp_mask & ~__GFP_FS); +} +/** * gfs2_inode_lookup - Lookup an inode * @sb: The super block
@@ -132,6 +145,7 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned int type,struct gfs2_glock *io_gl;int extra_flags =0 ; +gfs2_setup_inode (inode); error =gfs2_glock_get (sdp, no_addr, &gfs2_inode_glops,CREATE , &ip->i_gl);if (unlikely (error))
@@ -752,6 +766,7 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry, error = -ENOMEM ;if (!inode) goto fail_gunlock; +gfs2_setup_inode (inode); ip =GFS2_I (inode); error =posix_acl_create (dir, &mode, &default_acl, &acl);
fs/gfs2/inode.h +1 -0
@@ -86,6 +86,7 @@ static inline int gfs2_check_internal_file_size(struct inode *inode,return -EIO ; } +void gfs2_setup_inode (struct inode *inode);struct inode *gfs2_inode_lookup (struct super_block *sb,unsigned type,u64 no_addr,u64 no_formal_ino,unsigned int blktype);
fs/gfs2/ops_fstype.c +1 -1
@@ -1183,7 +1183,7 @@ static int gfs2_fill_super(struct super_block *sb, struct fs_context *fc) mapping =gfs2_aspace (sdp); mapping->a_ops = &gfs2_rgrp_aops; -mapping_set_gfp_mask (mapping,GFP_NOFS ); +gfs2_setup_inode (sdp->sd_inode); error =init_names (sdp, silent);if (error)
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 441/614 ASoC: fsl_xcvr: clear the channel status control memory
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Shengjiu Wang <[email protected]>
[ Upstream commit 73b97d46dde64fa184d47865d4a532d818c3a007 ]
memset_io() writes memory byte by byte with __raw_writeb() on the arm platform if the size is word. but XCVR data RAM memory can't be accessed with byte address, so with memset_io() the channel status control memory is not really cleared, use writel_relaxed() instead.
--- sound/soc/fsl/fsl_xcvr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
sound/soc/fsl/fsl_xcvr.c +1 -1
@@ -1421,7 +1421,7 @@ static irqreturn_t irq0_isr(int irq, void *devid)bitrev32 (val); }/* clear CS control register */ -memset_io (reg_ctrl,0 ,sizeof (val)); +writel_relaxed (0 , reg_ctrl); } }else { regmap_read(xcvr->regmap, FSL_XCVR_RX_CS_DATA_0,
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 442/614 firmware_loader: make RUST_FW_LOADER_ABSTRACTIONS select FW_LOADER
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alexandre Courbot <[email protected]>
[ Upstream commit 9906efa545d1d2cf25a614eeb219d3f8d5a302cd ]
The use of firmware_loader is an implementation detail of drivers rather than a dependency. FW_LOADER is typically selected rather than depended on; the Rust abstractions should do the same thing.
--- drivers/base/firmware_loader/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/base/firmware_loader/Kconfig +1 -1
@@ -38,7 +38,7 @@ config FW_LOADER_DEBUG config RUST_FW_LOADER_ABSTRACTIONS bool "Rust Firmware Loader abstractions" depends on RUST - depends on FW_LOADER=y + select FW_LOADER help This enables the Rust abstractions for the firmware loader API.
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 443/614 greybus: gb-beagleplay: Fix timeout handling in bootloader functions
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Haotian Zhang <[email protected]>
[ Upstream commit e6df0f649cff08da7a2feb6d963b39076ca129f9 ]
wait_for_completion_timeout() returns the remaining jiffies (at least 1) on success or 0 on timeout, but never negative error codes. The current code incorrectly checks for negative values, causing timeouts to be ignored and treated as success.
Check for a zero return value to correctly identify and handle timeout events.
--- drivers/greybus/gb-beagleplay.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
drivers/greybus/gb-beagleplay.c +6 -6
@@ -644,8 +644,8 @@ static int cc1352_bootloader_wait_for_ack(struct gb_beagleplay *bg) ret =wait_for_completion_timeout ( &bg->fwl_ack_com,msecs_to_jiffies (CC1352_BOOTLOADER_TIMEOUT )); -if (ret <0 ) -return dev_err_probe (&bg->sd->dev, ret, +if (!ret) +return dev_err_probe (&bg->sd->dev, -ETIMEDOUT ,"Failed to acquire ack semaphore" );switch (READ_ONCE (bg->fwl_ack)) {
@@ -683,8 +683,8 @@ static int cc1352_bootloader_get_status(struct gb_beagleplay *bg) ret =wait_for_completion_timeout ( &bg->fwl_cmd_response_com,msecs_to_jiffies (CC1352_BOOTLOADER_TIMEOUT )); -if (ret <0 ) -return dev_err_probe (&bg->sd->dev, ret, +if (!ret) +return dev_err_probe (&bg->sd->dev, -ETIMEDOUT ,"Failed to acquire last status semaphore" );switch (READ_ONCE (bg->fwl_cmd_response)) {
@@ -768,8 +768,8 @@ static int cc1352_bootloader_crc32(struct gb_beagleplay *bg, u32 *crc32) ret =wait_for_completion_timeout ( &bg->fwl_cmd_response_com,msecs_to_jiffies (CC1352_BOOTLOADER_TIMEOUT )); -if (ret <0 ) -return dev_err_probe (&bg->sd->dev, ret, +if (!ret) +return dev_err_probe (&bg->sd->dev, -ETIMEDOUT ,"Failed to acquire last status semaphore" ); *crc32 =READ_ONCE (bg->fwl_cmd_response);
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 444/614 fs: refactor file timestamp update logic
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christoph Hellwig <[email protected]>
[ Upstream commit 3cd9a42f1b5e34d3972237cbf8541af60844cbd4 ]
Currently the two high-level APIs use two helper functions to implement almost all of the logic. Refactor the two helpers and the common logic into a new file_update_time_flags routine that gets the iocb flags or 0 in case of file_update_time passed so that the entire logic is contained in a single function and can be easily understood and modified.
Stable-dep-of: 7f30e7a42371 ("fs: lift the FMODE_NOCMTIME check into file_update_time_flags")
--- fs/inode.c | 54 +++++++++++++++++------------------------------------- 1 file changed, 17 insertions(+), 37 deletions(-)
fs/inode.c +17 -37
@@ -2322,10 +2322,12 @@ struct timespec64 current_time(struct inode *inode) }EXPORT_SYMBOL (current_time); -static int inode_needs_update_time (struct inode *inode) +static int file_update_time_flags (struct file *file,unsigned int flags) { +struct inode *inode =file_inode (file);struct timespec64 now, ts; -int sync_it =0 ; +int sync_mode =0 ; +int ret =0 ;/* First try to exhaust all avenues to not sync */ if (IS_NOCMTIME (inode))
@@ -2335,29 +2337,23 @@ static int inode_needs_update_time(struct inode *inode) ts =inode_get_mtime (inode);if (!timespec64_equal (&ts, &now)) - sync_it |=S_MTIME ; - + sync_mode |=S_MTIME ; ts =inode_get_ctime (inode);if (!timespec64_equal (&ts, &now)) - sync_it |=S_CTIME ; - + sync_mode |=S_CTIME ;if (IS_I_VERSION (inode) &&inode_iversion_need_inc (inode)) - sync_it |=S_VERSION ; + sync_mode |=S_VERSION ; -return sync_it; -} - -static int __file_update_time (struct file *file,int sync_mode) -{ -int ret =0 ; -struct inode *inode =file_inode (file); +if (!sync_mode) +return 0 ; -/* try to update time settings */ -if (!mnt_get_write_access_file (file)) { - ret =inode_update_time (inode, sync_mode); -mnt_put_write_access_file (file); - } +if (flags &IOCB_NOWAIT ) +return -EAGAIN ; +if (mnt_get_write_access_file (file)) +return 0 ; + ret =inode_update_time (inode, sync_mode); +mnt_put_write_access_file (file);return ret; }
@@ -2377,14 +2373,7 @@ static int __file_update_time(struct file *file, int sync_mode)*/ int file_update_time (struct file *file) { -int ret; -struct inode *inode =file_inode (file); - - ret =inode_needs_update_time (inode); -if (ret <=0 ) -return ret; - -return __file_update_time (file, ret); +return file_update_time_flags (file,0 ); }EXPORT_SYMBOL (file_update_time);
@@ -2406,7 +2395,6 @@ EXPORT_SYMBOL(file_update_time);static int file_modified_flags (struct file *file,int flags) {int ret; -struct inode *inode =file_inode (file);/* * Clear the security bits if the process is not being run by root.
@@ -2415,17 +2403,9 @@ static int file_modified_flags(struct file *file, int flags) ret =file_remove_privs_flags (file, flags);if (ret)return ret; -if (unlikely (file->f_mode &FMODE_NOCMTIME ))return 0 ; - - ret =inode_needs_update_time (inode); -if (ret <=0 ) -return ret; -if (flags &IOCB_NOWAIT ) -return -EAGAIN ; - -return __file_update_time (file, ret); +return file_update_time_flags (file, flags); }/**
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 445/614 fs: lift the FMODE_NOCMTIME check into file_update_time_flags
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christoph Hellwig <[email protected]>
[ Upstream commit 7f30e7a42371af4bba53f9a875a0d320cead9f4b ]
FMODE_NOCMTIME used to be just a hack for the legacy XFS handle-based "invisible I/O", but commit e5e9b24ab8fa ("nfsd: freeze c/mtime updates with outstanding WRITE_ATTRS delegation") started using it from generic callers.
I'm not sure other file systems are actually read for this in general, so the above commit should get a closer look, but for it to make any sense, file_update_time needs to respect the flag.
Lift the check from file_modified_flags to file_update_time so that users of file_update_time inherit the behavior and so that all the checks are done in one place.
--- fs/inode.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
fs/inode.c +2 -2
@@ -2332,6 +2332,8 @@ static int file_update_time_flags(struct file *file, unsigned int flags)/* First try to exhaust all avenues to not sync */ if (IS_NOCMTIME (inode))return 0 ; +if (unlikely (file->f_mode &FMODE_NOCMTIME )) +return 0 ; now =current_time (inode);
@@ -2403,8 +2405,6 @@ static int file_modified_flags(struct file *file, int flags) ret =file_remove_privs_flags (file, flags);if (ret)return ret; -if (unlikely (file->f_mode &FMODE_NOCMTIME )) -return 0 ;return file_update_time_flags (file, flags); }
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 446/614 misc: rp1: Fix an error handling path in rp1_probe()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christophe JAILLET <[email protected]>
[ Upstream commit 43cd4b634ef90c4e2ff75eaeb361786fa04c8874 ]
When DT is used to get the reference of 'rp1_node', it should be released when not needed anymore, otherwise it is leaking.
In such a case, add the missing of_node_put() call at the end of the probe, as already done in the error handling path.
--- drivers/misc/rp1/rp1_pci.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/misc/rp1/rp1_pci.c +3 -0
@@ -289,6 +289,9 @@ static int rp1_probe(struct pci_dev *pdev, const struct pci_device_id *id) goto err_unload_overlay; } +if (skip_ovl) +of_node_put (rp1_node); +return 0 ; err_unload_overlay:
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 447/614 kernfs: fix memory leak of kernfs_iattrs in __kernfs_new_node
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Will Rosenberg <[email protected]>
[ Upstream commit 382b1e8f30f779af8d6d33268e53df7de579ef3c ]
There exists a memory leak of kernfs_iattrs contained as an element of kernfs_node allocated in __kernfs_new_node(). __kernfs_setattr() allocates kernfs_iattrs as a sub-object, and the LSM security check incorrectly errors out and does not free the kernfs_iattrs sub-object.
Make an additional error out case that properly frees kernfs_iattrs if security_kernfs_init_security() fails.
--- fs/kernfs/dir.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
fs/kernfs/dir.c +4 -1
@@ -675,11 +675,14 @@ static struct kernfs_node *__kernfs_new_node(struct kernfs_root *root,if (parent) { ret =security_kernfs_init_security (parent, kn);if (ret) - goto err_out3; + goto err_out4; }return kn; + err_out4: +simple_xattrs_free (&kn->iattr->xattrs,NULL ); +kmem_cache_free (kernfs_iattrs_cache, kn->iattr); err_out3:spin_lock (&root->kernfs_idr_lock);idr_remove (&root->ino_idr, (u32 )kernfs_ino (kn));
Signature · 1 line
2.51.0
Re: [PATCH 6.18 447/614] kernfs: fix memory leak of kernfs_iattrs in __kernfs_new_node
Quoted 1 line · Greg Kroah-Hartman
6.18-stable review patch. If anyone has any objections, please let me know.
Please see https://lkml.org/lkml/2025/12/16/1248.
Greg Kroah-Hartman
maintainerPATCH 448/614 drm/amd/display: Fix logical vs bitwise bug in get_embedded_panel_info_v2_1()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dan Carpenter <[email protected]>
[ Upstream commit 1a79482699b4d1e43948d14f0c7193dc1dcad858 ]
The .H_SYNC_POLARITY and .V_SYNC_POLARITY variables are 1 bit bitfields of a u32. The ATOM_HSYNC_POLARITY define is 0x2 and the ATOM_VSYNC_POLARITY is 0x4. When we do a bitwise negate of 0, 2, or 4 then the last bit is always 1 so this code always sets .H_SYNC_POLARITY and .V_SYNC_POLARITY to true.
This code is instead intended to check if the ATOM_HSYNC_POLARITY or ATOM_VSYNC_POLARITY flags are set and reverse the result. In other words, it's supposed to be a logical negate instead of a bitwise negate.
--- drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c +4 -4
@@ -1480,10 +1480,10 @@ static enum bp_result get_embedded_panel_info_v2_1(/* not provided by VBIOS */ info->lcd_timing.misc_info.HORIZONTAL_CUT_OFF =0 ; - info->lcd_timing.misc_info.H_SYNC_POLARITY = ~(uint32_t ) (lvds->lcd_timing.miscinfo - &ATOM_HSYNC_POLARITY ); - info->lcd_timing.misc_info.V_SYNC_POLARITY = ~(uint32_t ) (lvds->lcd_timing.miscinfo - &ATOM_VSYNC_POLARITY ); + info->lcd_timing.misc_info.H_SYNC_POLARITY = !(lvds->lcd_timing.miscinfo & +ATOM_HSYNC_POLARITY ); + info->lcd_timing.misc_info.V_SYNC_POLARITY = !(lvds->lcd_timing.miscinfo & +ATOM_VSYNC_POLARITY );/* not provided by VBIOS */ info->lcd_timing.misc_info.VERTICAL_CUT_OFF =0 ;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 449/614 drm/amdkfd: assign AID to uuid in topology for SPX mode
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Huang <[email protected]>
[ Upstream commit 089702632f1dd38fadc9af13816485d6aa518dbb ]
XCD id is assigned to uuid, which causes some performance drop in SPX mode, assigning AID back will resolve the issue.
--- drivers/gpu/drm/amd/amdkfd/kfd_topology.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/gpu/drm/amd/amdkfd/kfd_topology.c +3 -1
@@ -530,7 +530,9 @@ static ssize_t node_show(struct kobject *kobj, struct attribute *attr,sysfs_show_32bit_prop (buffer, offs,"sdma_fw_version" , dev->gpu->kfd->sdma_fw_version);sysfs_show_64bit_prop (buffer, offs,"unique_id" , - dev->gpu->xcp ? + dev->gpu->xcp && + (dev->gpu->xcp->xcp_mgr->mode != +AMDGPU_SPX_PARTITION_MODE ) ? dev->gpu->xcp->unique_id : dev->gpu->adev->unique_id); sysfs_show_32bit_prop(buffer, offs, "num_xcc",
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 450/614 hwmon: sy7636a: Fix regulator_enable resource leak on error path
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Haotian Zhang <[email protected]>
[ Upstream commit 2f88425ef590b7fcc2324334b342e048edc144a9 ]
In sy7636a_sensor_probe(), regulator_enable() is called but if devm_hwmon_device_register_with_info() fails, the function returns without calling regulator_disable(), leaving the regulator enabled and leaking the reference count.
Switch to devm_regulator_get_enable() to automatically manage the regulator resource.
--- drivers/hwmon/sy7636a-hwmon.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-)
drivers/hwmon/sy7636a-hwmon.c +1 -6
@@ -66,18 +66,13 @@ static const struct hwmon_chip_info sy7636a_chip_info = {static int sy7636a_sensor_probe (struct platform_device *pdev) {struct regmap *regmap =dev_get_regmap (pdev->dev.parent,NULL ); -struct regulator *regulator;struct device *hwmon_dev;int err;if (!regmap)return -EPROBE_DEFER ; - regulator =devm_regulator_get (&pdev->dev,"vcom" ); -if (IS_ERR (regulator)) -return PTR_ERR (regulator); - - err =regulator_enable (regulator); + err =devm_regulator_get_enable (&pdev->dev,"vcom" );if (err)return err;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 451/614 ACPI: processor_core: fix map_x2apic_id for amd-pstate on am4
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: René Rebe <[email protected]>
[ Upstream commit 17e7972979e147cc51d4a165e6b6b0f93273ca68 ]
On all AMD AM4 systems I have seen, e.g ASUS X470-i, Pro WS X570 Ace and equivalent Gigabyte, amd-pstate does not initialize when the x2apic is enabled in the BIOS. Kernel debug messages include:
[ 0.315438] acpi LNXCPU:00: Failed to get CPU physical ID. [ 0.354756] ACPI CPPC: No CPC descriptor for CPU:0 [ 0.714951] amd_pstate: the _CPC object is not present in SBIOS or ACPI disabled
I tracked this down to map_x2apic_id() checking device_declaration passed in via the type argument of acpi_get_phys_id() via map_madt_entry() while map_lapic_id() does not.
It appears these BIOSes use Processor statements for declaring the CPUs in the ACPI namespace instead of processor device objects (which should have been used). CPU declarations via Processor statements were deprecated in ACPI 6.0 that was released 10 years ago. They should not be used any more in any contemporary platform firmware.
I tried to contact Asus support multiple times, but never received a reply nor did any BIOS update ever change this.
Fix amd-pstate w/ x2apic on am4 by allowing map_x2apic_id() to work with CPUs declared via Processor statements for IDs less than 255, which is consistent with ACPI 5.0 that still allowed Processor statements to be used for declaring CPUs.
--- drivers/acpi/processor_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/acpi/processor_core.c +1 -1
@@ -54,7 +54,7 @@ static int map_x2apic_id(struct acpi_subtable_header *entry,if (!(apic->lapic_flags &ACPI_MADT_ENABLED ))return -ENODEV ; -if (device_declaration && (apic->uid == acpi_id)) { +if (apic->uid == acpi_id && (device_declaration || acpi_id <255 )) { *apic_id = apic->local_apic_id;return 0 ; }
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 452/614 ublk: prevent invalid access with DEBUG
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kevin Brodsky <[email protected]>
[ Upstream commit c6a45ee7607de3a350008630f4369b1b5ac80884 ]
ublk_ch_uring_cmd_local() may jump to the out label before initialising the io pointer. This will cause trouble if DEBUG is defined, because the pr_devel() call dereferences io. Clang reports:
drivers/block/ublk_drv.c:2403:6: error: variable 'io' is used uninitialized whenever 'if' condition is true [-Werror,-Wsometimes-uninitialized]
2403 | if (tag >= ub->dev_info.queue_depth)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
drivers/block/ublk_drv.c:2492:32: note: uninitialized use occurs here
2492 | __func__, cmd_op, tag, ret, io->flags);
|Fix this by initialising io to NULL and checking it before dereferencing it.
--- drivers/block/ublk_drv.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/block/ublk_drv.c +2 -2
@@ -2367,7 +2367,7 @@ static int ublk_ch_uring_cmd_local(struct io_uring_cmd *cmd,u16 buf_idx =UBLK_INVALID_BUF_IDX ;struct ublk_device *ub = cmd->file->private_data;struct ublk_queue *ubq; -struct ublk_io *io; +struct ublk_io *io =NULL ;u32 cmd_op = cmd->cmd_op;u16 q_id =READ_ONCE (ub_src->q_id);u16 tag =READ_ONCE (ub_src->tag);
@@ -2488,7 +2488,7 @@ static int ublk_ch_uring_cmd_local(struct io_uring_cmd *cmd, out:pr_devel ("%s: complete: cmd op %d, tag %d ret %x io_flags %x\n" , - __func__, cmd_op, tag, ret, io->flags); + __func__, cmd_op, tag, ret, io ? io->flags :0 );return ret; }
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 453/614 selftests/landlock: Fix makefile header list
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matthieu Buffet <[email protected]>
[ Upstream commit e61462232a58bddd818fa6a913a9a2e76fd3634f ]
Make all headers part of make's dependencies computations. Otherwise, updating audit.h, common.h, scoped_base_variants.h, scoped_common.h, scoped_multiple_domain_variants.h, or wrappers.h, re-running make and running selftests could lead to testing stale headers.
--- tools/testing/selftests/landlock/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/testing/selftests/landlock/Makefile +1 -1
@@ -4,7 +4,7 @@ CFLAGS += -Wall -O2 $(KHDR_INCLUDES) -LOCAL_HDRS += common.h +LOCAL_HDRS += $(wildcard *.h) src_test := $(wildcard *_test.c)
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 454/614 bpf: Fix exclusive map memory leak
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Edward Adam Davis <[email protected]>
[ Upstream commit 688b745401ab16e2e1a3b504863f0a45fd345638 ]
When excl_prog_hash is 0 and excl_prog_hash_size is non-zero, the map also needs to be freed. Otherwise, the map memory will not be reclaimed, just like the memory leak problem reported by syzbot [1].
syzbot reported:
BUG: memory leak
backtrace (crc 7b9fb9b4):
map_create+0x322/0x11e0 kernel/bpf/syscall.c:1512
__sys_bpf+0x3556/0x3610 kernel/bpf/syscall.c:6131--- kernel/bpf/syscall.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
kernel/bpf/syscall.c +2 -1
@@ -1585,7 +1585,8 @@ static int map_create(union bpf_attr *attr, bpfptr_t uattr) goto free_map; } }else if (attr->excl_prog_hash_size) { -return -EINVAL ; + err = -EINVAL ; + goto free_map; } err =security_bpf_map_create (map, attr, token, uattr.is_kernel);
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 455/614 ext4: improve integrity checking in __mb_check_buddy by enhancing order-0 validation
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yongjian Sun <[email protected]>
[ Upstream commit d9ee3ff810f1cc0e253c9f2b17b668b973cb0e06 ]
When the MB_CHECK_ASSERT macro is enabled, we found that the current validation logic in __mb_check_buddy has a gap in detecting certain invalid buddy states, particularly related to order-0 (bitmap) bits.
The original logic consists of three steps:
1. Validates higher-order buddies: if a higher-order bit is set, at most one of the two corresponding lower-order bits may be free; if a higher-order bit is clear, both lower-order bits must be allocated (and their bitmap bits must be 0).
2. For any set bit in order-0, ensures all corresponding higher-order bits are not free.
3. Verifies that all preallocated blocks (pa) in the group have pa_pstart within bounds and their bitmap bits marked as allocated.
However, this approach fails to properly validate cases where order-0 bits are incorrectly cleared (0), allowing some invalid configurations to pass:
corrupt integral
order 3 1 1
order 2 1 1 1 1
order 1 1 1 1 1 1 1 1 1
order 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1
Here we get two adjacent free blocks at order-0 with inconsistent higher-order state, and the right one shows the correct scenario.
The root cause is insufficient validation of order-0 zero bits. To fix this and improve completeness without significant performance cost, we refine the logic:
1. Maintain the top-down higher-order validation, but we no longer check the cases where the higher-order bit is 0, as this case will be covered in step 2.
2. Enhance order-0 checking by examining pairs of bits:
- If either bit in a pair is set (1), all corresponding higher-order bits must not be free.
- If both bits are clear (0), then exactly one of the corresponding higher-order bits must be free
3. Keep the preallocation (pa) validation unchanged.
This change closes the validation gap, ensuring illegal buddy states involving order-0 are correctly detected, while removing redundant checks and maintaining efficiency.
Message-ID: <[email protected]>
--- fs/ext4/mballoc.c | 49 +++++++++++++++++++++++++++++++---------------- 1 file changed, 32 insertions(+), 17 deletions(-)
fs/ext4/mballoc.c +32 -17
@@ -682,6 +682,24 @@ do { \ } \ }while (0 ) +/* +* Perform buddy integrity check with the following steps: +* +* 1. Top-down validation (from highest order down to order 1, excluding order-0 bitmap): +* For each pair of adjacent orders, if a higher-order bit is set (indicating a free block), +* at most one of the two corresponding lower-order bits may be clear (free). +* +* 2. Order-0 (bitmap) validation, performed on bit pairs: +* - If either bit in a pair is set (1, allocated), then all corresponding higher-order bits +* must not be free (0). +* - If both bits in a pair are clear (0, free), then exactly one of the corresponding +* higher-order bits must be free (0). +* +* 3. Preallocation (pa) list validation: +* For each preallocated block (pa) in the group: +* - Verify that pa_pstart falls within the bounds of this block group. +* - Ensure the corresponding bit(s) in the order-0 bitmap are marked as allocated (1). +*/ static void __mb_check_buddy(struct ext4_buddy *e4b, char *file,const char *function,int line) {
@@ -723,15 +741,6 @@ static void __mb_check_buddy(struct ext4_buddy *e4b, char *file,continue ; } -/* both bits in buddy2 must be 1 */ -MB_CHECK_ASSERT (mb_test_bit (i <<1 , buddy2)); -MB_CHECK_ASSERT (mb_test_bit ((i <<1 ) +1 , buddy2)); - -for (j =0 ; j < (1 << order); j++) { - k = (i * (1 << order)) + j; -MB_CHECK_ASSERT ( - !mb_test_bit (k, e4b->bd_bitmap)); - } count++; }MB_CHECK_ASSERT (e4b->bd_info->bb_counters[order] == count);
@@ -747,15 +756,21 @@ static void __mb_check_buddy(struct ext4_buddy *e4b, char *file, fragments++; fstart = i; } -continue ; + }else { + fstart =-1 ; } - fstart =-1 ; -/* check used bits only */ -for (j =0 ; j < e4b->bd_blkbits +1 ; j++) { - buddy2 =mb_find_buddy (e4b, j, &max2); - k = i >> j; -MB_CHECK_ASSERT (k < max2); -MB_CHECK_ASSERT (mb_test_bit (k, buddy2)); +if (!(i &1 )) { +int in_use, zero_bit_count =0 ; + + in_use =mb_test_bit (i, buddy) ||mb_test_bit (i +1 , buddy); +for (j =1 ; j < e4b->bd_blkbits +2 ; j++) { + buddy2 =mb_find_buddy (e4b, j, &max2); + k = i >> j; +MB_CHECK_ASSERT (k < max2); +if (!mb_test_bit (k, buddy2)) + zero_bit_count++; + } +MB_CHECK_ASSERT (zero_bit_count == !in_use); } }MB_CHECK_ASSERT (!EXT4_MB_GRP_NEED_INIT (e4b->bd_info));
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 456/614 selftests/net: packetdrill: pass send_omit_free to MSG_ZEROCOPY tests
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Willem de Bruijn <[email protected]>
[ Upstream commit c01a6e5b2e4f21d31cf725b9f3803cb0280b1b8d ]
The --send_omit_free flag is needed for TCP zero copy tests, to ensure that packetdrill doesn't free the send() buffer after the send() call.
--- .../net/packetdrill/tcp_syscall_bad_arg_sendmsg-empty-iov.pkt | 4 ++++ .../testing/selftests/net/packetdrill/tcp_zerocopy_basic.pkt | 2 ++ .../testing/selftests/net/packetdrill/tcp_zerocopy_batch.pkt | 2 ++ .../testing/selftests/net/packetdrill/tcp_zerocopy_client.pkt | 2 ++ .../testing/selftests/net/packetdrill/tcp_zerocopy_closed.pkt | 2 ++ .../selftests/net/packetdrill/tcp_zerocopy_epoll_edge.pkt | 3 +++ .../net/packetdrill/tcp_zerocopy_epoll_exclusive.pkt | 3 +++ .../selftests/net/packetdrill/tcp_zerocopy_epoll_oneshot.pkt | 3 +++ .../net/packetdrill/tcp_zerocopy_fastopen-client.pkt | 2 ++ .../net/packetdrill/tcp_zerocopy_fastopen-server.pkt | 2 ++ .../selftests/net/packetdrill/tcp_zerocopy_maxfrags.pkt | 2 ++ .../testing/selftests/net/packetdrill/tcp_zerocopy_small.pkt | 2 ++ 12 files changed, 29 insertions(+)
tools/testing/selftests/net/packetdrill/tcp_syscall_bad_arg_sendmsg-empty-iov.pkt +4 -0
@@ -1,6 +1,10 @@ // SPDX-License-Identifier: GPL-2.0 // Test that we correctly skip zero-length IOVs. + +--send_omit_free // do not reuse send buffers with zerocopy + `./defaults.sh` + 0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3 +0 setsockopt(3, SOL_SOCKET, SO_ZEROCOPY, [1], 4) = 0 +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
tools/testing/selftests/net/packetdrill/tcp_zerocopy_basic.pkt +2 -0
@@ -4,6 +4,8 @@ // send a packet with MSG_ZEROCOPY and receive the notification ID // repeat and verify IDs are consecutive +--send_omit_free // do not reuse send buffers with zerocopy + `./defaults.sh` 0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
tools/testing/selftests/net/packetdrill/tcp_zerocopy_batch.pkt +2 -0
@@ -3,6 +3,8 @@ // // send multiple packets, then read one range of all notifications. +--send_omit_free // do not reuse send buffers with zerocopy + `./defaults.sh` 0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
tools/testing/selftests/net/packetdrill/tcp_zerocopy_client.pkt +2 -0
@@ -1,6 +1,8 @@ // SPDX-License-Identifier: GPL-2.0 // Minimal client-side zerocopy test +--send_omit_free // do not reuse send buffers with zerocopy + `./defaults.sh` 0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 4
tools/testing/selftests/net/packetdrill/tcp_zerocopy_closed.pkt +2 -0
@@ -7,6 +7,8 @@ // First send on a closed socket and wait for (absent) notification. // Then connect and send and verify that notification nr. is zero. +--send_omit_free // do not reuse send buffers with zerocopy + `./defaults.sh` 0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 4
tools/testing/selftests/net/packetdrill/tcp_zerocopy_epoll_edge.pkt +3 -0
@@ -7,6 +7,9 @@ // fire two sends with MSG_ZEROCOPY and receive the acks. confirm that EPOLLERR // is correctly fired only once, when EPOLLET is set. send another packet with // MSG_ZEROCOPY. confirm that EPOLLERR is correctly fired again only once. + +--send_omit_free // do not reuse send buffers with zerocopy + `./defaults.sh` 0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
tools/testing/selftests/net/packetdrill/tcp_zerocopy_epoll_exclusive.pkt +3 -0
@@ -8,6 +8,9 @@ // fire two sends with MSG_ZEROCOPY and receive the acks. confirm that EPOLLERR // is correctly fired only once, when EPOLLET is set. send another packet with // MSG_ZEROCOPY. confirm that EPOLLERR is correctly fired again only once. + +--send_omit_free // do not reuse send buffers with zerocopy + `./defaults.sh` 0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
tools/testing/selftests/net/packetdrill/tcp_zerocopy_epoll_oneshot.pkt +3 -0
@@ -8,6 +8,9 @@ // is correctly fired only once, when EPOLLONESHOT is set. send another packet // with MSG_ZEROCOPY. confirm that EPOLLERR is not fired. Rearm the FD and // confirm that EPOLLERR is correctly set. + +--send_omit_free // do not reuse send buffers with zerocopy + `./defaults.sh` 0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
tools/testing/selftests/net/packetdrill/tcp_zerocopy_fastopen-client.pkt +2 -0
@@ -8,6 +8,8 @@ // one will have no data in the initial send. On return 0 the // zerocopy notification counter is not incremented. Verify this too. +--send_omit_free // do not reuse send buffers with zerocopy + `./defaults.sh` // Send a FastOpen request, no cookie yet so no data in SYN
tools/testing/selftests/net/packetdrill/tcp_zerocopy_fastopen-server.pkt +2 -0
@@ -4,6 +4,8 @@ // send data with MSG_FASTOPEN | MSG_ZEROCOPY and verify that the // kernel returns the notification ID. +--send_omit_free // do not reuse send buffers with zerocopy + `./defaults.sh ./set_sysctls.py /proc/sys/net/ipv4/tcp_fastopen=0x207`
tools/testing/selftests/net/packetdrill/tcp_zerocopy_maxfrags.pkt +2 -0
@@ -7,6 +7,8 @@ // because each iovec element becomes a frag // 3) the PSH bit is set on an skb when it runs out of fragments +--send_omit_free // do not reuse send buffers with zerocopy + `./defaults.sh` 0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
tools/testing/selftests/net/packetdrill/tcp_zerocopy_small.pkt +2 -0
@@ -4,6 +4,8 @@ // verify that SO_EE_CODE_ZEROCOPY_COPIED is set on zerocopy // packets of all sizes, including the smallest payload, 1B. +--send_omit_free // do not reuse send buffers with zerocopy + `./defaults.sh` 0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 457/614 of: Skip devicetree kunit tests when RISCV+ACPI doesnt populate root node
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guenter Roeck <[email protected]>
[ Upstream commit 546dbb0223102813ffb5bbcb9443a47c3183f195 ]
Starting with commit 69a8b62a7aa1 ("riscv: acpi: avoid errors caused by probing DT devices when ACPI is used"), riscv images no longer populate devicetree if ACPI is enabled. This causes unit tests to fail which require the root node to be set.
# Subtest: of_dtb
# module: of_test
1..2
# of_dtb_root_node_found_by_path: EXPECTATION FAILED at drivers/of/of_test.c:21 Expected np is not null, but is
# of_dtb_root_node_found_by_path: pass:0 fail:1 skip:0 total:1
not ok 1 of_dtb_root_node_found_by_path
# of_dtb_root_node_populates_of_root: EXPECTATION FAILED at drivers/of/of_test.c:31 Expected of_root is not null, but is
# of_dtb_root_node_populates_of_root: pass:0 fail:1 skip:0 total:1 not ok 2 of_dtb_root_node_populates_of_root
Skip those tests for RISCV if the root node is not populated.
--- drivers/of/of_kunit_helpers.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/of/of_kunit_helpers.c +3 -2
@@ -18,8 +18,9 @@*/ void of_root_kunit_skip (struct kunit *test) { -if (IS_ENABLED (CONFIG_ARM64 ) &&IS_ENABLED (CONFIG_ACPI ) && !of_root) -kunit_skip (test,"arm64+acpi doesn't populate a root node" ); +if ((IS_ENABLED (CONFIG_ARM64 ) ||IS_ENABLED (CONFIG_RISCV )) && +IS_ENABLED (CONFIG_ACPI ) && !of_root) +kunit_skip (test,"arm64/riscv+acpi doesn't populate a root node" ); }EXPORT_SYMBOL_GPL (of_root_kunit_skip);
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 458/614 virtio_vdpa: fix misleading return in void function
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alok Tiwari <[email protected]>
[ Upstream commit e40b6abe0b1247d43bc61942aa7534fca7209e44 ]
virtio_vdpa_set_status() is declared as returning void, but it used "return vdpa_set_status()" Since vdpa_set_status() also returns void, the return statement is unnecessary and misleading. Remove it.
Message-Id: <[email protected]>
--- drivers/virtio/virtio_vdpa.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/virtio/virtio_vdpa.c +1 -1
@@ -80,7 +80,7 @@ static void virtio_vdpa_set_status(struct virtio_device *vdev, u8 status) {struct vdpa_device *vdpa =vd_get_vdpa (vdev); -return vdpa_set_status (vdpa, status); +vdpa_set_status (vdpa, status); }static void virtio_vdpa_reset (struct virtio_device *vdev)
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 459/614 virtio: fix kernel-doc for mapping/free_coherent functions
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kriish Sharma <[email protected]>
[ Upstream commit f8113000855a8cc2c6d8e19b97a390f1c082285d ]
Documentation build reported:
WARNING: ./drivers/virtio/virtio_ring.c:3174 function parameter 'vaddr' not described in 'virtqueue_map_free_coherent' WARNING: ./drivers/virtio/virtio_ring.c:3308 expecting prototype for virtqueue_mapping_error(). Prototype was for virtqueue_map_mapping_error() instead
The kernel-doc block for virtqueue_map_free_coherent() omitted the @vaddr parameter, and the kernel-doc header for virtqueue_map_mapping_error() used the wrong function name (virtqueue_mapping_error) instead of the actual function name.
This change updates:
- the function name in the comment to virtqueue_map_mapping_error()
- adds the missing @vaddr description in the comment for virtqueue_map_free_coherent()
Message-Id: <[email protected]>
--- drivers/virtio/virtio_ring.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
drivers/virtio/virtio_ring.c +4 -3
@@ -3166,6 +3166,7 @@ EXPORT_SYMBOL_GPL(virtqueue_map_alloc_coherent);* @vdev: the virtio device we are talking to * @map: metadata for performing mapping * @size: the size of the buffer +* @vaddr: the virtual address that needs to be freed * @map_handle: the mapped address that needs to be freed * */
@@ -3190,7 +3191,7 @@ EXPORT_SYMBOL_GPL(virtqueue_map_free_coherent);* @dir: mapping direction * @attrs: mapping attributes * -* Returns mapped address. Caller should check that by virtqueue_mapping_error(). +* Returns mapped address. Caller should check that by virtqueue_map_mapping_error(). */ dma_addr_t virtqueue_map_page_attrs(const struct virtqueue *_vq, struct page *page,
@@ -3249,7 +3250,7 @@ EXPORT_SYMBOL_GPL(virtqueue_unmap_page_attrs);* The caller calls this to do dma mapping in advance. The DMA address can be * passed to this _vq when it is in pre-mapped mode. * -* return mapped address. Caller should check that by virtqueue_mapping_error(). +* return mapped address. Caller should check that by virtqueue_map_mapping_error(). */ dma_addr_t virtqueue_map_single_attrs(const struct virtqueue *_vq, void *ptr, size_t size,
@@ -3299,7 +3300,7 @@ void virtqueue_unmap_single_attrs(const struct virtqueue *_vq,EXPORT_SYMBOL_GPL (virtqueue_unmap_single_attrs);/** -* virtqueue_mapping_error - check dma address +* virtqueue_map_mapping_error - check dma address * @_vq: the struct virtqueue we're talking about. * @addr: DMA address *
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 460/614 virtio: fix typo in virtio_device_ready() comment
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael S. Tsirkin <[email protected]>
[ Upstream commit 361173f95ae4b726ebbbf0bd594274f5576c4abc ]
"coherenct" -> "coherent"
Message-Id: <db286e9a65449347f6584e68c9960fd5ded2b4b0.1763026134.git.mst@redhat.com>
--- include/linux/virtio_config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
include/linux/virtio_config.h +1 -1
@@ -362,7 +362,7 @@ void virtio_device_ready(struct virtio_device *dev)* specific set_status() method. * * A well behaved device will only notify a virtqueue after -* DRIVER_OK, this means the device should "see" the coherenct +* DRIVER_OK, this means the device should "see" the coherent * memory write that set vq->broken as false which is done by * the driver when it sees DRIVER_OK, then the following * driver's vring_interrupt() will see vq->broken as false so
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 461/614 virtio: fix whitespace in virtio_config_ops
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael S. Tsirkin <[email protected]>
[ Upstream commit 7831791e77a1cd29528d4dc336ce14466aef5ba6 ]
The finalize_features documentation uses a tab between words. Use space instead.
Message-Id: <39d7685c82848dc6a876d175e33a1407f6ab3fc1.1763026134.git.mst@redhat.com>
--- include/linux/virtio_config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
include/linux/virtio_config.h +1 -1
@@ -86,7 +86,7 @@ struct virtqueue_info {* vdev: the virtio_device * This sends the driver feature bits to the device: it can change * the dev->feature bits if it wants. -* Note that despite the name this can be called any number of +* Note that despite the name this can be called any number of * times. * Returns 0 on success or error status * @bus_name: return the bus name associated with the device (optional)
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 462/614 virtio: fix grammar in virtio_queue_info docs
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael S. Tsirkin <[email protected]>
[ Upstream commit 63598fba55ab9d384818fed48dc04006cecf7be4 ]
Fix grammar in the description of @ctx
Message-Id: <a5cf2b92573200bdb1c1927e559d3930d61a4af2.1763026134.git.mst@redhat.com>
--- include/linux/virtio_config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
include/linux/virtio_config.h +1 -1
@@ -24,7 +24,7 @@ typedef void vq_callback_t(struct virtqueue *);* a virtqueue unused by the driver. * @callback: A callback to invoke on a used buffer notification. * NULL for a virtqueue that does not need a callback. -* @ctx: A flag to indicate to maintain an extra context per virtqueue. +* @ctx: whether to maintain an extra context per virtqueue. */ struct virtqueue_info {const char *name;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 463/614 virtio: fix grammar in virtio_map_ops docs
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael S. Tsirkin <[email protected]>
[ Upstream commit c15f42e09178d2849744ccf064200f5e7f71e688 ]
Fix grammar issues in the virtio_map_ops docs:
- missing article before "transport"
- "implements" -> "implement" to match subject
Message-Id: <3f7bcae5a984f14b72e67e82572b110acb06fa7e.1763026134.git.mst@redhat.com>
--- include/linux/virtio_config.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
include/linux/virtio_config.h +2 -2
@@ -141,8 +141,8 @@ struct virtio_config_ops {/** * struct virtio_map_ops - operations for mapping buffer for a virtio device -* Note: For transport that has its own mapping logic it must -* implements all of the operations +* Note: For a transport that has its own mapping logic it must +* implement all of the operations * @map_page: map a buffer to the device * map: metadata for performing mapping * page: the page that will be mapped by the device
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 464/614 virtio: standardize Returns documentation style
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael S. Tsirkin <[email protected]>
[ Upstream commit 5e88a5a97d113619b674ebfdd1d2065f2edd10eb ]
Remove colons after "Returns" in virtio_map_ops function documentation - both to avoid triggering an htmldoc warning and for consistency with virtio_config_ops.
This affects map_page, alloc, need_sync, and max_mapping_size.
Message-Id: <c262893fa21f4b1265147ef864574a9bd173348f.1763026134.git.mst@redhat.com>
--- include/linux/virtio_config.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
include/linux/virtio_config.h +4 -4
@@ -150,7 +150,7 @@ struct virtio_config_ops {* size: the buffer size * dir: mapping direction * attrs: mapping attributes -* Returns: the mapped address +* Returns the mapped address * @unmap_page: unmap a buffer from the device * map: device specific mapping map * map_handle: the mapped address
@@ -172,7 +172,7 @@ struct virtio_config_ops {* size: the size of the buffer * map_handle: the mapping address to sync * gfp: allocation flag (GFP_XXX) -* Returns: virtual address of the allocated buffer +* Returns virtual address of the allocated buffer * @free: free a coherent buffer mapping * map: metadata for performing mapping * size: the size of the buffer
@@ -182,13 +182,13 @@ struct virtio_config_ops {* @need_sync: if the buffer needs synchronization * map: metadata for performing mapping * map_handle: the mapped address -* Returns: whether the buffer needs synchronization +* Returns whether the buffer needs synchronization * @mapping_error: if the mapping address is error * map: metadata for performing mapping * map_handle: the mapped address * @max_mapping_size: get the maximum buffer size that can be mapped * map: metadata for performing mapping -* Returns: the maximum buffer size that can be mapped +* Returns the maximum buffer size that can be mapped */ struct virtio_map_ops { dma_addr_t (*map_page)(union virtio_map map, struct page *page,
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 465/614 virtio: fix virtqueue_set_affinity() docs
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael S. Tsirkin <[email protected]>
[ Upstream commit 43236d8bbafff94b423afecc4a692dd90602d426 ]
Rewrite the comment for better grammar and clarity.
Message-Id: <e317e91bd43b070e5eaec0ebbe60c5749d02e2dd.1763026134.git.mst@redhat.com>
--- include/linux/virtio_config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
include/linux/virtio_config.h +1 -1
@@ -384,7 +384,7 @@ const char *virtio_bus_name(struct virtio_device *vdev)* @vq: the virtqueue * @cpu_mask: the cpu mask * -* Pay attention the function are best-effort: the affinity hint may not be set +* Note that this function is best-effort: the affinity hint may not be set * due to config support, irq type and sharing. * */
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 466/614 virtio: fix map ops comment
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael S. Tsirkin <[email protected]>
[ Upstream commit deb55fc994e3dc38f139c0147c15fc2a9db27086 ]
@free will free the map handle not sync it. Fix the doc to match.
Message-Id: <f6ff1c7aff8401900bf362007d7fb52dfdb6a15b.1763026134.git.mst@redhat.com>
--- include/linux/virtio_config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
include/linux/virtio_config.h +1 -1
@@ -177,7 +177,7 @@ struct virtio_config_ops {* map: metadata for performing mapping * size: the size of the buffer * vaddr: virtual address of the buffer -* map_handle: the mapping address to sync +* map_handle: the mapping address that needs to be freed * attrs: unmapping attributes * @need_sync: if the buffer needs synchronization * map: metadata for performing mapping
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 467/614 vdpa/mlx5: Fix incorrect error code reporting in query_virtqueues
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alok Tiwari <[email protected]>
[ Upstream commit f0ea2e91093ac979d07ebd033e0f45869b1d2608 ]
When query_virtqueues() fails, the error log prints the variable err instead of cmd->err. Since err may still be zero at this point, the log message can misleadingly report a success value 0 even though the command actually failed.
Even worse, once err is set to the first failure, subsequent logs print that same stale value. This makes the error reporting appear one step behind the actual failing queue index, which is confusing and misleading.
Fix the log to report cmd->err, which reflects the real failure code returned by the firmware.
Message-Id: <[email protected]>
--- drivers/vdpa/mlx5/net/mlx5_vnet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/vdpa/mlx5/net/mlx5_vnet.c +1 -1
@@ -1256,7 +1256,7 @@ static int query_virtqueues(struct mlx5_vdpa_net *ndev,int vq_idx = start_vq + i;if (cmd->err) { -mlx5_vdpa_err (mvdev,"query vq %d failed, err: %d\n" , vq_idx, err); +mlx5_vdpa_err (mvdev,"query vq %d failed, err: %d\n" , vq_idx, cmd->err);if (!err) err = cmd->err;continue ;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 468/614 vhost: Fix kthread worker cgroup failure handling
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mike Christie <[email protected]>
[ Upstream commit f3f64c2eaffbc3169bbe1e5d1e897e6dacc839d1 ]
If we fail to attach to a cgroup we are leaking the id. This adds a new goto to free the id.
Message-Id: <[email protected]>
--- drivers/vhost/vhost.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/vhost/vhost.c +3 -1
@@ -804,11 +804,13 @@ static int vhost_kthread_worker_create(struct vhost_worker *worker, ret =vhost_attach_task_to_cgroups (worker);if (ret) - goto stop_worker; + goto free_id; worker->id = id;return 0 ; +free_id: +xa_erase (&dev->worker_xa, id); stop_worker:vhost_kthread_do_stop (worker);return ret;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 469/614 vdpa/pds: use %pe for ERR_PTR() in event handler registration
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alok Tiwari <[email protected]>
[ Upstream commit 731ca4a4cc52fd5c5ae309edcfd2d7e54ece3321 ]
Use %pe instead of %ps when printing ERR_PTR() values. %ps is intended for string pointers, while %pe correctly prints symbolic error names for error pointers returned via ERR_PTR().
This shows the returned error value more clearly.
Message-Id: <[email protected]>
--- drivers/vdpa/pds/vdpa_dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/vdpa/pds/vdpa_dev.c +1 -1
@@ -51,7 +51,7 @@ static int pds_vdpa_register_event_handler(struct pds_vdpa_device *pdsv) err =pdsc_register_notify (nb);if (err) { nb->notifier_call =NULL ; -dev_err (dev,"failed to register pds event handler: %ps\n" , +dev_err (dev,"failed to register pds event handler: %pe\n" ,ERR_PTR (err));return -EINVAL ; }
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 470/614 virtio: clean up features qword/dword terms
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael S. Tsirkin <[email protected]>
[ Upstream commit 9513f25056b22100ddffe24898c587873b0d022c ]
virtio pci uses word to mean "16 bits". mmio uses it to mean "32 bits".
To avoid confusion, let's avoid the term in core virtio altogether. Just say U64 to mean "64 bit".
Message-ID: <ad53b7b6be87fc524f45abaeca0bb05fb3633397.1764225384.git.mst@redhat.com>
--- drivers/vhost/net.c | 12 +++++------ drivers/virtio/virtio.c | 12 +++++------ drivers/virtio/virtio_debug.c | 10 ++++----- drivers/virtio/virtio_pci_modern_dev.c | 6 +++--- include/linux/virtio.h | 2 +- include/linux/virtio_config.h | 2 +- include/linux/virtio_features.h | 29 +++++++++++++------------- include/linux/virtio_pci_modern.h | 8 +++---- 8 files changed, 41 insertions(+), 40 deletions(-)
drivers/vhost/net.c +6 -6
@@ -69,7 +69,7 @@ MODULE_PARM_DESC(experimental_zcopytx, "Enable Zero Copy TX;"#define VHOST_DMA_IS_DONE (len) ((__force u32)(len) >= (__force u32)VHOST_DMA_DONE_LEN) -static const u64 vhost_net_features[VIRTIO_FEATURES_DWORDS ] = { +static const u64 vhost_net_features[VIRTIO_FEATURES_U64S ] = {VHOST_FEATURES | (1ULL <<VHOST_NET_F_VIRTIO_NET_HDR ) | (1ULL << VIRTIO_NET_F_MRG_RXBUF) |
@@ -1731,7 +1731,7 @@ static long vhost_net_set_owner(struct vhost_net *n)static long vhost_net_ioctl (struct file *f,unsigned int ioctl,unsigned long arg) { -u64 all_features[VIRTIO_FEATURES_DWORDS ]; +u64 all_features[VIRTIO_FEATURES_U64S ];struct vhost_net *n = f->private_data;void __user *argp = (void __user *)arg;u64 __user *featurep = argp;
@@ -1763,7 +1763,7 @@ static long vhost_net_ioctl(struct file *f, unsigned int ioctl,/* Copy the net features, up to the user-provided buffer size */ argp +=sizeof (u64); - copied =min (count,VIRTIO_FEATURES_DWORDS ); + copied =min (count, (u64 )VIRTIO_FEATURES_U64S );if (copy_to_user (argp, vhost_net_features, copied *sizeof (u64)))return -EFAULT ;
@@ -1778,13 +1778,13 @@ static long vhost_net_ioctl(struct file *f, unsigned int ioctl,virtio_features_zero (all_features); argp +=sizeof (u64); - copied =min (count,VIRTIO_FEATURES_DWORDS ); + copied =min (count, (u64 )VIRTIO_FEATURES_U64S );if (copy_from_user (all_features, argp, copied *sizeof (u64)))return -EFAULT ;/* * Any feature specified by user-space above -* VIRTIO_FEATURES_MAX is not supported by definition. +* VIRTIO_FEATURES_BITS is not supported by definition. */ for (i = copied; i < count; ++i) { if (copy_from_user(&features, featurep + 1 + i,
@@ -1794,7 +1794,7 @@ static long vhost_net_ioctl(struct file *f, unsigned int ioctl,return -EOPNOTSUPP ; } -for (i =0 ; i <VIRTIO_FEATURES_DWORDS ; i++) +for (i =0 ; i <VIRTIO_FEATURES_U64S ; i++)if (all_features[i] & ~vhost_net_features[i])return -EOPNOTSUPP ;
drivers/virtio/virtio.c +6 -6
@@ -53,7 +53,7 @@ static ssize_t features_show(struct device *_d,/* We actually represent this as a bitstring, as it could be * arbitrary length in future. */ -for (i =0 ; i <VIRTIO_FEATURES_MAX ; i++) +for (i =0 ; i <VIRTIO_FEATURES_BITS ; i++) len +=sysfs_emit_at (buf, len,"%c" ,__virtio_test_bit (dev, i) ?'1' :'0' ); len +=sysfs_emit_at (buf, len,"\n" );
@@ -272,8 +272,8 @@ static int virtio_dev_probe(struct device *_d)int err, i;struct virtio_device *dev =dev_to_virtio (_d);struct virtio_driver *drv =drv_to_virtio (dev->dev.driver); -u64 device_features[VIRTIO_FEATURES_DWORDS ]; -u64 driver_features[VIRTIO_FEATURES_DWORDS ]; +u64 device_features[VIRTIO_FEATURES_U64S ]; +u64 driver_features[VIRTIO_FEATURES_U64S ];u64 driver_features_legacy;/* We have a driver! */
@@ -286,7 +286,7 @@ static int virtio_dev_probe(struct device *_d)virtio_features_zero (driver_features);for (i =0 ; i < drv->feature_table_size; i++) {unsigned int f = drv->feature_table[i]; -if (!WARN_ON_ONCE (f >=VIRTIO_FEATURES_MAX )) +if (!WARN_ON_ONCE (f >=VIRTIO_FEATURES_BITS ))virtio_features_set_bit (driver_features, f); }
@@ -303,7 +303,7 @@ static int virtio_dev_probe(struct device *_d) }if (virtio_features_test_bit (device_features,VIRTIO_F_VERSION_1 )) { -for (i =0 ; i <VIRTIO_FEATURES_DWORDS ; ++i) +for (i =0 ; i <VIRTIO_FEATURES_U64S ; ++i) dev->features_array[i] = driver_features[i] & device_features[i]; }else {
@@ -325,7 +325,7 @@ static int virtio_dev_probe(struct device *_d) goto err;if (drv->validate) { -u64 features[VIRTIO_FEATURES_DWORDS ]; +u64 features[VIRTIO_FEATURES_U64S ];virtio_features_copy (features, dev->features_array); err = drv->validate (dev);
drivers/virtio/virtio_debug.c +5 -5
@@ -8,12 +8,12 @@ static struct dentry *virtio_debugfs_dir;static int virtio_debug_device_features_show (struct seq_file *s,void *data) { -u64 device_features[VIRTIO_FEATURES_DWORDS ]; +u64 device_features[VIRTIO_FEATURES_U64S ];struct virtio_device *dev = s->private;unsigned int i;virtio_get_features (dev, device_features); -for (i =0 ; i <VIRTIO_FEATURES_MAX ; i++) { +for (i =0 ; i <VIRTIO_FEATURES_BITS ; i++) {if (virtio_features_test_bit (device_features, i))seq_printf (s,"%u\n" , i); }
@@ -26,7 +26,7 @@ static int virtio_debug_filter_features_show(struct seq_file *s, void *data)struct virtio_device *dev = s->private;unsigned int i; -for (i =0 ; i <VIRTIO_FEATURES_MAX ; i++) { +for (i =0 ; i <VIRTIO_FEATURES_BITS ; i++) {if (virtio_features_test_bit (dev->debugfs_filter_features, i))seq_printf (s,"%u\n" , i); }
@@ -50,7 +50,7 @@ static int virtio_debug_filter_feature_add(void *data, u64 val) {struct virtio_device *dev = data; -if (val >=VIRTIO_FEATURES_MAX ) +if (val >=VIRTIO_FEATURES_BITS )return -EINVAL ;virtio_features_set_bit (dev->debugfs_filter_features, val);
@@ -64,7 +64,7 @@ static int virtio_debug_filter_feature_del(void *data, u64 val) {struct virtio_device *dev = data; -if (val >=VIRTIO_FEATURES_MAX ) +if (val >=VIRTIO_FEATURES_BITS )return -EINVAL ;virtio_features_clear_bit (dev->debugfs_filter_features, val);
drivers/virtio/virtio_pci_modern_dev.c +3 -3
@@ -401,7 +401,7 @@ void vp_modern_get_extended_features(struct virtio_pci_modern_device *mdev,int i;virtio_features_zero (features); -for (i =0 ; i <VIRTIO_FEATURES_WORDS ; i++) { +for (i =0 ; i <VIRTIO_FEATURES_BITS /32 ; i++) {u64 cur;vp_iowrite32 (i, &cfg->device_feature_select);
@@ -427,7 +427,7 @@ vp_modern_get_driver_extended_features(struct virtio_pci_modern_device *mdev,int i;virtio_features_zero (features); -for (i =0 ; i <VIRTIO_FEATURES_WORDS ; i++) { +for (i =0 ; i <VIRTIO_FEATURES_BITS /32 ; i++) {u64 cur;vp_iowrite32 (i, &cfg->guest_feature_select);
@@ -448,7 +448,7 @@ void vp_modern_set_extended_features(struct virtio_pci_modern_device *mdev,struct virtio_pci_common_cfg __iomem *cfg = mdev->common;int i; -for (i =0 ; i <VIRTIO_FEATURES_WORDS ; i++) { +for (i =0 ; i <VIRTIO_FEATURES_BITS /32 ; i++) {u32 cur = features[i >>1 ] >> (32 * (i &1 ));vp_iowrite32 (i, &cfg->guest_feature_select);
include/linux/virtio.h +1 -1
@@ -177,7 +177,7 @@ struct virtio_device {union virtio_map vmap;#ifdef CONFIG_VIRTIO_DEBUG struct dentry *debugfs_dir; -u64 debugfs_filter_features[VIRTIO_FEATURES_DWORDS ]; +u64 debugfs_filter_features[VIRTIO_FEATURES_U64S ];#endif };
include/linux/virtio_config.h +1 -1
@@ -80,7 +80,7 @@ struct virtqueue_info {* Returns the first 64 feature bits. * @get_extended_features: * vdev: the virtio_device -* Returns the first VIRTIO_FEATURES_MAX feature bits (all we currently +* Returns the first VIRTIO_FEATURES_BITS feature bits (all we currently * need). * @finalize_features: confirm what device features we'll be using. * vdev: the virtio_device
include/linux/virtio_features.h +15 -14
@@ -4,15 +4,16 @@#include <linux/bits.h> -#define VIRTIO_FEATURES_DWORDS 2 -#define VIRTIO_FEATURES_MAX (VIRTIO_FEATURES_DWORDS * 64) -#define VIRTIO_FEATURES_WORDS (VIRTIO_FEATURES_DWORDS * 2) +#define VIRTIO_FEATURES_U64S 2 +#define VIRTIO_FEATURES_BITS (VIRTIO_FEATURES_U64S * 64) +#define VIRTIO_BIT (b) BIT_ULL((b) & 0x3f) -#define VIRTIO_DWORD (b) ((b) >> 6) +#define VIRTIO_U64 (b) ((b) >> 6) +#define VIRTIO_DECLARE_FEATURES (name) \ union { \ u64 name; \ - u64 name##_array[VIRTIO_FEATURES_DWORDS];\ + u64 name##_array[VIRTIO_FEATURES_U64S];\ }static inline bool virtio_features_chk_bit (unsigned int bit)
@@ -22,9 +23,9 @@ static inline bool virtio_features_chk_bit(unsigned int bit)* Don't care returning the correct value: the build * will fail before any bad features access */ -BUILD_BUG_ON (bit >=VIRTIO_FEATURES_MAX ); +BUILD_BUG_ON (bit >=VIRTIO_FEATURES_BITS ); }else { -if (WARN_ON_ONCE (bit >=VIRTIO_FEATURES_MAX )) +if (WARN_ON_ONCE (bit >=VIRTIO_FEATURES_BITS ))return false; }return true;
@@ -34,26 +35,26 @@ static inline bool virtio_features_test_bit(const u64 *features, unsigned int bit) {return virtio_features_chk_bit (bit) && - !!(features[VIRTIO_DWORD (bit)] &VIRTIO_BIT (bit)); + !!(features[VIRTIO_U64 (bit)] &VIRTIO_BIT (bit)); }static inline void virtio_features_set_bit (u64 *features,unsigned int bit) {if (virtio_features_chk_bit (bit)) - features[VIRTIO_DWORD (bit)] |=VIRTIO_BIT (bit); + features[VIRTIO_U64 (bit)] |=VIRTIO_BIT (bit); }static inline void virtio_features_clear_bit (u64 *features,unsigned int bit) {if (virtio_features_chk_bit (bit)) - features[VIRTIO_DWORD (bit)] &= ~VIRTIO_BIT (bit); + features[VIRTIO_U64 (bit)] &= ~VIRTIO_BIT (bit); }static inline void virtio_features_zero (u64 *features) { -memset (features,0 ,sizeof (features[0 ]) *VIRTIO_FEATURES_DWORDS ); +memset (features,0 ,sizeof (features[0 ]) *VIRTIO_FEATURES_U64S ); }static inline void virtio_features_from_u64 (u64 *features,u64 from)
@@ -66,7 +67,7 @@ static inline bool virtio_features_equal(const u64 *f1, const u64 *f2) {int i; -for (i =0 ; i <VIRTIO_FEATURES_DWORDS ; ++i) +for (i =0 ; i <VIRTIO_FEATURES_U64S ; ++i)if (f1[i] != f2[i])return false;return true;
@@ -74,14 +75,14 @@ static inline bool virtio_features_equal(const u64 *f1, const u64 *f2)static inline void virtio_features_copy (u64 *to,const u64 *from) { -memcpy (to, from,sizeof (to[0 ]) *VIRTIO_FEATURES_DWORDS ); +memcpy (to, from,sizeof (to[0 ]) *VIRTIO_FEATURES_U64S ); }static inline void virtio_features_andnot (u64 *to,const u64 *f1,const u64 *f2) {int i; -for (i =0 ; i <VIRTIO_FEATURES_DWORDS ; i++) +for (i =0 ; i <VIRTIO_FEATURES_U64S ; i++) to[i] = f1[i] & ~f2[i]; }
include/linux/virtio_pci_modern.h +4 -4
@@ -107,7 +107,7 @@ void vp_modern_set_extended_features(struct virtio_pci_modern_device *mdev,static inline u64 vp_modern_get_features (struct virtio_pci_modern_device *mdev) { -u64 features_array[VIRTIO_FEATURES_DWORDS ]; +u64 features_array[VIRTIO_FEATURES_U64S ];vp_modern_get_extended_features (mdev, features_array);return features_array[0 ];
@@ -116,11 +116,11 @@ vp_modern_get_features(struct virtio_pci_modern_device *mdev)static inline u64 vp_modern_get_driver_features (struct virtio_pci_modern_device *mdev) { -u64 features_array[VIRTIO_FEATURES_DWORDS ]; +u64 features_array[VIRTIO_FEATURES_U64S ];int i;vp_modern_get_driver_extended_features (mdev, features_array); -for (i =1 ; i <VIRTIO_FEATURES_DWORDS ; ++i) +for (i =1 ; i <VIRTIO_FEATURES_U64S ; ++i)WARN_ON_ONCE (features_array[i]);return features_array[0 ]; }
@@ -128,7 +128,7 @@ vp_modern_get_driver_features(struct virtio_pci_modern_device *mdev)static inline void vp_modern_set_features (struct virtio_pci_modern_device *mdev,u64 features) { -u64 features_array[VIRTIO_FEATURES_DWORDS ]; +u64 features_array[VIRTIO_FEATURES_U64S ];virtio_features_from_u64 (features_array, features);vp_modern_set_extended_features (mdev, features_array);
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 471/614 ASoC: Intel: catpt: Fix error path in hw_params()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Cezary Rojewski <[email protected]>
[ Upstream commit 86a5b621be658fc8fe594ca6db317d64de30cce1 ]
Do not leave any resources hanging on the DSP side if applying user settings fails.
--- sound/soc/intel/catpt/pcm.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
sound/soc/intel/catpt/pcm.c +3 -1
@@ -417,8 +417,10 @@ static int catpt_dai_hw_params(struct snd_pcm_substream *substream,return CATPT_IPC_ERROR (ret); ret =catpt_dai_apply_usettings (dai, stream); -if (ret) +if (ret) { +catpt_ipc_free_stream (cdev, stream->info.stream_hw_id);return ret; + } stream->allocated = true;return 0 ;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 472/614 spi: airoha-snfi: en7523: workaround flash damaging if UART_TXD was short to GND
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mikhail Kshevetskiy <[email protected]>
[ Upstream commit 061795b345aff371df8f71d54ae7c7dc8ae630d0 ]
Airoha EN7523 specific bug
--------------------------
We found that some serial console may pull TX line to GROUND during board boot time. Airoha uses TX line as one of its bootstrap pins. On the EN7523 SoC this may lead to booting in RESERVED boot mode.
It was found that some flashes operates incorrectly in RESERVED mode. Micron and Skyhigh flashes are definitely affected by the issue, Winbond flashes are not affected.
Details:
--------
DMA reading of odd pages on affected flashes operates incorrectly. Page reading offset (start of the page) on hardware level is replaced by 0x10. Thus results in incorrect data reading. As result OS loading becomes impossible.
Usage of UBI make things even worse. On attaching, UBI will detects corruptions (because of wrong reading of odd pages) and will try to recover. For recovering UBI will erase and write 'damaged' blocks with a valid information. This will destroy all UBI data.
Non-DMA reading is OK.
This patch detects booting in reserved mode, turn off DMA and print big fat warning.
It's worth noting that the boot configuration is preserved across reboots. Therefore, to boot normally, you should do the following:
- disconnect the serial console from the board,
- power cycle the board.
--- drivers/spi/spi-airoha-snfi.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-)
drivers/spi/spi-airoha-snfi.c +24 -1
@@ -1030,6 +1030,11 @@ static const struct spi_controller_mem_ops airoha_snand_mem_ops = { .dirmap_write = airoha_snand_dirmap_write, }; +static const struct spi_controller_mem_ops airoha_snand_nodma_mem_ops = { + .supports_op = airoha_snand_supports_op, + .exec_op = airoha_snand_exec_op, +}; +static int airoha_snand_setup (struct spi_device *spi) {struct airoha_snand_ctrl *as_ctrl;
@@ -1104,7 +1109,9 @@ static int airoha_snand_probe(struct platform_device *pdev)struct airoha_snand_ctrl *as_ctrl;struct device *dev = &pdev->dev;struct spi_controller *ctrl; +bool dma_enable = true;void __iomem *base; +u32 sfc_strap;int err; ctrl =devm_spi_alloc_host (dev,sizeof (*as_ctrl));
@@ -1139,12 +1146,28 @@ static int airoha_snand_probe(struct platform_device *pdev)return dev_err_probe (dev,PTR_ERR (as_ctrl->spi_clk),"unable to get spi clk\n" ); +if (device_is_compatible (dev,"airoha,en7523-snand" )) { + err =regmap_read (as_ctrl->regmap_ctrl, +REG_SPI_CTRL_SFC_STRAP , &sfc_strap); +if (err) +return err; + +if (!(sfc_strap &0x04 )) { + dma_enable = false; +dev_warn (dev,"Detected booting in RESERVED mode (UART_TXD was short to GND).\n" ); +dev_warn (dev,"This mode is known for incorrect DMA reading of some flashes.\n" ); +dev_warn (dev,"Much slower PIO mode will be used to prevent flash data damage.\n" ); +dev_warn (dev,"Unplug UART cable and power cycle board to get full performance.\n" ); + } + } + err =dma_set_mask (as_ctrl->dev,DMA_BIT_MASK (32 ));if (err)return err; ctrl->num_chipselect =2 ; - ctrl->mem_ops = &airoha_snand_mem_ops; + ctrl->mem_ops = dma_enable ? &airoha_snand_mem_ops + : &airoha_snand_nodma_mem_ops; ctrl->bits_per_word_mask =SPI_BPW_MASK (8 ); ctrl->mode_bits =SPI_RX_DUAL ; ctrl->setup = airoha_snand_setup;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 473/614 soc: samsung: exynos-pmu: Fix structure initialization
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Marek Szyprowski <[email protected]>
[ Upstream commit 2224ea67c75d0a0b9eaf803d0dfdab8d0c601c35 ]
Commit 78b72897a5c8 ("soc: samsung: exynos-pmu: Enable CPU Idle for gs101") added system wide suspend/resume callbacks to Exynos PMU driver, but some items used by these callbacks are initialized only on GS101-compatible boards. Move that initialization to exynos_pmu_probe() to avoid potential lockdep warnings like below observed during system suspend/resume cycle:
INFO: trying to register non-static key.
The code is fine but needs lockdep annotation, or maybe you didn't initialize this object before use? turning off the locking correctness validator.
CPU: 0 UID: 0 PID: 2134 Comm: rtcwake Not tainted 6.18.0-rc7-next-20251126-00039-g1d656a1af243 #11794 PREEMPT Hardware name: Samsung Exynos (Flattened Device Tree) Call trace: unwind_backtrace from show_stack+0x10/0x14 show_stack from dump_stack_lvl+0x68/0x88 dump_stack_lvl from register_lock_class+0x970/0x988 register_lock_class from __lock_acquire+0xc8/0x29ec __lock_acquire from lock_acquire+0x134/0x39c lock_acquire from _raw_spin_lock+0x38/0x48 _raw_spin_lock from exynos_cpupm_suspend_noirq+0x18/0x34 exynos_cpupm_suspend_noirq from dpm_run_callback+0x98/0x2b8 dpm_run_callback from device_suspend_noirq+0x8c/0x310
--- drivers/soc/samsung/exynos-pmu.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-)
drivers/soc/samsung/exynos-pmu.c +3 -4
@@ -585,10 +585,6 @@ static int setup_cpuhp_and_cpuidle(struct device *dev)if (!pmu_context->in_cpuhp)return -ENOMEM ; -raw_spin_lock_init (&pmu_context->cpupm_lock); - pmu_context->sys_inreboot = false; - pmu_context->sys_insuspend = false; -/* set PMU to power on */ for_each_online_cpu (cpu)gs101_cpuhp_pmu_online (cpu);
@@ -657,6 +653,9 @@ static int exynos_pmu_probe(struct platform_device *pdev) pmu_context->pmureg = regmap; pmu_context->dev = dev; +raw_spin_lock_init (&pmu_context->cpupm_lock); + pmu_context->sys_inreboot = false; + pmu_context->sys_insuspend = false;if (pmu_context->pmu_data && pmu_context->pmu_data->pmu_cpuhp) { ret =setup_cpuhp_and_cpuidle (dev);
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 474/614 ARM: dts: samsung: universal_c210: turn off SDIO WLAN chip during system suspend
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Marek Szyprowski <[email protected]>
[ Upstream commit 97aee67e2406ea381408915e606c5f86448f3949 ]
Commit 8c3170628a9c ("wifi: brcmfmac: keep power during suspend if board requires it") changed default behavior of the BRCMFMAC driver, which now keeps SDIO card powered during system suspend to enable optional support for WOWL. This feature is not supported by the legacy Exynos4 based boards and leads to WLAN disfunction after system suspend/resume cycle. Fix this by annotating SDIO host used by WLAN chip with 'cap-power-off-card' property, which should have been there from the beginning.
--- arch/arm/boot/dts/samsung/exynos4210-universal_c210.dts | 1 + 1 file changed, 1 insertion(+)
arch/arm/boot/dts/samsung/exynos4210-universal_c210.dts +1 -0
@@ -610,6 +610,7 @@ &sdhci_3 { #size-cells = <0>; non-removable; + cap-power-off-card; bus-width = <4>; mmc-pwrseq = <&wlan_pwrseq>; vmmc-supply = <&ldo5_reg>;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 475/614 ARM: dts: samsung: exynos4210-i9100: turn off SDIO WLAN chip during system suspend
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Marek Szyprowski <[email protected]>
[ Upstream commit 863d69923bdb6f414d0a3f504f1dfaeacbc00b09 ]
Commit 8c3170628a9c ("wifi: brcmfmac: keep power during suspend if board requires it") changed default behavior of the BRCMFMAC driver, which now keeps SDIO card powered during system suspend to enable optional support for WOWL. This feature is not supported by the legacy Exynos4 based boards and leads to WLAN disfunction after system suspend/resume cycle. Fix this by annotating SDIO host used by WLAN chip with 'cap-power-off-card' property, which should have been there from the beginning.
--- arch/arm/boot/dts/samsung/exynos4210-i9100.dts | 1 + 1 file changed, 1 insertion(+)
arch/arm/boot/dts/samsung/exynos4210-i9100.dts +1 -0
@@ -853,6 +853,7 @@ &sdhci_3 { #size-cells = <0>; non-removable; + cap-power-off-card; bus-width = <4>; mmc-pwrseq = <&wlan_pwrseq>; vmmc-supply = <&vtf_reg>;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 476/614 ARM: dts: samsung: exynos4210-trats: turn off SDIO WLAN chip during system suspend
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Marek Szyprowski <[email protected]>
[ Upstream commit 97cc9c346b2c9cde075b9420fc172137d2427711 ]
Commit 8c3170628a9c ("wifi: brcmfmac: keep power during suspend if board requires it") changed default behavior of the BRCMFMAC driver, which now keeps SDIO card powered during system suspend to enable optional support for WOWL. This feature is not supported by the legacy Exynos4 based boards and leads to WLAN disfunction after system suspend/resume cycle. Fix this by annotating SDIO host used by WLAN chip with 'cap-power-off-card' property, which should have been there from the beginning.
--- arch/arm/boot/dts/samsung/exynos4210-trats.dts | 1 + 1 file changed, 1 insertion(+)
arch/arm/boot/dts/samsung/exynos4210-trats.dts +1 -0
@@ -518,6 +518,7 @@ &sdhci_3 { #size-cells = <0>; non-removable; + cap-power-off-card; bus-width = <4>; mmc-pwrseq = <&wlan_pwrseq>; vmmc-supply = <&tflash_reg>;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 477/614 ARM: dts: samsung: exynos4412-midas: turn off SDIO WLAN chip during system suspend
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Marek Szyprowski <[email protected]>
[ Upstream commit 2ff147fdfa99b8cbb8c2833e685fde7c42580ae6 ]
Commit 8c3170628a9c ("wifi: brcmfmac: keep power during suspend if board requires it") changed default behavior of the BRCMFMAC driver, which now keeps SDIO card powered during system suspend to enable optional support for WOWL. This feature is not supported by the legacy Exynos4 based boards and leads to WLAN disfunction after system suspend/resume cycle. Fix this by annotating SDIO host used by WLAN chip with 'cap-power-off-card' property, which should have been there from the beginning.
--- arch/arm/boot/dts/samsung/exynos4412-midas.dtsi | 1 + 1 file changed, 1 insertion(+)
arch/arm/boot/dts/samsung/exynos4412-midas.dtsi +1 -0
@@ -1440,6 +1440,7 @@ &sdhci_3 { #address-cells = <1>; #size-cells = <0>; non-removable; + cap-power-off-card; bus-width = <4>; mmc-pwrseq = <&wlan_pwrseq>;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 478/614 regulator: core: Protect regulator_supply_alias_list with regulator_list_mutex
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: sparkhuang <[email protected]>
[ Upstream commit 0cc15a10c3b4ab14cd71b779fd5c9ca0cb2bc30d ]
regulator_supply_alias_list was accessed without any locking in regulator_supply_alias(), regulator_register_supply_alias(), and regulator_unregister_supply_alias(). Concurrent registration, unregistration and lookups can race, leading to:
1 use-after-free if an alias entry is removed while being read, 2 duplicate entries when two threads register the same alias, 3 inconsistent alias mappings observed by consumers.
Protect all traversals, insertions and deletions on regulator_supply_alias_list with the existing regulator_list_mutex.
--- drivers/regulator/core.c | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-)
drivers/regulator/core.c +20 -12
@@ -1947,6 +1947,7 @@ static void regulator_supply_alias(struct device **dev, const char **supply) {struct regulator_supply_alias *map; +mutex_lock (®ulator_list_mutex); map =regulator_find_supply_alias (*dev, *supply);if (map) { dev_dbg(*dev, "Mapping supply %s to %s,%s\n",
@@ -1955,6 +1956,7 @@ static void regulator_supply_alias(struct device **dev, const char **supply) *dev = map->alias_dev; *supply = map->alias_supply; } +mutex_unlock (®ulator_list_mutex); }static int regulator_match (struct device *dev,const void *data)
@@ -2497,22 +2499,26 @@ int regulator_register_supply_alias(struct device *dev, const char *id, const char *alias_id) {struct regulator_supply_alias *map; +struct regulator_supply_alias *new_map; - map =regulator_find_supply_alias (dev, id); -if (map) -return -EEXIST ; - - map =kzalloc (sizeof (struct regulator_supply_alias ),GFP_KERNEL ); -if (!map) + new_map =kzalloc (sizeof (struct regulator_supply_alias ),GFP_KERNEL ); +if (!new_map)return -ENOMEM ; - map->src_dev = dev; - map->src_supply = id; - map->alias_dev = alias_dev; - map->alias_supply = alias_id; - -list_add (&map->list, ®ulator_supply_alias_list); +mutex_lock (®ulator_list_mutex); + map =regulator_find_supply_alias (dev, id); +if (map) { +mutex_unlock (®ulator_list_mutex); +kfree (new_map); +return -EEXIST ; + } + new_map->src_dev = dev; + new_map->src_supply = id; + new_map->alias_dev = alias_dev; + new_map->alias_supply = alias_id; +list_add (&new_map->list, ®ulator_supply_alias_list); +mutex_unlock (®ulator_list_mutex);pr_info ("Adding alias for supply %s,%s -> %s,%s\n" , id,dev_name (dev), alias_id,dev_name (alias_dev));
@@ -2532,11 +2538,13 @@ void regulator_unregister_supply_alias(struct device *dev, const char *id) {struct regulator_supply_alias *map; +mutex_lock (®ulator_list_mutex); map =regulator_find_supply_alias (dev, id);if (map) {list_del (&map->list);kfree (map); } +mutex_unlock (®ulator_list_mutex); }EXPORT_SYMBOL_GPL (regulator_unregister_supply_alias);
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 479/614 arm64: dts: mediatek: mt8195: Fix address range for JPEG decoder core 1
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chen-Yu Tsai <[email protected]>
[ Upstream commit ce48af13e6381772cc27676be63a6d9176c14a49 ]
The base address of JPEG decoder core 1 should start at 0x10000, and have a size of 0x10000, i.e. it is right after core 0.
Instead the core has the same base address as core 0, and with a crazy large size. This looks like a mixup of address and size cells when the ranges were converted.
This causes the kernel to fail to register the second core due to sysfs name conflicts:
sysfs: cannot create duplicate filename '/devices/platform/soc/soc:jpeg-decoder@1a040000/1a040000.jpgdec'
Fix up the address range.
--- arch/arm64/boot/dts/mediatek/mt8195.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/arm64/boot/dts/mediatek/mt8195.dtsi +1 -1
@@ -3067,7 +3067,7 @@ jpgdec@0,0 { jpgdec@0,10000 { compatible = "mediatek,mt8195-jpgdec-hw"; - reg = <0 0 0x10000 0x10000>;/* JPGDEC_C1 */ + reg = <0 0x10000 0 0x10000>;/* JPGDEC_C1 */ iommus = <&iommu_vdo M4U_PORT_L19_JPGDEC_WDMA0>, <&iommu_vdo M4U_PORT_L19_JPGDEC_BSDMA0>, <&iommu_vdo M4U_PORT_L19_JPGDEC_WDMA1>,
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 480/614 Reinstate "resource: avoid unnecessary lookups in find_next_iomem_res()"
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ilias Stamatis <[email protected]>
[ Upstream commit 6fb3acdebf65a72df0a95f9fd2c901ff2bc9a3a2 ]
Commit 97523a4edb7b ("kernel/resource: remove first_lvl / siblings_only logic") removed an optimization introduced by commit 756398750e11 ("resource: avoid unnecessary lookups in find_next_iomem_res()"). That was not called out in the message of the first commit explicitly so it's not entirely clear whether removing the optimization happened inadvertently or not.
As the original commit message of the optimization explains there is no point considering the children of a subtree in find_next_iomem_res() if the top level range does not match.
Reinstating the optimization results in performance improvements in systems where /proc/iomem is ~5k lines long. Calling mmap() on /dev/mem in such platforms takes 700-1500μs without the optimisation and 10-50μs with the optimisation.
Note that even though commit 97523a4edb7b removed the 'sibling_only' parameter from next_resource(), newer kernels have basically reinstated it under the name 'skip_children'.
--- kernel/resource.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-)
kernel/resource.c +9 -1
@@ -341,6 +341,8 @@ static int find_next_iomem_res(resource_size_t start, resource_size_t end, unsigned long flags, unsigned long desc, struct resource *res) { + /* Skip children until we find a top level range that matches */ + bool skip_children = true;struct resource *p;if (!res)
@@ -351,7 +353,7 @@ static int find_next_iomem_res(resource_size_t start, resource_size_t end,read_lock (&resource_lock); -for_each_resource (&iomem_resource, p, false) { +for_each_resource (&iomem_resource, p, skip_children) {/* If we passed the resource we are looking for, stop */ if (p->start > end) { p =NULL ;
@@ -362,6 +364,12 @@ static int find_next_iomem_res(resource_size_t start, resource_size_t end,if (p->end < start)continue ; +/* +* We found a top level range that matches what we are looking +* for. Time to start checking children too. +*/ + skip_children = false; +/* Found a match, break */ if (is_type_match (p, flags, desc))break ;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 481/614 netfilter: flowtable: check for maximum number of encapsulations in bridge vlan
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pablo Neira Ayuso <[email protected]>
[ Upstream commit 634f3853cc98d73bdec8918010ee29b06981583e ]
Add a sanity check to skip path discovery if the maximum number of encapsulation is reached. While at it, check for underflow too.
--- net/netfilter/nft_flow_offload.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
net/netfilter/nft_flow_offload.c +8 -1
@@ -141,12 +141,19 @@ static void nft_dev_path_info(const struct net_device_path_stack *stack, info->ingress_vlans |=BIT (info->num_encaps -1 );break ;case DEV_PATH_BR_VLAN_TAG : +if (info->num_encaps >=NF_FLOW_TABLE_ENCAP_MAX ) { + info->indev =NULL ; +break ; + } info->encap[info->num_encaps].id = path->bridge.vlan_id; info->encap[info->num_encaps].proto = path->bridge.vlan_proto; info->num_encaps++;break ;case DEV_PATH_BR_VLAN_UNTAG : - info->num_encaps--; +if (WARN_ON_ONCE (info->num_encaps-- ==0 )) { + info->indev =NULL ; +break ; + }break ;case DEV_PATH_BR_VLAN_KEEP :break ;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 482/614 netfilter: nf_conncount: rework API to use sk_buff directly
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Fernando Fernandez Mancera <[email protected]>
[ Upstream commit be102eb6a0e7c03db00e50540622f4e43b2d2844 ]
When using nf_conncount infrastructure for non-confirmed connections a duplicated track is possible due to an optimization introduced since commit d265929930e2 ("netfilter: nf_conncount: reduce unnecessary GC").
In order to fix this introduce a new conncount API that receives directly an sk_buff struct. It fetches the tuple and zone and the corresponding ct from it. It comes with both existing conncount variants nf_conncount_count_skb() and nf_conncount_add_skb(). In addition remove the old API and adjust all the users to use the new one.
This way, for each sk_buff struct it is possible to check if there is a ct present and already confirmed. If so, skip the add operation.
--- include/net/netfilter/nf_conntrack_count.h | 17 +- net/netfilter/nf_conncount.c | 177 ++++++++++++++------- net/netfilter/nft_connlimit.c | 21 +-- net/netfilter/xt_connlimit.c | 14 +- net/openvswitch/conntrack.c | 16 +- 5 files changed, 142 insertions(+), 103 deletions(-)
include/net/netfilter/nf_conntrack_count.h +8 -9
@@ -18,15 +18,14 @@ struct nf_conncount_list {struct nf_conncount_data *nf_conncount_init (struct net *net,unsigned int keylen);void nf_conncount_destroy (struct net *net,struct nf_conncount_data *data); -unsigned int nf_conncount_count (struct net *net, -struct nf_conncount_data *data, -const u32 *key, -const struct nf_conntrack_tuple *tuple, -const struct nf_conntrack_zone *zone); - -int nf_conncount_add (struct net *net,struct nf_conncount_list *list, -const struct nf_conntrack_tuple *tuple, -const struct nf_conntrack_zone *zone); +unsigned int nf_conncount_count_skb (struct net *net, +const struct sk_buff *skb, +u16 l3num, +struct nf_conncount_data *data, +const u32 *key); + +int nf_conncount_add_skb (struct net *net,const struct sk_buff *skb, +u16 l3num,struct nf_conncount_list *list);void nf_conncount_list_init (struct nf_conncount_list *list);
net/netfilter/nf_conncount.c +120 -57
298 lines not on this page · raw message
net/netfilter/nft_connlimit.c +3 -18
@@ -24,26 +24,11 @@ static inline void nft_connlimit_do_eval(struct nft_connlimit *priv,const struct nft_pktinfo *pkt, const struct nft_set_ext *ext) { - const struct nf_conntrack_zone *zone = &nf_ct_zone_dflt; -const struct nf_conntrack_tuple *tuple_ptr; -struct nf_conntrack_tuple tuple; -enum ip_conntrack_info ctinfo; -const struct nf_conn *ct; unsigned int count; +int err; - tuple_ptr = &tuple; - - ct =nf_ct_get (pkt->skb, &ctinfo); -if (ct !=NULL ) { - tuple_ptr = &ct->tuplehash[IP_CT_DIR_ORIGINAL ].tuple; - zone =nf_ct_zone (ct); - }else if (!nf_ct_get_tuplepr (pkt->skb,skb_network_offset (pkt->skb), -nft_pf (pkt),nft_net (pkt), &tuple)) { - regs->verdict.code =NF_DROP ; -return ; - } - -if (nf_conncount_add (nft_net (pkt), priv->list, tuple_ptr, zone)) { + err =nf_conncount_add_skb (nft_net (pkt), pkt->skb,nft_pf (pkt), priv->list); +if (err) { regs->verdict.code =NF_DROP ;return ; }
net/netfilter/xt_connlimit.c +3 -11
@@ -31,8 +31,6 @@ connlimit_mt(const struct sk_buff *skb, struct xt_action_param *par) {struct net *net =xt_net (par);const struct xt_connlimit_info *info = par->matchinfo; -struct nf_conntrack_tuple tuple; -const struct nf_conntrack_tuple *tuple_ptr = &tuple;const struct nf_conntrack_zone *zone = &nf_ct_zone_dflt;enum ip_conntrack_info ctinfo;const struct nf_conn *ct;
@@ -40,13 +38,8 @@ connlimit_mt(const struct sk_buff *skb, struct xt_action_param *par)u32 key[5 ]; ct =nf_ct_get (skb, &ctinfo); -if (ct !=NULL ) { - tuple_ptr = &ct->tuplehash[IP_CT_DIR_ORIGINAL ].tuple; +if (ct) zone =nf_ct_zone (ct); - }else if (!nf_ct_get_tuplepr (skb,skb_network_offset (skb), -xt_family (par), net, &tuple)) { - goto hotdrop; - }if (xt_family (par) ==NFPROTO_IPV6 ) {const struct ipv6hdr *iph =ipv6_hdr (skb);
@@ -69,10 +62,9 @@ connlimit_mt(const struct sk_buff *skb, struct xt_action_param *par) key[1 ] = zone->id; } - connections =nf_conncount_count (net, info->data, key, tuple_ptr, - zone); + connections =nf_conncount_count_skb (net, skb,xt_family (par), info->data, key);if (connections ==0 ) -/* kmalloc failed, drop it entirely */ +/* kmalloc failed or tuple couldn't be found, drop it entirely */ goto hotdrop;return (connections > info->limit) ^ !!(info->flags &XT_CONNLIMIT_INVERT );
net/openvswitch/conntrack.c +8 -8
@@ -928,8 +928,8 @@ static u32 ct_limit_get(const struct ovs_ct_limit_info *info, u16 zone) }static int ovs_ct_check_limit (struct net *net, -const struct ovs_conntrack_info *info, -const struct nf_conntrack_tuple *tuple) +const struct sk_buff *skb, +const struct ovs_conntrack_info *info) {struct ovs_net *ovs_net =net_generic (net, ovs_net_id);const struct ovs_ct_limit_info *ct_limit_info = ovs_net->ct_limit_info;
@@ -942,8 +942,9 @@ static int ovs_ct_check_limit(struct net *net,if (per_zone_limit ==OVS_CT_LIMIT_UNLIMITED )return 0 ; - connections =nf_conncount_count (net, ct_limit_info->data, - &conncount_key, tuple, &info->zone); + connections =nf_conncount_count_skb (net, skb, info->family, + ct_limit_info->data, + &conncount_key);if (connections > per_zone_limit)return -ENOMEM ;
@@ -972,8 +973,7 @@ static int ovs_ct_commit(struct net *net, struct sw_flow_key *key,#if IS_ENABLED (CONFIG_NETFILTER_CONNCOUNT )if (static_branch_unlikely (&ovs_ct_limit_enabled)) {if (!nf_ct_is_confirmed (ct)) { - err =ovs_ct_check_limit (net, info, - &ct->tuplehash[IP_CT_DIR_ORIGINAL ].tuple); + err =ovs_ct_check_limit (net, skb, info);if (err) { net_warn_ratelimited("openvswitch: zone: %u " "exceeds conntrack limit\n",
@@ -1770,8 +1770,8 @@ static int __ovs_ct_limit_get_zone_limit(struct net *net, zone_limit.limit = limit;nf_ct_zone_init (&ct_zone, zone_id,NF_CT_DEFAULT_ZONE_DIR ,0 ); - zone_limit.count =nf_conncount_count (net, data, &conncount_key,NULL , - &ct_zone); + zone_limit.count =nf_conncount_count_skb (net,NULL ,0 , data, + &conncount_key);return nla_put_nohdr (reply,sizeof (zone_limit), &zone_limit); }
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 483/614 netfilter: nft_connlimit: update the count if add was skipped
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Fernando Fernandez Mancera <[email protected]>
[ Upstream commit 69894e5b4c5e28cda5f32af33d4a92b7a4b93b0e ]
Connlimit expression can be used for all kind of packets and not only for packets with connection state new. See this ruleset as example:
table ip filter {
chain input {
type filter hook input priority filter; policy accept;
tcp dport 22 ct count over 4 counter
}
}Currently, if the connection count goes over the limit the counter will count the packets. When a connection is closed, the connection count won't decrement as it should because it is only updated for new connections due to an optimization on __nf_conncount_add() that prevents updating the list if the connection is duplicated.
To solve this problem, check whether the connection was skipped and if so, update the list. Adjust count_tree() too so the same fix is applied for xt_connlimit.
--- net/netfilter/nf_conncount.c | 12 ++++++++---- net/netfilter/nft_connlimit.c | 13 +++++++++++-- 2 files changed, 19 insertions(+), 6 deletions(-)
net/netfilter/nf_conncount.c +8 -4
@@ -179,7 +179,7 @@ static int __nf_conncount_add(struct net *net,if (ct &&nf_ct_is_confirmed (ct)) {if (refcounted)nf_ct_put (ct); -return 0 ; +return -EEXIST ; }if ((u32 )jiffies == list->last_gc)
@@ -398,7 +398,7 @@ insert_tree(struct net *net,int ret; ret =nf_conncount_add_skb (net, skb, l3num, &rbconn->list); -if (ret) +if (ret && ret != -EEXIST ) count =0 ;/* hotdrop */ else count = rbconn->list.count;
@@ -501,10 +501,14 @@ count_tree(struct net *net,/* same source network -> be counted! */ ret =__nf_conncount_add (net, skb, l3num, &rbconn->list);spin_unlock_bh (&rbconn->list.list_lock); -if (ret) +if (ret && ret != -EEXIST ) {return 0 ;/* hotdrop */ -else + }else { +/* -EEXIST means add was skipped, update the list */ +if (ret == -EEXIST ) +nf_conncount_gc_list (net, &rbconn->list);return rbconn->list.count; + } } }
net/netfilter/nft_connlimit.c +11 -2
@@ -29,8 +29,17 @@ static inline void nft_connlimit_do_eval(struct nft_connlimit *priv, err =nf_conncount_add_skb (nft_net (pkt), pkt->skb,nft_pf (pkt), priv->list);if (err) { - regs->verdict.code =NF_DROP ; -return ; +if (err == -EEXIST ) { +/* Call gc to update the list count if any connection has +* been closed already. This is useful for softlimit +* connections like limiting bandwidth based on a number +* of open connections. +*/ +nf_conncount_gc_list (nft_net (pkt), priv->list); + }else { + regs->verdict.code =NF_DROP ; +return ; + } } count =READ_ONCE (priv->list->count);
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 484/614 iavf: Implement settime64 with -EOPNOTSUPP
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michal Schmidt <[email protected]>
[ Upstream commit 1e43ebcd5152b3e681a334cc6542fb21770c3a2e ]
ptp_clock_settime() assumes every ptp_clock has implemented settime64(). Stub it with -EOPNOTSUPP to prevent a NULL dereference.
The fix is similar to commit 329d050bbe63 ("gve: Implement settime64 with -EOPNOTSUPP").
--- drivers/net/ethernet/intel/iavf/iavf_ptp.c | 7 +++++++ 1 file changed, 7 insertions(+)
drivers/net/ethernet/intel/iavf/iavf_ptp.c +7 -0
@@ -252,6 +252,12 @@ static int iavf_ptp_gettimex64(struct ptp_clock_info *info,return iavf_read_phc_indirect (adapter, ts, sts); } +static int iavf_ptp_settime64 (struct ptp_clock_info *info, +const struct timespec64 *ts) +{ +return -EOPNOTSUPP ; +} +/** * iavf_ptp_cache_phc_time - Cache PHC time for performing timestamp extension * @adapter: private adapter structure
@@ -320,6 +326,7 @@ static int iavf_ptp_register_clock(struct iavf_adapter *adapter) KBUILD_MODNAME, dev_name(dev)); ptp_info->owner =THIS_MODULE ; ptp_info->gettimex64 = iavf_ptp_gettimex64; + ptp_info->settime64 = iavf_ptp_settime64; ptp_info->do_aux_work = iavf_ptp_do_aux_work; clock =ptp_clock_register (ptp_info, dev);
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 485/614 net: vxlan: prevent NULL deref in vxlan_xmit_one
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Antoine Tenart <[email protected]>
[ Upstream commit 1f73a56f986005f0bc64ed23873930e2ee4f5911 ]
Neither sock4 nor sock6 pointers are guaranteed to be non-NULL in vxlan_xmit_one, e.g. if the iface is brought down. This can lead to the following NULL dereference:
BUG: kernel NULL pointer dereference, address: 0000000000000010 Oops: Oops: 0000 [#1] SMP NOPTI RIP: 0010:vxlan_xmit_one+0xbb3/0x1580 Call Trace: vxlan_xmit+0x429/0x610 dev_hard_start_xmit+0x55/0xa0 __dev_queue_xmit+0x6d0/0x7f0 ip_finish_output2+0x24b/0x590 ip_output+0x63/0x110
Mentioned commits changed the code path in vxlan_xmit_one and as a side effect the sock4/6 pointer validity checks in vxlan(6)_get_route were lost. Fix this by adding back checks.
Since both commits being fixed were released in the same version (v6.7) and are strongly related, bundle the fixes in a single commit.
--- drivers/net/vxlan/vxlan_core.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-)
drivers/net/vxlan/vxlan_core.c +15 -3
@@ -2349,7 +2349,7 @@ void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,int addr_family;__u8 tos, ttl;int ifindex; -int err; +int err =0 ;u32 flags = vxlan->cfg.flags;bool use_cache;bool udp_sum = false;
@@ -2454,12 +2454,18 @@ void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,rcu_read_lock ();if (addr_family ==AF_INET ) { -struct vxlan_sock *sock4 =rcu_dereference (vxlan->vn4_sock); +struct vxlan_sock *sock4;u16 ipcb_flags =0 ;struct rtable *rt;__be16 df =0 ;__be32 saddr; + sock4 =rcu_dereference (vxlan->vn4_sock); +if (unlikely (!sock4)) { + reason =SKB_DROP_REASON_DEV_READY ; + goto tx_error; + } +if (!ifindex) ifindex = sock4->sock->sk->sk_bound_dev_if;
@@ -2534,10 +2540,16 @@ void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, ipcb_flags);#if IS_ENABLED (CONFIG_IPV6 ) } else { -struct vxlan_sock *sock6 =rcu_dereference (vxlan->vn6_sock); +struct vxlan_sock *sock6;struct in6_addr saddr;u16 ip6cb_flags =0 ; + sock6 =rcu_dereference (vxlan->vn6_sock); +if (unlikely (!sock6)) { + reason =SKB_DROP_REASON_DEV_READY ; + goto tx_error; + } +if (!ifindex) ifindex = sock6->sock->sk->sk_bound_dev_if;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 486/614 net: stmmac: fix rx limit check in stmmac_rx_zc()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alexey Kodanev <[email protected]>
[ Upstream commit 8048168df56e225c94e50b04cb7b0514135d7a1c ]
The extra "count >= limit" check in stmmac_rx_zc() is redundant and has no effect because the value of "count" doesn't change after the while condition at this point.
However, it can change after "read_again:" label:
while (count < limit) {
...
if (count >= limit)
break;
read_again:
...
/* XSK pool expects RX frame 1:1 mapped to XSK buffer */
if (likely(status & rx_not_ls)) {
xsk_buff_free(buf->xdp);
buf->xdp = NULL;
dirty++;
count++;
goto read_again;
}
...This patch addresses the same issue previously resolved in stmmac_rx() by commit fa02de9e7588 ("net: stmmac: fix rx budget limit check"). The fix is the same: move the check after the label to ensure that it bounds the goto loop.
--- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +1 -1
@@ -5258,10 +5258,10 @@ static int stmmac_rx_zc(struct stmmac_priv *priv, int limit, u32 queue) len =0 ; } +read_again:if (count >= limit)break ; -read_again: buf1_len =0 ; entry = next_entry; buf = &rx_q->buf_pool[entry];
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 487/614 mtd: rawnand: renesas: Handle devm_pm_runtime_enable() errors
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Haotian Zhang <[email protected]>
[ Upstream commit a3623e1ae1ed6be4d49b2ccb9996a9d2b65c1828 ]
devm_pm_runtime_enable() can fail due to memory allocation failures. The current code ignores its return value and proceeds with pm_runtime_resume_and_get(), which may operate on incorrectly initialized runtime PM state.
Check the return value of devm_pm_runtime_enable() and return the error code if it fails.
--- drivers/mtd/nand/raw/renesas-nand-controller.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/mtd/nand/raw/renesas-nand-controller.c +4 -1
@@ -1336,7 +1336,10 @@ static int rnandc_probe(struct platform_device *pdev)if (IS_ERR (rnandc->regs))return PTR_ERR (rnandc->regs); -devm_pm_runtime_enable (&pdev->dev); + ret =devm_pm_runtime_enable (&pdev->dev); +if (ret) +return ret; + ret =pm_runtime_resume_and_get (&pdev->dev);if (ret <0 )return ret;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 488/614 spi: ch341: fix out-of-bounds memory access in ch341_transfer_one
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tianchu Chen <[email protected]>
[ Upstream commit 545d1287e40a55242f6ab68bcc1ba3b74088b1bc ]
Discovered by Atuin - Automated Vulnerability Discovery Engine.
The 'len' variable is calculated as 'min(32, trans->len + 1)', which includes the 1-byte command header.
When copying data from 'trans->tx_buf' to 'ch341->tx_buf + 1', using 'len' as the length is incorrect because:
1. It causes an out-of-bounds read from 'trans->tx_buf' (which has size 'trans->len', i.e., 'len - 1' in this context).
2. It can cause an out-of-bounds write to 'ch341->tx_buf' if 'len' is CH341_PACKET_LENGTH (32). Writing 32 bytes to ch341->tx_buf + 1 overflows the buffer.
Fix this by copying 'len - 1' bytes.
--- drivers/spi/spi-ch341.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/spi/spi-ch341.c +1 -1
@@ -78,7 +78,7 @@ static int ch341_transfer_one(struct spi_controller *host, ch341->tx_buf[0 ] =CH341A_CMD_SPI_STREAM ; -memcpy (ch341->tx_buf +1 , trans->tx_buf, len); +memcpy (ch341->tx_buf +1 , trans->tx_buf, len -1 ); ret =usb_bulk_msg (ch341->udev, ch341->write_pipe, ch341->tx_buf, len,NULL ,CH341_DEFAULT_TIMEOUT );
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 489/614 arm64/pageattr: Propagate return value from __change_memory_common
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dev Jain <[email protected]>
[ Upstream commit e5efd56fa157d2e7d789949d1d64eccbac18a897 ]
The rodata=on security measure requires that any code path which does vmalloc -> set_memory_ro/set_memory_rox must protect the linear map alias too. Therefore, if such a call fails, we must abort set_memory_* and caller must take appropriate action; currently we are suppressing the error, and there is a real chance of such an error arising post commit a166563e7ec3 ("arm64: mm: support large block mapping when rodata=full"). Therefore, propagate any error to the caller.
--- arch/arm64/mm/pageattr.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
arch/arm64/mm/pageattr.c +4 -1
@@ -148,6 +148,7 @@ static int change_memory_common(unsigned long addr, int numpages,unsigned long size =PAGE_SIZE * numpages;unsigned long end = start + size;struct vm_struct *area; +int ret;int i;if (!PAGE_ALIGNED (addr)) {
@@ -185,8 +186,10 @@ static int change_memory_common(unsigned long addr, int numpages,if (rodata_full && (pgprot_val (set_mask) ==PTE_RDONLY ||pgprot_val (clear_mask) ==PTE_RDONLY )) {for (i =0 ; i < area->nr_pages; i++) { -__change_memory_common ((u64 )page_address (area->pages[i]), + ret =__change_memory_common ((u64 )page_address (area->pages[i]),PAGE_SIZE , set_mask, clear_mask); +if (ret) +return ret; } }
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 490/614 vfio/pci: Use RCU for error/request triggers to avoid circular locking
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Williamson <[email protected]>
[ Upstream commit 98693e0897f754e3f51ce6626ed5f785f625ba2b ]
Thanks to a device generating an ACS violation during bus reset, lockdep reported the following circular locking issue:
CPU0: SET_IRQS (MSI/X): holds igate, acquires memory_lock
CPU1: HOT_RESET: holds memory_lock, acquires pci_bus_sem
CPU2: AER: holds pci_bus_sem, acquires igate
This results in a potential 3-way deadlock.
Remove the pci_bus_sem->igate leg of the triangle by using RCU to peek at the eventfd rather than locking it with igate.
--- drivers/vfio/pci/vfio_pci_core.c | 68 ++++++++++++++++++++++--------- drivers/vfio/pci/vfio_pci_intrs.c | 52 ++++++++++++++--------- drivers/vfio/pci/vfio_pci_priv.h | 4 ++ include/linux/vfio_pci_core.h | 10 ++++- 4 files changed, 93 insertions(+), 41 deletions(-)
drivers/vfio/pci/vfio_pci_core.c +48 -20
@@ -41,6 +41,40 @@ static bool nointxmask;static bool disable_vga;static bool disable_idle_d3; +static void vfio_pci_eventfd_rcu_free (struct rcu_head *rcu) +{ +struct vfio_pci_eventfd *eventfd = + container_of(rcu, struct vfio_pci_eventfd, rcu); + +eventfd_ctx_put (eventfd->ctx); +kfree (eventfd); +} + +int vfio_pci_eventfd_replace_locked (struct vfio_pci_core_device *vdev, +struct vfio_pci_eventfd __rcu **peventfd, +struct eventfd_ctx *ctx) +{ +struct vfio_pci_eventfd *new =NULL ; +struct vfio_pci_eventfd *old; + +lockdep_assert_held (&vdev->igate); + +if (ctx) { + new =kzalloc (sizeof (*new),GFP_KERNEL_ACCOUNT ); +if (!new) +return -ENOMEM ; + + new->ctx = ctx; + } + + old =rcu_replace_pointer (*peventfd, new, +lockdep_is_held (&vdev->igate)); +if (old) +call_rcu (&old->rcu, vfio_pci_eventfd_rcu_free); + +return 0 ; +} +/* List of PF's that vfio_pci_core_sriov_configure() has been called on */ static DEFINE_MUTEX (vfio_pci_sriov_pfs_mutex);static LIST_HEAD (vfio_pci_sriov_pfs);
@@ -696,14 +730,8 @@ void vfio_pci_core_close_device(struct vfio_device *core_vdev)vfio_pci_core_disable (vdev);mutex_lock (&vdev->igate); -if (vdev->err_trigger) { -eventfd_ctx_put (vdev->err_trigger); - vdev->err_trigger =NULL ; - } -if (vdev->req_trigger) { -eventfd_ctx_put (vdev->req_trigger); - vdev->req_trigger =NULL ; - } +vfio_pci_eventfd_replace_locked (vdev, &vdev->err_trigger,NULL ); +vfio_pci_eventfd_replace_locked (vdev, &vdev->req_trigger,NULL );mutex_unlock (&vdev->igate); }EXPORT_SYMBOL_GPL (vfio_pci_core_close_device);
@@ -1800,21 +1828,21 @@ void vfio_pci_core_request(struct vfio_device *core_vdev, unsigned int count)struct vfio_pci_core_device *vdev = container_of(core_vdev, struct vfio_pci_core_device, vdev);struct pci_dev *pdev = vdev->pdev; +struct vfio_pci_eventfd *eventfd; -mutex_lock (&vdev->igate); - -if (vdev->req_trigger) { +rcu_read_lock (); + eventfd =rcu_dereference (vdev->req_trigger); +if (eventfd) {if (!(count %10 ))pci_notice_ratelimited (pdev,"Relaying device request to user (#%u)\n" , count); -eventfd_signal (vdev->req_trigger); +eventfd_signal (eventfd->ctx); }else if (count ==0 ) {pci_warn (pdev,"No device request channel registered, blocked until released by user\n" ); } - -mutex_unlock (&vdev->igate); +rcu_read_unlock (); }EXPORT_SYMBOL_GPL (vfio_pci_core_request);
@@ -2227,13 +2255,13 @@ pci_ers_result_t vfio_pci_core_aer_err_detected(struct pci_dev *pdev, pci_channel_state_t state) {struct vfio_pci_core_device *vdev =dev_get_drvdata (&pdev->dev); +struct vfio_pci_eventfd *eventfd; -mutex_lock (&vdev->igate); - -if (vdev->err_trigger) -eventfd_signal (vdev->err_trigger); - -mutex_unlock (&vdev->igate); +rcu_read_lock (); + eventfd =rcu_dereference (vdev->err_trigger); +if (eventfd) +eventfd_signal (eventfd->ctx); +rcu_read_unlock ();return PCI_ERS_RESULT_CAN_RECOVER ; }
drivers/vfio/pci/vfio_pci_intrs.c +33 -19
98 lines not on this page · raw message
drivers/vfio/pci/vfio_pci_priv.h +4 -0
@@ -26,6 +26,10 @@ struct vfio_pci_ioeventfd {bool vfio_pci_intx_mask (struct vfio_pci_core_device *vdev);void vfio_pci_intx_unmask (struct vfio_pci_core_device *vdev); +int vfio_pci_eventfd_replace_locked (struct vfio_pci_core_device *vdev, +struct vfio_pci_eventfd __rcu **peventfd, +struct eventfd_ctx *ctx); +int vfio_pci_set_irqs_ioctl (struct vfio_pci_core_device *vdev,uint32_t flags,unsigned index,unsigned start,unsigned count,void *data);
include/linux/vfio_pci_core.h +8 -2
@@ -12,6 +12,7 @@#include <linux/pci.h> #include <linux/vfio.h> #include <linux/irqbypass.h> +#include <linux/rcupdate.h> #include <linux/types.h> #include <linux/uuid.h> #include <linux/notifier.h>
@@ -27,6 +28,11 @@struct vfio_pci_core_device ;struct vfio_pci_region ; +struct vfio_pci_eventfd { +struct eventfd_ctx *ctx; +struct rcu_head rcu; +}; +struct vfio_pci_regops {ssize_t (*rw)(struct vfio_pci_core_device *vdev,char __user *buf,size_t count,loff_t *ppos,bool iswrite);
@@ -83,8 +89,8 @@ struct vfio_pci_core_device {struct pci_saved_state *pci_saved_state;struct pci_saved_state *pm_save;int ioeventfds_nr; -struct eventfd_ctx *err_trigger; -struct eventfd_ctx *req_trigger; +struct vfio_pci_eventfd __rcu *err_trigger; +struct vfio_pci_eventfd __rcu *req_trigger;struct eventfd_ctx *pm_wake_eventfd_ctx;struct list_head dummy_resources_list;struct mutex ioeventfds_lock;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 491/614 landlock: Fix handling of disconnected directories
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mickaël Salaün <[email protected]>
[ Upstream commit 49c9e09d961025b22e61ef9ad56aa1c21b6ce2f1 ]
Disconnected files or directories can appear when they are visible and opened from a bind mount, but have been renamed or moved from the source of the bind mount in a way that makes them inaccessible from the mount point (i.e. out of scope).
Previously, access rights tied to files or directories opened through a disconnected directory were collected by walking the related hierarchy down to the root of the filesystem, without taking into account the mount point because it couldn't be found. This could lead to inconsistent access results, potential access right widening, and hard-to-debug renames, especially since such paths cannot be printed.
For a sandboxed task to create a disconnected directory, it needs to have write access (i.e. FS_MAKE_REG, FS_REMOVE_FILE, and FS_REFER) to the underlying source of the bind mount, and read access to the related
mount point. Because a sandboxed task cannot acquire more access
rights than those defined by its Landlock domain, this could lead to inconsistent access rights due to missing permissions that should be inherited from the mount point hierarchy, while inheriting permissions from the filesystem hierarchy hidden by this mount point instead.
Landlock now handles files and directories opened from disconnected directories by taking into account the filesystem hierarchy when the mount point is not found in the hierarchy walk, and also always taking into account the mount point from which these disconnected directories were opened. This ensures that a rename is not allowed if it would widen access rights [1].
The rationale is that, even if disconnected hierarchies might not be visible or accessible to a sandboxed task, relying on the collected access rights from them improves the guarantee that access rights will not be widened during a rename because of the access right comparison between the source and the destination (see LANDLOCK_ACCESS_FS_REFER). It may look like this would grant more access on disconnected files and directories, but the security policies are always enforced for all the evaluated hierarchies. This new behavior should be less surprising to users and safer from an access control perspective.
Remove a wrong WARN_ON_ONCE() canary in collect_domain_accesses() and fix the related comment.
Because opened files have their access rights stored in the related file security properties, there is no impact for disconnected or unlinked files.
--- security/landlock/errata/abi-1.h | 16 +++++++++++++ security/landlock/fs.c | 40 ++++++++++++++++++++++---------- 2 files changed, 44 insertions(+), 12 deletions(-) create mode 100644 security/landlock/errata/abi-1.h
security/landlock/errata/abi-1.h new file +16 -0
@@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +/** +* DOC: erratum_3 +* +* Erratum 3: Disconnected directory handling +* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +* +* This fix addresses an issue with disconnected directories that occur when a +* directory is moved outside the scope of a bind mount. The change ensures +* that evaluated access rights include both those from the disconnected file +* hierarchy down to its filesystem root and those from the related mount point +* hierarchy. This prevents access right widening through rename or link +* actions. +*/ +LANDLOCK_ERRATUM (3 )
security/landlock/fs.c +28 -12
@@ -909,21 +909,31 @@ static bool is_access_to_paths_allowed(break ; } } +if (unlikely (IS_ROOT (walker_path.dentry))) { -/* -* Stops at disconnected root directories. Only allows -* access to internal filesystems (e.g. nsfs, which is -* reachable through /proc/<pid>/ns/<namespace>). -*/ -if (walker_path.mnt->mnt_flags &MNT_INTERNAL ) { +if (likely (walker_path.mnt->mnt_flags &MNT_INTERNAL )) { +/* +* Stops and allows access when reaching disconnected root +* directories that are part of internal filesystems (e.g. nsfs, +* which is reachable through /proc/<pid>/ns/<namespace>). +*/ allowed_parent1 = true; allowed_parent2 = true; +break ; } -break ; + +/* +* We reached a disconnected root directory from a bind mount. +* Let's continue the walk with the mount point we missed. +*/ +dput (walker_path.dentry); + walker_path.dentry = walker_path.mnt->mnt_root; +dget (walker_path.dentry); + }else { + parent_dentry =dget_parent (walker_path.dentry); +dput (walker_path.dentry); + walker_path.dentry = parent_dentry; } - parent_dentry =dget_parent (walker_path.dentry); -dput (walker_path.dentry); - walker_path.dentry = parent_dentry; }path_put (&walker_path);
@@ -1021,6 +1031,9 @@ static access_mask_t maybe_remove(const struct dentry *const dentry)* file. While walking from @dir to @mnt_root, we record all the domain's * allowed accesses in @layer_masks_dom. * +* Because of disconnected directories, this walk may not reach @mnt_dir. In +* this case, the walk will continue to @mnt_dir after this call. +* * This is similar to is_access_to_paths_allowed() but much simpler because it * only handles walking on the same mount point and only checks one set of * accesses.
@@ -1062,8 +1075,11 @@ static bool collect_domain_accesses(break ; } -/* We should not reach a root other than @mnt_root. */ -if (dir == mnt_root ||WARN_ON_ONCE (IS_ROOT (dir))) +/* +* Stops at the mount point or the filesystem root for a disconnected +* directory. +*/ +if (dir == mnt_root ||unlikely (IS_ROOT (dir)))break ; parent_dentry =dget_parent (dir);
Signature · 1 line
2.51.0
PATCH 1/2 selftests/landlock: Add tests for access through disconnected paths
From: Tingmao Wang <[email protected]>
[ Upstream commit a18ee3f31fd714173a62515d049d77e76ab55649 ]
This adds tests for the edge case discussed in [1], with specific ones for rename and link operations when the operands are through disconnected paths, as that go through a separate code path in Landlock.
This has resulted in a warning, due to collect_domain_accesses() not expecting to reach a different root from path->mnt:
# RUN layout1_bind.path_disconnected ...
# OK layout1_bind.path_disconnected
ok 96 layout1_bind.path_disconnected
# RUN layout1_bind.path_disconnected_rename ...
[..] ------------[ cut here ]------------
[..] WARNING: CPU: 3 PID: 385 at security/landlock/fs.c:1065 collect_domain_accesses
[..] ...
[..] RIP: 0010:collect_domain_accesses (security/landlock/fs.c:1065 (discriminator 2) security/landlock/fs.c:1031 (discriminator 2)) [..] current_check_refer_path (security/landlock/fs.c:1205)
[..] ...
[..] hook_path_rename (security/landlock/fs.c:1526)
[..] security_path_rename (security/security.c:2026 (discriminator 1))
[..] do_renameat2 (fs/namei.c:5264)
# OK layout1_bind.path_disconnected_rename
ok 97 layout1_bind.path_disconnected_rename
Move the const char definitions a bit above so that we can use the path for s4d1 in cleanup code.
--- tools/testing/selftests/landlock/fs_test.c | 423 ++++++++++++++++++++- 1 file changed, 415 insertions(+), 8 deletions(-)
tools/testing/selftests/landlock/fs_test.c +415 -8
@@ -4559,6 +4559,18 @@ TEST_F_FORK(ioctl, handle_file_access_file)FIXTURE (layout1_bind) {};/* clang-format on */ +static const char bind_dir_s1d3[] =TMP_DIR "/s2d1/s2d2/s1d3" ; +static const char bind_file1_s1d3[] =TMP_DIR "/s2d1/s2d2/s1d3/f1" ; + +/* Move targets for disconnected path tests. */ +static const char dir_s4d1[] =TMP_DIR "/s4d1" ; +static const char file1_s4d1[] =TMP_DIR "/s4d1/f1" ; +static const char file2_s4d1[] =TMP_DIR "/s4d1/f2" ; +static const char dir_s4d2[] =TMP_DIR "/s4d1/s4d2" ; +static const char file1_s4d2[] =TMP_DIR "/s4d1/s4d2/f1" ; +static const char file1_name[] ="f1" ; +static const char file2_name[] ="f2" ; +FIXTURE_SETUP (layout1_bind) {prepare_layout (_metadata);
@@ -4574,14 +4586,14 @@ FIXTURE_TEARDOWN_PARENT(layout1_bind) {/* umount(dir_s2d2)) is handled by namespace lifetime. */ +remove_path (file1_s4d1); +remove_path (file2_s4d1); +remove_layout1 (_metadata);cleanup_layout (_metadata); } -static const char bind_dir_s1d3[] =TMP_DIR "/s2d1/s2d2/s1d3" ; -static const char bind_file1_s1d3[] =TMP_DIR "/s2d1/s2d2/s1d3/f1" ; -/* * layout1_bind hierarchy: *
@@ -4592,20 +4604,25 @@ static const char bind_file1_s1d3[] = TMP_DIR "/s2d1/s2d2/s1d3/f1";* │ └── s1d2 * │ ├── f1 * │ ├── f2 -* │ └── s1d3 +* │ └── s1d3 [disconnected by path_disconnected] * │ ├── f1 * │ └── f2 * ├── s2d1 * │ ├── f1 -* │ └── s2d2 +* │ └── s2d2 [bind mount from s1d2] * │ ├── f1 * │ ├── f2 * │ └── s1d3 * │ ├── f1 * │ └── f2 -* └── s3d1 -* └── s3d2 -* └── s3d3 +* ├── s3d1 +* │ └── s3d2 +* │ └── s3d3 +* └── s4d1 [renamed from s1d3 by path_disconnected] +* ├── f1 +* ├── f2 +* └── s4d2 +* └── f1 */ TEST_F_FORK (layout1_bind, no_restriction)
@@ -4804,6 +4821,396 @@ TEST_F_FORK(layout1_bind, reparent_cross_mount)ASSERT_EQ (0 ,rename (bind_file1_s1d3, file1_s2d2)); } +/* +* Make sure access to file through a disconnected path works as expected. +* This test moves s1d3 to s4d1. +*/ +TEST_F_FORK(layout1_bind, path_disconnected) +{ +const struct rule layer1_allow_all[] = { + { + .path =TMP_DIR , + .access =ACCESS_ALL , + }, + {}, + }; +const struct rule layer2_allow_just_f1[] = { + { + .path = file1_s1d3, + .access =LANDLOCK_ACCESS_FS_READ_FILE , + }, + {}, + }; +const struct rule layer3_only_s1d2[] = { + { + .path = dir_s1d2, + .access =LANDLOCK_ACCESS_FS_READ_FILE , + }, + {}, + }; + +/* Landlock should not deny access just because it is disconnected. */ +int ruleset_fd_l1 = +create_ruleset (_metadata,ACCESS_ALL , layer1_allow_all); + +/* Creates the new ruleset now before we move the dir containing the file. */ +int ruleset_fd_l2 = +create_ruleset (_metadata,ACCESS_RW , layer2_allow_just_f1); +int ruleset_fd_l3 = +create_ruleset (_metadata,ACCESS_RW , layer3_only_s1d2); +int bind_s1d3_fd; + +ASSERT_LE (0 , ruleset_fd_l1); +ASSERT_LE (0 , ruleset_fd_l2); +ASSERT_LE (0 , ruleset_fd_l3); + +enforce_ruleset (_metadata, ruleset_fd_l1); +EXPECT_EQ (0 ,close (ruleset_fd_l1)); + + bind_s1d3_fd =open (bind_dir_s1d3,O_PATH |O_CLOEXEC ); +ASSERT_LE (0 , bind_s1d3_fd); + +/* Tests access is possible before we move. */ +EXPECT_EQ (0 ,test_open_rel (bind_s1d3_fd, file1_name,O_RDONLY )); +EXPECT_EQ (0 ,test_open_rel (bind_s1d3_fd, file2_name,O_RDONLY )); +EXPECT_EQ (0 ,test_open_rel (bind_s1d3_fd,".." ,O_RDONLY |O_DIRECTORY )); + +/* Makes it disconnected. */ + ASSERT_EQ(0, rename(dir_s1d3, dir_s4d1)) + { +TH_LOG ("Failed to rename %s to %s: %s" , dir_s1d3, dir_s4d1, +strerror (errno)); + } + +/* Tests that access is still possible. */ +EXPECT_EQ (0 ,test_open_rel (bind_s1d3_fd, file1_name,O_RDONLY )); +EXPECT_EQ (0 ,test_open_rel (bind_s1d3_fd, file2_name,O_RDONLY )); + +/* +* Tests that ".." is not possible (not because of Landlock, but just +* because it's disconnected). +*/ +EXPECT_EQ (ENOENT , +test_open_rel (bind_s1d3_fd,".." ,O_RDONLY |O_DIRECTORY )); + +/* This should still work with a narrower rule. */ +enforce_ruleset (_metadata, ruleset_fd_l2); +EXPECT_EQ (0 ,close (ruleset_fd_l2)); + +EXPECT_EQ (0 ,test_open (file1_s4d1,O_RDONLY )); +/* +* Accessing a file through a disconnected file descriptor can still be +* allowed by a rule tied to this file, even if it is no longer visible in +* its mount point. +*/ +EXPECT_EQ (0 ,test_open_rel (bind_s1d3_fd, file1_name,O_RDONLY )); +EXPECT_EQ (EACCES ,test_open_rel (bind_s1d3_fd, file2_name,O_RDONLY )); + +enforce_ruleset (_metadata, ruleset_fd_l3); +EXPECT_EQ (0 ,close (ruleset_fd_l3)); + +EXPECT_EQ (EACCES ,test_open (file1_s4d1,O_RDONLY )); +/* +* Accessing a file through a disconnected file descriptor can still be +* allowed by a rule tied to the original mount point, even if it is no +* longer visible in its mount point. +*/ +EXPECT_EQ (0 ,test_open_rel (bind_s1d3_fd, file1_name,O_RDONLY )); +EXPECT_EQ (EACCES ,test_open_rel (bind_s1d3_fd, file2_name,O_RDONLY )); +} + +/* +* Test that renameat with disconnected paths works under Landlock. This test +* moves s1d3 to s4d2, so that we can have a rule allowing refers on the move +* target's immediate parent. +*/ +TEST_F_FORK(layout1_bind, path_disconnected_rename) +{ +const struct rule layer1[] = { + { + .path = dir_s1d2, + .access =LANDLOCK_ACCESS_FS_REFER | +LANDLOCK_ACCESS_FS_MAKE_DIR | +LANDLOCK_ACCESS_FS_REMOVE_DIR | +LANDLOCK_ACCESS_FS_MAKE_REG | +LANDLOCK_ACCESS_FS_REMOVE_FILE | +LANDLOCK_ACCESS_FS_READ_FILE , + }, + { + .path = dir_s4d1, + .access =LANDLOCK_ACCESS_FS_REFER | +LANDLOCK_ACCESS_FS_MAKE_DIR | +LANDLOCK_ACCESS_FS_REMOVE_DIR | +LANDLOCK_ACCESS_FS_MAKE_REG | +LANDLOCK_ACCESS_FS_REMOVE_FILE | +LANDLOCK_ACCESS_FS_READ_FILE , + }, + {} + }; + +/* This layer only handles LANDLOCK_ACCESS_FS_READ_FILE. */ +const struct rule layer2_only_s1d2[] = { + { + .path = dir_s1d2, + .access =LANDLOCK_ACCESS_FS_READ_FILE , + }, + {}, + }; +int ruleset_fd_l1, ruleset_fd_l2; +pid_t child_pid; +int bind_s1d3_fd, status; + + ASSERT_EQ(0, mkdir(dir_s4d1, 0755)) + { +TH_LOG ("Failed to create %s: %s" , dir_s4d1,strerror (errno)); + } + ruleset_fd_l1 =create_ruleset (_metadata,ACCESS_ALL , layer1); + ruleset_fd_l2 =create_ruleset (_metadata,LANDLOCK_ACCESS_FS_READ_FILE , + layer2_only_s1d2); +ASSERT_LE (0 , ruleset_fd_l1); +ASSERT_LE (0 , ruleset_fd_l2); + +enforce_ruleset (_metadata, ruleset_fd_l1); +EXPECT_EQ (0 ,close (ruleset_fd_l1)); + + bind_s1d3_fd =open (bind_dir_s1d3,O_PATH |O_CLOEXEC ); +ASSERT_LE (0 , bind_s1d3_fd); +EXPECT_EQ (0 ,test_open_rel (bind_s1d3_fd, file1_name,O_RDONLY )); + +/* Tests ENOENT priority over EACCES for disconnected directory. */ +EXPECT_EQ (EACCES ,test_open_rel (bind_s1d3_fd,".." ,O_DIRECTORY )); + ASSERT_EQ(0, rename(dir_s1d3, dir_s4d2)) + { +TH_LOG ("Failed to rename %s to %s: %s" , dir_s1d3, dir_s4d2, +strerror (errno)); + } +EXPECT_EQ (ENOENT ,test_open_rel (bind_s1d3_fd,".." ,O_DIRECTORY )); + +/* +* The file is no longer under s1d2 but we should still be able to access it +* with layer 2 because its mount point is evaluated as the first valid +* directory because it was initially a parent. Do a fork to test this so +* we don't prevent ourselves from renaming it back later. +*/ + child_pid =fork (); +ASSERT_LE (0 , child_pid); +if (child_pid ==0 ) { +enforce_ruleset (_metadata, ruleset_fd_l2); +EXPECT_EQ (0 ,close (ruleset_fd_l2)); +EXPECT_EQ (0 ,test_open_rel (bind_s1d3_fd, file1_name,O_RDONLY )); +EXPECT_EQ (EACCES ,test_open (file1_s4d2,O_RDONLY )); + +/* +* Tests that access widening checks indeed prevents us from renaming it +* back. +*/ +EXPECT_EQ (-1 ,rename (dir_s4d2, dir_s1d3)); +EXPECT_EQ (EXDEV , errno); + +/* +* Including through the now disconnected fd (but it should return +* EXDEV). +*/ +EXPECT_EQ (-1 ,renameat (bind_s1d3_fd, file1_name,AT_FDCWD , + file1_s2d2)); +EXPECT_EQ (EXDEV , errno); +_exit (_metadata->exit_code); +return ; + } + +EXPECT_EQ (child_pid,waitpid (child_pid, &status,0 )); +EXPECT_EQ (1 ,WIFEXITED (status)); +EXPECT_EQ (EXIT_SUCCESS ,WEXITSTATUS (status)); + + ASSERT_EQ(0, rename(dir_s4d2, dir_s1d3)) + { +TH_LOG ("Failed to rename %s back to %s: %s" , dir_s4d1, dir_s1d3, +strerror (errno)); + } + +/* Now checks that we can access it under l2. */ + child_pid =fork (); +ASSERT_LE (0 , child_pid); +if (child_pid ==0 ) { +enforce_ruleset (_metadata, ruleset_fd_l2); +EXPECT_EQ (0 ,close (ruleset_fd_l2)); +EXPECT_EQ (0 ,test_open_rel (bind_s1d3_fd, file1_name,O_RDONLY )); +EXPECT_EQ (0 ,test_open (file1_s1d3,O_RDONLY )); +_exit (_metadata->exit_code); +return ; + } + +EXPECT_EQ (child_pid,waitpid (child_pid, &status,0 )); +EXPECT_EQ (1 ,WIFEXITED (status)); +EXPECT_EQ (EXIT_SUCCESS ,WEXITSTATUS (status)); + +/* +* Also test that we can rename via a disconnected path. We move the +* dir back to the disconnected place first, then we rename file1 to +* file2 through our dir fd. +*/ + ASSERT_EQ(0, rename(dir_s1d3, dir_s4d2)) + { +TH_LOG ("Failed to rename %s to %s: %s" , dir_s1d3, dir_s4d2, +strerror (errno)); + } +ASSERT_EQ (0 , + renameat(bind_s1d3_fd, file1_name, bind_s1d3_fd, file2_name)) + { +TH_LOG ("Failed to rename %s to %s within disconnected %s: %s" , + file1_name, file2_name, bind_dir_s1d3,strerror (errno)); + } +EXPECT_EQ (0 ,test_open_rel (bind_s1d3_fd, file2_name,O_RDONLY )); + ASSERT_EQ(0, renameat(bind_s1d3_fd, file2_name, AT_FDCWD, file1_s2d2)) + { +TH_LOG ("Failed to rename %s to %s through disconnected %s: %s" , + file2_name, file1_s2d2, bind_dir_s1d3,strerror (errno)); + } +EXPECT_EQ (0 ,test_open (file1_s2d2,O_RDONLY )); +EXPECT_EQ (0 ,test_open (file1_s1d2,O_RDONLY )); + +/* Move it back using the disconnected path as the target. */ + ASSERT_EQ(0, renameat(AT_FDCWD, file1_s2d2, bind_s1d3_fd, file1_name)) + { +TH_LOG ("Failed to rename %s to %s through disconnected %s: %s" , + file1_s1d2, file1_name, bind_dir_s1d3,strerror (errno)); + } + +/* Now make it connected again. */ + ASSERT_EQ(0, rename(dir_s4d2, dir_s1d3)) + { +TH_LOG ("Failed to rename %s back to %s: %s" , dir_s4d2, dir_s1d3, +strerror (errno)); + } + +/* Checks again that we can access it under l2. */ +enforce_ruleset (_metadata, ruleset_fd_l2); +EXPECT_EQ (0 ,close (ruleset_fd_l2)); +EXPECT_EQ (0 ,test_open_rel (bind_s1d3_fd, file1_name,O_RDONLY )); +EXPECT_EQ (0 ,test_open (file1_s1d3,O_RDONLY )); +} + +/* +* Test that linkat(2) with disconnected paths works under Landlock. This +* test moves s1d3 to s4d1. +*/ +TEST_F_FORK(layout1_bind, path_disconnected_link) +{ +/* Ruleset to be applied after renaming s1d3 to s4d1. */ +const struct rule layer1[] = { + { + .path = dir_s4d1, + .access =LANDLOCK_ACCESS_FS_REFER | +LANDLOCK_ACCESS_FS_READ_FILE | +LANDLOCK_ACCESS_FS_MAKE_REG | +LANDLOCK_ACCESS_FS_REMOVE_FILE , + }, + { + .path = dir_s2d2, + .access =LANDLOCK_ACCESS_FS_REFER | +LANDLOCK_ACCESS_FS_READ_FILE | +LANDLOCK_ACCESS_FS_MAKE_REG | +LANDLOCK_ACCESS_FS_REMOVE_FILE , + }, + {} + }; +int ruleset_fd, bind_s1d3_fd; + +/* Removes unneeded files created by layout1, otherwise it will EEXIST. */ +ASSERT_EQ (0 ,unlink (file1_s1d2)); +ASSERT_EQ (0 ,unlink (file2_s1d3)); + + bind_s1d3_fd =open (bind_dir_s1d3,O_PATH |O_CLOEXEC ); +ASSERT_LE (0 , bind_s1d3_fd); +EXPECT_EQ (0 ,test_open_rel (bind_s1d3_fd, file1_name,O_RDONLY )); + +/* Disconnects bind_s1d3_fd. */ + ASSERT_EQ(0, rename(dir_s1d3, dir_s4d1)) + { +TH_LOG ("Failed to rename %s to %s: %s" , dir_s1d3, dir_s4d1, +strerror (errno)); + } + +/* Need this later to test different parent link. */ + ASSERT_EQ(0, mkdir(dir_s4d2, 0755)) + { +TH_LOG ("Failed to create %s: %s" , dir_s4d2,strerror (errno)); + } + + ruleset_fd =create_ruleset (_metadata,ACCESS_ALL , layer1); +ASSERT_LE (0 , ruleset_fd); +enforce_ruleset (_metadata, ruleset_fd); +EXPECT_EQ (0 ,close (ruleset_fd)); + +/* From disconnected to connected. */ + ASSERT_EQ(0, linkat(bind_s1d3_fd, file1_name, AT_FDCWD, file1_s2d2, 0)) + { +TH_LOG ("Failed to link %s to %s via disconnected %s: %s" , + file1_name, file1_s2d2, bind_dir_s1d3,strerror (errno)); + } + +/* Tests that we can access via the new link... */ + EXPECT_EQ(0, test_open(file1_s2d2, O_RDONLY)) + { +TH_LOG ("Failed to open newly linked %s: %s" , file1_s2d2, +strerror (errno)); + } + +/* ...as well as the old one. */ + EXPECT_EQ(0, test_open(file1_s4d1, O_RDONLY)) + { +TH_LOG ("Failed to open original %s: %s" , file1_s4d1, +strerror (errno)); + } + +/* From connected to disconnected. */ +ASSERT_EQ (0 ,unlink (file1_s4d1)); + ASSERT_EQ(0, linkat(AT_FDCWD, file1_s2d2, bind_s1d3_fd, file2_name, 0)) + { +TH_LOG ("Failed to link %s to %s via disconnected %s: %s" , + file1_s2d2, file2_name, bind_dir_s1d3,strerror (errno)); + } +EXPECT_EQ (0 ,test_open (file2_s4d1,O_RDONLY )); +ASSERT_EQ (0 ,unlink (file1_s2d2)); + +/* From disconnected to disconnected (same parent). */ +ASSERT_EQ (0 , + linkat(bind_s1d3_fd, file2_name, bind_s1d3_fd, file1_name, 0)) + { +TH_LOG ("Failed to link %s to %s within disconnected %s: %s" , + file2_name, file1_name, bind_dir_s1d3,strerror (errno)); + } + EXPECT_EQ(0, test_open(file1_s4d1, O_RDONLY)) + { +TH_LOG ("Failed to open newly linked %s: %s" , file1_s4d1, +strerror (errno)); + } + EXPECT_EQ(0, test_open_rel(bind_s1d3_fd, file1_name, O_RDONLY)) + { +TH_LOG ("Failed to open %s through newly created link under disconnected path: %s" , + file1_name,strerror (errno)); + } +ASSERT_EQ (0 ,unlink (file2_s4d1)); + +/* From disconnected to disconnected (different parent). */ +ASSERT_EQ (0 , + linkat(bind_s1d3_fd, file1_name, bind_s1d3_fd, "s4d2/f1", 0)) + { +TH_LOG ("Failed to link %s to %s within disconnected %s: %s" , + file1_name,"s4d2/f1" , bind_dir_s1d3,strerror (errno)); + } + EXPECT_EQ(0, test_open(file1_s4d2, O_RDONLY)) + { +TH_LOG ("Failed to open %s after link: %s" , file1_s4d2, +strerror (errno)); + } + EXPECT_EQ(0, test_open_rel(bind_s1d3_fd, "s4d2/f1", O_RDONLY)) + { +TH_LOG ("Failed to open %s through disconnected path after link: %s" , +"s4d2/f1" ,strerror (errno)); + } +} +#define LOWER_BASE TMP_DIR "/lower"#define LOWER_DATA LOWER_BASE "/data"static const char lower_fl1[] =LOWER_DATA "/fl1" ;
PATCH 2/2 selftests/landlock: Add disconnected leafs and branch test suites
In reply to Greg Kroah-Hartman[ Upstream commit 54f9baf537b0a091adad860ec92e3e18e0a0754c ]
Test disconnected directories with two test suites (layout4_disconnected_leafs and layout5_disconnected_branch) and 43 variants to cover the main corner cases.
These tests are complementary to the previous commit.
Add test_renameat() and test_exchangeat() helpers.
Test coverage for security/landlock is 92.1% of 1927 lines according to LLVM 20.
--- tools/testing/selftests/landlock/fs_test.c | 1051 ++++++++++++++++++++ 1 file changed, 1051 insertions(+)
tools/testing/selftests/landlock/fs_test.c +1051 -0
@@ -2267,6 +2267,22 @@ static int test_exchange(const char *const oldpath, const char *const newpath)return 0 ; } +static int test_renameat (int olddirfd,const char *oldpath,int newdirfd, +const char *newpath) +{ +if (renameat2 (olddirfd, oldpath, newdirfd, newpath,0 )) +return errno; +return 0 ; +} + +static int test_exchangeat (int olddirfd,const char *oldpath,int newdirfd, +const char *newpath) +{ +if (renameat2 (olddirfd, oldpath, newdirfd, newpath,RENAME_EXCHANGE )) +return errno; +return 0 ; +} + TEST_F_FORK(layout1, rename_file) {const struct rule rules[] = {
@@ -5211,6 +5227,1041 @@ TEST_F_FORK(layout1_bind, path_disconnected_link) } } +/* +* layout4_disconnected_leafs with bind mount and renames: +* +* tmp +* ├── s1d1 +* │ └── s1d2 [source of the bind mount] +* │ ├── s1d31 +* │ │ └── s1d41 [now renamed beneath s3d1] +* │ │ ├── f1 +* │ │ └── f2 +* │ └── s1d32 +* │ └── s1d42 [now renamed beneath s4d1] +* │ ├── f3 +* │ └── f4 +* ├── s2d1 +* │ └── s2d2 [bind mount of s1d2] +* │ ├── s1d31 +* │ │ └── s1d41 [opened FD, now renamed beneath s3d1] +* │ │ ├── f1 +* │ │ └── f2 +* │ └── s1d32 +* │ └── s1d42 [opened FD, now renamed beneath s4d1] +* │ ├── f3 +* │ └── f4 +* ├── s3d1 +* │ └── s1d41 [renamed here] +* │ ├── f1 +* │ └── f2 +* └── s4d1 +* └── s1d42 [renamed here] +* ├── f3 +* └── f4 +*/ +/* clang-format off */ +FIXTURE (layout4_disconnected_leafs) { +int s2d2_fd; +}; +/* clang-format on */ + +FIXTURE_SETUP (layout4_disconnected_leafs) +{ +prepare_layout (_metadata); + +create_file (_metadata,TMP_DIR "/s1d1/s1d2/s1d31/s1d41/f1" ); +create_file (_metadata,TMP_DIR "/s1d1/s1d2/s1d31/s1d41/f2" ); +create_file (_metadata,TMP_DIR "/s1d1/s1d2/s1d32/s1d42/f3" ); +create_file (_metadata,TMP_DIR "/s1d1/s1d2/s1d32/s1d42/f4" ); +create_directory (_metadata,TMP_DIR "/s2d1/s2d2" ); +create_directory (_metadata,TMP_DIR "/s3d1" ); +create_directory (_metadata,TMP_DIR "/s4d1" ); + + self->s2d2_fd = +open (TMP_DIR "/s2d1/s2d2" ,O_DIRECTORY |O_PATH |O_CLOEXEC ); +ASSERT_LE (0 , self->s2d2_fd); + +set_cap (_metadata,CAP_SYS_ADMIN ); +ASSERT_EQ (0 ,mount (TMP_DIR "/s1d1/s1d2" ,TMP_DIR "/s2d1/s2d2" ,NULL , +MS_BIND ,NULL )); +clear_cap (_metadata,CAP_SYS_ADMIN ); +} + +FIXTURE_TEARDOWN_PARENT (layout4_disconnected_leafs) +{ +/* umount(TMP_DIR "/s2d1") is handled by namespace lifetime. */ + +/* Removes files after renames. */ +remove_path (TMP_DIR "/s3d1/s1d41/f1" ); +remove_path (TMP_DIR "/s3d1/s1d41/f2" ); +remove_path (TMP_DIR "/s4d1/s1d42/f1" ); +remove_path (TMP_DIR "/s4d1/s1d42/f3" ); +remove_path (TMP_DIR "/s4d1/s1d42/f4" ); +remove_path (TMP_DIR "/s4d1/s1d42/f5" ); + +cleanup_layout (_metadata); +} + +FIXTURE_VARIANT (layout4_disconnected_leafs) +{ +/* +* Parent of the bind mount source. It should always be ignored when +* testing against files under the s1d41 or s1d42 disconnected directories. +*/ +const __u64 allowed_s1d1; +/* +* Source of bind mount (to s2d2). It should always be enforced when +* testing against files under the s1d41 or s1d42 disconnected directories. +*/ +const __u64 allowed_s1d2; +/* +* Original parent of s1d41. It should always be ignored when testing +* against files under the s1d41 disconnected directory. +*/ +const __u64 allowed_s1d31; +/* +* Original parent of s1d42. It should always be ignored when testing +* against files under the s1d42 disconnected directory. +*/ +const __u64 allowed_s1d32; +/* +* Opened and disconnected source directory. It should always be enforced +* when testing against files under the s1d41 disconnected directory. +*/ +const __u64 allowed_s1d41; +/* +* Opened and disconnected source directory. It should always be enforced +* when testing against files under the s1d42 disconnected directory. +*/ +const __u64 allowed_s1d42; +/* +* File in the s1d41 disconnected directory. It should always be enforced +* when testing against itself under the s1d41 disconnected directory. +*/ +const __u64 allowed_f1; +/* +* File in the s1d41 disconnected directory. It should always be enforced +* when testing against itself under the s1d41 disconnected directory. +*/ +const __u64 allowed_f2; +/* +* File in the s1d42 disconnected directory. It should always be enforced +* when testing against itself under the s1d42 disconnected directory. +*/ +const __u64 allowed_f3; +/* +* Parent of the bind mount destination. It should always be enforced when +* testing against files under the s1d41 or s1d42 disconnected directories. +*/ +const __u64 allowed_s2d1; +/* +* Directory covered by the bind mount. It should always be ignored when +* testing against files under the s1d41 or s1d42 disconnected directories. +*/ +const __u64 allowed_s2d2; +/* +* New parent of the renamed s1d41. It should always be ignored when +* testing against files under the s1d41 disconnected directory. +*/ +const __u64 allowed_s3d1; +/* +* New parent of the renamed s1d42. It should always be ignored when +* testing against files under the s1d42 disconnected directory. +*/ +const __u64 allowed_s4d1; + +/* Expected result of the call to open([fd:s1d41]/f1, O_RDONLY). */ +const int expected_read_result; +/* Expected result of the call to renameat([fd:s1d41]/f1, [fd:s1d42]/f1). */ +const int expected_rename_result; +/* +* Expected result of the call to renameat([fd:s1d41]/f2, [fd:s1d42]/f3, +* RENAME_EXCHANGE). +*/ +const int expected_exchange_result; +/* Expected result of the call to renameat([fd:s1d42]/f4, [fd:s1d42]/f5). */ +const int expected_same_dir_rename_result; +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(layout4_disconnected_leafs, s1d1_mount_src_parent) { +/* clang-format on */ + .allowed_s1d1 =LANDLOCK_ACCESS_FS_REFER | +LANDLOCK_ACCESS_FS_READ_FILE | +LANDLOCK_ACCESS_FS_EXECUTE | + LANDLOCK_ACCESS_FS_MAKE_REG, + .expected_read_result = EACCES, + .expected_same_dir_rename_result = EACCES, + .expected_rename_result = EACCES, + .expected_exchange_result =EACCES , +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(layout4_disconnected_leafs, s1d2_mount_src_refer) { +/* clang-format on */ + .allowed_s1d2 =LANDLOCK_ACCESS_FS_REFER |LANDLOCK_ACCESS_FS_READ_FILE , + .expected_read_result = 0, + .expected_same_dir_rename_result = EACCES, + .expected_rename_result = EACCES, + .expected_exchange_result = EACCES, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(layout4_disconnected_leafs, s1d2_mount_src_create) { +/* clang-format on */ + .allowed_s1d2 =LANDLOCK_ACCESS_FS_READ_FILE | + LANDLOCK_ACCESS_FS_MAKE_REG, + .expected_read_result = 0, + .expected_same_dir_rename_result = 0, + .expected_rename_result = EXDEV, + .expected_exchange_result =EXDEV , +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(layout4_disconnected_leafs, s1d2_mount_src_rename) { +/* clang-format on */ + .allowed_s1d2 =LANDLOCK_ACCESS_FS_REFER |LANDLOCK_ACCESS_FS_MAKE_REG , + .expected_read_result = EACCES, + .expected_same_dir_rename_result = 0, + .expected_rename_result = 0, + .expected_exchange_result = 0, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(layout4_disconnected_leafs, s1d31_s1d32_old_parent) { +/* clang-format on */ + .allowed_s1d31 =LANDLOCK_ACCESS_FS_REFER | +LANDLOCK_ACCESS_FS_READ_FILE | +LANDLOCK_ACCESS_FS_EXECUTE | + LANDLOCK_ACCESS_FS_MAKE_REG, + .allowed_s1d32 =LANDLOCK_ACCESS_FS_REFER | +LANDLOCK_ACCESS_FS_READ_FILE | +LANDLOCK_ACCESS_FS_EXECUTE | + LANDLOCK_ACCESS_FS_MAKE_REG, + .expected_read_result = EACCES, + .expected_same_dir_rename_result = EACCES, + .expected_rename_result = EACCES, + .expected_exchange_result =EACCES , +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(layout4_disconnected_leafs, s1d41_s1d42_disconnected_refer) { +/* clang-format on */ + .allowed_s1d41 =LANDLOCK_ACCESS_FS_REFER | +LANDLOCK_ACCESS_FS_READ_FILE , + .allowed_s1d42 = LANDLOCK_ACCESS_FS_REFER | +LANDLOCK_ACCESS_FS_READ_FILE , + .expected_read_result = 0, + .expected_same_dir_rename_result = EACCES, + .expected_rename_result = EACCES, + .expected_exchange_result = EACCES, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(layout4_disconnected_leafs, s1d41_s1d42_disconnected_create) { +/* clang-format on */ + .allowed_s1d41 =LANDLOCK_ACCESS_FS_READ_FILE | + LANDLOCK_ACCESS_FS_MAKE_REG, + .allowed_s1d42 =LANDLOCK_ACCESS_FS_READ_FILE | + LANDLOCK_ACCESS_FS_MAKE_REG, + .expected_read_result = 0, + .expected_same_dir_rename_result = 0, + .expected_rename_result = EXDEV, + .expected_exchange_result =EXDEV , +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(layout4_disconnected_leafs, s1d41_s1d42_disconnected_rename_even) { +/* clang-format on */ + .allowed_s1d41 =LANDLOCK_ACCESS_FS_REFER |LANDLOCK_ACCESS_FS_MAKE_REG , + .allowed_s1d42 = LANDLOCK_ACCESS_FS_REFER | LANDLOCK_ACCESS_FS_MAKE_REG, + .expected_read_result = EACCES, + .expected_same_dir_rename_result = 0, + .expected_rename_result = 0, + .expected_exchange_result = 0, +}; + +/* The destination directory has more access right. */ +/* clang-format off */ +FIXTURE_VARIANT_ADD(layout4_disconnected_leafs, s1d41_s1d42_disconnected_rename_more) { +/* clang-format on */ + .allowed_s1d41 = LANDLOCK_ACCESS_FS_REFER | LANDLOCK_ACCESS_FS_MAKE_REG, + .allowed_s1d42 =LANDLOCK_ACCESS_FS_REFER | +LANDLOCK_ACCESS_FS_MAKE_REG | + LANDLOCK_ACCESS_FS_EXECUTE, + .expected_read_result = EACCES, + .expected_same_dir_rename_result = 0, +/* Access denied. */ + .expected_rename_result = EXDEV, + .expected_exchange_result = EXDEV, +}; + +/* The destination directory has less access right. */ +/* clang-format off */ +FIXTURE_VARIANT_ADD(layout4_disconnected_leafs, s1d41_s1d42_disconnected_rename_less) { +/* clang-format on */ + .allowed_s1d41 =LANDLOCK_ACCESS_FS_REFER | +LANDLOCK_ACCESS_FS_MAKE_REG | + LANDLOCK_ACCESS_FS_EXECUTE, + .allowed_s1d42 = LANDLOCK_ACCESS_FS_REFER | LANDLOCK_ACCESS_FS_MAKE_REG, + .expected_read_result = EACCES, + .expected_same_dir_rename_result = 0, +/* Access allowed. */ + .expected_rename_result = 0, + .expected_exchange_result =EXDEV , +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(layout4_disconnected_leafs, s2d1_mount_dst_parent_create) { +/* clang-format on */ + .allowed_s2d1 =LANDLOCK_ACCESS_FS_READ_FILE | +LANDLOCK_ACCESS_FS_MAKE_REG , + .expected_read_result = 0, + .expected_same_dir_rename_result = 0, + .expected_rename_result = EXDEV, + .expected_exchange_result = EXDEV, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(layout4_disconnected_leafs, s2d1_mount_dst_parent_refer) { +/* clang-format on */ + .allowed_s2d1 = LANDLOCK_ACCESS_FS_REFER | LANDLOCK_ACCESS_FS_READ_FILE, + .expected_read_result = 0, + .expected_same_dir_rename_result = EACCES, + .expected_rename_result = EACCES, + .expected_exchange_result =EACCES , +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(layout4_disconnected_leafs, s2d1_mount_dst_parent_mini) { +/* clang-format on */ + .allowed_s2d1 =LANDLOCK_ACCESS_FS_REFER | +LANDLOCK_ACCESS_FS_READ_FILE | +LANDLOCK_ACCESS_FS_MAKE_REG , + .expected_read_result = 0, + .expected_same_dir_rename_result = 0, + .expected_rename_result = 0, + .expected_exchange_result = 0, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(layout4_disconnected_leafs, s2d2_covered_by_mount) { +/* clang-format on */ + .allowed_s2d2 =LANDLOCK_ACCESS_FS_REFER | +LANDLOCK_ACCESS_FS_READ_FILE | +LANDLOCK_ACCESS_FS_EXECUTE | + LANDLOCK_ACCESS_FS_MAKE_REG, + .expected_read_result = EACCES, + .expected_same_dir_rename_result = EACCES, + .expected_rename_result = EACCES, + .expected_exchange_result = EACCES, +}; + +/* Tests collect_domain_accesses(). */ +/* clang-format off */ +FIXTURE_VARIANT_ADD(layout4_disconnected_leafs, s3d1_s4d1_new_parent_refer) { +/* clang-format on */ + .allowed_s3d1 = LANDLOCK_ACCESS_FS_REFER | LANDLOCK_ACCESS_FS_READ_FILE, + .allowed_s4d1 = LANDLOCK_ACCESS_FS_REFER | LANDLOCK_ACCESS_FS_READ_FILE, + .expected_read_result = 0, + .expected_same_dir_rename_result = EACCES, + .expected_rename_result = EACCES, + .expected_exchange_result =EACCES , +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(layout4_disconnected_leafs, s3d1_s4d1_new_parent_create) { +/* clang-format on */ + .allowed_s3d1 =LANDLOCK_ACCESS_FS_READ_FILE | +LANDLOCK_ACCESS_FS_MAKE_REG , + .allowed_s4d1 = LANDLOCK_ACCESS_FS_READ_FILE | +LANDLOCK_ACCESS_FS_MAKE_REG , + .expected_read_result = 0, + .expected_same_dir_rename_result = 0, + .expected_rename_result = EXDEV, + .expected_exchange_result = EXDEV, +}; + +FIXTURE_VARIANT_ADD (layout4_disconnected_leafs, + s3d1_s4d1_disconnected_rename_even){ +/* clang-format on */ + .allowed_s3d1 =LANDLOCK_ACCESS_FS_REFER |LANDLOCK_ACCESS_FS_MAKE_REG , + .allowed_s4d1 = LANDLOCK_ACCESS_FS_REFER | LANDLOCK_ACCESS_FS_MAKE_REG, + .expected_read_result = EACCES, + .expected_same_dir_rename_result = 0, + .expected_rename_result = 0, + .expected_exchange_result = 0, +}; + +/* The destination directory has more access right. */ +/* clang-format off */ +FIXTURE_VARIANT_ADD(layout4_disconnected_leafs, s3d1_s4d1_disconnected_rename_more) { +/* clang-format on */ + .allowed_s3d1 = LANDLOCK_ACCESS_FS_REFER | LANDLOCK_ACCESS_FS_MAKE_REG, + .allowed_s4d1 =LANDLOCK_ACCESS_FS_REFER |LANDLOCK_ACCESS_FS_MAKE_REG | + LANDLOCK_ACCESS_FS_EXECUTE, + .expected_read_result = EACCES, + .expected_same_dir_rename_result = 0, +/* Access denied. */ + .expected_rename_result = EXDEV, + .expected_exchange_result = EXDEV, +}; + +/* The destination directory has less access right. */ +/* clang-format off */ +FIXTURE_VARIANT_ADD(layout4_disconnected_leafs, s3d1_s4d1_disconnected_rename_less) { +/* clang-format on */ + .allowed_s3d1 =LANDLOCK_ACCESS_FS_REFER |LANDLOCK_ACCESS_FS_MAKE_REG | + LANDLOCK_ACCESS_FS_EXECUTE, + .allowed_s4d1 = LANDLOCK_ACCESS_FS_REFER | LANDLOCK_ACCESS_FS_MAKE_REG, + .expected_read_result = EACCES, + .expected_same_dir_rename_result = 0, +/* Access allowed. */ + .expected_rename_result = 0, + .expected_exchange_result =EXDEV , +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(layout4_disconnected_leafs, f1_f2_f3) { +/* clang-format on */ + .allowed_f1 =LANDLOCK_ACCESS_FS_READ_FILE , + .allowed_f2 = LANDLOCK_ACCESS_FS_READ_FILE, + .allowed_f3 = LANDLOCK_ACCESS_FS_READ_FILE, + .expected_read_result = 0, + .expected_same_dir_rename_result = EACCES, + .expected_rename_result = EACCES, + .expected_exchange_result = EACCES, +}; + +TEST_F_FORK(layout4_disconnected_leafs, read_rename_exchange) +{ + const __u64 handled_access = +LANDLOCK_ACCESS_FS_REFER |LANDLOCK_ACCESS_FS_READ_FILE | +LANDLOCK_ACCESS_FS_EXECUTE |LANDLOCK_ACCESS_FS_MAKE_REG ; +const struct rule rules[] = { + { + .path =TMP_DIR "/s1d1" , + .access = variant->allowed_s1d1, + }, + { + .path =TMP_DIR "/s1d1/s1d2" , + .access = variant->allowed_s1d2, + }, + { + .path =TMP_DIR "/s1d1/s1d2/s1d31" , + .access = variant->allowed_s1d31, + }, + { + .path =TMP_DIR "/s1d1/s1d2/s1d32" , + .access = variant->allowed_s1d32, + }, + { + .path =TMP_DIR "/s1d1/s1d2/s1d31/s1d41" , + .access = variant->allowed_s1d41, + }, + { + .path =TMP_DIR "/s1d1/s1d2/s1d32/s1d42" , + .access = variant->allowed_s1d42, + }, + { + .path =TMP_DIR "/s1d1/s1d2/s1d31/s1d41/f1" , + .access = variant->allowed_f1, + }, + { + .path =TMP_DIR "/s1d1/s1d2/s1d31/s1d41/f2" , + .access = variant->allowed_f2, + }, + { + .path =TMP_DIR "/s1d1/s1d2/s1d32/s1d42/f3" , + .access = variant->allowed_f3, + }, + { + .path =TMP_DIR "/s2d1" , + .access = variant->allowed_s2d1, + }, +/* s2d2_fd */ + { + .path =TMP_DIR "/s3d1" , + .access = variant->allowed_s3d1, + }, + { + .path =TMP_DIR "/s4d1" , + .access = variant->allowed_s4d1, + }, + {}, + }; +int ruleset_fd, s1d41_bind_fd, s1d42_bind_fd; + + ruleset_fd =create_ruleset (_metadata, handled_access, rules); +ASSERT_LE (0 , ruleset_fd); + +/* Adds rule for the covered directory. */ +if (variant->allowed_s2d2) { +ASSERT_EQ (0 ,landlock_add_rule ( + ruleset_fd,LANDLOCK_RULE_PATH_BENEATH , + &(struct landlock_path_beneath_attr ){ + .parent_fd = self->s2d2_fd, + .allowed_access = + variant->allowed_s2d2, + }, +0 )); + } +EXPECT_EQ (0 ,close (self->s2d2_fd)); + + s1d41_bind_fd =open (TMP_DIR "/s2d1/s2d2/s1d31/s1d41" , +O_DIRECTORY |O_PATH |O_CLOEXEC ); +ASSERT_LE (0 , s1d41_bind_fd); + s1d42_bind_fd =open (TMP_DIR "/s2d1/s2d2/s1d32/s1d42" , +O_DIRECTORY |O_PATH |O_CLOEXEC ); +ASSERT_LE (0 , s1d42_bind_fd); + +/* Disconnects and checks source and destination directories. */ +EXPECT_EQ (0 ,test_open_rel (s1d41_bind_fd,".." ,O_DIRECTORY )); +EXPECT_EQ (0 ,test_open_rel (s1d42_bind_fd,".." ,O_DIRECTORY )); +/* Renames to make it accessible through s3d1/s1d41 */ +ASSERT_EQ (0 ,test_renameat (AT_FDCWD ,TMP_DIR "/s1d1/s1d2/s1d31/s1d41" , +AT_FDCWD ,TMP_DIR "/s3d1/s1d41" )); +/* Renames to make it accessible through s4d1/s1d42 */ +ASSERT_EQ (0 ,test_renameat (AT_FDCWD ,TMP_DIR "/s1d1/s1d2/s1d32/s1d42" , +AT_FDCWD ,TMP_DIR "/s4d1/s1d42" )); +EXPECT_EQ (ENOENT ,test_open_rel (s1d41_bind_fd,".." ,O_DIRECTORY )); +EXPECT_EQ (ENOENT ,test_open_rel (s1d42_bind_fd,".." ,O_DIRECTORY )); + +enforce_ruleset (_metadata, ruleset_fd); +EXPECT_EQ (0 ,close (ruleset_fd)); + +EXPECT_EQ (variant->expected_read_result, +test_open_rel (s1d41_bind_fd,"f1" ,O_RDONLY )); + +EXPECT_EQ (variant->expected_rename_result, +test_renameat (s1d41_bind_fd,"f1" , s1d42_bind_fd,"f1" )); +EXPECT_EQ (variant->expected_exchange_result, +test_exchangeat (s1d41_bind_fd,"f2" , s1d42_bind_fd,"f3" )); + +EXPECT_EQ (variant->expected_same_dir_rename_result, +test_renameat (s1d42_bind_fd,"f4" , s1d42_bind_fd,"f5" )); +} + +/* +* layout5_disconnected_branch before rename: +* +* tmp +* ├── s1d1 +* │ └── s1d2 [source of the first bind mount] +* │ └── s1d3 +* │ ├── s1d41 +* │ │ ├── f1 +* │ │ └── f2 +* │ └── s1d42 +* │ ├── f3 +* │ └── f4 +* ├── s2d1 +* │ └── s2d2 [source of the second bind mount] +* │ └── s2d3 +* │ └── s2d4 [first s1d2 bind mount] +* │ └── s1d3 +* │ ├── s1d41 +* │ │ ├── f1 +* │ │ └── f2 +* │ └── s1d42 +* │ ├── f3 +* │ └── f4 +* ├── s3d1 +* │ └── s3d2 [second s2d2 bind mount] +* │ └── s2d3 +* │ └── s2d4 [first s1d2 bind mount] +* │ └── s1d3 +* │ ├── s1d41 +* │ │ ├── f1 +* │ │ └── f2 +* │ └── s1d42 +* │ ├── f3 +* │ └── f4 +* └── s4d1 +* +* After rename: +* +* tmp +* ├── s1d1 +* │ └── s1d2 [source of the first bind mount] +* │ └── s1d3 +* │ ├── s1d41 +* │ │ ├── f1 +* │ │ └── f2 +* │ └── s1d42 +* │ ├── f3 +* │ └── f4 +* ├── s2d1 +* │ └── s2d2 [source of the second bind mount] +* ├── s3d1 +* │ └── s3d2 [second s2d2 bind mount] +* └── s4d1 +* └── s2d3 [renamed here] +* └── s2d4 [first s1d2 bind mount] +* └── s1d3 +* ├── s1d41 +* │ ├── f1 +* │ └── f2 +* └── s1d42 +* ├── f3 +* └── f4 +* +* Decision path for access from the s3d1/s3d2/s2d3/s2d4/s1d3 file descriptor: +* 1. first bind mount: s1d3 -> s1d2 +* 2. second bind mount: s2d3 +* 3. tmp mount: s4d1 -> tmp [disconnected branch] +* 4. second bind mount: s2d2 +* 5. tmp mount: s3d1 -> tmp +* 6. parent mounts: [...] -> / +* +* The s4d1 directory is evaluated even if it is not in the s2d2 mount. +*/ + +/* clang-format off */ +FIXTURE (layout5_disconnected_branch) { +int s2d4_fd, s3d2_fd; +}; +/* clang-format on */ + +FIXTURE_SETUP (layout5_disconnected_branch) +{ +prepare_layout (_metadata); + +create_file (_metadata,TMP_DIR "/s1d1/s1d2/s1d3/s1d41/f1" ); +create_file (_metadata,TMP_DIR "/s1d1/s1d2/s1d3/s1d41/f2" ); +create_file (_metadata,TMP_DIR "/s1d1/s1d2/s1d3/s1d42/f3" ); +create_file (_metadata,TMP_DIR "/s1d1/s1d2/s1d3/s1d42/f4" ); +create_directory (_metadata,TMP_DIR "/s2d1/s2d2/s2d3/s2d4" ); +create_directory (_metadata,TMP_DIR "/s3d1/s3d2" ); +create_directory (_metadata,TMP_DIR "/s4d1" ); + + self->s2d4_fd =open (TMP_DIR "/s2d1/s2d2/s2d3/s2d4" , +O_DIRECTORY |O_PATH |O_CLOEXEC ); +ASSERT_LE (0 , self->s2d4_fd); + + self->s3d2_fd = +open (TMP_DIR "/s3d1/s3d2" ,O_DIRECTORY |O_PATH |O_CLOEXEC ); +ASSERT_LE (0 , self->s3d2_fd); + +set_cap (_metadata,CAP_SYS_ADMIN ); +ASSERT_EQ (0 ,mount (TMP_DIR "/s1d1/s1d2" ,TMP_DIR "/s2d1/s2d2/s2d3/s2d4" , +NULL ,MS_BIND ,NULL )); +ASSERT_EQ (0 ,mount (TMP_DIR "/s2d1/s2d2" ,TMP_DIR "/s3d1/s3d2" ,NULL , +MS_BIND |MS_REC ,NULL )); +clear_cap (_metadata,CAP_SYS_ADMIN ); +} + +FIXTURE_TEARDOWN_PARENT (layout5_disconnected_branch) +{ +/* Bind mounts are handled by namespace lifetime. */ + +/* Removes files after renames. */ +remove_path (TMP_DIR "/s1d1/s1d2/s1d3/s1d41/f1" ); +remove_path (TMP_DIR "/s1d1/s1d2/s1d3/s1d41/f2" ); +remove_path (TMP_DIR "/s1d1/s1d2/s1d3/s1d42/f1" ); +remove_path (TMP_DIR "/s1d1/s1d2/s1d3/s1d42/f3" ); +remove_path (TMP_DIR "/s1d1/s1d2/s1d3/s1d42/f4" ); +remove_path (TMP_DIR "/s1d1/s1d2/s1d3/s1d42/f5" ); + +cleanup_layout (_metadata); +} + +FIXTURE_VARIANT (layout5_disconnected_branch) +{ +/* +* Parent of all files. It should always be enforced when testing against +* files under the s1d41 or s1d42 disconnected directories. +*/ +const __u64 allowed_base; +/* +* Parent of the first bind mount source. It should always be ignored when +* testing against files under the s1d41 or s1d42 disconnected directories. +*/ +const __u64 allowed_s1d1; +const __u64 allowed_s1d2; +const __u64 allowed_s1d3; +const __u64 allowed_s2d1; +const __u64 allowed_s2d2; +const __u64 allowed_s2d3; +const __u64 allowed_s2d4; +const __u64 allowed_s3d1; +const __u64 allowed_s3d2; +const __u64 allowed_s4d1; + +/* Expected result of the call to open([fd:s1d3]/s1d41/f1, O_RDONLY). */ +const int expected_read_result; +/* +* Expected result of the call to renameat([fd:s1d3]/s1d41/f1, +* [fd:s1d3]/s1d42/f1). +*/ +const int expected_rename_result; +/* +* Expected result of the call to renameat([fd:s1d3]/s1d41/f2, +* [fd:s1d3]/s1d42/f3, RENAME_EXCHANGE). +*/ +const int expected_exchange_result; +/* +* Expected result of the call to renameat([fd:s1d3]/s1d42/f4, +* [fd:s1d3]/s1d42/f5). +*/ +const int expected_same_dir_rename_result; +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(layout5_disconnected_branch, s1d1_mount1_src_parent) { +/* clang-format on */ + .allowed_s1d1 =LANDLOCK_ACCESS_FS_REFER | +LANDLOCK_ACCESS_FS_READ_FILE | +LANDLOCK_ACCESS_FS_EXECUTE | + LANDLOCK_ACCESS_FS_MAKE_REG, + .expected_read_result = EACCES, + .expected_same_dir_rename_result = EACCES, + .expected_rename_result = EACCES, + .expected_exchange_result = EACCES, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(layout5_disconnected_branch, s1d2_mount1_src_refer) { +/* clang-format on */ + .allowed_s1d2 = LANDLOCK_ACCESS_FS_REFER | LANDLOCK_ACCESS_FS_READ_FILE, + .expected_read_result = 0, + .expected_same_dir_rename_result = EACCES, + .expected_rename_result = EACCES, + .expected_exchange_result = EACCES, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(layout5_disconnected_branch, s1d2_mount1_src_create) { +/* clang-format on */ + .allowed_s1d2 =LANDLOCK_ACCESS_FS_READ_FILE | + LANDLOCK_ACCESS_FS_MAKE_REG, + .expected_read_result = 0, + .expected_same_dir_rename_result = 0, + .expected_rename_result = EXDEV, + .expected_exchange_result = EXDEV, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(layout5_disconnected_branch, s1d2_mount1_src_rename) { +/* clang-format on */ + .allowed_s1d2 = LANDLOCK_ACCESS_FS_REFER | LANDLOCK_ACCESS_FS_MAKE_REG, + .expected_read_result = EACCES, + .expected_same_dir_rename_result = 0, + .expected_rename_result = 0, + .expected_exchange_result = 0, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(layout5_disconnected_branch, s1d3_fd_refer) { +/* clang-format on */ + .allowed_s1d3 = LANDLOCK_ACCESS_FS_REFER | LANDLOCK_ACCESS_FS_READ_FILE, + .expected_read_result = 0, + .expected_same_dir_rename_result = EACCES, + .expected_rename_result = EACCES, + .expected_exchange_result = EACCES, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(layout5_disconnected_branch, s1d3_fd_create) { +/* clang-format on */ + .allowed_s1d3 =LANDLOCK_ACCESS_FS_READ_FILE | + LANDLOCK_ACCESS_FS_MAKE_REG, + .expected_read_result = 0, + .expected_same_dir_rename_result = 0, + .expected_rename_result = EXDEV, + .expected_exchange_result = EXDEV, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(layout5_disconnected_branch, s1d3_fd_rename) { +/* clang-format on */ + .allowed_s1d3 = LANDLOCK_ACCESS_FS_REFER | LANDLOCK_ACCESS_FS_MAKE_REG, + .expected_read_result = EACCES, + .expected_same_dir_rename_result = 0, + .expected_rename_result = 0, + .expected_exchange_result = 0, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(layout5_disconnected_branch, s1d3_fd_full) { +/* clang-format on */ + .allowed_s1d3 =LANDLOCK_ACCESS_FS_REFER | +LANDLOCK_ACCESS_FS_READ_FILE | +LANDLOCK_ACCESS_FS_EXECUTE | + LANDLOCK_ACCESS_FS_MAKE_REG, + .expected_read_result = 0, + .expected_same_dir_rename_result = 0, + .expected_rename_result = 0, + .expected_exchange_result = 0, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(layout5_disconnected_branch, s2d1_mount2_src_parent) { +/* clang-format on */ + .allowed_s2d1 =LANDLOCK_ACCESS_FS_REFER | +LANDLOCK_ACCESS_FS_READ_FILE | +LANDLOCK_ACCESS_FS_EXECUTE | + LANDLOCK_ACCESS_FS_MAKE_REG, + .expected_read_result = EACCES, + .expected_same_dir_rename_result = EACCES, + .expected_rename_result = EACCES, + .expected_exchange_result = EACCES, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(layout5_disconnected_branch, s2d2_mount2_src_refer) { +/* clang-format on */ + .allowed_s2d2 = LANDLOCK_ACCESS_FS_REFER | LANDLOCK_ACCESS_FS_READ_FILE, + .expected_read_result = 0, + .expected_same_dir_rename_result = EACCES, + .expected_rename_result = EACCES, + .expected_exchange_result = EACCES, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(layout5_disconnected_branch, s2d2_mount2_src_create) { +/* clang-format on */ + .allowed_s2d2 =LANDLOCK_ACCESS_FS_READ_FILE | + LANDLOCK_ACCESS_FS_MAKE_REG, + .expected_read_result = 0, + .expected_same_dir_rename_result = 0, + .expected_rename_result = EXDEV, + .expected_exchange_result = EXDEV, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(layout5_disconnected_branch, s2d2_mount2_src_rename) { +/* clang-format on */ + .allowed_s2d2 = LANDLOCK_ACCESS_FS_REFER | LANDLOCK_ACCESS_FS_MAKE_REG, + .expected_read_result = EACCES, + .expected_same_dir_rename_result = 0, + .expected_rename_result = 0, + .expected_exchange_result = 0, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(layout5_disconnected_branch, s2d3_mount1_dst_parent_refer) { +/* clang-format on */ + .allowed_s2d3 = LANDLOCK_ACCESS_FS_REFER | LANDLOCK_ACCESS_FS_READ_FILE, + .expected_read_result = 0, + .expected_same_dir_rename_result = EACCES, + .expected_rename_result = EACCES, + .expected_exchange_result = EACCES, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(layout5_disconnected_branch, s2d3_mount1_dst_parent_create) { +/* clang-format on */ + .allowed_s2d3 =LANDLOCK_ACCESS_FS_READ_FILE | + LANDLOCK_ACCESS_FS_MAKE_REG, + .expected_read_result = 0, + .expected_same_dir_rename_result = 0, + .expected_rename_result = EXDEV, + .expected_exchange_result = EXDEV, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(layout5_disconnected_branch, s2d3_mount1_dst_parent_rename) { +/* clang-format on */ + .allowed_s2d3 = LANDLOCK_ACCESS_FS_REFER | LANDLOCK_ACCESS_FS_MAKE_REG, + .expected_read_result = EACCES, + .expected_same_dir_rename_result = 0, + .expected_rename_result = 0, + .expected_exchange_result = 0, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(layout5_disconnected_branch, s2d4_mount1_dst) { +/* clang-format on */ + .allowed_s2d4 =LANDLOCK_ACCESS_FS_REFER | +LANDLOCK_ACCESS_FS_READ_FILE | +LANDLOCK_ACCESS_FS_EXECUTE | + LANDLOCK_ACCESS_FS_MAKE_REG, + .expected_read_result = EACCES, + .expected_same_dir_rename_result = EACCES, + .expected_rename_result = EACCES, + .expected_exchange_result = EACCES, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(layout5_disconnected_branch, s3d1_mount2_dst_parent_refer) { +/* clang-format on */ + .allowed_s3d1 = LANDLOCK_ACCESS_FS_REFER | LANDLOCK_ACCESS_FS_READ_FILE, + .expected_read_result = 0, + .expected_same_dir_rename_result = EACCES, + .expected_rename_result = EACCES, + .expected_exchange_result = EACCES, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(layout5_disconnected_branch, s3d1_mount2_dst_parent_create) { +/* clang-format on */ + .allowed_s3d1 =LANDLOCK_ACCESS_FS_READ_FILE | + LANDLOCK_ACCESS_FS_MAKE_REG, + .expected_read_result = 0, + .expected_same_dir_rename_result = 0, + .expected_rename_result = EXDEV, + .expected_exchange_result = EXDEV, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(layout5_disconnected_branch, s3d1_mount2_dst_parent_rename) { +/* clang-format on */ + .allowed_s3d1 = LANDLOCK_ACCESS_FS_REFER | LANDLOCK_ACCESS_FS_MAKE_REG, + .expected_read_result = EACCES, + .expected_same_dir_rename_result = 0, + .expected_rename_result = 0, + .expected_exchange_result = 0, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(layout5_disconnected_branch, s3d2_mount1_dst) { +/* clang-format on */ + .allowed_s3d2 =LANDLOCK_ACCESS_FS_REFER | +LANDLOCK_ACCESS_FS_READ_FILE | +LANDLOCK_ACCESS_FS_EXECUTE | + LANDLOCK_ACCESS_FS_MAKE_REG, + .expected_read_result = EACCES, + .expected_same_dir_rename_result = EACCES, + .expected_rename_result = EACCES, + .expected_exchange_result = EACCES, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(layout5_disconnected_branch, s4d1_rename_parent_refer) { +/* clang-format on */ + .allowed_s4d1 = LANDLOCK_ACCESS_FS_REFER | LANDLOCK_ACCESS_FS_READ_FILE, + .expected_read_result = 0, + .expected_same_dir_rename_result = EACCES, + .expected_rename_result = EACCES, + .expected_exchange_result = EACCES, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(layout5_disconnected_branch, s4d1_rename_parent_create) { +/* clang-format on */ + .allowed_s4d1 =LANDLOCK_ACCESS_FS_READ_FILE | + LANDLOCK_ACCESS_FS_MAKE_REG, + .expected_read_result = 0, + .expected_same_dir_rename_result = 0, + .expected_rename_result = EXDEV, + .expected_exchange_result = EXDEV, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(layout5_disconnected_branch, s4d1_rename_parent_rename) { +/* clang-format on */ + .allowed_s4d1 = LANDLOCK_ACCESS_FS_REFER | LANDLOCK_ACCESS_FS_MAKE_REG, + .expected_read_result = EACCES, + .expected_same_dir_rename_result = 0, + .expected_rename_result = 0, + .expected_exchange_result = 0, +}; + +TEST_F_FORK(layout5_disconnected_branch, read_rename_exchange) +{ +const __u64 handled_access = +LANDLOCK_ACCESS_FS_REFER |LANDLOCK_ACCESS_FS_READ_FILE | +LANDLOCK_ACCESS_FS_EXECUTE |LANDLOCK_ACCESS_FS_MAKE_REG ; +const struct rule rules[] = { + { + .path =TMP_DIR "/s1d1" , + .access = variant->allowed_s1d1, + }, + { + .path =TMP_DIR "/s1d1/s1d2" , + .access = variant->allowed_s1d2, + }, + { + .path =TMP_DIR "/s1d1/s1d2/s1d3" , + .access = variant->allowed_s1d3, + }, + { + .path =TMP_DIR "/s2d1" , + .access = variant->allowed_s2d1, + }, + { + .path =TMP_DIR "/s2d1/s2d2" , + .access = variant->allowed_s2d2, + }, + { + .path =TMP_DIR "/s2d1/s2d2/s2d3" , + .access = variant->allowed_s2d3, + }, +/* s2d4_fd */ + { + .path =TMP_DIR "/s3d1" , + .access = variant->allowed_s3d1, + }, +/* s3d2_fd */ + { + .path =TMP_DIR "/s4d1" , + .access = variant->allowed_s4d1, + }, + {}, + }; +int ruleset_fd, s1d3_bind_fd; + + ruleset_fd =create_ruleset (_metadata, handled_access, rules); +ASSERT_LE (0 , ruleset_fd); + +/* Adds rules for the covered directories. */ +if (variant->allowed_s2d4) { +ASSERT_EQ (0 ,landlock_add_rule ( + ruleset_fd,LANDLOCK_RULE_PATH_BENEATH , + &(struct landlock_path_beneath_attr ){ + .parent_fd = self->s2d4_fd, + .allowed_access = + variant->allowed_s2d4, + }, +0 )); + } +EXPECT_EQ (0 ,close (self->s2d4_fd)); + +if (variant->allowed_s3d2) { +ASSERT_EQ (0 ,landlock_add_rule ( + ruleset_fd,LANDLOCK_RULE_PATH_BENEATH , + &(struct landlock_path_beneath_attr ){ + .parent_fd = self->s3d2_fd, + .allowed_access = + variant->allowed_s3d2, + }, +0 )); + } +EXPECT_EQ (0 ,close (self->s3d2_fd)); + + s1d3_bind_fd =open (TMP_DIR "/s3d1/s3d2/s2d3/s2d4/s1d3" , +O_DIRECTORY |O_PATH |O_CLOEXEC ); +ASSERT_LE (0 , s1d3_bind_fd); + +/* Disconnects and checks source and destination directories. */ +EXPECT_EQ (0 ,test_open_rel (s1d3_bind_fd,".." ,O_DIRECTORY )); +EXPECT_EQ (0 ,test_open_rel (s1d3_bind_fd,"../.." ,O_DIRECTORY )); +/* Renames to make it accessible through s3d1/s1d41 */ +ASSERT_EQ (0 ,test_renameat (AT_FDCWD ,TMP_DIR "/s2d1/s2d2/s2d3" , +AT_FDCWD ,TMP_DIR "/s4d1/s2d3" )); +EXPECT_EQ (0 ,test_open_rel (s1d3_bind_fd,".." ,O_DIRECTORY )); +EXPECT_EQ (ENOENT ,test_open_rel (s1d3_bind_fd,"../.." ,O_DIRECTORY )); + +enforce_ruleset (_metadata, ruleset_fd); +EXPECT_EQ (0 ,close (ruleset_fd)); + +EXPECT_EQ (variant->expected_read_result, +test_open_rel (s1d3_bind_fd,"s1d41/f1" ,O_RDONLY )); + +EXPECT_EQ (variant->expected_rename_result, +test_renameat (s1d3_bind_fd,"s1d41/f1" , s1d3_bind_fd, +"s1d42/f1" )); +EXPECT_EQ (variant->expected_exchange_result, +test_exchangeat (s1d3_bind_fd,"s1d41/f2" , s1d3_bind_fd, +"s1d42/f3" )); + +EXPECT_EQ (variant->expected_same_dir_rename_result, +test_renameat (s1d3_bind_fd,"s1d42/f4" , s1d3_bind_fd, +"s1d42/f5" )); +} +#define LOWER_BASE TMP_DIR "/lower"#define LOWER_DATA LOWER_BASE "/data"static const char lower_fl1[] =LOWER_DATA "/fl1" ;
Greg Kroah-Hartman
maintainerPATCH 492/614 net: phy: aquantia: check for NVMEM deferral
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Robert Marko <[email protected]>
[ Upstream commit a6c121a2432eee2c4ebceb1483ccd4a50a52983d ]
Currently, if NVMEM provider is probed later than Aquantia, loading the firmware will fail with -EINVAL.
To fix this, simply check for -EPROBE_DEFER when NVMEM is attempted and return it.
--- drivers/net/phy/aquantia/aquantia_firmware.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/phy/aquantia/aquantia_firmware.c +1 -1
@@ -369,7 +369,7 @@ int aqr_firmware_load(struct phy_device *phydev)* assume that, and load a new image. */ ret =aqr_firmware_load_nvmem (phydev); -if (!ret) +if (ret == -EPROBE_DEFER || !ret)return ret; ret =aqr_firmware_load_fs (phydev);
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 493/614 selftests: bonding: add delay before each xvlan_over_bond connectivity check
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hangbin Liu <[email protected]>
[ Upstream commit 2c28ee720ad14f58eb88a97ec3efe7c5c315ea5d ]
Jakub reported increased flakiness in bond_macvlan_ipvlan.sh on regular kernel, while the tests consistently pass on a debug kernel. This suggests a timing-sensitive issue.
To mitigate this, introduce a short sleep before each xvlan_over_bond connectivity check. The delay helps ensure neighbor and route cache have fully converged before verifying connectivity.
The sleep interval is kept minimal since check_connection() is invoked nearly 100 times during the test.
--- .../testing/selftests/drivers/net/bonding/bond_macvlan_ipvlan.sh | 1 + 1 file changed, 1 insertion(+)
tools/testing/selftests/drivers/net/bonding/bond_macvlan_ipvlan.sh +1 -0
@@ -30,6 +30,7 @@ check_connection() local message=${3} RET=0 + sleep 0.25 ip netns exec ${ns} ping ${target} -c 4 -i 0.1 &>/dev/null check_err $? "ping failed" log_test "${bond_mode}/${xvlan_type}_${xvlan_mode}: ${message}"
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 494/614 net: netpoll: initialize work queue before error checks
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Breno Leitao <[email protected]>
[ Upstream commit e5235eb6cfe02a51256013a78f7b28779a7740d5 ]
Prevent a kernel warning when netconsole setup fails on devices with IFF_DISABLE_NETPOLL flag. The warning (at kernel/workqueue.c:4242 in __flush_work) occurs because the cleanup path tries to cancel an uninitialized work queue.
When __netpoll_setup() encounters a device with IFF_DISABLE_NETPOLL, it fails early and calls skb_pool_flush() for cleanup. This function calls cancel_work_sync(&np->refill_wq), but refill_wq hasn't been initialized yet, triggering the warning.
Move INIT_WORK() to the beginning of __netpoll_setup(), ensuring the work queue is properly initialized before any potential failure points. This allows the cleanup path to safely cancel the work queue regardless of where the setup fails.
--- net/core/netpoll.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/core/netpoll.c +1 -1
@@ -554,6 +554,7 @@ int __netpoll_setup(struct netpoll *np, struct net_device *ndev)int err;skb_queue_head_init (&np->skb_pool); +INIT_WORK (&np->refill_wq, refill_skbs_work_handler);if (ndev->priv_flags &IFF_DISABLE_NETPOLL ) { np_err(np, "%s doesn't support polling, aborting\n",
@@ -591,7 +592,6 @@ int __netpoll_setup(struct netpoll *np, struct net_device *ndev)/* fill up the skb queue */ refill_skbs (np); -INIT_WORK (&np->refill_wq, refill_skbs_work_handler);/* last thing to do is link it to the net device structure */ rcu_assign_pointer (ndev->npinfo, npinfo);
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 495/614 mtd: lpddr_cmds: fix signed shifts in lpddr_cmds
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ivan Stepchenko <[email protected]>
[ Upstream commit c909fec69f84b39e63876c69b9df2c178c6b76ba ]
There are several places where a value of type 'int' is shifted by lpddr->chipshift. lpddr->chipshift is derived from QINFO geometry and might reach 31 when QINFO reports a 2 GiB size - the maximum supported by LPDDR(1) compliant chips. This may cause unexpected sign-extensions when casting the integer value to the type of 'unsigned long'.
Use '1UL << lpddr->chipshift' and cast 'j' to unsigned long before shifting so the computation is performed at the destination width.
Found by Linux Verification Center (linuxtesting.org) with SVACE.
--- drivers/mtd/lpddr/lpddr_cmds.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/mtd/lpddr/lpddr_cmds.c +4 -4
@@ -79,7 +79,7 @@ struct mtd_info *lpddr_cmdset(struct map_info *map)mutex_init (&shared[i].lock);for (j =0 ; j < lpddr->qinfo->HWPartsNum; j++) { *chip = lpddr->chips[i]; - chip->start += j << lpddr->chipshift; + chip->start += (unsigned long )j << lpddr->chipshift; chip->oldstate = chip->state =FL_READY ; chip->priv = &shared[i];/* those should be reset too since
@@ -559,7 +559,7 @@ static int lpddr_point(struct mtd_info *mtd, loff_t adr, size_t len,break ;if ((len + ofs -1 ) >> lpddr->chipshift) - thislen = (1 <<lpddr->chipshift) - ofs; + thislen = (1UL << lpddr->chipshift) - ofs;else thislen = len;/* get the chip */
@@ -575,7 +575,7 @@ static int lpddr_point(struct mtd_info *mtd, loff_t adr, size_t len, len -= thislen; ofs =0 ; - last_end +=1 << lpddr->chipshift; + last_end +=1UL << lpddr->chipshift; chipnum++; chip = &lpddr->chips[chipnum]; }
@@ -601,7 +601,7 @@ static int lpddr_unpoint (struct mtd_info *mtd, loff_t adr, size_t len)break ;if ((len + ofs -1 ) >> lpddr->chipshift) - thislen = (1 <<lpddr->chipshift) - ofs; + thislen = (1UL << lpddr->chipshift) - ofs;else thislen = len;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 496/614 rqspinlock: Enclose lock/unlock within lock entry acquisitions
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kumar Kartikeya Dwivedi <[email protected]>
[ Upstream commit beb7021a6003d9c6a463fffca0d6311efb8e0e66 ]
Ritesh reported that timeouts occurred frequently for rqspinlock despite reentrancy on the same lock on the same CPU in [0]. This patch closes one of the races leading to this behavior, and reduces the frequency of timeouts.
We currently have a tiny window between the fast-path cmpxchg and the grabbing of the lock entry where an NMI could land, attempt the same lock that was just acquired, and end up timing out. This is not ideal. Instead, move the lock entry acquisition from the fast path to before the cmpxchg, and remove the grabbing of the lock entry in the slow path, assuming it was already taken by the fast path. The TAS fallback is invoked directly without being preceded by the typical fast path, therefore we must continue to grab the deadlock detection entry in that case.
Case on lock leading to missed AA:
cmpxchg lock A
<NMI> ... rqspinlock acquisition of A ... timeout </NMI>
grab_held_lock_entry(A)
There is a similar case when unlocking the lock. If the NMI lands between the WRITE_ONCE and smp_store_release, it is possible that we end up in a situation where the NMI fails to diagnose the AA condition, leading to a timeout.
Case on unlock leading to missed AA:
WRITE_ONCE(rqh->locks[rqh->cnt - 1], NULL)
<NMI> ... rqspinlock acquisition of A ... timeout </NMI>
smp_store_release(A->locked, 0)
The patch changes the order on unlock to smp_store_release() succeeded by WRITE_ONCE() of NULL. This avoids the missed AA detection described above, but may lead to a false positive if the NMI lands between these two statements, which is acceptable (and preferred over a timeout).
The original intention of the reverse order on unlock was to prevent the following possible misdiagnosis of an ABBA scenario:
grab entry A
lock A
grab entry B
lock B
unlock B
smp_store_release(B->locked, 0)
grab entry B lock B grab entry A lock A ! <detect ABBA>
WRITE_ONCE(rqh->locks[rqh->cnt - 1], NULL)
If the store release were is after the WRITE_ONCE, the other CPU would not observe B in the table of the CPU unlocking the lock B. However, since the threads are obviously participating in an ABBA deadlock, it is no longer appealing to use the order above since it may lead to a 250 ms timeout due to missed AA detection.
[0]: https://lore.kernel.org/bpf/CAH6OuBTjG+N=+GGwcpOUbeDN563oz4iVcU3rbse68egp9wj9_A@mail.gmail.com
--- include/asm-generic/rqspinlock.h | 60 +++++++++++++++++--------------- kernel/bpf/rqspinlock.c | 15 ++++---- 2 files changed, 38 insertions(+), 37 deletions(-)
include/asm-generic/rqspinlock.h +32 -28
@@ -129,8 +129,8 @@ static __always_inline void release_held_lock_entry(void)* <error> for lock B * release_held_lock_entry * -* try_cmpxchg_acquire for lock A * grab_held_lock_entry +* try_cmpxchg_acquire for lock A * * Lack of any ordering means reordering may occur such that dec, inc * are done before entry is overwritten. This permits a remote lock
@@ -139,13 +139,8 @@ static __always_inline void release_held_lock_entry(void)* CPU holds a lock it is attempting to acquire, leading to false ABBA * diagnosis). * -* In case of unlock, we will always do a release on the lock word after -* releasing the entry, ensuring that other CPUs cannot hold the lock -* (and make conclusions about deadlocks) until the entry has been -* cleared on the local CPU, preventing any anomalies. Reordering is -* still possible there, but a remote CPU cannot observe a lock in our -* table which it is already holding, since visibility entails our -* release store for the said lock has not retired. +* The case of unlock is treated differently due to NMI reentrancy, see +* comments in res_spin_unlock. * * In theory we don't have a problem if the dec and WRITE_ONCE above get * reordered with each other, we either notice an empty NULL entry on
@@ -175,10 +170,22 @@ static __always_inline int res_spin_lock(rqspinlock_t *lock) {int val =0 ; -if (likely (atomic_try_cmpxchg_acquire (&lock->val, &val, _Q_LOCKED_VAL))) { -grab_held_lock_entry (lock); +/* +* Grab the deadlock detection entry before doing the cmpxchg, so that +* reentrancy due to NMIs between the succeeding cmpxchg and creation of +* held lock entry can correctly detect an acquisition attempt in the +* interrupted context. +* +* cmpxchg lock A +* <NMI> +* res_spin_lock(A) --> missed AA, leads to timeout +* </NMI> +* grab_held_lock_entry(A) +*/ +grab_held_lock_entry (lock); + +if (likely (atomic_try_cmpxchg_acquire (&lock->val, &val, _Q_LOCKED_VAL)))return 0 ; - }return resilient_queued_spin_lock_slowpath (lock, val); }
@@ -192,28 +199,25 @@ static __always_inline void res_spin_unlock(rqspinlock_t *lock) {struct rqspinlock_held *rqh =this_cpu_ptr (&rqspinlock_held_locks); -if (unlikely (rqh->cnt >RES_NR_HELD )) - goto unlock; -WRITE_ONCE (rqh->locks[rqh->cnt -1 ],NULL ); -unlock:/* -* Release barrier, ensures correct ordering. See release_held_lock_entry -* for details. Perform release store instead of queued_spin_unlock, -* since we use this function for test-and-set fallback as well. When we -* have CONFIG_QUEUED_SPINLOCKS=n, we clear the full 4-byte lockword. +* Release barrier, ensures correct ordering. Perform release store +* instead of queued_spin_unlock, since we use this function for the TAS +* fallback as well. When we have CONFIG_QUEUED_SPINLOCKS=n, we clear +* the full 4-byte lockword. * -* Like release_held_lock_entry, we can do the release before the dec. -* We simply care about not seeing the 'lock' in our table from a remote -* CPU once the lock has been released, which doesn't rely on the dec. +* Perform the smp_store_release before clearing the lock entry so that +* NMIs landing in the unlock path can correctly detect AA issues. The +* opposite order shown below may lead to missed AA checks: * -* Unlike smp_wmb(), release is not a two way fence, hence it is -* possible for a inc to move up and reorder with our clearing of the -* entry. This isn't a problem however, as for a misdiagnosis of ABBA, -* the remote CPU needs to hold this lock, which won't be released until -* the store below is done, which would ensure the entry is overwritten -* to NULL, etc. +* WRITE_ONCE(rqh->locks[rqh->cnt - 1], NULL) +* <NMI> +* res_spin_lock(A) --> missed AA, leads to timeout +* </NMI> +* smp_store_release(A->locked, 0) */ smp_store_release (&lock->locked,0 ); +if (likely (rqh->cnt <=RES_NR_HELD )) +WRITE_ONCE (rqh->locks[rqh->cnt -1 ],NULL );this_cpu_dec (rqspinlock_held_locks.cnt); }
kernel/bpf/rqspinlock.c +6 -9
@@ -275,6 +275,10 @@ int __lockfunc resilient_tas_spin_lock(rqspinlock_t *lock)int val, ret =0 ;RES_INIT_TIMEOUT (ts); +/* +* The fast path is not invoked for the TAS fallback, so we must grab +* the deadlock detection entry here. +*/ grab_held_lock_entry (lock);/*
@@ -397,10 +401,7 @@ int __lockfunc resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val) goto queue; } -/* -* Grab an entry in the held locks array, to enable deadlock detection. -*/ -grab_held_lock_entry (lock); +/* Deadlock detection entry already held after failing fast path. */ /* * We're pending, wait for the owner to go away.
@@ -448,11 +449,7 @@ int __lockfunc resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val)*/ queue:lockevent_inc (lock_slowpath); -/* -* Grab deadlock detection entry for the queue path. -*/ -grab_held_lock_entry (lock); - +/* Deadlock detection entry already held after failing fast path. */ node =this_cpu_ptr (&rqnodes[0 ].mcs); idx = node->count++; tail =encode_tail (smp_processor_id (), idx);
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 497/614 rqspinlock: Use trylock fallback when per-CPU rqnode is busy
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kumar Kartikeya Dwivedi <[email protected]>
[ Upstream commit 81d5a6a438595e46be191d602e5c2d6d73992fdc ]
In addition to deferring to the trylock fallback in NMIs, only do so when an rqspinlock waiter is queued on the current CPU. This is detected by noticing a non-zero node index. This allows NMI waiters to join the waiter queue if it isn't interrupting an existing rqspinlock waiter, and increase the chances of fairly obtaining the lock, performing deadlock detection as the head, and not being starved while attempting the trylock.
The trylock path in particular is unlikely to succeed under contention, as it relies on the lock word becoming 0, which indicates no contention. This means that the most likely result for NMIs attempting a trylock is a timeout under contention if they don't hit an AA or ABBA case.
The core problem being addressed through the fixed commit was removing the dependency edge between an NMI queue waiter and the queue waiter it is interrupting. Whenever a circular dependency forms, and with no way to break it (as non-head waiters don't poll for deadlocks or timeouts), we would enter into a deadlock. A trylock either breaks such an edge by probing for deadlocks, and finally terminating the waiting loop using a timeout.
By excluding queueing on CPUs where the node index is non-zero for NMIs, this sort of dependency is broken. The CPU enters the trylock path for those cases, and falls back to deadlock checks and timeouts. However, in other case where it doesn't interrupt the CPU in the slow path while its queued on the lock, it can join the queue as a normal waiter, and avoid trylock associated starvation and subsequent timeouts.
There are a few remaining cases here that matter: the NMI can still preempt the owner in its critical section, and if it queues as a non-head waiter, it can end up impeding the progress of the owner. While this won't deadlock, since the head waiter will eventually signal the NMI waiter to either stop (due to a timeout), it can still lead to long timeouts. These gaps will be addressed in subsequent commits.
Note that while the node count detection approach is less conservative than simply deferring NMIs to trylock, it is going to return errors where attempts to lock B in NMI happen while waiters for lock A are in a lower context on the same CPU. However, this only occurs when the lower context is queued in the slow path, and the NMI attempt can proceed without failure in all other cases. To continue to prevent AA deadlocks (or ABBA in a similar NMI interrupting lower context pattern), we'd need a more fleshed out algorithm to unlink NMI waiters after they queue and detect such cases. However, all that complexity isn't appealing yet to reduce the failure rate in the small window inside the slow path.
It is important to note that reentrancy in the slow path can also happen through trace_contention_{begin,end}, but in those cases, unlike an NMI, the forward progress of the head waiter (or the predecessor in general) is not being blocked.
--- kernel/bpf/rqspinlock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/bpf/rqspinlock.c +1 -1
@@ -465,7 +465,7 @@ int __lockfunc resilient_queued_spin_lock_slowpath(rqspinlock_t *lock, u32 val)* any MCS node. This is not the most elegant solution, but is * simple enough. */ -if (unlikely (idx >= _Q_MAX_NODES ||in_nmi ())) { +if (unlikely (idx >= _Q_MAX_NODES || (in_nmi () && idx >0 ))) {lockevent_inc (lock_no_node);RES_RESET_TIMEOUT (ts,RES_DEF_TIMEOUT );while (!queued_spin_trylock (lock)) {
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 498/614 remoteproc: qcom_q6v5_wcss: fix parsing of qcom,halt-regs
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alexandru Gagniuc <[email protected]>
[ Upstream commit 7e81fa8d809ed1e67ae9ecd52d20a20c2c65d877 ]
The "qcom,halt-regs" consists of a phandle reference followed by the three offsets within syscon for halt registers. Thus, we need to request 4 integers from of_property_read_variable_u32_array(), with the halt_reg ofsets at indexes 1, 2, and 3. Offset 0 is the phandle.
With MAX_HALT_REG at 3, of_property_read_variable_u32_array() returns -EOVERFLOW, causing .probe() to fail.
Increase MAX_HALT_REG to 4, and update the indexes accordingly.
--- drivers/remoteproc/qcom_q6v5_wcss.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/remoteproc/qcom_q6v5_wcss.c +4 -4
@@ -85,7 +85,7 @@#define TCSR_WCSS_CLK_MASK 0x1F#define TCSR_WCSS_CLK_ENABLE 0x14 -#define MAX_HALT_REG 3 +#define MAX_HALT_REG 4enum {WCSS_IPQ8074 ,WCSS_QCS404 ,
@@ -864,9 +864,9 @@ static int q6v5_wcss_init_mmio(struct q6v5_wcss *wcss,return -EINVAL ; } - wcss->halt_q6 = halt_reg[0 ]; - wcss->halt_wcss = halt_reg[1 ]; - wcss->halt_nc = halt_reg[2 ]; + wcss->halt_q6 = halt_reg[1 ]; + wcss->halt_wcss = halt_reg[2 ]; + wcss->halt_nc = halt_reg[3 ];return 0 ; }
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 499/614 md/raid5: fix IO hang when array is broken with IO inflight
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yu Kuai <[email protected]>
[ Upstream commit a913d1f6a7f607c110aeef8b58c8988f47a4b24e ]
Following test can cause IO hang:
mdadm -CvR /dev/md0 -l10 -n4 /dev/sd[abcd] --assume-clean --chunk=64K --bitmap=none sleep 5
echo 1 > /sys/block/sda/device/delete
echo 1 > /sys/block/sdb/device/delete
echo 1 > /sys/block/sdc/device/delete
echo 1 > /sys/block/sdd/device/delete
dd if=/dev/md0 of=/dev/null bs=8k count=1 iflag=direct
Root cause:
1) all disks removed, however all rdevs in the array is still in sync, IO will be issued normally.
2) IO failure from sda, and set badblocks failed, sda will be faulty and MD_SB_CHANGING_PENDING will be set.
3) error recovery try to recover this IO from other disks, IO will be issued to sdb, sdc, and sdd.
4) IO failure from sdb, and set badblocks failed again, now array is broken and will become read-only.
5) IO failure from sdc and sdd, however, stripe can't be handled anymore because MD_SB_CHANGING_PENDING is set:
handle_stripe
handle_stripe
if (test_bit MD_SB_CHANGING_PENDING)
set_bit STRIPE_HANDLE
goto finish
// skip handling failed stripe
release_stripe
if (test_bit STRIPE_HANDLE)
list_add_tail conf->hand_list
6) later raid5d can't handle failed stripe as well:
raid5d
md_check_recovery
md_update_sb
if (!md_is_rdwr())
// can't clear pending bit
return if (test_bit MD_SB_CHANGING_PENDING)
break;
// can't handle failed stripe
Since MD_SB_CHANGING_PENDING can never be cleared for read-only array, fix this problem by skip this checking for read-only array.
--- drivers/md/raid5.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/md/raid5.c +4 -2
@@ -4956,7 +4956,8 @@ static void handle_stripe(struct stripe_head *sh) goto finish;if (s.handle_bad_blocks || -test_bit (MD_SB_CHANGE_PENDING , &conf->mddev->sb_flags)) { + (md_is_rdwr (conf->mddev) && +test_bit (MD_SB_CHANGE_PENDING , &conf->mddev->sb_flags))) {set_bit (STRIPE_HANDLE , &sh->state); goto finish; }
@@ -6768,7 +6769,8 @@ static void raid5d(struct md_thread *thread)int batch_size, released;unsigned int offset; -if (test_bit (MD_SB_CHANGE_PENDING , &mddev->sb_flags)) +if (md_is_rdwr (mddev) && +test_bit (MD_SB_CHANGE_PENDING , &mddev->sb_flags))break ; released =release_stripe_list (conf, conf->temp_inactive_list);
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 500/614 clk: keystone: fix compile testing
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
[ Upstream commit b276445e98fe28609688fb85b89a81b803910e63 ]
Some keystone clock drivers can be selected when COMPILE_TEST is enabled but since commit b745c0794e2f ("clk: keystone: Add sci-clk driver support") they are never actually built.
Enable compile testing by allowing the build system to process the keystone drivers.
--- drivers/clk/Makefile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/clk/Makefile +1 -2
@@ -125,8 +125,7 @@ obj-$(CONFIG_ARCH_HISI) += hisilicon/ obj-y += imgtec/ obj-y += imx/ obj-y += ingenic/ -obj-$(CONFIG_ARCH_K3) += keystone/ -obj-$(CONFIG_ARCH_KEYSTONE) += keystone/ +obj-y += keystone/ obj-y += mediatek/ obj-$(CONFIG_ARCH_MESON) += meson/ obj-y += microchip/
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 501/614 smb: smbdirect: introduce SMBDIRECT_DEBUG_ERR_PTR() helper
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Stefan Metzmacher <[email protected]>
[ Upstream commit 1f3fd108c5c5a9885c6c276a2489c49b60a6b90d ]
This can be used like this:
int err = somefunc();
pr_warn("err=%1pe\n", SMBDIRECT_DEBUG_ERR_PTR(err));This will be used in the following fixes in order
to be prepared to identify real world problems
more easily.
Stable-dep-of: 425c32750b48 ("smb: server: relax WARN_ON_ONCE(SMBDIRECT_SOCKET_*) checks in recv_done() and smb_direct_cm_handler()")
--- fs/smb/common/smbdirect/smbdirect_socket.h | 13 +++++++++++++ 1 file changed, 13 insertions(+)
fs/smb/common/smbdirect/smbdirect_socket.h +13 -0
@@ -74,6 +74,19 @@ const char *smbdirect_socket_status_string(enum smbdirect_socket_status status)return "<unknown>" ; } +/* +* This can be used with %1pe to print errors as strings or '0' +* And it avoids warnings like: warn: passing zero to 'ERR_PTR' +* from smatch -p=kernel --pedantic +*/ +static __always_inline +const void * __must_check SMBDIRECT_DEBUG_ERR_PTR(long error) +{ +if (error ==0 ) +return NULL ; +return ERR_PTR (error); +} +enum smbdirect_keepalive_status {SMBDIRECT_KEEPALIVE_NONE ,SMBDIRECT_KEEPALIVE_PENDING ,
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 502/614 smb: smbdirect: introduce SMBDIRECT_CHECK_STATUS_{WARN,DISCONNECT}()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Stefan Metzmacher <[email protected]>
[ Upstream commit 1adb2dab9727c5beaaf253f67bf4fc2c54ae70e7 ]
These will be used in various places in order to assert the current status mostly during the connect and negotiation phase. It will replace the WARN_ON_ONCE(sc->status != ...) calls, which are very useless in order to identify the problem that happened.
As a start client and server will need to define their own __SMBDIRECT_SOCKET_DISCONNECT(__sc) macro in order to use SMBDIRECT_CHECK_STATUS_DISCONNECT().
Stable-dep-of: 425c32750b48 ("smb: server: relax WARN_ON_ONCE(SMBDIRECT_SOCKET_*) checks in recv_done() and smb_direct_cm_handler()")
--- fs/smb/common/smbdirect/smbdirect_socket.h | 38 ++++++++++++++++++++++ 1 file changed, 38 insertions(+)
fs/smb/common/smbdirect/smbdirect_socket.h +38 -0
@@ -394,6 +394,44 @@ static __always_inline void smbdirect_socket_init(struct smbdirect_socket *sc)init_waitqueue_head (&sc->mr_io.cleanup.wait_queue); } +#define __SMBDIRECT_CHECK_STATUS_FAILED (__sc, __expected_status, __error_cmd, __unexpected_cmd) ({ \ + bool __failed = false; \ + if (unlikely((__sc)->first_error)) { \ + __failed = true; \ + __error_cmd \ + } else if (unlikely((__sc)->status != (__expected_status))) { \ + __failed = true; \ + __unexpected_cmd \ + } \ + __failed; \ +}) + +#define __SMBDIRECT_CHECK_STATUS_WARN (__sc, __expected_status, __unexpected_cmd) \ + __SMBDIRECT_CHECK_STATUS_FAILED(__sc, __expected_status, \ + , \ + { \ + const struct sockaddr_storage *__src = NULL; \ + const struct sockaddr_storage *__dst = NULL; \ + if ((__sc)->rdma.cm_id) { \ + __src = &(__sc)->rdma.cm_id->route.addr.src_addr; \ + __dst = &(__sc)->rdma.cm_id->route.addr.dst_addr; \ + } \ + WARN_ONCE(1, \ + "expected[%s] != %s first_error=%1pe local=%pISpsfc remote=%pISpsfc\n", \ + smbdirect_socket_status_string(__expected_status), \ + smbdirect_socket_status_string((__sc)->status), \ + SMBDIRECT_DEBUG_ERR_PTR((__sc)->first_error), \ + __src, __dst); \ + __unexpected_cmd \ + }) + +#define SMBDIRECT_CHECK_STATUS_WARN(__sc, __expected_status) \ + __SMBDIRECT_CHECK_STATUS_WARN(__sc, __expected_status, /* nothing */) + +#define SMBDIRECT_CHECK_STATUS_DISCONNECT (__sc, __expected_status) \ + __SMBDIRECT_CHECK_STATUS_WARN(__sc, __expected_status, \ + __SMBDIRECT_SOCKET_DISCONNECT(__sc);) +struct smbdirect_send_io {struct smbdirect_socket *socket;struct ib_cqe cqe;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 503/614 smb: server: relax WARN_ON_ONCE(SMBDIRECT_SOCKET_*) checks in recv_done() and smb_direct_cm_handler()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Stefan Metzmacher <[email protected]>
[ Upstream commit 425c32750b48956a6e156b6a4609d281ee471359 ]
Namjae reported the following:
I have a simple file copy test with windows 11 client, and get the following error message.
[ 894.140312] ------------[ cut here ]------------ [ 894.140316] WARNING: CPU: 1 PID: 116 at fs/smb/server/transport_rdma.c:642 recv_done+0x308/0x360 [ksmbd] [ 894.140335] Modules linked in: ksmbd cmac nls_utf8 nls_ucs2_utils
libarc4 nls_iso8859_1 snd_hda_codec_intelhdmi snd_hda_codec_hdmi snd_hda_codec_alc882 snd_hda_codec_realtek_lib snd_hda_codec_generic rpcrdma intel_rapl_msr rdma_ucm intel_rapl_common snd_hda_intel ib_iser snd_hda_codec intel_uncore_frequency intel_uncore_frequency_common snd_hda_core intel_tcc_cooling x86_pkg_temp_thermal intel_powerclamp snd_intel_dspcfg libiscsi snd_intel_sdw_acpi coretemp scsi_transport_iscsi snd_hwdep kvm_intel i915 snd_pcm ib_umad rdma_cm snd_seq_midi ib_ipoib kvm snd_seq_midi_event iw_cm snd_rawmidi ghash_clmulni_intel ib_cm aesni_intel snd_seq mei_hdcp drm_buddy rapl snd_seq_device eeepc_wmi asus_wmi snd_timer intel_cstate ttm snd drm_client_lib drm_display_helper sparse_keymap soundcore platform_profile mxm_wmi wmi_bmof joydev mei_me cec acpi_pad mei rc_core drm_kms_helper input_leds i2c_algo_bit mac_hid sch_fq_codel msr parport_pc ppdev lp nfsd parport auth_rpcgss binfmt_misc nfs_acl lockd grace drm sunrpc ramoops efi_pstore
[ 894.140414] reed_solomon pstore_blk pstore_zone autofs4 btrfs
blake2b_generic xor raid6_pq mlx5_ib ib_uverbs ib_core hid_generic uas
usbhid hid r8169 i2c_i801 usb_storage i2c_mux i2c_smbus mlx5_core
realtek ahci mlxfw psample libahci video wmi [last unloaded: ksmbd]
[ 894.140442] CPU: 1 UID: 0 PID: 116 Comm: kworker/1:1H Tainted: G
W 6.18.0-rc5+ #1 PREEMPT(voluntary)
[ 894.140447] Tainted: [W]=WARN
[ 894.140448] Hardware name: System manufacturer System Product
Name/H110M-K, BIOS 3601 12/12/2017
[ 894.140450] Workqueue: ib-comp-wq ib_cq_poll_work [ib_core]
[ 894.140476] RIP: 0010:recv_done+0x308/0x360 [ksmbd]
[ 894.140487] Code: 2e f2 ff ff 5b 41 5c 41 5d 41 5e 41 5f 5d c3 cc
cc cc cc 41 8b 55 10 49 8b 75 08 b9 02 00 00 00 e8 ed f4 f2 c3 e9 59
fd ff ff <0f> 0b e9 02 ff ff ff 49 8b 74 24 28 49 8d 94 24 c8 00 00 00
bf 00
[ 894.140490] RSP: 0018:ffffa47ec03f3d78 EFLAGS: 00010293
[ 894.140492] RAX: 0000000000000001 RBX: ffff8eb84c818000 RCX: 000000010002ba00
[ 894.140494] RDX: 0000000037600001 RSI: 0000000000000083 RDI: ffff8eb92ec9ee40
[ 894.140496] RBP: ffffa47ec03f3da0 R08: 0000000000000000 R09: 0000000000000010
[ 894.140498] R10: ffff8eb801705680 R11: fefefefefefefeff R12: ffff8eb7454b8810
[ 894.140499] R13: ffff8eb746deb988 R14: ffff8eb746deb980 R15: ffff8eb84c818000
[ 894.140501] FS: 0000000000000000(0000) GS:ffff8eb9a7355000(0000)
knlGS:0000000000000000
[ 894.140503] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 894.140505] CR2: 00002d9401d60018 CR3: 0000000010a40006 CR4: 00000000003726f0
[ 894.140507] Call Trace:
[ 894.140509] <TASK>
[ 894.140512] __ib_process_cq+0x8e/0x190 [ib_core]
[ 894.140530] ib_cq_poll_work+0x2f/0x90 [ib_core]
[ 894.140545] process_scheduled_works+0xd4/0x430
[ 894.140554] worker_thread+0x12a/0x270
[ 894.140558] kthread+0x10d/0x250
[ 894.140564] ? __pfx_worker_thread+0x10/0x10
[ 894.140567] ? __pfx_kthread+0x10/0x10
[ 894.140571] ret_from_fork+0x11a/0x160
[ 894.140574] ? __pfx_kthread+0x10/0x10
[ 894.140577] ret_from_fork_asm+0x1a/0x30
[ 894.140584] </TASK>
[ 894.140585] ---[ end trace 0000000000000000 ]---
[ 894.154363] ------------[ cut here ]------------
[ 894.154367] WARNING: CPU: 3 PID: 5543 at
fs/smb/server/transport_rdma.c:1728 smb_direct_cm_handler+0x121/0x130
[ksmbd]
[ 894.154384] Modules linked in: ksmbd cmac nls_utf8 nls_ucs2_utilslibarc4 nls_iso8859_1 snd_hda_codec_intelhdmi snd_hda_codec_hdmi snd_hda_codec_alc882 snd_hda_codec_realtek_lib snd_hda_codec_generic rpcrdma intel_rapl_msr rdma_ucm intel_rapl_common snd_hda_intel ib_iser snd_hda_codec intel_uncore_frequency intel_uncore_frequency_common snd_hda_core intel_tcc_cooling x86_pkg_temp_thermal intel_powerclamp snd_intel_dspcfg libiscsi snd_intel_sdw_acpi coretemp scsi_transport_iscsi snd_hwdep kvm_intel i915 snd_pcm ib_umad rdma_cm snd_seq_midi ib_ipoib kvm snd_seq_midi_event iw_cm snd_rawmidi ghash_clmulni_intel ib_cm aesni_intel snd_seq mei_hdcp drm_buddy rapl snd_seq_device eeepc_wmi asus_wmi snd_timer intel_cstate ttm snd drm_client_lib drm_display_helper sparse_keymap soundcore platform_profile mxm_wmi wmi_bmof joydev mei_me cec acpi_pad mei rc_core drm_kms_helper input_leds i2c_algo_bit mac_hid sch_fq_codel msr parport_pc ppdev lp nfsd parport auth_rpcgss binfmt_misc nfs_acl lockd grace drm sunrpc ramoops efi_pstore
[ 894.154456] reed_solomon pstore_blk pstore_zone autofs4 btrfs
blake2b_generic xor raid6_pq mlx5_ib ib_uverbs ib_core hid_generic uas
usbhid hid r8169 i2c_i801 usb_storage i2c_mux i2c_smbus mlx5_core
realtek ahci mlxfw psample libahci video wmi [last unloaded: ksmbd]
[ 894.154483] CPU: 3 UID: 0 PID: 5543 Comm: kworker/3:6 Tainted: G
W 6.18.0-rc5+ #1 PREEMPT(voluntary)
[ 894.154487] Tainted: [W]=WARN
[ 894.154488] Hardware name: System manufacturer System Product
Name/H110M-K, BIOS 3601 12/12/2017
[ 894.154490] Workqueue: ib_cm cm_work_handler [ib_cm]
[ 894.154499] RIP: 0010:smb_direct_cm_handler+0x121/0x130 [ksmbd]
[ 894.154507] Code: e7 e8 13 b1 ef ff 44 89 e1 4c 89 ee 48 c7 c7 80
d7 59 c1 48 89 c2 e8 2e 4d ef c3 31 c0 5b 41 5c 41 5d 41 5e 5d c3 cc
cc cc cc <0f> 0b eb a5 66 66 2e 0f 1f 84 00 00 00 00 00 90 90 90 90 90
90 90
[ 894.154510] RSP: 0018:ffffa47ec1b27c00 EFLAGS: 00010206
[ 894.154512] RAX: ffffffffc1304e00 RBX: ffff8eb89ae50880 RCX: 0000000000000000
[ 894.154514] RDX: ffff8eb730960000 RSI: ffffa47ec1b27c60 RDI: ffff8eb7454b9400
[ 894.154515] RBP: ffffa47ec1b27c20 R08: 0000000000000002 R09: ffff8eb730b8c18b
[ 894.154517] R10: 0000000000000001 R11: 0000000000000001 R12: 0000000000000009
[ 894.154518] R13: ffff8eb7454b9400 R14: ffff8eb7454b8810 R15: ffff8eb815c43000
[ 894.154520] FS: 0000000000000000(0000) GS:ffff8eb9a7455000(0000)
knlGS:0000000000000000
[ 894.154522] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 894.154523] CR2: 00007fe1310e99d0 CR3: 0000000010a40005 CR4: 00000000003726f0
[ 894.154525] Call Trace:
[ 894.154527] <TASK>
[ 894.154530] cma_cm_event_handler+0x27/0xd0 [rdma_cm]
[ 894.154541] cma_ib_handler+0x99/0x2e0 [rdma_cm]
[ 894.154551] cm_process_work+0x28/0xf0 [ib_cm]
[ 894.154557] cm_queue_work_unlock+0x41/0xf0 [ib_cm]
[ 894.154563] cm_work_handler+0x2eb/0x25b0 [ib_cm]
[ 894.154568] ? pwq_activate_first_inactive+0x52/0x70
[ 894.154572] ? pwq_dec_nr_in_flight+0x244/0x330
[ 894.154575] process_scheduled_works+0xd4/0x430
[ 894.154579] worker_thread+0x12a/0x270
[ 894.154581] kthread+0x10d/0x250
[ 894.154585] ? __pfx_worker_thread+0x10/0x10
[ 894.154587] ? __pfx_kthread+0x10/0x10
[ 894.154590] ret_from_fork+0x11a/0x160
[ 894.154593] ? __pfx_kthread+0x10/0x10
[ 894.154596] ret_from_fork_asm+0x1a/0x30
[ 894.154602] </TASK>
[ 894.154603] ---[ end trace 0000000000000000 ]---
[ 894.154931] ksmbd: smb_direct: disconnected
[ 894.157278] ksmbd: smb_direct: disconnectedI guess sc->first_error is already set and sc->status is thus unexpected, so this should avoid the WARN[_ON]_ONCE() if sc->first_error is already set and have a usable error path.
While there set sc->first_error as soon as possible.
v1 of this patch revealed the real problem with this message:
[ 309.560973] expected[NEGOTIATE_NEEDED] != RDMA_CONNECT_RUNNING first_error=0 local=192.168.0.200:445 remote=192.168.0.100:60445 [ 309.561034] WARNING: CPU: 2 PID: 78 at transport_rdma.c:643
recv_done+0x2fa/0x3d0 [ksmbd]
Some drivers (at least mlx5_ib) might post a recv completion before RDMA_CM_EVENT_ESTABLISHED, so we need to adjust our expectation in that case.
--- fs/smb/server/transport_rdma.c | 40 +++++++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 8 deletions(-)
fs/smb/server/transport_rdma.c +32 -8
@@ -19,6 +19,8 @@#include <rdma/rdma_cm.h> #include <rdma/rw.h> +#define __SMBDIRECT_SOCKET_DISCONNECT (__sc) smb_direct_disconnect_rdma_connection(__sc) +#include "glob.h" #include "connection.h" #include "smb_common.h"
@@ -231,6 +233,9 @@ static void smb_direct_disconnect_rdma_work(struct work_struct *work)struct smbdirect_socket *sc = container_of(work, struct smbdirect_socket, disconnect_work); +if (sc->first_error ==0 ) + sc->first_error = -ECONNABORTED ; +/* * make sure this and other work is not queued again * but here we don't block and avoid
@@ -241,9 +246,6 @@ static void smb_direct_disconnect_rdma_work(struct work_struct *work)disable_delayed_work (&sc->idle.timer_work);disable_work (&sc->idle.immediate_work); -if (sc->first_error ==0 ) - sc->first_error = -ECONNABORTED ; -switch (sc->status) {case SMBDIRECT_SOCKET_NEGOTIATE_NEEDED :case SMBDIRECT_SOCKET_NEGOTIATE_RUNNING :
@@ -287,6 +289,9 @@ static void smb_direct_disconnect_rdma_work(struct work_struct *work)static void smb_direct_disconnect_rdma_connection (struct smbdirect_socket *sc) { +if (sc->first_error ==0 ) + sc->first_error = -ECONNABORTED ; +/* * make sure other work (than disconnect_work) is * not queued again but here we don't block and avoid
@@ -296,9 +301,6 @@ smb_direct_disconnect_rdma_connection(struct smbdirect_socket *sc)disable_work (&sc->idle.immediate_work);disable_delayed_work (&sc->idle.timer_work); -if (sc->first_error ==0 ) - sc->first_error = -ECONNABORTED ; -switch (sc->status) {case SMBDIRECT_SOCKET_RESOLVE_ADDR_FAILED :case SMBDIRECT_SOCKET_RESOLVE_ROUTE_FAILED :
@@ -639,7 +641,18 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc)return ; } sc->recv_io.reassembly.full_packet_received = true; -WARN_ON_ONCE (sc->status !=SMBDIRECT_SOCKET_NEGOTIATE_NEEDED ); +/* +* Some drivers (at least mlx5_ib) might post a +* recv completion before RDMA_CM_EVENT_ESTABLISHED, +* we need to adjust our expectation in that case. +*/ +if (!sc->first_error && sc->status ==SMBDIRECT_SOCKET_RDMA_CONNECT_RUNNING ) + sc->status =SMBDIRECT_SOCKET_NEGOTIATE_NEEDED ; +if (SMBDIRECT_CHECK_STATUS_WARN (sc,SMBDIRECT_SOCKET_NEGOTIATE_NEEDED )) { +put_recvmsg (sc, recvmsg); +smb_direct_disconnect_rdma_connection (sc); +return ; + } sc->status =SMBDIRECT_SOCKET_NEGOTIATE_RUNNING ;enqueue_reassembly (sc, recvmsg,0 );wake_up (&sc->status_wait);
@@ -1725,7 +1738,18 @@ static int smb_direct_cm_handler(struct rdma_cm_id *cm_id,switch (event->event) {case RDMA_CM_EVENT_ESTABLISHED : { -WARN_ON_ONCE (sc->status !=SMBDIRECT_SOCKET_RDMA_CONNECT_RUNNING ); +/* +* Some drivers (at least mlx5_ib) might post a +* recv completion before RDMA_CM_EVENT_ESTABLISHED, +* we need to adjust our expectation in that case. +* +* As we already started the negotiation, we just +* ignore RDMA_CM_EVENT_ESTABLISHED here. +*/ +if (!sc->first_error && sc->status >SMBDIRECT_SOCKET_RDMA_CONNECT_RUNNING ) +break ; +if (SMBDIRECT_CHECK_STATUS_DISCONNECT (sc,SMBDIRECT_SOCKET_RDMA_CONNECT_RUNNING )) +break ; sc->status =SMBDIRECT_SOCKET_NEGOTIATE_NEEDED ;wake_up (&sc->status_wait);break ;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 504/614 smb: client: relax WARN_ON_ONCE(SMBDIRECT_SOCKET_*) checks in recv_done() and smbd_conn_upcall()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Stefan Metzmacher <[email protected]>
[ Upstream commit dc10cf1368af8cb816dcaa2502ba7d44fff20612 ]
sc->first_error might already be set and sc->status is thus unexpected, so this should avoid the WARN[_ON]_ONCE() if sc->first_error is already set and have a usable error path.
While there set sc->first_error as soon as possible.
This is done based on a problem seen in similar places on the server. And there it was already very useful in order to find the problem when we have a meaningful WARN_ONCE() that prints details about the connection.
This is much more useful:
[ 309.560973] expected[NEGOTIATE_NEEDED] != RDMA_CONNECT_RUNNING first_error=0 local=192.168.0.200:445 remote=192.168.0.100:60445 [ 309.561034] WARNING: CPU: 2 PID: 78 at transport_rdma.c:643
recv_done+0x2fa/0x3d0 [ksmbd]
than what we had before (only):
[ 894.140316] WARNING: CPU: 1 PID: 116 at
fs/smb/server/transport_rdma.c:642 recv_done+0x308/0x360 [ksmbd]
--- fs/smb/client/smbdirect.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-)
fs/smb/client/smbdirect.c +15 -13
@@ -7,6 +7,7 @@#include <linux/module.h> #include <linux/highmem.h> #include <linux/folio_queue.h> +#define __SMBDIRECT_SOCKET_DISCONNECT (__sc) smbd_disconnect_rdma_connection(__sc)#include "../common/smbdirect/smbdirect_pdu.h" #include "smbdirect.h" #include "cifs_debug.h"
@@ -186,6 +187,9 @@ static void smbd_disconnect_rdma_work(struct work_struct *work)struct smbdirect_socket *sc = container_of(work, struct smbdirect_socket, disconnect_work); +if (sc->first_error ==0 ) + sc->first_error = -ECONNABORTED ; +/* * make sure this and other work is not queued again * but here we don't block and avoid
@@ -197,9 +201,6 @@ static void smbd_disconnect_rdma_work(struct work_struct *work)disable_work (&sc->idle.immediate_work);disable_delayed_work (&sc->idle.timer_work); -if (sc->first_error ==0 ) - sc->first_error = -ECONNABORTED ; -switch (sc->status) {case SMBDIRECT_SOCKET_NEGOTIATE_NEEDED :case SMBDIRECT_SOCKET_NEGOTIATE_RUNNING :
@@ -242,6 +243,9 @@ static void smbd_disconnect_rdma_work(struct work_struct *work)static void smbd_disconnect_rdma_connection (struct smbdirect_socket *sc) { +if (sc->first_error ==0 ) + sc->first_error = -ECONNABORTED ; +/* * make sure other work (than disconnect_work) is * not queued again but here we don't block and avoid
@@ -252,9 +256,6 @@ static void smbd_disconnect_rdma_connection(struct smbdirect_socket *sc)disable_work (&sc->idle.immediate_work);disable_delayed_work (&sc->idle.timer_work); -if (sc->first_error ==0 ) - sc->first_error = -ECONNABORTED ; -switch (sc->status) {case SMBDIRECT_SOCKET_RESOLVE_ADDR_FAILED :case SMBDIRECT_SOCKET_RESOLVE_ROUTE_FAILED :
@@ -322,27 +323,27 @@ static int smbd_conn_upcall(switch (event->event) {case RDMA_CM_EVENT_ADDR_RESOLVED : -WARN_ON_ONCE (sc->status !=SMBDIRECT_SOCKET_RESOLVE_ADDR_RUNNING ); +if (SMBDIRECT_CHECK_STATUS_DISCONNECT (sc,SMBDIRECT_SOCKET_RESOLVE_ADDR_RUNNING )) +break ; sc->status =SMBDIRECT_SOCKET_RESOLVE_ROUTE_NEEDED ;wake_up (&sc->status_wait);break ;case RDMA_CM_EVENT_ROUTE_RESOLVED : -WARN_ON_ONCE (sc->status !=SMBDIRECT_SOCKET_RESOLVE_ROUTE_RUNNING ); +if (SMBDIRECT_CHECK_STATUS_DISCONNECT (sc,SMBDIRECT_SOCKET_RESOLVE_ROUTE_RUNNING )) +break ; sc->status =SMBDIRECT_SOCKET_RDMA_CONNECT_NEEDED ;wake_up (&sc->status_wait);break ;case RDMA_CM_EVENT_ADDR_ERROR :log_rdma_event (ERR ,"connecting failed event=%s\n" , event_name); -WARN_ON_ONCE (sc->status !=SMBDIRECT_SOCKET_RESOLVE_ADDR_RUNNING ); sc->status =SMBDIRECT_SOCKET_RESOLVE_ADDR_FAILED ;smbd_disconnect_rdma_work (&sc->disconnect_work);break ;case RDMA_CM_EVENT_ROUTE_ERROR :log_rdma_event (ERR ,"connecting failed event=%s\n" , event_name); -WARN_ON_ONCE (sc->status !=SMBDIRECT_SOCKET_RESOLVE_ROUTE_RUNNING ); sc->status =SMBDIRECT_SOCKET_RESOLVE_ROUTE_FAILED ;smbd_disconnect_rdma_work (&sc->disconnect_work);break ;
@@ -428,7 +429,8 @@ static int smbd_conn_upcall(min_t (u8, sp->responder_resources, peer_responder_resources); -WARN_ON_ONCE (sc->status !=SMBDIRECT_SOCKET_RDMA_CONNECT_RUNNING ); +if (SMBDIRECT_CHECK_STATUS_DISCONNECT (sc,SMBDIRECT_SOCKET_RDMA_CONNECT_RUNNING )) +break ; sc->status =SMBDIRECT_SOCKET_NEGOTIATE_NEEDED ;wake_up (&sc->status_wait);break ;
@@ -437,7 +439,6 @@ static int smbd_conn_upcall(case RDMA_CM_EVENT_UNREACHABLE :case RDMA_CM_EVENT_REJECTED :log_rdma_event (ERR ,"connecting failed event=%s\n" , event_name); -WARN_ON_ONCE (sc->status !=SMBDIRECT_SOCKET_RDMA_CONNECT_RUNNING ); sc->status =SMBDIRECT_SOCKET_RDMA_CONNECT_FAILED ;smbd_disconnect_rdma_work (&sc->disconnect_work);break ;
@@ -699,7 +700,8 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc) negotiate_done =process_negotiation_response (response, wc->byte_len);put_receive_buffer (sc, response); -WARN_ON_ONCE (sc->status !=SMBDIRECT_SOCKET_NEGOTIATE_RUNNING ); +if (SMBDIRECT_CHECK_STATUS_WARN (sc,SMBDIRECT_SOCKET_NEGOTIATE_RUNNING )) + negotiate_done = false;if (!negotiate_done) { sc->status =SMBDIRECT_SOCKET_NEGOTIATE_FAILED ;smbd_disconnect_rdma_connection (sc);
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 505/614 um: Disable KASAN_INLINE when STATIC_LINK is selected
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christophe Leroy (CS GROUP) <[email protected]>
[ Upstream commit a3209bb94b36351f11e0d9e72ac44e5dd777a069 ]
um doesn't support KASAN_INLINE together with STATIC_LINK.
Instead of failing the build, disable KASAN_INLINE when STATIC_LINK is selected.
--- arch/um/Kconfig | 1 + arch/um/include/asm/kasan.h | 4 ---- 2 files changed, 1 insertion(+), 4 deletions(-)
arch/um/Kconfig +1 -0
@@ -5,6 +5,7 @@ menu "UML-specific options" config UML bool default y + select ARCH_DISABLE_KASAN_INLINE if STATIC_LINK select ARCH_NEEDS_DEFER_KASAN if STATIC_LINK select ARCH_WANTS_DYNAMIC_TASK_STRUCT select ARCH_HAS_CACHE_LINE_SIZE
arch/um/include/asm/kasan.h +0 -4
@@ -24,10 +24,6 @@#ifdef CONFIG_KASAN void kasan_init (void ); - -#if defined(CONFIG_STATIC_LINK ) && defined(CONFIG_KASAN_INLINE ) -#error UML does not work in KASAN_INLINE mode with STATIC_LINK enabled! -#endif #else static inline void kasan_init (void ) { }#endif /* CONFIG_KASAN */
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 506/614 net: dsa: b53: fix VLAN_ID_IDX write size for BCM5325/65
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jonas Gorski <[email protected]>
[ Upstream commit 6f268e275c74dae0536e0b61982a8db25bcf4f16 ]
Since BCM5325 and BCM5365 only support up to 256 VLANs, the VLAN_ID_IDX register is only 8 bit wide, not 16 bit, so use an appropriate accessor.
--- drivers/net/dsa/b53/b53_common.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
drivers/net/dsa/b53/b53_common.c +6 -2
@@ -1924,8 +1924,12 @@ static int b53_arl_op(struct b53_device *dev, int op, int port,/* Perform a read for the given MAC and VID */ b53_write48 (dev,B53_ARLIO_PAGE ,B53_MAC_ADDR_IDX , mac); -if (!is5325m (dev)) -b53_write16 (dev,B53_ARLIO_PAGE ,B53_VLAN_ID_IDX , vid); +if (!is5325m (dev)) { +if (is5325 (dev) ||is5365 (dev)) +b53_write8 (dev,B53_ARLIO_PAGE ,B53_VLAN_ID_IDX , vid); +else +b53_write16 (dev,B53_ARLIO_PAGE ,B53_VLAN_ID_IDX , vid); + }/* Issue a read operation for this MAC */ ret =b53_arl_rw_op (dev,1 );
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 507/614 net: dsa: b53: fix extracting VID from entry for BCM5325/65
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jonas Gorski <[email protected]>
[ Upstream commit 9316012dd01952f75e37035360138ccc786ef727 ]
BCM5325/65's Entry register uses the highest three bits for VALID/STATIC/AGE, so shifting by 53 only will add these to b53_arl_entry::vid.
So make sure to mask the vid value as well, to not get invalid VIDs.
--- drivers/net/dsa/b53/b53_priv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/dsa/b53/b53_priv.h +1 -1
@@ -338,7 +338,7 @@ static inline void b53_arl_to_entry_25(struct b53_arl_entry *ent, ent->is_age = !!(mac_vid &ARLTBL_AGE_25 ); ent->is_static = !!(mac_vid &ARLTBL_STATIC_25 );u64_to_ether_addr (mac_vid, ent->mac); - ent->vid = mac_vid >>ARLTBL_VID_S_65 ; + ent->vid = (mac_vid >>ARLTBL_VID_S_65 ) &ARLTBL_VID_MASK_25 ; } static inline void b53_arl_from_entry(u64 *mac_vid, u32 *fwd_entry,
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 508/614 net: dsa: b53: b53_arl_read{,25}(): use the entry for comparision
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jonas Gorski <[email protected]>
[ Upstream commit a6e4fd38bf2f2e2363b61c27f4e6c49b14e4bb07 ]
Align the b53_arl_read{,25}() functions by consistently using the parsed arl entry instead of parsing the raw registers again.
Stable-dep-of: 8e46aacea426 ("net: dsa: b53: use same ARL search result offset for BCM5325/65")
--- drivers/net/dsa/b53/b53_common.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-)
drivers/net/dsa/b53/b53_common.c +10 -12
@@ -1830,7 +1830,7 @@ static int b53_arl_rw_op(struct b53_device *dev, unsigned int op)return b53_arl_op_wait (dev); } -static int b53_arl_read (struct b53_device *dev,u64 mac, +static int b53_arl_read (struct b53_device *dev,const u8 *mac,u16 vid,struct b53_arl_entry *ent,u8 *idx) {DECLARE_BITMAP (free_bins,B53_ARLTBL_MAX_BIN_ENTRIES );
@@ -1854,14 +1854,13 @@ static int b53_arl_read(struct b53_device *dev, u64 mac, B53_ARLTBL_DATA_ENTRY(i), &fwd_entry);b53_arl_to_entry (ent, mac_vid, fwd_entry); -if (!(fwd_entry &ARLTBL_VALID )) { +if (!ent->is_valid) {set_bit (i, free_bins);continue ; } -if ((mac_vid &ARLTBL_MAC_MASK ) != mac) +if (!ether_addr_equal (ent->mac, mac))continue ; -if (dev->vlan_enabled && - ((mac_vid >>ARLTBL_VID_S ) &ARLTBL_VID_MASK ) != vid) +if (dev->vlan_enabled && ent->vid != vid)continue ; *idx = i;return 0 ;
@@ -1871,7 +1870,7 @@ static int b53_arl_read(struct b53_device *dev, u64 mac,return *idx >= dev->num_arl_bins ? -ENOSPC : -ENOENT ; } -static int b53_arl_read_25 (struct b53_device *dev,u64 mac, +static int b53_arl_read_25 (struct b53_device *dev,const u8 *mac,u16 vid,struct b53_arl_entry *ent,u8 *idx) {DECLARE_BITMAP (free_bins,B53_ARLTBL_MAX_BIN_ENTRIES );
@@ -1893,14 +1892,13 @@ static int b53_arl_read_25(struct b53_device *dev, u64 mac,b53_arl_to_entry_25 (ent, mac_vid); -if (!(mac_vid &ARLTBL_VALID_25 )) { +if (!ent->is_valid) {set_bit (i, free_bins);continue ; } -if ((mac_vid &ARLTBL_MAC_MASK ) != mac) +if (!ether_addr_equal (ent->mac, mac))continue ; -if (dev->vlan_enabled && - ((mac_vid >>ARLTBL_VID_S_65 ) &ARLTBL_VID_MASK_25 ) != vid) +if (dev->vlan_enabled && ent->vid != vid)continue ; *idx = i;return 0 ;
@@ -1937,9 +1935,9 @@ static int b53_arl_op(struct b53_device *dev, int op, int port,return ret;if (is5325 (dev) ||is5365 (dev)) - ret =b53_arl_read_25 (dev, mac, vid, &ent, &idx); + ret =b53_arl_read_25 (dev, addr, vid, &ent, &idx);else - ret =b53_arl_read (dev, mac, vid, &ent, &idx); + ret =b53_arl_read (dev, addr, vid, &ent, &idx);/* If this is a read, just finish now */ if (op)
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 509/614 net: dsa: b53: move reading ARL entries into their own function
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jonas Gorski <[email protected]>
[ Upstream commit 4a291fe7226736a465ddb3fa93c21fcef7162ec7 ]
Instead of duplicating the whole code iterating over all bins for BCM5325, factor out reading and parsing the entry into its own functions, and name it the modern one after the first chip with that ARL format, (BCM53)95.
Stable-dep-of: 8e46aacea426 ("net: dsa: b53: use same ARL search result offset for BCM5325/65")
--- drivers/net/dsa/b53/b53_common.c | 69 +++++++++++--------------------- 1 file changed, 23 insertions(+), 46 deletions(-)
drivers/net/dsa/b53/b53_common.c +23 -46
@@ -1830,48 +1830,30 @@ static int b53_arl_rw_op(struct b53_device *dev, unsigned int op)return b53_arl_op_wait (dev); } -static int b53_arl_read (struct b53_device *dev,const u8 *mac, -u16 vid,struct b53_arl_entry *ent,u8 *idx) +static void b53_arl_read_entry_25 (struct b53_device *dev, +struct b53_arl_entry *ent,u8 idx) { -DECLARE_BITMAP (free_bins,B53_ARLTBL_MAX_BIN_ENTRIES ); -unsigned int i; -int ret; - - ret =b53_arl_op_wait (dev); -if (ret) -return ret; - -bitmap_zero (free_bins, dev->num_arl_bins); - -/* Read the bins */ -for (i =0 ; i < dev->num_arl_bins; i++) { -u64 mac_vid; -u32 fwd_entry; +u64 mac_vid; -b53_read64 (dev,B53_ARLIO_PAGE , -B53_ARLTBL_MAC_VID_ENTRY (i), &mac_vid); -b53_read32 (dev,B53_ARLIO_PAGE , -B53_ARLTBL_DATA_ENTRY (i), &fwd_entry); -b53_arl_to_entry (ent, mac_vid, fwd_entry); +b53_read64 (dev,B53_ARLIO_PAGE ,B53_ARLTBL_MAC_VID_ENTRY (idx), + &mac_vid); +b53_arl_to_entry_25 (ent, mac_vid); +} -if (!ent->is_valid) { -set_bit (i, free_bins); -continue ; - } -if (!ether_addr_equal (ent->mac, mac)) -continue ; -if (dev->vlan_enabled && ent->vid != vid) -continue ; - *idx = i; -return 0 ; - } +static void b53_arl_read_entry_95 (struct b53_device *dev, +struct b53_arl_entry *ent,u8 idx) +{ +u32 fwd_entry; +u64 mac_vid; - *idx =find_first_bit (free_bins, dev->num_arl_bins); -return *idx >= dev->num_arl_bins ? -ENOSPC : -ENOENT ; +b53_read64 (dev,B53_ARLIO_PAGE ,B53_ARLTBL_MAC_VID_ENTRY (idx), + &mac_vid); +b53_read32 (dev,B53_ARLIO_PAGE ,B53_ARLTBL_DATA_ENTRY (idx), &fwd_entry); +b53_arl_to_entry (ent, mac_vid, fwd_entry); } -static int b53_arl_read_25 (struct b53_device *dev,const u8 *mac, -u16 vid,struct b53_arl_entry *ent,u8 *idx) +static int b53_arl_read (struct b53_device *dev,const u8 *mac, +u16 vid,struct b53_arl_entry *ent,u8 *idx) {DECLARE_BITMAP (free_bins,B53_ARLTBL_MAX_BIN_ENTRIES );unsigned int i;
@@ -1885,12 +1867,10 @@ static int b53_arl_read_25(struct b53_device *dev, const u8 *mac,/* Read the bins */ for (i =0 ; i < dev->num_arl_bins; i++) { -u64 mac_vid; - -b53_read64 (dev,B53_ARLIO_PAGE , -B53_ARLTBL_MAC_VID_ENTRY (i), &mac_vid); - -b53_arl_to_entry_25 (ent, mac_vid); +if (is5325 (dev) ||is5365 (dev)) +b53_arl_read_entry_25 (dev, ent, i); +else +b53_arl_read_entry_95 (dev, ent, i);if (!ent->is_valid) {set_bit (i, free_bins);
@@ -1934,10 +1914,7 @@ static int b53_arl_op(struct b53_device *dev, int op, int port,if (ret)return ret; -if (is5325 (dev) ||is5365 (dev)) - ret =b53_arl_read_25 (dev, addr, vid, &ent, &idx); -else - ret =b53_arl_read (dev, addr, vid, &ent, &idx); + ret =b53_arl_read (dev, addr, vid, &ent, &idx);/* If this is a read, just finish now */ if (op)
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 510/614 net: dsa: b53: move writing ARL entries into their own functions
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jonas Gorski <[email protected]>
[ Upstream commit bf6e9d2ae1dbafee53ec4ccd126595172e1e5278 ]
Move writing ARL entries into individual functions for each format.
Stable-dep-of: 8e46aacea426 ("net: dsa: b53: use same ARL search result offset for BCM5325/65")
--- drivers/net/dsa/b53/b53_common.c | 38 ++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 12 deletions(-)
drivers/net/dsa/b53/b53_common.c +26 -12
@@ -1840,6 +1840,16 @@ static void b53_arl_read_entry_25(struct b53_device *dev,b53_arl_to_entry_25 (ent, mac_vid); } +static void b53_arl_write_entry_25 (struct b53_device *dev, +const struct b53_arl_entry *ent,u8 idx) +{ +u64 mac_vid; + +b53_arl_from_entry_25 (&mac_vid, ent); +b53_write64 (dev,B53_ARLIO_PAGE ,B53_ARLTBL_MAC_VID_ENTRY (idx), + mac_vid); +} +static void b53_arl_read_entry_95 (struct b53_device *dev,struct b53_arl_entry *ent,u8 idx) {
@@ -1852,6 +1862,19 @@ static void b53_arl_read_entry_95(struct b53_device *dev,b53_arl_to_entry (ent, mac_vid, fwd_entry); } +static void b53_arl_write_entry_95 (struct b53_device *dev, +const struct b53_arl_entry *ent,u8 idx) +{ +u32 fwd_entry; +u64 mac_vid; + +b53_arl_from_entry (&mac_vid, &fwd_entry, ent); +b53_write64 (dev,B53_ARLIO_PAGE ,B53_ARLTBL_MAC_VID_ENTRY (idx), + mac_vid); +b53_write32 (dev,B53_ARLIO_PAGE ,B53_ARLTBL_DATA_ENTRY (idx), + fwd_entry); +} +static int b53_arl_read (struct b53_device *dev,const u8 *mac,u16 vid,struct b53_arl_entry *ent,u8 *idx) {
@@ -1892,9 +1915,8 @@ static int b53_arl_op(struct b53_device *dev, int op, int port, const unsigned char *addr, u16 vid, bool is_valid) { struct b53_arl_entry ent; -u32 fwd_entry; -u64 mac, mac_vid =0 ;u8 idx =0 ; +u64 mac;int ret;/* Convert the array into a 64-bit MAC */
@@ -1931,7 +1953,6 @@ static int b53_arl_op(struct b53_device *dev, int op, int port,/* We could not find a matching MAC, so reset to a new entry */ dev_dbg (dev->dev,"{%pM,%.4d} not found, using idx: %d\n" , addr, vid, idx); - fwd_entry =0 ;break ;default : dev_dbg(dev->dev, "{%pM,%.4d} found, using idx: %d\n",
@@ -1959,16 +1980,9 @@ static int b53_arl_op(struct b53_device *dev, int op, int port, ent.is_age = false;memcpy (ent.mac, addr,ETH_ALEN );if (is5325 (dev) ||is5365 (dev)) -b53_arl_from_entry_25 (&mac_vid, &ent); +b53_arl_write_entry_25 (dev, &ent, idx);else -b53_arl_from_entry (&mac_vid, &fwd_entry, &ent); - -b53_write64 (dev,B53_ARLIO_PAGE , -B53_ARLTBL_MAC_VID_ENTRY (idx), mac_vid); - -if (!is5325 (dev) && !is5365 (dev)) -b53_write32 (dev,B53_ARLIO_PAGE , -B53_ARLTBL_DATA_ENTRY (idx), fwd_entry); +b53_arl_write_entry_95 (dev, &ent, idx);return b53_arl_rw_op (dev,0 ); }
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 511/614 net: dsa: b53: provide accessors for accessing ARL_SRCH_CTL
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jonas Gorski <[email protected]>
[ Upstream commit 1716be6db04af53bac9b869f01156a460595cf41 ]
In order to more easily support more formats, move accessing ARL_SRCH_CTL into helper functions to contain the differences.
Stable-dep-of: 8e46aacea426 ("net: dsa: b53: use same ARL search result offset for BCM5325/65")
--- drivers/net/dsa/b53/b53_common.c | 37 +++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 13 deletions(-)
drivers/net/dsa/b53/b53_common.c +24 -13
@@ -2017,18 +2017,37 @@ int b53_fdb_del(struct dsa_switch *ds, int port, }EXPORT_SYMBOL (b53_fdb_del); -static int b53_arl_search_wait (struct b53_device *dev) +static void b53_read_arl_srch_ctl (struct b53_device *dev,u8 *val) { -unsigned int timeout =1000 ; -u8 reg, offset; +u8 offset; + +if (is5325 (dev) ||is5365 (dev)) + offset =B53_ARL_SRCH_CTL_25 ; +else + offset =B53_ARL_SRCH_CTL ; + +b53_read8 (dev,B53_ARLIO_PAGE , offset, val); +} + +static void b53_write_arl_srch_ctl (struct b53_device *dev,u8 val) +{ +u8 offset;if (is5325 (dev) ||is5365 (dev)) offset =B53_ARL_SRCH_CTL_25 ;else offset =B53_ARL_SRCH_CTL ; +b53_write8 (dev,B53_ARLIO_PAGE , offset, val); +} + +static int b53_arl_search_wait (struct b53_device *dev) +{ +unsigned int timeout =1000 ; +u8 reg; + do { - b53_read8(dev, B53_ARLIO_PAGE, offset, ®); + b53_read_arl_srch_ctl(dev, ®); if (!(reg & ARL_SRCH_STDN)) return -ENOENT;
@@ -2083,23 +2102,15 @@ int b53_fdb_dump(struct dsa_switch *ds, int port,unsigned int count =0 , results_per_hit =1 ;struct b53_device *priv = ds->priv;struct b53_arl_entry results[2 ]; -u8 offset;int ret; -u8 reg;if (priv->num_arl_bins >2 ) results_per_hit =2 ;mutex_lock (&priv->arl_mutex); -if (is5325 (priv) ||is5365 (priv)) - offset =B53_ARL_SRCH_CTL_25 ; -else - offset =B53_ARL_SRCH_CTL ; -/* Start search operation */ - reg =ARL_SRCH_STDN ; -b53_write8 (priv,B53_ARLIO_PAGE , offset, reg); +b53_write_arl_srch_ctl (priv,ARL_SRCH_STDN ); do { ret = b53_arl_search_wait(priv);
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 512/614 net: dsa: b53: split reading search entry into their own functions
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jonas Gorski <[email protected]>
[ Upstream commit e0c476f325a8c9b961a3d446c24d3c8ecae7d186 ]
Split reading search entries into a function for each format.
Stable-dep-of: 8e46aacea426 ("net: dsa: b53: use same ARL search result offset for BCM5325/65")
--- drivers/net/dsa/b53/b53_common.c | 56 ++++++++++++++++++++++---------- 1 file changed, 38 insertions(+), 18 deletions(-)
drivers/net/dsa/b53/b53_common.c +38 -18
@@ -2060,28 +2060,48 @@ static int b53_arl_search_wait(struct b53_device *dev)return -ETIMEDOUT ; } -static void b53_arl_search_rd (struct b53_device *dev,u8 idx, -struct b53_arl_entry *ent) +static void b53_arl_search_read_25 (struct b53_device *dev,u8 idx, +struct b53_arl_entry *ent) {u64 mac_vid; -if (is5325 (dev)) { -b53_read64 (dev,B53_ARLIO_PAGE ,B53_ARL_SRCH_RSTL_0_MACVID_25 , - &mac_vid); -b53_arl_to_entry_25 (ent, mac_vid); - }else if (is5365 (dev)) { -b53_read64 (dev,B53_ARLIO_PAGE ,B53_ARL_SRCH_RSTL_0_MACVID_65 , - &mac_vid); -b53_arl_to_entry_25 (ent, mac_vid); - }else { -u32 fwd_entry; +b53_read64 (dev,B53_ARLIO_PAGE ,B53_ARL_SRCH_RSTL_0_MACVID_25 , + &mac_vid); +b53_arl_to_entry_25 (ent, mac_vid); +} -b53_read64 (dev,B53_ARLIO_PAGE ,B53_ARL_SRCH_RSTL_MACVID (idx), - &mac_vid); -b53_read32 (dev,B53_ARLIO_PAGE ,B53_ARL_SRCH_RSTL (idx), - &fwd_entry); -b53_arl_to_entry (ent, mac_vid, fwd_entry); - } +static void b53_arl_search_read_65 (struct b53_device *dev,u8 idx, +struct b53_arl_entry *ent) +{ +u64 mac_vid; + +b53_read64 (dev,B53_ARLIO_PAGE ,B53_ARL_SRCH_RSTL_0_MACVID_65 , + &mac_vid); +b53_arl_to_entry_25 (ent, mac_vid); +} + +static void b53_arl_search_read_95 (struct b53_device *dev,u8 idx, +struct b53_arl_entry *ent) +{ +u32 fwd_entry; +u64 mac_vid; + +b53_read64 (dev,B53_ARLIO_PAGE ,B53_ARL_SRCH_RSTL_MACVID (idx), + &mac_vid); +b53_read32 (dev,B53_ARLIO_PAGE ,B53_ARL_SRCH_RSTL (idx), + &fwd_entry); +b53_arl_to_entry (ent, mac_vid, fwd_entry); +} + +static void b53_arl_search_rd (struct b53_device *dev,u8 idx, +struct b53_arl_entry *ent) +{ +if (is5325 (dev)) +b53_arl_search_read_25 (dev, idx, ent); +else if (is5365 (dev)) +b53_arl_search_read_65 (dev, idx, ent); +else +b53_arl_search_read_95 (dev, idx, ent); } static int b53_fdb_copy(int port, const struct b53_arl_entry *ent,
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 513/614 net: dsa: b53: move ARL entry functions into ops struct
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jonas Gorski <[email protected]>
[ Upstream commit a7e73339ad46ade76d29fb6cc7d7854222608c26 ]
Now that the differences in ARL entry formats are neatly contained into functions per chip family, wrap them into an ops struct and add wrapper functions to access them.
Stable-dep-of: 8e46aacea426 ("net: dsa: b53: use same ARL search result offset for BCM5325/65")
--- drivers/net/dsa/b53/b53_common.c | 67 ++++++++++++++++++++++---------- drivers/net/dsa/b53/b53_priv.h | 30 ++++++++++++++ 2 files changed, 76 insertions(+), 21 deletions(-)
drivers/net/dsa/b53/b53_common.c +46 -21
@@ -1890,10 +1890,7 @@ static int b53_arl_read(struct b53_device *dev, const u8 *mac,/* Read the bins */ for (i =0 ; i < dev->num_arl_bins; i++) { -if (is5325 (dev) ||is5365 (dev)) -b53_arl_read_entry_25 (dev, ent, i); -else -b53_arl_read_entry_95 (dev, ent, i); +b53_arl_read_entry (dev, ent, i);if (!ent->is_valid) {set_bit (i, free_bins);
@@ -1979,10 +1976,7 @@ static int b53_arl_op(struct b53_device *dev, int op, int port, ent.is_static = true; ent.is_age = false;memcpy (ent.mac, addr,ETH_ALEN ); -if (is5325 (dev) ||is5365 (dev)) -b53_arl_write_entry_25 (dev, &ent, idx); -else -b53_arl_write_entry_95 (dev, &ent, idx); +b53_arl_write_entry (dev, &ent, idx);return b53_arl_rw_op (dev,0 ); }
@@ -2093,17 +2087,6 @@ static void b53_arl_search_read_95(struct b53_device *dev, u8 idx,b53_arl_to_entry (ent, mac_vid, fwd_entry); } -static void b53_arl_search_rd (struct b53_device *dev,u8 idx, -struct b53_arl_entry *ent) -{ -if (is5325 (dev)) -b53_arl_search_read_25 (dev, idx, ent); -else if (is5365 (dev)) -b53_arl_search_read_65 (dev, idx, ent); -else -b53_arl_search_read_95 (dev, idx, ent); -} -static int b53_fdb_copy (int port,const struct b53_arl_entry *ent,dsa_fdb_dump_cb_t *cb,void *data) {
@@ -2137,13 +2120,13 @@ int b53_fdb_dump(struct dsa_switch *ds, int port,if (ret)break ; -b53_arl_search_rd (priv,0 , &results[0 ]); +b53_arl_search_read (priv,0 , &results[0 ]); ret =b53_fdb_copy (port, &results[0 ], cb, data);if (ret)break ;if (results_per_hit ==2 ) { -b53_arl_search_rd (priv,1 , &results[1 ]); +b53_arl_search_read (priv,1 , &results[1 ]); ret =b53_fdb_copy (port, &results[1 ], cb, data);if (ret)break ;
@@ -2669,6 +2652,24 @@ static const struct dsa_switch_ops b53_switch_ops = { .port_change_mtu = b53_change_mtu, }; +static const struct b53_arl_ops b53_arl_ops_25 = { + .arl_read_entry = b53_arl_read_entry_25, + .arl_write_entry = b53_arl_write_entry_25, + .arl_search_read = b53_arl_search_read_25, +}; + +static const struct b53_arl_ops b53_arl_ops_65 = { + .arl_read_entry = b53_arl_read_entry_25, + .arl_write_entry = b53_arl_write_entry_25, + .arl_search_read = b53_arl_search_read_65, +}; + +static const struct b53_arl_ops b53_arl_ops_95 = { + .arl_read_entry = b53_arl_read_entry_95, + .arl_write_entry = b53_arl_write_entry_95, + .arl_search_read = b53_arl_search_read_95, +}; +struct b53_chip_data {u32 chip_id;const char *dev_name;
@@ -2682,6 +2683,7 @@ struct b53_chip_data {u8 duplex_reg;u8 jumbo_pm_reg;u8 jumbo_size_reg; +const struct b53_arl_ops *arl_ops; };#define B53_VTA_REGS \
@@ -2701,6 +2703,7 @@ static const struct b53_chip_data b53_switch_chips[] = { .arl_buckets = 1024, .imp_port = 5, .duplex_reg = B53_DUPLEX_STAT_FE, + .arl_ops = &b53_arl_ops_25, }, { .chip_id = BCM5365_DEVICE_ID,
@@ -2711,6 +2714,7 @@ static const struct b53_chip_data b53_switch_chips[] = { .arl_buckets = 1024, .imp_port = 5, .duplex_reg = B53_DUPLEX_STAT_FE, + .arl_ops = &b53_arl_ops_65, }, { .chip_id = BCM5389_DEVICE_ID,
@@ -2724,6 +2728,7 @@ static const struct b53_chip_data b53_switch_chips[] = { .duplex_reg = B53_DUPLEX_STAT_GE, .jumbo_pm_reg = B53_JUMBO_PORT_MASK, .jumbo_size_reg = B53_JUMBO_MAX_SIZE, + .arl_ops = &b53_arl_ops_95, }, { .chip_id = BCM5395_DEVICE_ID,
@@ -2737,6 +2742,7 @@ static const struct b53_chip_data b53_switch_chips[] = { .duplex_reg = B53_DUPLEX_STAT_GE, .jumbo_pm_reg = B53_JUMBO_PORT_MASK, .jumbo_size_reg = B53_JUMBO_MAX_SIZE, + .arl_ops = &b53_arl_ops_95, }, { .chip_id = BCM5397_DEVICE_ID,
@@ -2750,6 +2756,7 @@ static const struct b53_chip_data b53_switch_chips[] = { .duplex_reg = B53_DUPLEX_STAT_GE, .jumbo_pm_reg = B53_JUMBO_PORT_MASK, .jumbo_size_reg = B53_JUMBO_MAX_SIZE, + .arl_ops = &b53_arl_ops_95, }, { .chip_id = BCM5398_DEVICE_ID,
@@ -2763,6 +2770,7 @@ static const struct b53_chip_data b53_switch_chips[] = { .duplex_reg = B53_DUPLEX_STAT_GE, .jumbo_pm_reg = B53_JUMBO_PORT_MASK, .jumbo_size_reg = B53_JUMBO_MAX_SIZE, + .arl_ops = &b53_arl_ops_95, }, { .chip_id = BCM53101_DEVICE_ID,
@@ -2776,6 +2784,7 @@ static const struct b53_chip_data b53_switch_chips[] = { .duplex_reg = B53_DUPLEX_STAT_GE, .jumbo_pm_reg = B53_JUMBO_PORT_MASK, .jumbo_size_reg = B53_JUMBO_MAX_SIZE, + .arl_ops = &b53_arl_ops_95, }, { .chip_id = BCM53115_DEVICE_ID,
@@ -2789,6 +2798,7 @@ static const struct b53_chip_data b53_switch_chips[] = { .duplex_reg = B53_DUPLEX_STAT_GE, .jumbo_pm_reg = B53_JUMBO_PORT_MASK, .jumbo_size_reg = B53_JUMBO_MAX_SIZE, + .arl_ops = &b53_arl_ops_95, }, { .chip_id = BCM53125_DEVICE_ID,
@@ -2802,6 +2812,7 @@ static const struct b53_chip_data b53_switch_chips[] = { .duplex_reg = B53_DUPLEX_STAT_GE, .jumbo_pm_reg = B53_JUMBO_PORT_MASK, .jumbo_size_reg = B53_JUMBO_MAX_SIZE, + .arl_ops = &b53_arl_ops_95, }, { .chip_id = BCM53128_DEVICE_ID,
@@ -2815,6 +2826,7 @@ static const struct b53_chip_data b53_switch_chips[] = { .duplex_reg = B53_DUPLEX_STAT_GE, .jumbo_pm_reg = B53_JUMBO_PORT_MASK, .jumbo_size_reg = B53_JUMBO_MAX_SIZE, + .arl_ops = &b53_arl_ops_95, }, { .chip_id = BCM63XX_DEVICE_ID,
@@ -2828,6 +2840,7 @@ static const struct b53_chip_data b53_switch_chips[] = { .duplex_reg = B53_DUPLEX_STAT_63XX, .jumbo_pm_reg = B53_JUMBO_PORT_MASK_63XX, .jumbo_size_reg = B53_JUMBO_MAX_SIZE_63XX, + .arl_ops = &b53_arl_ops_95, }, { .chip_id = BCM53010_DEVICE_ID,
@@ -2841,6 +2854,7 @@ static const struct b53_chip_data b53_switch_chips[] = { .duplex_reg = B53_DUPLEX_STAT_GE, .jumbo_pm_reg = B53_JUMBO_PORT_MASK, .jumbo_size_reg = B53_JUMBO_MAX_SIZE, + .arl_ops = &b53_arl_ops_95, }, { .chip_id = BCM53011_DEVICE_ID,
@@ -2854,6 +2868,7 @@ static const struct b53_chip_data b53_switch_chips[] = { .duplex_reg = B53_DUPLEX_STAT_GE, .jumbo_pm_reg = B53_JUMBO_PORT_MASK, .jumbo_size_reg = B53_JUMBO_MAX_SIZE, + .arl_ops = &b53_arl_ops_95, }, { .chip_id = BCM53012_DEVICE_ID,
@@ -2867,6 +2882,7 @@ static const struct b53_chip_data b53_switch_chips[] = { .duplex_reg = B53_DUPLEX_STAT_GE, .jumbo_pm_reg = B53_JUMBO_PORT_MASK, .jumbo_size_reg = B53_JUMBO_MAX_SIZE, + .arl_ops = &b53_arl_ops_95, }, { .chip_id = BCM53018_DEVICE_ID,
@@ -2880,6 +2896,7 @@ static const struct b53_chip_data b53_switch_chips[] = { .duplex_reg = B53_DUPLEX_STAT_GE, .jumbo_pm_reg = B53_JUMBO_PORT_MASK, .jumbo_size_reg = B53_JUMBO_MAX_SIZE, + .arl_ops = &b53_arl_ops_95, }, { .chip_id = BCM53019_DEVICE_ID,
@@ -2893,6 +2910,7 @@ static const struct b53_chip_data b53_switch_chips[] = { .duplex_reg = B53_DUPLEX_STAT_GE, .jumbo_pm_reg = B53_JUMBO_PORT_MASK, .jumbo_size_reg = B53_JUMBO_MAX_SIZE, + .arl_ops = &b53_arl_ops_95, }, { .chip_id = BCM58XX_DEVICE_ID,
@@ -2906,6 +2924,7 @@ static const struct b53_chip_data b53_switch_chips[] = { .duplex_reg = B53_DUPLEX_STAT_GE, .jumbo_pm_reg = B53_JUMBO_PORT_MASK, .jumbo_size_reg = B53_JUMBO_MAX_SIZE, + .arl_ops = &b53_arl_ops_95, }, { .chip_id = BCM583XX_DEVICE_ID,
@@ -2919,6 +2938,7 @@ static const struct b53_chip_data b53_switch_chips[] = { .duplex_reg = B53_DUPLEX_STAT_GE, .jumbo_pm_reg = B53_JUMBO_PORT_MASK, .jumbo_size_reg = B53_JUMBO_MAX_SIZE, + .arl_ops = &b53_arl_ops_95, },/* Starfighter 2 */ {
@@ -2933,6 +2953,7 @@ static const struct b53_chip_data b53_switch_chips[] = { .duplex_reg = B53_DUPLEX_STAT_GE, .jumbo_pm_reg = B53_JUMBO_PORT_MASK, .jumbo_size_reg = B53_JUMBO_MAX_SIZE, + .arl_ops = &b53_arl_ops_95, }, { .chip_id = BCM7445_DEVICE_ID,
@@ -2946,6 +2967,7 @@ static const struct b53_chip_data b53_switch_chips[] = { .duplex_reg = B53_DUPLEX_STAT_GE, .jumbo_pm_reg = B53_JUMBO_PORT_MASK, .jumbo_size_reg = B53_JUMBO_MAX_SIZE, + .arl_ops = &b53_arl_ops_95, }, { .chip_id = BCM7278_DEVICE_ID,
@@ -2959,6 +2981,7 @@ static const struct b53_chip_data b53_switch_chips[] = { .duplex_reg = B53_DUPLEX_STAT_GE, .jumbo_pm_reg = B53_JUMBO_PORT_MASK, .jumbo_size_reg = B53_JUMBO_MAX_SIZE, + .arl_ops = &b53_arl_ops_95, }, { .chip_id = BCM53134_DEVICE_ID,
@@ -2973,6 +2996,7 @@ static const struct b53_chip_data b53_switch_chips[] = { .duplex_reg = B53_DUPLEX_STAT_GE, .jumbo_pm_reg = B53_JUMBO_PORT_MASK, .jumbo_size_reg = B53_JUMBO_MAX_SIZE, + .arl_ops = &b53_arl_ops_95, }, };
@@ -3001,6 +3025,7 @@ static int b53_switch_init(struct b53_device *dev) dev->num_vlans = chip->vlans; dev->num_arl_bins = chip->arl_bins; dev->num_arl_buckets = chip->arl_buckets; + dev->arl_ops = chip->arl_ops;break ; } }
drivers/net/dsa/b53/b53_priv.h +30 -0
@@ -58,6 +58,17 @@ struct b53_io_ops { bool link_up); }; +struct b53_arl_entry ; + +struct b53_arl_ops { +void (*arl_read_entry)(struct b53_device *dev, +struct b53_arl_entry *ent,u8 idx); +void (*arl_write_entry)(struct b53_device *dev, +const struct b53_arl_entry *ent,u8 idx); +void (*arl_search_read)(struct b53_device *dev,u8 idx, +struct b53_arl_entry *ent); +}; +#define B53_INVALID_LANE 0xffenum {
@@ -127,6 +138,7 @@ struct b53_device {struct mutex stats_mutex;struct mutex arl_mutex;const struct b53_io_ops *ops; +const struct b53_arl_ops *arl_ops;/* chip specific data */ u32 chip_id;
@@ -371,6 +383,24 @@ static inline void b53_arl_from_entry_25(u64 *mac_vid, *mac_vid |=ARLTBL_AGE_25 ; } +static inline void b53_arl_read_entry (struct b53_device *dev, +struct b53_arl_entry *ent,u8 idx) +{ + dev->arl_ops->arl_read_entry (dev, ent, idx); +} + +static inline void b53_arl_write_entry (struct b53_device *dev, +const struct b53_arl_entry *ent,u8 idx) +{ + dev->arl_ops->arl_write_entry (dev, ent, idx); +} + +static inline void b53_arl_search_read (struct b53_device *dev,u8 idx, +struct b53_arl_entry *ent) +{ + dev->arl_ops->arl_search_read (dev, idx, ent); +} +#ifdef CONFIG_BCM47XX #include <linux/bcm47xx_nvram.h>
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 514/614 net: dsa: b53: add support for 5389/5397/5398 ARL entry format
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jonas Gorski <[email protected]>
[ Upstream commit 300f78e8b6b7be17c2c78afeded75be68acb1aa7 ]
BCM5389, BCM5397 and BCM5398 use a different ARL entry format with just a 16 bit fwdentry register, as well as different search control and data offsets.
So add appropriate ops for them and switch those chips to use them.
Stable-dep-of: 8e46aacea426 ("net: dsa: b53: use same ARL search result offset for BCM5325/65")
--- drivers/net/dsa/b53/b53_common.c | 53 ++++++++++++++++++++++++++++++-- drivers/net/dsa/b53/b53_priv.h | 26 ++++++++++++++++ drivers/net/dsa/b53/b53_regs.h | 13 ++++++++ 3 files changed, 89 insertions(+), 3 deletions(-)
drivers/net/dsa/b53/b53_common.c +50 -3
@@ -1850,6 +1850,31 @@ static void b53_arl_write_entry_25(struct b53_device *dev, mac_vid); } +static void b53_arl_read_entry_89 (struct b53_device *dev, +struct b53_arl_entry *ent,u8 idx) +{ +u64 mac_vid; +u16 fwd_entry; + +b53_read64 (dev,B53_ARLIO_PAGE ,B53_ARLTBL_MAC_VID_ENTRY (idx), + &mac_vid); +b53_read16 (dev,B53_ARLIO_PAGE ,B53_ARLTBL_DATA_ENTRY (idx), &fwd_entry); +b53_arl_to_entry_89 (ent, mac_vid, fwd_entry); +} + +static void b53_arl_write_entry_89 (struct b53_device *dev, +const struct b53_arl_entry *ent,u8 idx) +{ +u32 fwd_entry; +u64 mac_vid; + +b53_arl_from_entry_89 (&mac_vid, &fwd_entry, ent); +b53_write64 (dev,B53_ARLIO_PAGE , +B53_ARLTBL_MAC_VID_ENTRY (idx), mac_vid); +b53_write16 (dev,B53_ARLIO_PAGE , +B53_ARLTBL_DATA_ENTRY (idx), fwd_entry); +} +static void b53_arl_read_entry_95 (struct b53_device *dev,struct b53_arl_entry *ent,u8 idx) {
@@ -2017,6 +2042,8 @@ static void b53_read_arl_srch_ctl(struct b53_device *dev, u8 *val)if (is5325 (dev) ||is5365 (dev)) offset =B53_ARL_SRCH_CTL_25 ; +else if (dev->chip_id ==BCM5389_DEVICE_ID ||is5397_98 (dev)) + offset =B53_ARL_SRCH_CTL_89 ;else offset =B53_ARL_SRCH_CTL ;
@@ -2029,6 +2056,8 @@ static void b53_write_arl_srch_ctl(struct b53_device *dev, u8 val)if (is5325 (dev) ||is5365 (dev)) offset =B53_ARL_SRCH_CTL_25 ; +else if (dev->chip_id ==BCM5389_DEVICE_ID ||is5397_98 (dev)) + offset =B53_ARL_SRCH_CTL_89 ;else offset =B53_ARL_SRCH_CTL ;
@@ -2074,6 +2103,18 @@ static void b53_arl_search_read_65(struct b53_device *dev, u8 idx,b53_arl_to_entry_25 (ent, mac_vid); } +static void b53_arl_search_read_89 (struct b53_device *dev,u8 idx, +struct b53_arl_entry *ent) +{ +u16 fwd_entry; +u64 mac_vid; + +b53_read64 (dev,B53_ARLIO_PAGE ,B53_ARL_SRCH_RSLT_MACVID_89 , + &mac_vid); +b53_read16 (dev,B53_ARLIO_PAGE ,B53_ARL_SRCH_RSLT_89 , &fwd_entry); +b53_arl_to_entry_89 (ent, mac_vid, fwd_entry); +} +static void b53_arl_search_read_95 (struct b53_device *dev,u8 idx,struct b53_arl_entry *ent) {
@@ -2664,6 +2705,12 @@ static const struct b53_arl_ops b53_arl_ops_65 = { .arl_search_read = b53_arl_search_read_65, }; +static const struct b53_arl_ops b53_arl_ops_89 = { + .arl_read_entry = b53_arl_read_entry_89, + .arl_write_entry = b53_arl_write_entry_89, + .arl_search_read = b53_arl_search_read_89, +}; +static const struct b53_arl_ops b53_arl_ops_95 = { .arl_read_entry = b53_arl_read_entry_95, .arl_write_entry = b53_arl_write_entry_95,
@@ -2728,7 +2775,7 @@ static const struct b53_chip_data b53_switch_chips[] = { .duplex_reg = B53_DUPLEX_STAT_GE, .jumbo_pm_reg = B53_JUMBO_PORT_MASK, .jumbo_size_reg = B53_JUMBO_MAX_SIZE, - .arl_ops = &b53_arl_ops_95, + .arl_ops = &b53_arl_ops_89, }, { .chip_id = BCM5395_DEVICE_ID,
@@ -2756,7 +2803,7 @@ static const struct b53_chip_data b53_switch_chips[] = { .duplex_reg = B53_DUPLEX_STAT_GE, .jumbo_pm_reg = B53_JUMBO_PORT_MASK, .jumbo_size_reg = B53_JUMBO_MAX_SIZE, - .arl_ops = &b53_arl_ops_95, + .arl_ops = &b53_arl_ops_89, }, { .chip_id = BCM5398_DEVICE_ID,
@@ -2770,7 +2817,7 @@ static const struct b53_chip_data b53_switch_chips[] = { .duplex_reg = B53_DUPLEX_STAT_GE, .jumbo_pm_reg = B53_JUMBO_PORT_MASK, .jumbo_size_reg = B53_JUMBO_MAX_SIZE, - .arl_ops = &b53_arl_ops_95, + .arl_ops = &b53_arl_ops_89, }, { .chip_id = BCM53101_DEVICE_ID,
drivers/net/dsa/b53/b53_priv.h +26 -0
@@ -353,6 +353,18 @@ static inline void b53_arl_to_entry_25(struct b53_arl_entry *ent, ent->vid = (mac_vid >>ARLTBL_VID_S_65 ) &ARLTBL_VID_MASK_25 ; } +static inline void b53_arl_to_entry_89 (struct b53_arl_entry *ent, +u64 mac_vid,u16 fwd_entry) +{ +memset (ent,0 ,sizeof (*ent)); + ent->port = fwd_entry &ARLTBL_DATA_PORT_ID_MASK_89 ; + ent->is_valid = !!(fwd_entry &ARLTBL_VALID_89 ); + ent->is_age = !!(fwd_entry &ARLTBL_AGE_89 ); + ent->is_static = !!(fwd_entry &ARLTBL_STATIC_89 ); +u64_to_ether_addr (mac_vid, ent->mac); + ent->vid = mac_vid >>ARLTBL_VID_S ; +} +static inline void b53_arl_from_entry (u64 *mac_vid,u32 *fwd_entry,const struct b53_arl_entry *ent) {
@@ -383,6 +395,20 @@ static inline void b53_arl_from_entry_25(u64 *mac_vid, *mac_vid |=ARLTBL_AGE_25 ; } +static inline void b53_arl_from_entry_89 (u64 *mac_vid,u32 *fwd_entry, +const struct b53_arl_entry *ent) +{ + *mac_vid =ether_addr_to_u64 (ent->mac); + *mac_vid |= (u64)(ent->vid &ARLTBL_VID_MASK ) <<ARLTBL_VID_S ; + *fwd_entry = ent->port &ARLTBL_DATA_PORT_ID_MASK_89 ; +if (ent->is_valid) + *fwd_entry |=ARLTBL_VALID_89 ; +if (ent->is_static) + *fwd_entry |=ARLTBL_STATIC_89 ; +if (ent->is_age) + *fwd_entry |=ARLTBL_AGE_89 ; +} +static inline void b53_arl_read_entry (struct b53_device *dev,struct b53_arl_entry *ent,u8 idx) {
drivers/net/dsa/b53/b53_regs.h +13 -0
@@ -342,12 +342,20 @@#define ARLTBL_STATIC BIT(15)#define ARLTBL_VALID BIT(16) +/* BCM5389 ARL Table Data Entry N Register format (16 bit) */ +#define ARLTBL_DATA_PORT_ID_MASK_89 GENMASK(8, 0) +#define ARLTBL_TC_MASK_89 GENMASK(12, 10) +#define ARLTBL_AGE_89 BIT(13) +#define ARLTBL_STATIC_89 BIT(14) +#define ARLTBL_VALID_89 BIT(15) +/* Maximum number of bin entries in the ARL for all switches */ #define B53_ARLTBL_MAX_BIN_ENTRIES 4/* ARL Search Control Register (8 bit) */ #define B53_ARL_SRCH_CTL 0x50#define B53_ARL_SRCH_CTL_25 0x20 +#define B53_ARL_SRCH_CTL_89 0x30#define ARL_SRCH_VLID BIT(0)#define ARL_SRCH_STDN BIT(7)
@@ -355,10 +363,12 @@#define B53_ARL_SRCH_ADDR 0x51#define B53_ARL_SRCH_ADDR_25 0x22#define B53_ARL_SRCH_ADDR_65 0x24 +#define B53_ARL_SRCH_ADDR_89 0x31#define ARL_ADDR_MASK GENMASK(14, 0)/* ARL Search MAC/VID Result (64 bit) */ #define B53_ARL_SRCH_RSTL_0_MACVID 0x60 +#define B53_ARL_SRCH_RSLT_MACVID_89 0x33/* Single register search result on 5325 */ #define B53_ARL_SRCH_RSTL_0_MACVID_25 0x24
@@ -368,6 +378,9 @@/* ARL Search Data Result (32 bit) */ #define B53_ARL_SRCH_RSTL_0 0x68 +/* BCM5389 ARL Search Data Result (16 bit) */ +#define B53_ARL_SRCH_RSLT_89 0x3b +#define B53_ARL_SRCH_RSTL_MACVID (x) (B53_ARL_SRCH_RSTL_0_MACVID + ((x) * 0x10))#define B53_ARL_SRCH_RSTL (x) (B53_ARL_SRCH_RSTL_0 + ((x) * 0x10))
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 515/614 net: dsa: b53: use same ARL search result offset for BCM5325/65
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jonas Gorski <[email protected]>
[ Upstream commit 8e46aacea4264bcb8d4265fb07577afff58ae78d ]
BCM5365's search result is at the same offset as BCM5325's search result, and they (mostly) share the same format, so switch BCM5365 to BCM5325's arl ops.
--- drivers/net/dsa/b53/b53_common.c | 18 +----------------- drivers/net/dsa/b53/b53_regs.h | 4 +--- 2 files changed, 2 insertions(+), 20 deletions(-)
drivers/net/dsa/b53/b53_common.c +1 -17
@@ -2093,16 +2093,6 @@ static void b53_arl_search_read_25(struct b53_device *dev, u8 idx,b53_arl_to_entry_25 (ent, mac_vid); } -static void b53_arl_search_read_65 (struct b53_device *dev,u8 idx, -struct b53_arl_entry *ent) -{ -u64 mac_vid; - -b53_read64 (dev,B53_ARLIO_PAGE ,B53_ARL_SRCH_RSTL_0_MACVID_65 , - &mac_vid); -b53_arl_to_entry_25 (ent, mac_vid); -} -static void b53_arl_search_read_89 (struct b53_device *dev,u8 idx,struct b53_arl_entry *ent) {
@@ -2699,12 +2689,6 @@ static const struct b53_arl_ops b53_arl_ops_25 = { .arl_search_read = b53_arl_search_read_25, }; -static const struct b53_arl_ops b53_arl_ops_65 = { - .arl_read_entry = b53_arl_read_entry_25, - .arl_write_entry = b53_arl_write_entry_25, - .arl_search_read = b53_arl_search_read_65, -}; -static const struct b53_arl_ops b53_arl_ops_89 = { .arl_read_entry = b53_arl_read_entry_89, .arl_write_entry = b53_arl_write_entry_89,
@@ -2761,7 +2745,7 @@ static const struct b53_chip_data b53_switch_chips[] = { .arl_buckets = 1024, .imp_port = 5, .duplex_reg = B53_DUPLEX_STAT_FE, - .arl_ops = &b53_arl_ops_65, + .arl_ops = &b53_arl_ops_25, }, { .chip_id = BCM5389_DEVICE_ID,
drivers/net/dsa/b53/b53_regs.h +1 -3
@@ -370,10 +370,8 @@#define B53_ARL_SRCH_RSTL_0_MACVID 0x60#define B53_ARL_SRCH_RSLT_MACVID_89 0x33 -/* Single register search result on 5325 */ +/* Single register search result on 5325/5365 */ #define B53_ARL_SRCH_RSTL_0_MACVID_25 0x24 -/* Single register search result on 5365 */ -#define B53_ARL_SRCH_RSTL_0_MACVID_65 0x30/* ARL Search Data Result (32 bit) */ #define B53_ARL_SRCH_RSTL_0 0x68
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 516/614 net: dsa: b53: fix CPU port unicast ARL entries for BCM5325/65
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jonas Gorski <[email protected]>
[ Upstream commit 85132103f700b1340fc17df8a981509d17bf4872 ]
On BCM5325 and BCM5365, unicast ARL entries use 8 as the value for the CPU port, so we need to translate it to/from 5 as used for the CPU port at most other places.
--- drivers/net/dsa/b53/b53_priv.h | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-)
drivers/net/dsa/b53/b53_priv.h +9 -4
@@ -344,12 +344,14 @@ static inline void b53_arl_to_entry_25(struct b53_arl_entry *ent, u64 mac_vid) {memset (ent,0 ,sizeof (*ent)); - ent->port = (mac_vid >>ARLTBL_DATA_PORT_ID_S_25 ) & -ARLTBL_DATA_PORT_ID_MASK_25 ; ent->is_valid = !!(mac_vid &ARLTBL_VALID_25 ); ent->is_age = !!(mac_vid &ARLTBL_AGE_25 ); ent->is_static = !!(mac_vid &ARLTBL_STATIC_25 );u64_to_ether_addr (mac_vid, ent->mac); + ent->port = (mac_vid >>ARLTBL_DATA_PORT_ID_S_25 ) & +ARLTBL_DATA_PORT_ID_MASK_25 ; +if (is_unicast_ether_addr (ent->mac) && ent->port ==B53_CPU_PORT ) + ent->port =B53_CPU_PORT_25 ; ent->vid = (mac_vid >>ARLTBL_VID_S_65 ) &ARLTBL_VID_MASK_25 ; }
@@ -383,8 +385,11 @@ static inline void b53_arl_from_entry_25(u64 *mac_vid, const struct b53_arl_entry *ent) { *mac_vid =ether_addr_to_u64 (ent->mac); - *mac_vid |= (u64)(ent->port &ARLTBL_DATA_PORT_ID_MASK_25 ) << -ARLTBL_DATA_PORT_ID_S_25 ; +if (is_unicast_ether_addr (ent->mac) && ent->port ==B53_CPU_PORT_25 ) + *mac_vid |= (u64 )B53_CPU_PORT <<ARLTBL_DATA_PORT_ID_S_25 ; +else + *mac_vid |= (u64)(ent->port &ARLTBL_DATA_PORT_ID_MASK_25 ) << +ARLTBL_DATA_PORT_ID_S_25 ; *mac_vid |= (u64)(ent->vid &ARLTBL_VID_MASK_25 ) <<ARLTBL_VID_S_65 ;if (ent->is_valid)
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 517/614 net: dsa: b53: add support for bcm63xx ARL entry format
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jonas Gorski <[email protected]>
[ Upstream commit 2b3013ac03028a2364d8779719bb6bfbc0212435 ]
The ARL registers of BCM63XX embedded switches are somewhat unique. The normal ARL table access registers have the same format as BCM5389, but the ARL search registers differ:
* SRCH_CTL is at the same offset of BCM5389, but 16 bits wide. It does not have more fields, just needs to be accessed by a 16 bit read.
* SRCH_RSLT_MACVID and SRCH_RSLT are aligned to 32 bit, and have shifted offsets.
* SRCH_RSLT has a different format than the normal ARL data entry register.
* There is only one set of ENTRY_N registers, implying a 1 bin layout.
So add appropriate ops for bcm63xx and let it use it.
Stable-dep-of: 3b08863469aa ("net: dsa: b53: fix BCM5325/65 ARL entry multicast port masks")
--- drivers/net/dsa/b53/b53_common.c | 44 +++++++++++++++++++++++++++----- drivers/net/dsa/b53/b53_priv.h | 15 +++++++++++ drivers/net/dsa/b53/b53_regs.h | 9 +++++++ 3 files changed, 61 insertions(+), 7 deletions(-)
drivers/net/dsa/b53/b53_common.c +37 -7
@@ -2042,12 +2042,20 @@ static void b53_read_arl_srch_ctl(struct b53_device *dev, u8 *val)if (is5325 (dev) ||is5365 (dev)) offset =B53_ARL_SRCH_CTL_25 ; -else if (dev->chip_id ==BCM5389_DEVICE_ID ||is5397_98 (dev)) +else if (dev->chip_id ==BCM5389_DEVICE_ID ||is5397_98 (dev) || +is63xx (dev)) offset =B53_ARL_SRCH_CTL_89 ;else offset =B53_ARL_SRCH_CTL ; -b53_read8 (dev,B53_ARLIO_PAGE , offset, val); +if (is63xx (dev)) { +u16 val16; + +b53_read16 (dev,B53_ARLIO_PAGE , offset, &val16); + *val = val16 &0xff ; + }else { +b53_read8 (dev,B53_ARLIO_PAGE , offset, val); + } }static void b53_write_arl_srch_ctl (struct b53_device *dev,u8 val)
@@ -2056,12 +2064,16 @@ static void b53_write_arl_srch_ctl(struct b53_device *dev, u8 val)if (is5325 (dev) ||is5365 (dev)) offset =B53_ARL_SRCH_CTL_25 ; -else if (dev->chip_id ==BCM5389_DEVICE_ID ||is5397_98 (dev)) +else if (dev->chip_id ==BCM5389_DEVICE_ID ||is5397_98 (dev) || +is63xx (dev)) offset =B53_ARL_SRCH_CTL_89 ;else offset =B53_ARL_SRCH_CTL ; -b53_write8 (dev,B53_ARLIO_PAGE , offset, val); +if (is63xx (dev)) +b53_write16 (dev,B53_ARLIO_PAGE , offset, val); +else +b53_write8 (dev,B53_ARLIO_PAGE , offset, val); }static int b53_arl_search_wait (struct b53_device *dev)
@@ -2105,6 +2117,18 @@ static void b53_arl_search_read_89(struct b53_device *dev, u8 idx,b53_arl_to_entry_89 (ent, mac_vid, fwd_entry); } +static void b53_arl_search_read_63xx (struct b53_device *dev,u8 idx, +struct b53_arl_entry *ent) +{ +u16 fwd_entry; +u64 mac_vid; + +b53_read64 (dev,B53_ARLIO_PAGE ,B53_ARL_SRCH_RSLT_MACVID_63XX , + &mac_vid); +b53_read16 (dev,B53_ARLIO_PAGE ,B53_ARL_SRCH_RSLT_63XX , &fwd_entry); +b53_arl_search_to_entry_63xx (ent, mac_vid, fwd_entry); +} +static void b53_arl_search_read_95 (struct b53_device *dev,u8 idx,struct b53_arl_entry *ent) {
@@ -2695,6 +2719,12 @@ static const struct b53_arl_ops b53_arl_ops_89 = { .arl_search_read = b53_arl_search_read_89, }; +static const struct b53_arl_ops b53_arl_ops_63xx = { + .arl_read_entry = b53_arl_read_entry_89, + .arl_write_entry = b53_arl_write_entry_89, + .arl_search_read = b53_arl_search_read_63xx, +}; +static const struct b53_arl_ops b53_arl_ops_95 = { .arl_read_entry = b53_arl_read_entry_95, .arl_write_entry = b53_arl_write_entry_95,
@@ -2864,14 +2894,14 @@ static const struct b53_chip_data b53_switch_chips[] = { .dev_name = "BCM63xx", .vlans = 4096, .enabled_ports = 0, /* pdata must provide them */ - .arl_bins = 4, - .arl_buckets = 1024, + .arl_bins = 1, + .arl_buckets = 4096, .imp_port = 8, .vta_regs = B53_VTA_REGS_63XX, .duplex_reg = B53_DUPLEX_STAT_63XX, .jumbo_pm_reg = B53_JUMBO_PORT_MASK_63XX, .jumbo_size_reg = B53_JUMBO_MAX_SIZE_63XX, - .arl_ops = &b53_arl_ops_95, + .arl_ops = &b53_arl_ops_63xx, }, { .chip_id = BCM53010_DEVICE_ID,
drivers/net/dsa/b53/b53_priv.h +15 -0
@@ -414,6 +414,21 @@ static inline void b53_arl_from_entry_89(u64 *mac_vid, u32 *fwd_entry, *fwd_entry |=ARLTBL_AGE_89 ; } +static inline void b53_arl_search_to_entry_63xx (struct b53_arl_entry *ent, +u64 mac_vid,u16 fwd_entry) +{ +memset (ent,0 ,sizeof (*ent)); +u64_to_ether_addr (mac_vid, ent->mac); + ent->vid = mac_vid >>ARLTBL_VID_S ; + + ent->port = fwd_entry &ARL_SRST_PORT_ID_MASK_63XX ; + ent->port >>=1 ; + + ent->is_age = !!(fwd_entry &ARL_SRST_AGE_63XX ); + ent->is_static = !!(fwd_entry &ARL_SRST_STATIC_63XX ); + ent->is_valid =1 ; +} +static inline void b53_arl_read_entry (struct b53_device *dev,struct b53_arl_entry *ent,u8 idx) {
drivers/net/dsa/b53/b53_regs.h +9 -0
@@ -364,11 +364,13 @@#define B53_ARL_SRCH_ADDR_25 0x22#define B53_ARL_SRCH_ADDR_65 0x24#define B53_ARL_SRCH_ADDR_89 0x31 +#define B53_ARL_SRCH_ADDR_63XX 0x32#define ARL_ADDR_MASK GENMASK(14, 0)/* ARL Search MAC/VID Result (64 bit) */ #define B53_ARL_SRCH_RSTL_0_MACVID 0x60#define B53_ARL_SRCH_RSLT_MACVID_89 0x33 +#define B53_ARL_SRCH_RSLT_MACVID_63XX 0x34/* Single register search result on 5325/5365 */ #define B53_ARL_SRCH_RSTL_0_MACVID_25 0x24
@@ -382,6 +384,13 @@#define B53_ARL_SRCH_RSTL_MACVID (x) (B53_ARL_SRCH_RSTL_0_MACVID + ((x) * 0x10))#define B53_ARL_SRCH_RSTL (x) (B53_ARL_SRCH_RSTL_0 + ((x) * 0x10)) +/* 63XX ARL Search Data Result (16 bit) */ +#define B53_ARL_SRCH_RSLT_63XX 0x3c +#define ARL_SRST_PORT_ID_MASK_63XX GENMASK(9, 1) +#define ARL_SRST_TC_MASK_63XX GENMASK(13, 11) +#define ARL_SRST_AGE_63XX BIT(14) +#define ARL_SRST_STATIC_63XX BIT(15) +/************************************************************************* * IEEE 802.1X Registers *************************************************************************/
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 518/614 net: dsa: b53: fix BCM5325/65 ARL entry multicast port masks
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jonas Gorski <[email protected]>
[ Upstream commit 3b08863469aa6028ac7c3120966f4e2f6051cf6b ]
We currently use the mask 0xf for writing and reading b53_entry::port, but this is only correct for unicast ARL entries. Multicast ARL entries use a bitmask, and 0xf is not enough space for ports > 3, which includes the CPU port.
So extend the mask accordingly to also fit port 4 (bit 4) and MII (bit 5). According to the datasheet the multicast port mask is [60:48], making it 12 bit wide, but bits 60-55 are reserved anyway, and collide with the priority field at [60:59], so I am not sure if this is valid. Therefore leave it at the actual used range, [53:48].
The ARL search result register differs a bit, and there the mask is only [52:48], so only spanning the user ports. The MII port bit is contained in the Search Result Extension register. So create a separate search result parse function that properly handles this.
--- drivers/net/dsa/b53/b53_common.c | 4 +++- drivers/net/dsa/b53/b53_priv.h | 25 +++++++++++++++++++++---- drivers/net/dsa/b53/b53_regs.h | 8 +++++++- 3 files changed, 31 insertions(+), 6 deletions(-)
drivers/net/dsa/b53/b53_common.c +3 -1
@@ -2099,10 +2099,12 @@ static void b53_arl_search_read_25(struct b53_device *dev, u8 idx, struct b53_arl_entry *ent) {u64 mac_vid; +u8 ext; +b53_read8 (dev,B53_ARLIO_PAGE ,B53_ARL_SRCH_RSLT_EXT_25 , &ext);b53_read64 (dev,B53_ARLIO_PAGE ,B53_ARL_SRCH_RSTL_0_MACVID_25 , &mac_vid); -b53_arl_to_entry_25 (ent, mac_vid); +b53_arl_search_to_entry_25 (ent, mac_vid, ext); } static void b53_arl_search_read_89(struct b53_device *dev, u8 idx,
drivers/net/dsa/b53/b53_priv.h +21 -4
@@ -348,8 +348,8 @@ static inline void b53_arl_to_entry_25(struct b53_arl_entry *ent, ent->is_age = !!(mac_vid &ARLTBL_AGE_25 ); ent->is_static = !!(mac_vid &ARLTBL_STATIC_25 );u64_to_ether_addr (mac_vid, ent->mac); - ent->port = (mac_vid >>ARLTBL_DATA_PORT_ID_S_25 ) & -ARLTBL_DATA_PORT_ID_MASK_25 ; + ent->port = (mac_vid &ARLTBL_DATA_PORT_ID_MASK_25 ) >> +ARLTBL_DATA_PORT_ID_S_25 ;if (is_unicast_ether_addr (ent->mac) && ent->port ==B53_CPU_PORT ) ent->port =B53_CPU_PORT_25 ; ent->vid = (mac_vid >>ARLTBL_VID_S_65 ) &ARLTBL_VID_MASK_25 ;
@@ -388,8 +388,8 @@ static inline void b53_arl_from_entry_25(u64 *mac_vid,if (is_unicast_ether_addr (ent->mac) && ent->port ==B53_CPU_PORT_25 ) *mac_vid |= (u64 )B53_CPU_PORT <<ARLTBL_DATA_PORT_ID_S_25 ;else - *mac_vid |= (u64)(ent->port &ARLTBL_DATA_PORT_ID_MASK_25 ) << -ARLTBL_DATA_PORT_ID_S_25 ; + *mac_vid |= ((u64 )ent->port <<ARLTBL_DATA_PORT_ID_S_25 ) & +ARLTBL_DATA_PORT_ID_MASK_25 ; *mac_vid |= (u64)(ent->vid &ARLTBL_VID_MASK_25 ) <<ARLTBL_VID_S_65 ;if (ent->is_valid)
@@ -414,6 +414,23 @@ static inline void b53_arl_from_entry_89(u64 *mac_vid, u32 *fwd_entry, *fwd_entry |=ARLTBL_AGE_89 ; } +static inline void b53_arl_search_to_entry_25 (struct b53_arl_entry *ent, +u64 mac_vid,u8 ext) +{ +memset (ent,0 ,sizeof (*ent)); + ent->is_valid = !!(mac_vid &ARLTBL_VALID_25 ); + ent->is_age = !!(mac_vid &ARLTBL_AGE_25 ); + ent->is_static = !!(mac_vid &ARLTBL_STATIC_25 ); +u64_to_ether_addr (mac_vid, ent->mac); + ent->vid = (mac_vid >>ARLTBL_VID_S_65 ) &ARLTBL_VID_MASK_25 ; + ent->port = (mac_vid &ARL_SRCH_RSLT_PORT_ID_MASK_25 ) >> +ARL_SRCH_RSLT_PORT_ID_S_25 ; +if (is_multicast_ether_addr (ent->mac) && (ext &ARL_SRCH_RSLT_EXT_MC_MII )) + ent->port |=BIT (B53_CPU_PORT_25 ); +else if (!is_multicast_ether_addr (ent->mac) && ent->port ==B53_CPU_PORT ) + ent->port =B53_CPU_PORT_25 ; +} +static inline void b53_arl_search_to_entry_63xx (struct b53_arl_entry *ent,u64 mac_vid,u16 fwd_entry) {
drivers/net/dsa/b53/b53_regs.h +7 -1
@@ -328,7 +328,7 @@#define ARLTBL_VID_MASK_25 0xff#define ARLTBL_VID_MASK 0xfff#define ARLTBL_DATA_PORT_ID_S_25 48 -#define ARLTBL_DATA_PORT_ID_MASK_25 0xf +#define ARLTBL_DATA_PORT_ID_MASK_25 GENMASK_ULL(53, 48)#define ARLTBL_VID_S_65 53#define ARLTBL_AGE_25 BIT_ULL(61)#define ARLTBL_STATIC_25 BIT_ULL(62)
@@ -374,6 +374,12 @@/* Single register search result on 5325/5365 */ #define B53_ARL_SRCH_RSTL_0_MACVID_25 0x24 +#define ARL_SRCH_RSLT_PORT_ID_S_25 48 +#define ARL_SRCH_RSLT_PORT_ID_MASK_25 GENMASK_ULL(52, 48) + +/* BCM5325/5365 Search result extend register (8 bit) */ +#define B53_ARL_SRCH_RSLT_EXT_25 0x2c +#define ARL_SRCH_RSLT_EXT_MC_MII BIT(2)/* ARL Search Data Result (32 bit) */ #define B53_ARL_SRCH_RSTL_0 0x68
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 519/614 net: dsa: b53: fix BCM5325/65 ARL entry VIDs
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jonas Gorski <[email protected]>
[ Upstream commit d39514e6a2d14f57830d649e2bf03b49612c2f73 ]
BCM5325/65's ARL entry registers do not contain the VID, only the search result register does. ARL entries have a separate VID entry register for the index into the VLAN table.
So make ARL entry accessors use the VID entry registers instead, and move the VLAN ID field definition to the search register definition.
--- drivers/net/dsa/b53/b53_common.c | 9 +++++++-- drivers/net/dsa/b53/b53_priv.h | 12 ++++++------ drivers/net/dsa/b53/b53_regs.h | 7 +++++-- 3 files changed, 18 insertions(+), 10 deletions(-)
drivers/net/dsa/b53/b53_common.c +7 -2
@@ -1833,19 +1833,24 @@ static int b53_arl_rw_op(struct b53_device *dev, unsigned int op)static void b53_arl_read_entry_25 (struct b53_device *dev,struct b53_arl_entry *ent,u8 idx) { +u8 vid_entry;u64 mac_vid; +b53_read8 (dev,B53_ARLIO_PAGE ,B53_ARLTBL_VID_ENTRY_25 (idx), + &vid_entry);b53_read64 (dev,B53_ARLIO_PAGE ,B53_ARLTBL_MAC_VID_ENTRY (idx), &mac_vid); -b53_arl_to_entry_25 (ent, mac_vid); +b53_arl_to_entry_25 (ent, mac_vid, vid_entry); }static void b53_arl_write_entry_25 (struct b53_device *dev,const struct b53_arl_entry *ent,u8 idx) { +u8 vid_entry;u64 mac_vid; -b53_arl_from_entry_25 (&mac_vid, ent); +b53_arl_from_entry_25 (&mac_vid, &vid_entry, ent); +b53_write8 (dev,B53_ARLIO_PAGE ,B53_ARLTBL_VID_ENTRY_25 (idx), vid_entry);b53_write64 (dev,B53_ARLIO_PAGE ,B53_ARLTBL_MAC_VID_ENTRY (idx), mac_vid); }
drivers/net/dsa/b53/b53_priv.h +6 -6
@@ -341,7 +341,7 @@ static inline void b53_arl_to_entry(struct b53_arl_entry *ent, }static inline void b53_arl_to_entry_25 (struct b53_arl_entry *ent, -u64 mac_vid) +u64 mac_vid,u8 vid_entry) {memset (ent,0 ,sizeof (*ent)); ent->is_valid = !!(mac_vid &ARLTBL_VALID_25 );
@@ -352,7 +352,7 @@ static inline void b53_arl_to_entry_25(struct b53_arl_entry *ent,ARLTBL_DATA_PORT_ID_S_25 ;if (is_unicast_ether_addr (ent->mac) && ent->port ==B53_CPU_PORT ) ent->port =B53_CPU_PORT_25 ; - ent->vid = (mac_vid >>ARLTBL_VID_S_65 ) &ARLTBL_VID_MASK_25 ; + ent->vid = vid_entry; } static inline void b53_arl_to_entry_89(struct b53_arl_entry *ent,
@@ -381,7 +381,7 @@ static inline void b53_arl_from_entry(u64 *mac_vid, u32 *fwd_entry, *fwd_entry |=ARLTBL_AGE ; } -static inline void b53_arl_from_entry_25 (u64 *mac_vid, +static inline void b53_arl_from_entry_25 (u64 *mac_vid,u8 *vid_entry,const struct b53_arl_entry *ent) { *mac_vid =ether_addr_to_u64 (ent->mac);
@@ -390,14 +390,13 @@ static inline void b53_arl_from_entry_25(u64 *mac_vid,else *mac_vid |= ((u64 )ent->port <<ARLTBL_DATA_PORT_ID_S_25 ) &ARLTBL_DATA_PORT_ID_MASK_25 ; - *mac_vid |= (u64)(ent->vid &ARLTBL_VID_MASK_25 ) << -ARLTBL_VID_S_65 ;if (ent->is_valid) *mac_vid |=ARLTBL_VALID_25 ;if (ent->is_static) *mac_vid |=ARLTBL_STATIC_25 ;if (ent->is_age) *mac_vid |=ARLTBL_AGE_25 ; + *vid_entry = ent->vid; } static inline void b53_arl_from_entry_89(u64 *mac_vid, u32 *fwd_entry,
@@ -422,7 +421,8 @@ static inline void b53_arl_search_to_entry_25(struct b53_arl_entry *ent, ent->is_age = !!(mac_vid &ARLTBL_AGE_25 ); ent->is_static = !!(mac_vid &ARLTBL_STATIC_25 );u64_to_ether_addr (mac_vid, ent->mac); - ent->vid = (mac_vid >>ARLTBL_VID_S_65 ) &ARLTBL_VID_MASK_25 ; + ent->vid = (mac_vid &ARL_SRCH_RSLT_VID_MASK_25 ) >> +ARL_SRCH_RSLT_VID_S_25 ; ent->port = (mac_vid &ARL_SRCH_RSLT_PORT_ID_MASK_25 ) >>ARL_SRCH_RSLT_PORT_ID_S_25 ;if (is_multicast_ether_addr (ent->mac) && (ext &ARL_SRCH_RSLT_EXT_MC_MII ))
drivers/net/dsa/b53/b53_regs.h +5 -2
@@ -325,11 +325,9 @@#define B53_ARLTBL_MAC_VID_ENTRY (n) ((0x10 * (n)) + 0x10)#define ARLTBL_MAC_MASK 0xffffffffffffULL#define ARLTBL_VID_S 48 -#define ARLTBL_VID_MASK_25 0xff#define ARLTBL_VID_MASK 0xfff#define ARLTBL_DATA_PORT_ID_S_25 48#define ARLTBL_DATA_PORT_ID_MASK_25 GENMASK_ULL(53, 48) -#define ARLTBL_VID_S_65 53#define ARLTBL_AGE_25 BIT_ULL(61)#define ARLTBL_STATIC_25 BIT_ULL(62)#define ARLTBL_VALID_25 BIT_ULL(63)
@@ -349,6 +347,9 @@#define ARLTBL_STATIC_89 BIT(14)#define ARLTBL_VALID_89 BIT(15) +/* BCM5325/BCM565 ARL Table VID Entry N Registers (8 bit) */ +#define B53_ARLTBL_VID_ENTRY_25 (n) ((0x2 * (n)) + 0x30) +/* Maximum number of bin entries in the ARL for all switches */ #define B53_ARLTBL_MAX_BIN_ENTRIES 4
@@ -376,6 +377,8 @@#define B53_ARL_SRCH_RSTL_0_MACVID_25 0x24#define ARL_SRCH_RSLT_PORT_ID_S_25 48#define ARL_SRCH_RSLT_PORT_ID_MASK_25 GENMASK_ULL(52, 48) +#define ARL_SRCH_RSLT_VID_S_25 53 +#define ARL_SRCH_RSLT_VID_MASK_25 GENMASK_ULL(60, 53)/* BCM5325/5365 Search result extend register (8 bit) */ #define B53_ARL_SRCH_RSLT_EXT_25 0x2c
Signature · 1 line
2.51.0