From: Javier Martinez Canillas javierm@redhat.com
[ Upstream commit 3367aa7d74d240261de2543ddb35531ccad9d884 ]
Drivers that want to remove registered conflicting framebuffers prior to register their own framebuffer, call to remove_conflicting_framebuffers().
This function takes the registration_lock mutex, to prevent a race when drivers register framebuffer devices. But if a conflicting framebuffer device is found, the underlaying platform device is unregistered and this will lead to the platform driver .remove callback to be called. Which in turn will call to unregister_framebuffer() that takes the same lock.
To prevent this, a struct fb_info.forced_out field was used as indication to unregister_framebuffer() whether the mutex has to be grabbed or not.
But this could be unsafe, since the fbdev core is making assumptions about what drivers may or may not do in their .remove callbacks. Allowing to run these callbacks with the registration_lock held can cause deadlocks, since the fbdev core has no control over what drivers do in their removal path.
A better solution is to drop the lock before platform_device_unregister(), so unregister_framebuffer() can take it when called from the fbdev driver. The lock is acquired again after the device has been unregistered and at this point the removal loop can be restarted.
Since the conflicting framebuffer device has already been removed, the loop would just finish when no more conflicting framebuffers are found.
Suggested-by: Daniel Vetter daniel.vetter@ffwll.ch Signed-off-by: Javier Martinez Canillas javierm@redhat.com Reviewed-by: Daniel Vetter daniel.vetter@ffwll.ch Link: https://patchwork.freedesktop.org/patch/msgid/20220511113039.1252432-1-javie... Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/video/fbdev/core/fbmem.c | 22 +++++++++++++++------- include/linux/fb.h | 1 - 2 files changed, 15 insertions(+), 8 deletions(-)
diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c index 7ee6eb2fa715..02b0cf2cfafe 100644 --- a/drivers/video/fbdev/core/fbmem.c +++ b/drivers/video/fbdev/core/fbmem.c @@ -1568,6 +1568,7 @@ static void do_remove_conflicting_framebuffers(struct apertures_struct *a, { int i;
+restart_removal: /* check all firmware fbs and kick off if the base addr overlaps */ for_each_registered_fb(i) { struct apertures_struct *gen_aper; @@ -1600,12 +1601,23 @@ static void do_remove_conflicting_framebuffers(struct apertures_struct *a, pr_warn("fb%d: no device set\n", i); do_unregister_framebuffer(registered_fb[i]); } else if (dev_is_platform(device)) { - registered_fb[i]->forced_out = true; + /* + * Drop the lock because if the device is unregistered, its + * driver will call to unregister_framebuffer(), that takes + * this lock. + */ + mutex_unlock(®istration_lock); platform_device_unregister(to_platform_device(device)); + mutex_lock(®istration_lock); } else { pr_warn("fb%d: cannot remove device\n", i); do_unregister_framebuffer(registered_fb[i]); } + /* + * Restart the removal loop now that the device has been + * unregistered and its associated framebuffer gone. + */ + goto restart_removal; } } } @@ -1876,13 +1888,9 @@ EXPORT_SYMBOL(register_framebuffer); void unregister_framebuffer(struct fb_info *fb_info) { - bool forced_out = fb_info->forced_out; - - if (!forced_out) - mutex_lock(®istration_lock); + mutex_lock(®istration_lock); do_unregister_framebuffer(fb_info); - if (!forced_out) - mutex_unlock(®istration_lock); + mutex_unlock(®istration_lock); } EXPORT_SYMBOL(unregister_framebuffer);
diff --git a/include/linux/fb.h b/include/linux/fb.h index 2892145468c9..07fcd0e56682 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -511,7 +511,6 @@ struct fb_info { } *apertures;
bool skip_vt_switch; /* no VT switch on suspend/resume required */ - bool forced_out; /* set when being removed by another driver */ };
static inline struct apertures_struct *alloc_apertures(unsigned int max_num) {
From: Borislav Petkov bp@suse.de
[ Upstream commit 6556551f8848f98eff356c8aacae42c8dd65b2df ]
Fix:
drivers/gpu/drm/r128/r128_cce.c: In function ‘r128_do_init_cce’: drivers/gpu/drm/r128/r128_cce.c:417:2: error: case label does not reduce to an integer constant case R128_PM4_64BM_64VCBM_64INDBM: ^~~~ drivers/gpu/drm/r128/r128_cce.c:418:2: error: case label does not reduce to an integer constant case R128_PM4_64PIO_64VCPIO_64INDPIO: ^~~~
See https://lore.kernel.org/r/YkwQ6%2BtIH8GQpuct@zn.tnic for the gory details as to why it triggers with older gccs only.
Reviewed-by: Randy Dunlap rdunlap@infradead.org Signed-off-by: Borislav Petkov bp@suse.de Cc: David Airlie airlied@linux.ie Cc: Daniel Vetter daniel@ffwll.ch Cc: Alex Deucher alexander.deucher@amd.com Cc: dri-devel@lists.freedesktop.org Signed-off-by: Daniel Vetter daniel.vetter@ffwll.ch Link: https://patchwork.freedesktop.org/patch/msgid/20220405151517.29753-5-bp@alie... Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/r128/r128_drv.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/r128/r128_drv.h b/drivers/gpu/drm/r128/r128_drv.h index 2e1bc01aa5c9..970e192b0d51 100644 --- a/drivers/gpu/drm/r128/r128_drv.h +++ b/drivers/gpu/drm/r128/r128_drv.h @@ -300,8 +300,8 @@ extern long r128_compat_ioctl(struct file *filp, unsigned int cmd, # define R128_PM4_64PIO_128INDBM (5 << 28) # define R128_PM4_64BM_128INDBM (6 << 28) # define R128_PM4_64PIO_64VCBM_64INDBM (7 << 28) -# define R128_PM4_64BM_64VCBM_64INDBM (8 << 28) -# define R128_PM4_64PIO_64VCPIO_64INDPIO (15 << 28) +# define R128_PM4_64BM_64VCBM_64INDBM (8U << 28) +# define R128_PM4_64PIO_64VCPIO_64INDPIO (15U << 28) # define R128_PM4_BUFFER_CNTL_NOUPDATE (1 << 27)
#define R128_PM4_BUFFER_WM_CNTL 0x0708
From: Sergey Ryazanov ryazanov.s.a@gmail.com
[ Upstream commit 70f119fb82af7f7417dc659faf02c91e1f853739 ]
The xmit path for the Ethernet encapsulated frames become more or less usable since d740d8fd2439 ("ath10k: unify tx mode and dispatch"). This change reorganize the xmit path in a manageable way to properly support various tx modes, but misses that the Ethernet encapsulated frame is a special case. We do not have an IEEE 802.11 header at the begining of them. But the HTT Tx handler still interprets first bytes of each frame as an IEEE 802.11 Frame Control field.
Than this code was copied by e62ee5c381c5 ("ath10k: Add support for htt_data_tx_desc_64 descriptor") and a2097d6444c3 ("ath10k: htt: High latency TX support") to another handlers. In fact the issue in the high latency (HL) handler was introduced by 83ac260151e7 ("ath10k: add mic bytes for pmf management packet").
Ethernet encapsulated frame tx mode stay unused until 75d85fd9993c ("ath10k: introduce basic tdls functionality") started using it for TDLS frames to avoid key selection issue in some firmwares.
Trying to interpret the begining of an Ethernet encapsulated frame as an IEEE 802.11 header was not hurt us noticeably since we need to meet two conditions: (1) xmit should be performed towards a TDLS peer, and (2) the TDLS peer should have a specific OUI part of its MAC address. Looks like that the rareness in TDLS communications of OUIs that can be interpreted as an 802.11 management frame saves users from facing this issue earlier.
Improve Ethernet tx mode support in the HTT Tx handler by avoiding interpreting its first bytes as an IEEE 802.11 header. While at it, make the ieee80211_hdr variable local to the code block that is guarded by !is_eth check. In this way, we clarify in which cases a frame can be interpreted as IEEE 802.11, and saves us from similar issues in the future.
Credits: this change as part of xmit encapsulation offloading support was originally made by QCA and then submitted for inclusion by John Crispin [1]. But the whole work was not accepted due to the lack of a part for 64-bits descriptors [2]. Zhijun You then pointed this out to me in a reply to my initial RFC patch series. And I made this slightly reworked version that covered all the HTT Tx handler variants.
1. https://lore.kernel.org/all/20191216092207.31032-1-john@phrozen.org/ 2. https://patchwork.kernel.org/project/linux-wireless/patch/20191216092207.310...
Reported-by: Zhijun You hujy652@gmail.com Signed-off-by: Vasanthakumar Thiagarajan vthiagar@qti.qualcomm.com Signed-off-by: John Crispin john@phrozen.org Signed-off-by: Sergey Ryazanov ryazanov.s.a@gmail.com Signed-off-by: Kalle Valo quic_kvalo@quicinc.com Link: https://lore.kernel.org/r/20220516032519.29831-3-ryazanov.s.a@gmail.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/wireless/ath/ath10k/htt_tx.c | 61 ++++++++++++++---------- 1 file changed, 35 insertions(+), 26 deletions(-)
diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c index 9842a4b2f78f..a19b0795c86d 100644 --- a/drivers/net/wireless/ath/ath10k/htt_tx.c +++ b/drivers/net/wireless/ath/ath10k/htt_tx.c @@ -1275,7 +1275,6 @@ static int ath10k_htt_tx_hl(struct ath10k_htt *htt, enum ath10k_hw_txrx_mode txm struct ath10k *ar = htt->ar; int res, data_len; struct htt_cmd_hdr *cmd_hdr; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)msdu->data; struct htt_data_tx_desc *tx_desc; struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(msdu); struct sk_buff *tmp_skb; @@ -1286,11 +1285,15 @@ static int ath10k_htt_tx_hl(struct ath10k_htt *htt, enum ath10k_hw_txrx_mode txm u16 flags1 = 0; u16 msdu_id = 0;
- if ((ieee80211_is_action(hdr->frame_control) || - ieee80211_is_deauth(hdr->frame_control) || - ieee80211_is_disassoc(hdr->frame_control)) && - ieee80211_has_protected(hdr->frame_control)) { - skb_put(msdu, IEEE80211_CCMP_MIC_LEN); + if (!is_eth) { + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)msdu->data; + + if ((ieee80211_is_action(hdr->frame_control) || + ieee80211_is_deauth(hdr->frame_control) || + ieee80211_is_disassoc(hdr->frame_control)) && + ieee80211_has_protected(hdr->frame_control)) { + skb_put(msdu, IEEE80211_CCMP_MIC_LEN); + } }
data_len = msdu->len; @@ -1387,7 +1390,6 @@ static int ath10k_htt_tx_32(struct ath10k_htt *htt, { struct ath10k *ar = htt->ar; struct device *dev = ar->dev; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)msdu->data; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(msdu); struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(msdu); struct ath10k_hif_sg_item sg_items[2]; @@ -1419,15 +1421,19 @@ static int ath10k_htt_tx_32(struct ath10k_htt *htt, txbuf_paddr = htt->txbuf.paddr + (sizeof(struct ath10k_htt_txbuf_32) * msdu_id);
- if ((ieee80211_is_action(hdr->frame_control) || - ieee80211_is_deauth(hdr->frame_control) || - ieee80211_is_disassoc(hdr->frame_control)) && - ieee80211_has_protected(hdr->frame_control)) { - skb_put(msdu, IEEE80211_CCMP_MIC_LEN); - } else if (!(skb_cb->flags & ATH10K_SKB_F_NO_HWCRYPT) && - txmode == ATH10K_HW_TXRX_RAW && - ieee80211_has_protected(hdr->frame_control)) { - skb_put(msdu, IEEE80211_CCMP_MIC_LEN); + if (!is_eth) { + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)msdu->data; + + if ((ieee80211_is_action(hdr->frame_control) || + ieee80211_is_deauth(hdr->frame_control) || + ieee80211_is_disassoc(hdr->frame_control)) && + ieee80211_has_protected(hdr->frame_control)) { + skb_put(msdu, IEEE80211_CCMP_MIC_LEN); + } else if (!(skb_cb->flags & ATH10K_SKB_F_NO_HWCRYPT) && + txmode == ATH10K_HW_TXRX_RAW && + ieee80211_has_protected(hdr->frame_control)) { + skb_put(msdu, IEEE80211_CCMP_MIC_LEN); + } }
skb_cb->paddr = dma_map_single(dev, msdu->data, msdu->len, @@ -1589,7 +1595,6 @@ static int ath10k_htt_tx_64(struct ath10k_htt *htt, { struct ath10k *ar = htt->ar; struct device *dev = ar->dev; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)msdu->data; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(msdu); struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(msdu); struct ath10k_hif_sg_item sg_items[2]; @@ -1621,15 +1626,19 @@ static int ath10k_htt_tx_64(struct ath10k_htt *htt, txbuf_paddr = htt->txbuf.paddr + (sizeof(struct ath10k_htt_txbuf_64) * msdu_id);
- if ((ieee80211_is_action(hdr->frame_control) || - ieee80211_is_deauth(hdr->frame_control) || - ieee80211_is_disassoc(hdr->frame_control)) && - ieee80211_has_protected(hdr->frame_control)) { - skb_put(msdu, IEEE80211_CCMP_MIC_LEN); - } else if (!(skb_cb->flags & ATH10K_SKB_F_NO_HWCRYPT) && - txmode == ATH10K_HW_TXRX_RAW && - ieee80211_has_protected(hdr->frame_control)) { - skb_put(msdu, IEEE80211_CCMP_MIC_LEN); + if (!is_eth) { + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)msdu->data; + + if ((ieee80211_is_action(hdr->frame_control) || + ieee80211_is_deauth(hdr->frame_control) || + ieee80211_is_disassoc(hdr->frame_control)) && + ieee80211_has_protected(hdr->frame_control)) { + skb_put(msdu, IEEE80211_CCMP_MIC_LEN); + } else if (!(skb_cb->flags & ATH10K_SKB_F_NO_HWCRYPT) && + txmode == ATH10K_HW_TXRX_RAW && + ieee80211_has_protected(hdr->frame_control)) { + skb_put(msdu, IEEE80211_CCMP_MIC_LEN); + } }
skb_cb->paddr = dma_map_single(dev, msdu->data, msdu->len,
From: Maxime Bizon mbizon@freebox.fr
[ Upstream commit 75a7062e533e309a9ca0812c69f3ac3cefadb8b1 ]
Because of this missing switch case, 160Mhz transmit was reported as 20Mhz, leading to wrong airtime calculation and AQL limiting max throughput.
Tested-on: QCA9984 hw2.0 PCI 10.4-3.10-00047
Signed-off-by: Maxime Bizon mbizon@freebox.fr Signed-off-by: Kalle Valo quic_kvalo@quicinc.com Link: https://lore.kernel.org/r/cd2735a40da7f4fcc5323e3fca3775e7b5402ece.camel@fre... Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/wireless/ath/ath10k/htt_rx.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index 771252dd6d4e..e8727c0b0171 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c @@ -3884,6 +3884,10 @@ ath10k_update_per_peer_tx_stats(struct ath10k *ar, arsta->tx_info.status.rates[0].flags |= IEEE80211_TX_RC_80_MHZ_WIDTH; break; + case RATE_INFO_BW_160: + arsta->tx_info.status.rates[0].flags |= + IEEE80211_TX_RC_160_MHZ_WIDTH; + break; }
if (peer_stats->succ_pkts) {
From: Mark Menzynski mmenzyns@redhat.com
[ Upstream commit 6b03816f869529393b37d03e5d75b68f7365a7a4 ]
Resources needed for output poll workers are destroyed in nouveau_fbcon_fini() before output poll workers are cleared in nouveau_display_fini(). This means there is a time between fbcon_fini() and display_fini(), where if output poll happens, it crashes.
This patch introduces another output poll clearing before fbcon resources are destroyed.
BUG: KASAN: use-after-free in __drm_fb_helper_initial_config_and_unlock.cold+0x1f3/0x291 [drm_kms_helper]
Cc: Ben Skeggs bskeggs@redhat.com Cc: Karol Herbst kherbst@redhat.com Cc: Lyude Paul lyude@redhat.com Cc: David Airlie airlied@linux.ie Cc: Daniel Vetter daniel@ffwll.ch Cc: dri-devel@lists.freedesktop.org Cc: nouveau@lists.freedesktop.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Mark Menzynski mmenzyns@redhat.com Reviewed-by: Lyude Paul lyude@redhat.com Signed-off-by: Lyude Paul lyude@redhat.com Link: https://patchwork.freedesktop.org/patch/msgid/20220523113541.10562-1-mmenzyn... Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/nouveau/nouveau_fbcon.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c index 4f9b3aa5deda..5226323e55d3 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c @@ -39,6 +39,7 @@
#include <drm/drm_crtc.h> #include <drm/drm_crtc_helper.h> +#include <drm/drm_probe_helper.h> #include <drm/drm_fb_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_atomic.h> @@ -605,6 +606,7 @@ nouveau_fbcon_fini(struct drm_device *dev) if (!drm->fbcon) return;
+ drm_kms_helper_poll_fini(dev); nouveau_fbcon_accel_fini(dev); nouveau_fbcon_destroy(dev, drm->fbcon); kfree(drm->fbcon);
From: Alyssa Rosenzweig alyssa.rosenzweig@collabora.com
[ Upstream commit 382435709516c1a7dc3843872792abf95e786c83 ]
Add handling for the HW_ISSUE_TTRX_2968_TTRX_3162 quirk. Logic ported from kbase. kbase lists this workaround as used on Mali-G57.
Reviewed-by: Steven Price steven.price@arm.com Signed-off-by: Alyssa Rosenzweig alyssa.rosenzweig@collabora.com Link: https://patchwork.freedesktop.org/patch/msgid/20220525145754.25866-3-alyssa.... Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/panfrost/panfrost_gpu.c | 3 +++ drivers/gpu/drm/panfrost/panfrost_issues.h | 3 +++ drivers/gpu/drm/panfrost/panfrost_regs.h | 1 + 3 files changed, 7 insertions(+)
diff --git a/drivers/gpu/drm/panfrost/panfrost_gpu.c b/drivers/gpu/drm/panfrost/panfrost_gpu.c index aa89926742fd..295bef27fb55 100644 --- a/drivers/gpu/drm/panfrost/panfrost_gpu.c +++ b/drivers/gpu/drm/panfrost/panfrost_gpu.c @@ -108,6 +108,9 @@ static void panfrost_gpu_init_quirks(struct panfrost_device *pfdev) quirks |= SC_LS_ALLOW_ATTR_TYPES; }
+ if (panfrost_has_hw_issue(pfdev, HW_ISSUE_TTRX_2968_TTRX_3162)) + quirks |= SC_VAR_ALGORITHM; + if (panfrost_has_hw_feature(pfdev, HW_FEATURE_TLS_HASHING)) quirks |= SC_TLS_HASH_ENABLE;
diff --git a/drivers/gpu/drm/panfrost/panfrost_issues.h b/drivers/gpu/drm/panfrost/panfrost_issues.h index 501a76c5e95f..41a714ce6fce 100644 --- a/drivers/gpu/drm/panfrost/panfrost_issues.h +++ b/drivers/gpu/drm/panfrost/panfrost_issues.h @@ -125,6 +125,9 @@ enum panfrost_hw_issue { * kernel must fiddle with L2 caches to prevent data leakage */ HW_ISSUE_TGOX_R1_1234,
+ /* Must set SC_VAR_ALGORITHM */ + HW_ISSUE_TTRX_2968_TTRX_3162, + HW_ISSUE_END };
diff --git a/drivers/gpu/drm/panfrost/panfrost_regs.h b/drivers/gpu/drm/panfrost/panfrost_regs.h index 0b6cd8fdcb47..accb4fa3adb8 100644 --- a/drivers/gpu/drm/panfrost/panfrost_regs.h +++ b/drivers/gpu/drm/panfrost/panfrost_regs.h @@ -195,6 +195,7 @@ #define SC_TLS_HASH_ENABLE BIT(17) #define SC_LS_ATTR_CHECK_DISABLE BIT(18) #define SC_ENABLE_TEXGRD_FLAGS BIT(25) +#define SC_VAR_ALGORITHM BIT(29) /* End SHADER_CONFIG register */
/* TILER_CONFIG register */
From: Alyssa Rosenzweig alyssa.rosenzweig@collabora.com
[ Upstream commit d8e53d8a4e0ae842ef5e83e0dfb0796980f710cf ]
L2_MMU_CONFIG is an implementation-defined register. Different Mali GPUs define slightly different MAX_READS and MAX_WRITES fields, which throttle outstanding reads and writes when set to non-zero values. When left as zero, reads and writes are not throttled.
Both kbase and panfrost always zero these registers. Per discussion with Steven Price, there are two reasons these quirks may be used:
1. Simulating slower memory subsystems. This use case is only of interest to system-on-chip designers; it is not relevant to mainline.
2. Working around broken memory subsystems. Hopefully we never see this case in mainline. If we do, we'll need to set this register based on an SoC-compatible, rather than generally matching on the GPU model.
To the best of our knowledge, these fields are zero at reset, so the write is not necessary. Let's remove the write to aid porting to new Mali GPUs, which have different layouts for the L2_MMU_CONFIG register.
Suggested-by: Steven Price steven.price@arm.com Reviewed-by: Steven Price steven.price@arm.com Signed-off-by: Alyssa Rosenzweig alyssa.rosenzweig@collabora.com Link: https://patchwork.freedesktop.org/patch/msgid/20220525145754.25866-8-alyssa.... Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/panfrost/panfrost_gpu.c | 12 ------------ 1 file changed, 12 deletions(-)
diff --git a/drivers/gpu/drm/panfrost/panfrost_gpu.c b/drivers/gpu/drm/panfrost/panfrost_gpu.c index 295bef27fb55..e1a6e763d0dc 100644 --- a/drivers/gpu/drm/panfrost/panfrost_gpu.c +++ b/drivers/gpu/drm/panfrost/panfrost_gpu.c @@ -127,18 +127,6 @@ static void panfrost_gpu_init_quirks(struct panfrost_device *pfdev) gpu_write(pfdev, GPU_TILER_CONFIG, quirks);
- quirks = gpu_read(pfdev, GPU_L2_MMU_CONFIG); - - /* Limit read & write ID width for AXI */ - if (panfrost_has_hw_feature(pfdev, HW_FEATURE_3BIT_EXT_RW_L2_MMU_CONFIG)) - quirks &= ~(L2_MMU_CONFIG_3BIT_LIMIT_EXTERNAL_READS | - L2_MMU_CONFIG_3BIT_LIMIT_EXTERNAL_WRITES); - else - quirks &= ~(L2_MMU_CONFIG_LIMIT_EXTERNAL_READS | - L2_MMU_CONFIG_LIMIT_EXTERNAL_WRITES); - - gpu_write(pfdev, GPU_L2_MMU_CONFIG, quirks); - quirks = 0; if ((panfrost_model_eq(pfdev, 0x860) || panfrost_model_eq(pfdev, 0x880)) && pfdev->features.revision >= 0x2000)
From: Alyssa Rosenzweig alyssa.rosenzweig@collabora.com
[ Upstream commit 952cd974509251d6b5074bc3677b8297826a6ef1 ]
The most important Valhall-specific quirks have been handled, so add the Valhall compatible and probe.
v2: Use arm,mali-valhall-jm compatible.
Reviewed-by: Steven Price steven.price@arm.com Signed-off-by: Alyssa Rosenzweig alyssa.rosenzweig@collabora.com Link: https://patchwork.freedesktop.org/patch/msgid/20220525145754.25866-10-alyssa... Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/panfrost/panfrost_drv.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/gpu/drm/panfrost/panfrost_drv.c b/drivers/gpu/drm/panfrost/panfrost_drv.c index b1e6d238674f..2d870cf73b07 100644 --- a/drivers/gpu/drm/panfrost/panfrost_drv.c +++ b/drivers/gpu/drm/panfrost/panfrost_drv.c @@ -665,6 +665,7 @@ static const struct of_device_id dt_match[] = { { .compatible = "arm,mali-t860", .data = &default_data, }, { .compatible = "arm,mali-t880", .data = &default_data, }, { .compatible = "arm,mali-bifrost", .data = &default_data, }, + { .compatible = "arm,mali-valhall-jm", .data = &default_data, }, { .compatible = "mediatek,mt8183-mali", .data = &mediatek_mt8183_data }, {} };
From: Wen Gong quic_wgong@quicinc.com
[ Upstream commit 8723750e2753868591ba86a57b0041c5e38047ad ]
When wlan load, firmware report the reg code with 0x6C for QCA6174, it is world reg which checked by ath_is_world_regd(), then the reg will be save into reg_world_copy of ath_common in ath_regd_init(). Later the regulatory of ath_common is updated to another country code such as "US" in ath_reg_notifier_apply() by below call stack. After that, regulatory_hint() is called in ath10k_mac_register() and it lead "iw reg get" show two regdomain info as below.
global country US: DFS-FCC (2400 - 2472 @ 40), (N/A, 30), (N/A) (5150 - 5250 @ 80), (N/A, 23), (N/A), AUTO-BW (5250 - 5350 @ 80), (N/A, 23), (0 ms), DFS, AUTO-BW (5470 - 5730 @ 160), (N/A, 23), (0 ms), DFS (5730 - 5850 @ 80), (N/A, 30), (N/A) (57240 - 71000 @ 2160), (N/A, 40), (N/A)
phy#0 country US: DFS-FCC (2400 - 2472 @ 40), (N/A, 30), (N/A) (5150 - 5250 @ 80), (N/A, 23), (N/A), AUTO-BW (5250 - 5350 @ 80), (N/A, 23), (0 ms), DFS, AUTO-BW (5470 - 5730 @ 160), (N/A, 23), (0 ms), DFS (5730 - 5850 @ 80), (N/A, 30), (N/A) (57240 - 71000 @ 2160), (N/A, 40), (N/A)
[ 4255.704975] Call Trace: [ 4255.704983] ath_reg_notifier_apply+0xa6/0xc5 [ath] [ 4255.704991] ath10k_reg_notifier+0x2f/0xd2 [ath10k_core] [ 4255.705010] wiphy_regulatory_register+0x5f/0x69 [cfg80211] [ 4255.705020] wiphy_register+0x459/0x8f0 [cfg80211] [ 4255.705042] ? ieee80211_register_hw+0x3a6/0x7d1 [mac80211] [ 4255.705049] ? __kmalloc+0xf4/0x218 [ 4255.705058] ? ieee80211_register_hw+0x3a6/0x7d1 [mac80211] [ 4255.705066] ? ath10k_mac_register+0x70/0xaab [ath10k_core] [ 4255.705075] ieee80211_register_hw+0x51a/0x7d1 [mac80211] [ 4255.705084] ath10k_mac_register+0x8b4/0xaab [ath10k_core] [ 4255.705094] ath10k_core_register_work+0xa5e/0xb45 [ath10k_core] [ 4255.705100] ? __schedule+0x61f/0x7d3 [ 4255.705105] process_one_work+0x1b7/0x392 [ 4255.705109] worker_thread+0x271/0x35d [ 4255.705112] ? pr_cont_work+0x58/0x58 [ 4255.705116] kthread+0x13f/0x147 [ 4255.705119] ? pr_cont_work+0x58/0x58 [ 4255.705123] ? kthread_destroy_worker+0x62/0x62 [ 4255.705126] ret_from_fork+0x22/0x40
At this moment, the two regdomain info is same, when run "iw reg set KR", the global regdomain info changed to KR, but the regdomain of phy#0 does not change again. It leads inconsistent values between global and phy#0 as below.
global country KR: DFS-JP (2402 - 2482 @ 40), (N/A, 13), (N/A) (5170 - 5250 @ 80), (N/A, 20), (N/A), AUTO-BW (5250 - 5330 @ 80), (N/A, 20), (0 ms), DFS, AUTO-BW (5490 - 5710 @ 160), (N/A, 30), (0 ms), DFS (5735 - 5835 @ 80), (N/A, 30), (N/A) (57000 - 66000 @ 2160), (N/A, 43), (N/A)
phy#0 country US: DFS-FCC (2400 - 2472 @ 40), (N/A, 30), (N/A) (5150 - 5250 @ 80), (N/A, 23), (N/A), AUTO-BW (5250 - 5350 @ 80), (N/A, 23), (0 ms), DFS, AUTO-BW (5470 - 5730 @ 160), (N/A, 23), (0 ms), DFS (5730 - 5850 @ 80), (N/A, 30), (N/A) (57240 - 71000 @ 2160), (N/A, 40), (N/A)
The initial reg code is 0x6C which saved in reg_world_copy of ath_common, and the code US is updated from cfg80211 later, so ath10k should also check the initial reg code before regulatory_hint().
After this fix, regdomain info is same between "iw reg get" and "iw reg set xx", it does not have the regdomain info of phy#0 again.
global country KR: DFS-JP (2402 - 2482 @ 40), (N/A, 13), (N/A) (5170 - 5250 @ 80), (N/A, 20), (N/A), AUTO-BW (5250 - 5330 @ 80), (N/A, 20), (0 ms), DFS, AUTO-BW (5490 - 5710 @ 160), (N/A, 30), (0 ms), DFS (5735 - 5835 @ 80), (N/A, 30), (N/A) (57000 - 66000 @ 2160), (N/A, 43), (N/A)
This does not effect the channel list and power which ath10k used. When the country code for regulatory_hint() in ath10k_mac_register() is same with the global country code, then reg_set_rd_driver() of cfg80211 called from crda which return -EALREADY to set_regdom() and then update_all_wiphy_regulatory() will not be called while wlan load. When run "iw reg set xx", reg_get_regdomain() which used by function handle_channel() in net/wirelss/reg.c always use the regdomain returned by get_cfg80211_regdom() because the initiator of last regulatory_request is NL80211_REGDOM_SET_BY_USER, get_cfg80211_regdom() is the global regdomain, then all the ieee80211_channel info is updated in handle_channel() with the global regdomain.
Tested-on: QCA6174 hw3.2 SDIO WLAN.RMH.4.4.1-00049 Tested-on: QCA9984 hw1.0 PCI 10.4-3.6-00104
Signed-off-by: Wen Gong quic_wgong@quicinc.com Signed-off-by: Kalle Valo quic_kvalo@quicinc.com Link: https://lore.kernel.org/r/20220525132247.23459-1-quic_wgong@quicinc.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/wireless/ath/ath10k/mac.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 3570a5895ea8..69da7b826387 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -10229,7 +10229,8 @@ int ath10k_mac_register(struct ath10k *ar) ar->hw->wiphy->software_iftypes |= BIT(NL80211_IFTYPE_AP_VLAN); }
- if (!ath_is_world_regd(&ar->ath_common.regulatory)) { + if (!ath_is_world_regd(&ar->ath_common.reg_world_copy) && + !ath_is_world_regd(&ar->ath_common.regulatory)) { ret = regulatory_hint(ar->hw->wiphy, ar->ath_common.regulatory.alpha2); if (ret)
From: Wang Yufen wangyufen@huawei.com
[ Upstream commit d8616ee2affcff37c5d315310da557a694a3303d ]
During TCP sockmap redirect pressure test, the following warning is triggered:
WARNING: CPU: 3 PID: 2145 at net/core/stream.c:205 sk_stream_kill_queues+0xbc/0xd0 CPU: 3 PID: 2145 Comm: iperf Kdump: loaded Tainted: G W 5.10.0+ #9 Call Trace: inet_csk_destroy_sock+0x55/0x110 inet_csk_listen_stop+0xbb/0x380 tcp_close+0x41b/0x480 inet_release+0x42/0x80 __sock_release+0x3d/0xa0 sock_close+0x11/0x20 __fput+0x9d/0x240 task_work_run+0x62/0x90 exit_to_user_mode_prepare+0x110/0x120 syscall_exit_to_user_mode+0x27/0x190 entry_SYSCALL_64_after_hwframe+0x44/0xa9
The reason we observed is that:
When the listener is closing, a connection may have completed the three-way handshake but not accepted, and the client has sent some packets. The child sks in accept queue release by inet_child_forget()->inet_csk_destroy_sock(), but psocks of child sks have not released.
To fix, add sock_map_destroy to release psocks.
Signed-off-by: Wang Yufen wangyufen@huawei.com Signed-off-by: Daniel Borkmann daniel@iogearbox.net Signed-off-by: Andrii Nakryiko andrii@kernel.org Acked-by: Jakub Sitnicki jakub@cloudflare.com Acked-by: John Fastabend john.fastabend@gmail.com Link: https://lore.kernel.org/bpf/20220524075311.649153-1-wangyufen@huawei.com Signed-off-by: Sasha Levin sashal@kernel.org --- include/linux/bpf.h | 1 + include/linux/skmsg.h | 1 + net/core/skmsg.c | 1 + net/core/sock_map.c | 23 +++++++++++++++++++++++ net/ipv4/tcp_bpf.c | 1 + 5 files changed, 27 insertions(+)
diff --git a/include/linux/bpf.h b/include/linux/bpf.h index 2b914a56a2c5..8e6092d0ea95 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -2104,6 +2104,7 @@ int sock_map_bpf_prog_query(const union bpf_attr *attr, union bpf_attr __user *uattr);
void sock_map_unhash(struct sock *sk); +void sock_map_destroy(struct sock *sk); void sock_map_close(struct sock *sk, long timeout); #else static inline int bpf_prog_offload_init(struct bpf_prog *prog, diff --git a/include/linux/skmsg.h b/include/linux/skmsg.h index c5a2d6f50f25..153b6dec9b6a 100644 --- a/include/linux/skmsg.h +++ b/include/linux/skmsg.h @@ -95,6 +95,7 @@ struct sk_psock { spinlock_t link_lock; refcount_t refcnt; void (*saved_unhash)(struct sock *sk); + void (*saved_destroy)(struct sock *sk); void (*saved_close)(struct sock *sk, long timeout); void (*saved_write_space)(struct sock *sk); void (*saved_data_ready)(struct sock *sk); diff --git a/net/core/skmsg.c b/net/core/skmsg.c index b0fcd0200e84..fc69154bbc88 100644 --- a/net/core/skmsg.c +++ b/net/core/skmsg.c @@ -720,6 +720,7 @@ struct sk_psock *sk_psock_init(struct sock *sk, int node) psock->eval = __SK_NONE; psock->sk_proto = prot; psock->saved_unhash = prot->unhash; + psock->saved_destroy = prot->destroy; psock->saved_close = prot->close; psock->saved_write_space = sk->sk_write_space;
diff --git a/net/core/sock_map.c b/net/core/sock_map.c index 81d4b4756a02..9f08ccfaf6da 100644 --- a/net/core/sock_map.c +++ b/net/core/sock_map.c @@ -1561,6 +1561,29 @@ void sock_map_unhash(struct sock *sk) } EXPORT_SYMBOL_GPL(sock_map_unhash);
+void sock_map_destroy(struct sock *sk) +{ + void (*saved_destroy)(struct sock *sk); + struct sk_psock *psock; + + rcu_read_lock(); + psock = sk_psock_get(sk); + if (unlikely(!psock)) { + rcu_read_unlock(); + if (sk->sk_prot->destroy) + sk->sk_prot->destroy(sk); + return; + } + + saved_destroy = psock->saved_destroy; + sock_map_remove_links(sk, psock); + rcu_read_unlock(); + sk_psock_stop(psock, true); + sk_psock_put(sk, psock); + saved_destroy(sk); +} +EXPORT_SYMBOL_GPL(sock_map_destroy); + void sock_map_close(struct sock *sk, long timeout) { void (*saved_close)(struct sock *sk, long timeout); diff --git a/net/ipv4/tcp_bpf.c b/net/ipv4/tcp_bpf.c index 0d3f68bb51c0..a1626afe87a1 100644 --- a/net/ipv4/tcp_bpf.c +++ b/net/ipv4/tcp_bpf.c @@ -540,6 +540,7 @@ static void tcp_bpf_rebuild_protos(struct proto prot[TCP_BPF_NUM_CFGS], struct proto *base) { prot[TCP_BPF_BASE] = *base; + prot[TCP_BPF_BASE].destroy = sock_map_destroy; prot[TCP_BPF_BASE].close = sock_map_close; prot[TCP_BPF_BASE].recvmsg = tcp_bpf_recvmsg; prot[TCP_BPF_BASE].sock_is_readable = sk_msg_is_readable;
From: David Zhang dingchen.zhang@amd.com
[ Upstream commit 6cc5c77300afbb285c4f41e04f3435ae3c484c40 ]
[why] When DC driver send PSR exit dmub command to DMUB FW, it might not wait until PSR exit. Then it may hit the following deadlock situation. 1. DC driver send HW LOCK command to DMUB FW due to frame update 2. DMUB FW Set the HW lock 3. DMUB execute PSR exit sequence and stuck at polling DPG Pending register due to the HW Lock is set 4. DC driver ask DMUB FW to unlock HW lock, but DMUB FW is polling DPG pending register
[how] The reason why DC driver doesn't wait until PSR exit is because some of the PSR state machine state is not update the dc driver. So when DC driver read back the PSR state, it take the state for PSR inactive.
Signed-off-by: David Zhang dingchen.zhang@amd.com Acked-by: Leo Li sunpeng.li@amd.com Reviewed-by: Harry Wentland harry.wentland@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/amd/display/dc/dc_types.h | 7 +++++++ drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c | 16 ++++++++++++++++ 2 files changed, 23 insertions(+)
diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index 2ba9f528c0fe..f1f11b3c205f 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -657,10 +657,17 @@ enum dc_psr_state { PSR_STATE4b, PSR_STATE4c, PSR_STATE4d, + PSR_STATE4_FULL_FRAME, + PSR_STATE4a_FULL_FRAME, + PSR_STATE4b_FULL_FRAME, + PSR_STATE4c_FULL_FRAME, + PSR_STATE4_FULL_FRAME_POWERUP, PSR_STATE5, PSR_STATE5a, PSR_STATE5b, PSR_STATE5c, + PSR_STATE_HWLOCK_MGR, + PSR_STATE_POLLVUPDATE, PSR_STATE_INVALID = 0xFF };
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c index 1d4f0c45b536..f941aa107dc6 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c @@ -74,6 +74,22 @@ static enum dc_psr_state convert_psr_state(uint32_t raw_state) state = PSR_STATE5b; else if (raw_state == 0x53) state = PSR_STATE5c; + else if (raw_state == 0x4A) + state = PSR_STATE4_FULL_FRAME; + else if (raw_state == 0x4B) + state = PSR_STATE4a_FULL_FRAME; + else if (raw_state == 0x4C) + state = PSR_STATE4b_FULL_FRAME; + else if (raw_state == 0x4D) + state = PSR_STATE4c_FULL_FRAME; + else if (raw_state == 0x4E) + state = PSR_STATE4_FULL_FRAME_POWERUP; + else if (raw_state == 0x60) + state = PSR_STATE_HWLOCK_MGR; + else if (raw_state == 0x61) + state = PSR_STATE_POLLVUPDATE; + else + state = PSR_STATE_INVALID;
return state; }
From: Wayne Lin Wayne.Lin@amd.com
[ Upstream commit 453b0016a054df0f442fda8a145b97a33816cab9 ]
[Why] Once mst topology is constructed, later on new connected monitors are reported to source by CSN message. Within CSN, there is no carried info of DPCD_REV comparing to LINK_ADDRESS reply. As the result, we might leave some ports connected to DP but without DPCD revision number which will affect us determining the capability of the DP Rx.
[How] Send out remote DPCD read when the port's dpcd_rev is 0x0 in detect_ctx(). Firstly, read out the value from DPCD 0x2200. If the return value is 0x0, it's likely the DP1.2 DP Rx then we reques revision from DPCD 0x0 again.
Reviewed-by: Hersen Wu hersenwu@amd.com Acked-by: Hamza Mahfooz hamza.mahfooz@amd.com Signed-off-by: Wayne Lin Wayne.Lin@amd.com Tested-by: Daniel Wheeler daniel.wheeler@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Sasha Levin sashal@kernel.org --- .../display/amdgpu_dm/amdgpu_dm_mst_types.c | 38 ++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index 2b9b095e5f03..1c02d873950d 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -361,12 +361,48 @@ dm_dp_mst_detect(struct drm_connector *connector, { struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); struct amdgpu_dm_connector *master = aconnector->mst_port; + struct drm_dp_mst_port *port = aconnector->port; + int connection_status;
if (drm_connector_is_unregistered(connector)) return connector_status_disconnected;
- return drm_dp_mst_detect_port(connector, ctx, &master->mst_mgr, + connection_status = drm_dp_mst_detect_port(connector, ctx, &master->mst_mgr, aconnector->port); + + if (port->pdt != DP_PEER_DEVICE_NONE && !port->dpcd_rev) { + uint8_t dpcd_rev; + int ret; + + ret = drm_dp_dpcd_readb(&port->aux, DP_DP13_DPCD_REV, &dpcd_rev); + + if (ret == 1) { + port->dpcd_rev = dpcd_rev; + + /* Could be DP1.2 DP Rx case*/ + if (!dpcd_rev) { + ret = drm_dp_dpcd_readb(&port->aux, DP_DPCD_REV, &dpcd_rev); + + if (ret == 1) + port->dpcd_rev = dpcd_rev; + } + + if (!dpcd_rev) + DRM_DEBUG_KMS("Can't decide DPCD revision number!"); + } + + /* + * Could be legacy sink, logical port etc on DP1.2. + * Will get Nack under these cases when issue remote + * DPCD read. + */ + if (ret != 1) + DRM_DEBUG_KMS("Can't access DPCD"); + } else if (port->pdt == DP_PEER_DEVICE_NONE) { + port->dpcd_rev = 0; + } + + return connection_status; }
static int dm_dp_mst_atomic_check(struct drm_connector *connector,
From: Douglas Anderson dianders@chromium.org
[ Upstream commit fae7d186403ee5a9375ec75938e0de99718e066a ]
If we're unable to read the EDID for a display because it's corrupt / bogus / invalid then we'll add a set of standard modes for the display. Since we have no true information about the connected display, these modes are essentially guesses but better than nothing. At the moment, none of the modes returned is marked as preferred, but the modes are sorted such that the higher resolution modes are listed first.
When userspace sees these modes presented by the kernel it needs to figure out which one to pick. At least one userspace, ChromeOS [1] seems to use the rules (which seem pretty reasonable): 1. Try to pick the first mode marked as preferred. 2. Try to pick the mode which matches the first detailed timing descriptor in the EDID. 3. If no modes were marked as preferred then pick the first mode.
Unfortunately, userspace's rules combined with what the kernel is doing causes us to fail section 4.2.2.6 (EDID Corruption Detection) of the DP 1.4a Link CTS. That test case says that, while it's OK to allow some implementation-specific fall-back modes if the EDID is bad that userspace should _default_ to 640x480.
Let's fix this by marking 640x480 as default for DP in the no-EDID case.
NOTES: - In the discussion around v3 of this patch [2] there was talk about solving this in userspace and I even implemented a patch that would have solved this for ChromeOS, but then the discussion turned back to solving this in the kernel. - Also in the discussion of v3 [2] it was requested to limit this change to just DP since folks were worried that it would break some subtle corner case on VGA or HDMI.
[1] https://source.chromium.org/chromium/chromium/src/+/a051f741d0a15caff2251301... [2] https://lore.kernel.org/r/20220513130533.v3.1.I31ec454f8d4ffce51a7708a8092f8...
Signed-off-by: Douglas Anderson dianders@chromium.org Reviewed-by: Abhinav Kumar quic_abhinavk@quicinc.com Reviewed-by: Dmitry Baryshkov dmitry.baryshkov@linaro.org Acked-by: Jani Nikula jani.nikula@intel.com Reviewed-by: Sean Paul seanpaul@chromium.org Link: https://patchwork.freedesktop.org/patch/msgid/20220601112302.v4.1.I31ec454f8... Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/drm_probe_helper.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c index 682359512996..2c7902b16321 100644 --- a/drivers/gpu/drm/drm_probe_helper.c +++ b/drivers/gpu/drm/drm_probe_helper.c @@ -516,8 +516,17 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector, count = drm_add_override_edid_modes(connector);
if (count == 0 && (connector->status == connector_status_connected || - connector->status == connector_status_unknown)) + connector->status == connector_status_unknown)) { count = drm_add_modes_noedid(connector, 1024, 768); + + /* + * Section 4.2.2.6 (EDID Corruption Detection) of the DP 1.4a + * Link CTS specifies that 640x480 (the official "failsafe" + * mode) needs to be the default if there's no EDID. + */ + if (connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort) + drm_set_preferred_mode(connector, 640, 480); + } count += drm_helper_probe_add_cmdline_mode(connector); if (count == 0) goto prune;
From: Yonghong Song yhs@fb.com
[ Upstream commit b58b2b3a31228bd9aaed9b96e9452dafd0d46024 ]
Currently, the 64bit relocation value in the instruction is computed as follows: __u64 imm = insn[0].imm + ((__u64)insn[1].imm << 32)
Suppose insn[0].imm = -1 (0xffffffff) and insn[1].imm = 1. With the above computation, insn[0].imm will first sign-extend to 64bit -1 (0xffffffffFFFFFFFF) and then add 0x1FFFFFFFF, producing incorrect value 0xFFFFFFFF. The correct value should be 0x1FFFFFFFF.
Changing insn[0].imm to __u32 first will prevent 64bit sign extension and fix the issue. Merging high and low 32bit values also changed from '+' to '|' to be consistent with other similar occurences in kernel and libbpf.
Acked-by: Andrii Nakryiko andrii@kernel.org Acked-by: Dave Marchevsky davemarchevsky@fb.com Signed-off-by: Yonghong Song yhs@fb.com Link: https://lore.kernel.org/r/20220607062610.3717378-1-yhs@fb.com Signed-off-by: Alexei Starovoitov ast@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- tools/lib/bpf/relo_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/lib/bpf/relo_core.c b/tools/lib/bpf/relo_core.c index ba4453dfd1ed..a9216b65724a 100644 --- a/tools/lib/bpf/relo_core.c +++ b/tools/lib/bpf/relo_core.c @@ -1024,7 +1024,7 @@ int bpf_core_patch_insn(const char *prog_name, struct bpf_insn *insn, return -EINVAL; }
- imm = insn[0].imm + ((__u64)insn[1].imm << 32); + imm = (__u32)insn[0].imm | ((__u64)insn[1].imm << 32); if (res->validate && imm != orig_val) { pr_warn("prog '%s': relo #%d: unexpected insn #%d (LDIMM64) value: got %llu, exp %u -> %u\n", prog_name, relo_idx,
From: Mateusz Palczewski mateusz.palczewski@intel.com
[ Upstream commit 35a2443d0910fdd6ce29d4f724447ad7029e8f23 ]
Make iavf_set_mac synchronous by waiting for a response from a PF. Without this iavf_set_mac is always returning success even though set_mac can be rejected by a PF. This ensures that when set_mac exits netdev MAC is updated. This is needed for sending ARPs with correct MAC after changing VF's MAC. This is also needed by bonding module.
Signed-off-by: Sylwester Dziedziuch sylwesterx.dziedziuch@intel.com Signed-off-by: Mateusz Palczewski mateusz.palczewski@intel.com Tested-by: Konrad Jankowski konrad0.jankowski@intel.com Signed-off-by: Tony Nguyen anthony.l.nguyen@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/intel/iavf/iavf.h | 7 +- drivers/net/ethernet/intel/iavf/iavf_main.c | 127 +++++++++++++++--- .../net/ethernet/intel/iavf/iavf_virtchnl.c | 61 ++++++++- 3 files changed, 174 insertions(+), 21 deletions(-)
diff --git a/drivers/net/ethernet/intel/iavf/iavf.h b/drivers/net/ethernet/intel/iavf/iavf.h index 0ea0361cd86b..69703801d1b0 100644 --- a/drivers/net/ethernet/intel/iavf/iavf.h +++ b/drivers/net/ethernet/intel/iavf/iavf.h @@ -145,7 +145,8 @@ struct iavf_mac_filter { u8 remove:1; /* filter needs to be removed */ u8 add:1; /* filter needs to be added */ u8 is_primary:1; /* filter is a default VF MAC */ - u8 padding:4; + u8 add_handled:1; /* received response for filter add */ + u8 padding:3; }; };
@@ -251,6 +252,7 @@ struct iavf_adapter { struct work_struct adminq_task; struct delayed_work client_task; wait_queue_head_t down_waitqueue; + wait_queue_head_t vc_waitqueue; struct iavf_q_vector *q_vectors; struct list_head vlan_filter_list; struct list_head mac_filter_list; @@ -295,6 +297,7 @@ struct iavf_adapter { #define IAVF_FLAG_QUEUES_DISABLED BIT(17) #define IAVF_FLAG_SETUP_NETDEV_FEATURES BIT(18) #define IAVF_FLAG_REINIT_MSIX_NEEDED BIT(20) +#define IAVF_FLAG_INITIAL_MAC_SET BIT(23) /* duplicates for common code */ #define IAVF_FLAG_DCB_ENABLED 0 /* flags for admin queue service task */ @@ -567,6 +570,8 @@ void iavf_enable_vlan_stripping_v2(struct iavf_adapter *adapter, u16 tpid); void iavf_disable_vlan_stripping_v2(struct iavf_adapter *adapter, u16 tpid); void iavf_enable_vlan_insertion_v2(struct iavf_adapter *adapter, u16 tpid); void iavf_disable_vlan_insertion_v2(struct iavf_adapter *adapter, u16 tpid); +int iavf_replace_primary_mac(struct iavf_adapter *adapter, + const u8 *new_mac); void iavf_set_vlan_offload_features(struct iavf_adapter *adapter, netdev_features_t prev_features, diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c index 2e2c153ce46a..2ec3ebb397f3 100644 --- a/drivers/net/ethernet/intel/iavf/iavf_main.c +++ b/drivers/net/ethernet/intel/iavf/iavf_main.c @@ -978,6 +978,7 @@ struct iavf_mac_filter *iavf_add_filter(struct iavf_adapter *adapter,
list_add_tail(&f->list, &adapter->mac_filter_list); f->add = true; + f->add_handled = false; f->is_new_mac = true; f->is_primary = ether_addr_equal(macaddr, adapter->hw.mac.addr); adapter->aq_required |= IAVF_FLAG_AQ_ADD_MAC_FILTER; @@ -989,47 +990,132 @@ struct iavf_mac_filter *iavf_add_filter(struct iavf_adapter *adapter, }
/** - * iavf_set_mac - NDO callback to set port mac address - * @netdev: network interface device structure - * @p: pointer to an address structure + * iavf_replace_primary_mac - Replace current primary address + * @adapter: board private structure + * @new_mac: new MAC address to be applied * - * Returns 0 on success, negative on failure + * Replace current dev_addr and send request to PF for removal of previous + * primary MAC address filter and addition of new primary MAC filter. + * Return 0 for success, -ENOMEM for failure. + * + * Do not call this with mac_vlan_list_lock! **/ -static int iavf_set_mac(struct net_device *netdev, void *p) +int iavf_replace_primary_mac(struct iavf_adapter *adapter, + const u8 *new_mac) { - struct iavf_adapter *adapter = netdev_priv(netdev); struct iavf_hw *hw = &adapter->hw; struct iavf_mac_filter *f; - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - if (ether_addr_equal(netdev->dev_addr, addr->sa_data)) - return 0;
spin_lock_bh(&adapter->mac_vlan_list_lock);
+ list_for_each_entry(f, &adapter->mac_filter_list, list) { + f->is_primary = false; + } + f = iavf_find_filter(adapter, hw->mac.addr); if (f) { f->remove = true; - f->is_primary = true; adapter->aq_required |= IAVF_FLAG_AQ_DEL_MAC_FILTER; }
- f = iavf_add_filter(adapter, addr->sa_data); + f = iavf_add_filter(adapter, new_mac); + if (f) { + /* Always send the request to add if changing primary MAC + * even if filter is already present on the list + */ f->is_primary = true; - ether_addr_copy(hw->mac.addr, addr->sa_data); + f->add = true; + adapter->aq_required |= IAVF_FLAG_AQ_ADD_MAC_FILTER; + ether_addr_copy(hw->mac.addr, new_mac); }
spin_unlock_bh(&adapter->mac_vlan_list_lock);
/* schedule the watchdog task to immediately process the request */ - if (f) + if (f) { queue_work(iavf_wq, &adapter->watchdog_task.work); + return 0; + } + return -ENOMEM; +} + +/** + * iavf_is_mac_set_handled - wait for a response to set MAC from PF + * @netdev: network interface device structure + * @macaddr: MAC address to set + * + * Returns true on success, false on failure + */ +static bool iavf_is_mac_set_handled(struct net_device *netdev, + const u8 *macaddr) +{ + struct iavf_adapter *adapter = netdev_priv(netdev); + struct iavf_mac_filter *f; + bool ret = false; + + spin_lock_bh(&adapter->mac_vlan_list_lock); + + f = iavf_find_filter(adapter, macaddr);
- return (f == NULL) ? -ENOMEM : 0; + if (!f || (!f->add && f->add_handled)) + ret = true; + + spin_unlock_bh(&adapter->mac_vlan_list_lock); + + return ret; +} + +/** + * iavf_set_mac - NDO callback to set port MAC address + * @netdev: network interface device structure + * @p: pointer to an address structure + * + * Returns 0 on success, negative on failure + */ +static int iavf_set_mac(struct net_device *netdev, void *p) +{ + struct iavf_adapter *adapter = netdev_priv(netdev); + struct sockaddr *addr = p; + bool handle_mac = iavf_is_mac_set_handled(netdev, addr->sa_data); + int ret; + + if (!is_valid_ether_addr(addr->sa_data)) + return -EADDRNOTAVAIL; + + ret = iavf_replace_primary_mac(adapter, addr->sa_data); + + if (ret) + return ret; + + /* If this is an initial set MAC during VF spawn do not wait */ + if (adapter->flags & IAVF_FLAG_INITIAL_MAC_SET) { + adapter->flags &= ~IAVF_FLAG_INITIAL_MAC_SET; + return 0; + } + + if (handle_mac) + goto done; + + ret = wait_event_interruptible_timeout(adapter->vc_waitqueue, false, msecs_to_jiffies(2500)); + + /* If ret < 0 then it means wait was interrupted. + * If ret == 0 then it means we got a timeout. + * else it means we got response for set MAC from PF, + * check if netdev MAC was updated to requested MAC, + * if yes then set MAC succeeded otherwise it failed return -EACCES + */ + if (ret < 0) + return ret; + + if (!ret) + return -EAGAIN; + +done: + if (!ether_addr_equal(netdev->dev_addr, addr->sa_data)) + return -EACCES; + + return 0; }
/** @@ -2445,6 +2531,8 @@ static void iavf_init_config_adapter(struct iavf_adapter *adapter) ether_addr_copy(netdev->perm_addr, adapter->hw.mac.addr); }
+ adapter->flags |= IAVF_FLAG_INITIAL_MAC_SET; + adapter->tx_desc_count = IAVF_DEFAULT_TXD; adapter->rx_desc_count = IAVF_DEFAULT_RXD; err = iavf_init_interrupt_scheme(adapter); @@ -4678,6 +4766,9 @@ static int iavf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) /* Setup the wait queue for indicating transition to down status */ init_waitqueue_head(&adapter->down_waitqueue);
+ /* Setup the wait queue for indicating virtchannel events */ + init_waitqueue_head(&adapter->vc_waitqueue); + return 0;
err_ioremap: diff --git a/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c b/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c index 1603e99bae4a..7c98ac1fe458 100644 --- a/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c +++ b/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c @@ -598,6 +598,8 @@ static void iavf_mac_add_ok(struct iavf_adapter *adapter) spin_lock_bh(&adapter->mac_vlan_list_lock); list_for_each_entry_safe(f, ftmp, &adapter->mac_filter_list, list) { f->is_new_mac = false; + if (!f->add && !f->add_handled) + f->add_handled = true; } spin_unlock_bh(&adapter->mac_vlan_list_lock); } @@ -618,6 +620,9 @@ static void iavf_mac_add_reject(struct iavf_adapter *adapter) if (f->remove && ether_addr_equal(f->macaddr, netdev->dev_addr)) f->remove = false;
+ if (!f->add && !f->add_handled) + f->add_handled = true; + if (f->is_new_mac) { list_del(&f->list); kfree(f); @@ -1970,6 +1975,7 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter, iavf_mac_add_reject(adapter); /* restore administratively set MAC address */ ether_addr_copy(adapter->hw.mac.addr, netdev->dev_addr); + wake_up(&adapter->vc_waitqueue); break; case VIRTCHNL_OP_DEL_VLAN: dev_err(&adapter->pdev->dev, "Failed to delete VLAN filter, error %s\n", @@ -2134,7 +2140,13 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter, if (!v_retval) iavf_mac_add_ok(adapter); if (!ether_addr_equal(netdev->dev_addr, adapter->hw.mac.addr)) - eth_hw_addr_set(netdev, adapter->hw.mac.addr); + if (!ether_addr_equal(netdev->dev_addr, + adapter->hw.mac.addr)) { + netif_addr_lock_bh(netdev); + eth_hw_addr_set(netdev, adapter->hw.mac.addr); + netif_addr_unlock_bh(netdev); + } + wake_up(&adapter->vc_waitqueue); break; case VIRTCHNL_OP_GET_STATS: { struct iavf_eth_stats *stats = @@ -2164,10 +2176,11 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter, /* restore current mac address */ ether_addr_copy(adapter->hw.mac.addr, netdev->dev_addr); } else { + netif_addr_lock_bh(netdev); /* refresh current mac address if changed */ - eth_hw_addr_set(netdev, adapter->hw.mac.addr); ether_addr_copy(netdev->perm_addr, adapter->hw.mac.addr); + netif_addr_unlock_bh(netdev); } spin_lock_bh(&adapter->mac_vlan_list_lock); iavf_add_filter(adapter, adapter->hw.mac.addr); @@ -2203,6 +2216,10 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter, } fallthrough; case VIRTCHNL_OP_GET_OFFLOAD_VLAN_V2_CAPS: { + struct iavf_mac_filter *f; + bool was_mac_changed; + u64 aq_required = 0; + if (v_opcode == VIRTCHNL_OP_GET_OFFLOAD_VLAN_V2_CAPS) memcpy(&adapter->vlan_v2_caps, msg, min_t(u16, msglen, @@ -2210,6 +2227,46 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,
iavf_process_config(adapter); adapter->flags |= IAVF_FLAG_SETUP_NETDEV_FEATURES; + was_mac_changed = !ether_addr_equal(netdev->dev_addr, + adapter->hw.mac.addr); + + spin_lock_bh(&adapter->mac_vlan_list_lock); + + /* re-add all MAC filters */ + list_for_each_entry(f, &adapter->mac_filter_list, list) { + if (was_mac_changed && + ether_addr_equal(netdev->dev_addr, f->macaddr)) + ether_addr_copy(f->macaddr, + adapter->hw.mac.addr); + + f->is_new_mac = true; + f->add = true; + f->add_handled = false; + f->remove = false; + } + + /* re-add all VLAN filters */ + if (VLAN_FILTERING_ALLOWED(adapter)) { + struct iavf_vlan_filter *vlf; + + if (!list_empty(&adapter->vlan_filter_list)) { + list_for_each_entry(vlf, + &adapter->vlan_filter_list, + list) + vlf->add = true; + + aq_required |= IAVF_FLAG_AQ_ADD_VLAN_FILTER; + } + } + + spin_unlock_bh(&adapter->mac_vlan_list_lock); + + netif_addr_lock_bh(netdev); + eth_hw_addr_set(netdev, adapter->hw.mac.addr); + netif_addr_unlock_bh(netdev); + + adapter->aq_required |= IAVF_FLAG_AQ_ADD_MAC_FILTER | + aq_required; } break; case VIRTCHNL_OP_ENABLE_QUEUES:
From: Duncan Ma duncan.ma@amd.com
[ Upstream commit 0c56705d8aae9696348cc320b71d531ede001b79 ]
[Why] In 3-way mpo pipes, there is a case that we overbook the CRB buffer size. At rare instances, overbooking the crb will cause underflow. This only happens when det_size changes dynamically based on pipe_cnt.
[How] Set min compbuff size to 1 segment when preparing BW.
Reviewed-by: Dmytro Laktyushkin Dmytro.Laktyushkin@amd.com Acked-by: Hamza Mahfooz hamza.mahfooz@amd.com Signed-off-by: Duncan Ma duncan.ma@amd.com Tested-by: Daniel Wheeler daniel.wheeler@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c index 54db2eca9e6b..1b02f0ebe957 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c @@ -201,7 +201,7 @@ struct _vcs_dpi_ip_params_st dcn3_15_ip = { .hostvm_max_page_table_levels = 2, .rob_buffer_size_kbytes = 64, .det_buffer_size_kbytes = DCN3_15_DEFAULT_DET_SIZE, - .min_comp_buffer_size_kbytes = DCN3_15_MIN_COMPBUF_SIZE_KB, + .min_comp_buffer_size_kbytes = 64, .config_return_buffer_size_in_kbytes = 1024, .compressed_buffer_segment_size_in_kbytes = 64, .meta_fifo_size_in_kentries = 32, @@ -297,6 +297,7 @@ struct _vcs_dpi_ip_params_st dcn3_16_ip = { .hostvm_max_page_table_levels = 2, .rob_buffer_size_kbytes = 64, .det_buffer_size_kbytes = DCN3_16_DEFAULT_DET_SIZE, + .min_comp_buffer_size_kbytes = 64, .config_return_buffer_size_in_kbytes = 1024, .compressed_buffer_segment_size_in_kbytes = 64, .meta_fifo_size_in_kentries = 32,
From: Duncan Ma duncan.ma@amd.com
[ Upstream commit d4965c53b95d7533dfc2309d2fc25838bd33220e ]
[Why] When switching from 1 pipe to 4to1 mpc combine, DppDtoClk aren't enabled for the disabled pipes pior to programming the pipes. Upon optimizing bandwidth, DppDto are enabled causing intermittent underflow.
[How] Update dppclk dto whenever pipe are flagged to enable.
Reviewed-by: Dmytro Laktyushkin Dmytro.Laktyushkin@amd.com Reviewed-by: Nicholas Kazlauskas Nicholas.Kazlauskas@amd.com Reviewed-by: Hansen Dsouza Hansen.Dsouza@amd.com Acked-by: Hamza Mahfooz hamza.mahfooz@amd.com Signed-off-by: Duncan Ma duncan.ma@amd.com Tested-by: Daniel Wheeler daniel.wheeler@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c index ec6aa8d8b251..8b2c15a3cd92 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c @@ -1412,11 +1412,15 @@ static void dcn20_update_dchubp_dpp( struct hubp *hubp = pipe_ctx->plane_res.hubp; struct dpp *dpp = pipe_ctx->plane_res.dpp; struct dc_plane_state *plane_state = pipe_ctx->plane_state; + struct dccg *dccg = dc->res_pool->dccg; bool viewport_changed = false;
if (pipe_ctx->update_flags.bits.dppclk) dpp->funcs->dpp_dppclk_control(dpp, false, true);
+ if (pipe_ctx->update_flags.bits.enable) + dccg->funcs->update_dpp_dto(dccg, dpp->inst, pipe_ctx->plane_res.bw.dppclk_khz); + /* TODO: Need input parameter to tell current DCHUB pipe tie to which OTG * VTG is within DCHUBBUB which is commond block share by each pipe HUBP. * VTG is 1:1 mapping with OTG. Each pipe HUBP will select which VTG
From: Rodrigo Siqueira Rodrigo.Siqueira@amd.com
[ Upstream commit c55300ad4a1814bac9191a4d2c7b0d74273aec7c ]
GCC throw warnings for the function dcn20_update_bounding_box due to its frame size that looks like this:
error: the frame size of 1936 bytes is larger than 1024 bytes [-Werror=frame-larger-than=]
This commit fixes this issue by eliminating an intermediary variable that creates a large array.
Cc: Stephen Rothwell sfr@canb.auug.org.au Cc: Hamza Mahfooz hamza.mahfooz@amd.com Cc: Aurabindo Pillai aurabindo.pillai@amd.com Reviewed-by: Harry Wentland harry.wentland@amd.com Reviewed-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Rodrigo Siqueira Rodrigo.Siqueira@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Sasha Levin sashal@kernel.org --- .../drm/amd/display/dc/dml/dcn20/dcn20_fpu.c | 38 +++++++++---------- 1 file changed, 18 insertions(+), 20 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c index f79dd40f8d81..48df4f225ac7 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c @@ -1428,21 +1428,20 @@ void dcn20_calculate_wm( void dcn20_update_bounding_box(struct dc *dc, struct _vcs_dpi_soc_bounding_box_st *bb, struct pp_smu_nv_clock_table *max_clocks, unsigned int *uclk_states, unsigned int num_states) { - struct _vcs_dpi_voltage_scaling_st calculated_states[DC__VOLTAGE_STATES]; - int i; int num_calculated_states = 0; int min_dcfclk = 0; + int i;
dc_assert_fp_enabled();
if (num_states == 0) return;
- memset(calculated_states, 0, sizeof(calculated_states)); + memset(bb->clock_limits, 0, sizeof(bb->clock_limits));
- if (dc->bb_overrides.min_dcfclk_mhz > 0) + if (dc->bb_overrides.min_dcfclk_mhz > 0) { min_dcfclk = dc->bb_overrides.min_dcfclk_mhz; - else { + } else { if (ASICREV_IS_NAVI12_P(dc->ctx->asic_id.hw_internal_rev)) min_dcfclk = 310; else @@ -1453,36 +1452,35 @@ void dcn20_update_bounding_box(struct dc *dc, struct _vcs_dpi_soc_bounding_box_s
for (i = 0; i < num_states; i++) { int min_fclk_required_by_uclk; - calculated_states[i].state = i; - calculated_states[i].dram_speed_mts = uclk_states[i] * 16 / 1000; + bb->clock_limits[i].state = i; + bb->clock_limits[i].dram_speed_mts = uclk_states[i] * 16 / 1000;
// FCLK:UCLK ratio is 1.08 min_fclk_required_by_uclk = div_u64(((unsigned long long)uclk_states[i]) * 1080, 1000000);
- calculated_states[i].fabricclk_mhz = (min_fclk_required_by_uclk < min_dcfclk) ? + bb->clock_limits[i].fabricclk_mhz = (min_fclk_required_by_uclk < min_dcfclk) ? min_dcfclk : min_fclk_required_by_uclk;
- calculated_states[i].socclk_mhz = (calculated_states[i].fabricclk_mhz > max_clocks->socClockInKhz / 1000) ? - max_clocks->socClockInKhz / 1000 : calculated_states[i].fabricclk_mhz; + bb->clock_limits[i].socclk_mhz = (bb->clock_limits[i].fabricclk_mhz > max_clocks->socClockInKhz / 1000) ? + max_clocks->socClockInKhz / 1000 : bb->clock_limits[i].fabricclk_mhz;
- calculated_states[i].dcfclk_mhz = (calculated_states[i].fabricclk_mhz > max_clocks->dcfClockInKhz / 1000) ? - max_clocks->dcfClockInKhz / 1000 : calculated_states[i].fabricclk_mhz; + bb->clock_limits[i].dcfclk_mhz = (bb->clock_limits[i].fabricclk_mhz > max_clocks->dcfClockInKhz / 1000) ? + max_clocks->dcfClockInKhz / 1000 : bb->clock_limits[i].fabricclk_mhz;
- calculated_states[i].dispclk_mhz = max_clocks->displayClockInKhz / 1000; - calculated_states[i].dppclk_mhz = max_clocks->displayClockInKhz / 1000; - calculated_states[i].dscclk_mhz = max_clocks->displayClockInKhz / (1000 * 3); + bb->clock_limits[i].dispclk_mhz = max_clocks->displayClockInKhz / 1000; + bb->clock_limits[i].dppclk_mhz = max_clocks->displayClockInKhz / 1000; + bb->clock_limits[i].dscclk_mhz = max_clocks->displayClockInKhz / (1000 * 3);
- calculated_states[i].phyclk_mhz = max_clocks->phyClockInKhz / 1000; + bb->clock_limits[i].phyclk_mhz = max_clocks->phyClockInKhz / 1000;
num_calculated_states++; }
- calculated_states[num_calculated_states - 1].socclk_mhz = max_clocks->socClockInKhz / 1000; - calculated_states[num_calculated_states - 1].fabricclk_mhz = max_clocks->socClockInKhz / 1000; - calculated_states[num_calculated_states - 1].dcfclk_mhz = max_clocks->dcfClockInKhz / 1000; + bb->clock_limits[num_calculated_states - 1].socclk_mhz = max_clocks->socClockInKhz / 1000; + bb->clock_limits[num_calculated_states - 1].fabricclk_mhz = max_clocks->socClockInKhz / 1000; + bb->clock_limits[num_calculated_states - 1].dcfclk_mhz = max_clocks->dcfClockInKhz / 1000;
- memcpy(bb->clock_limits, calculated_states, sizeof(bb->clock_limits)); bb->num_states = num_calculated_states;
// Duplicate the last state, DML always an extra state identical to max state to work
From: Xiaohui Zhang xiaohuizhang@ruc.edu.cn
[ Upstream commit feb54650bae25f2a2adfc493e3e254e7c27a3fba ]
Similar to the handling of amdgpu_mode_dumb_create in commit 54ef0b5461c0 ("drm/amdgpu: integer overflow in amdgpu_mode_dumb_create()"), we thought a patch might be needed here as well.
args->size is a u64. arg->pitch and args->height are u32. The multiplication will overflow instead of using the high 32 bits as intended.
Signed-off-by: Xiaohui Zhang xiaohuizhang@ruc.edu.cn Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/radeon/radeon_gem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c index 8c01a7f0e027..84843b3b3aef 100644 --- a/drivers/gpu/drm/radeon/radeon_gem.c +++ b/drivers/gpu/drm/radeon/radeon_gem.c @@ -833,7 +833,7 @@ int radeon_mode_dumb_create(struct drm_file *file_priv,
args->pitch = radeon_align_pitch(rdev, args->width, DIV_ROUND_UP(args->bpp, 8), 0); - args->size = args->pitch * args->height; + args->size = (u64)args->pitch * args->height; args->size = ALIGN(args->size, PAGE_SIZE);
r = radeon_gem_object_create(rdev, args->size, 0,
From: Xiaohui Zhang xiaohuizhang@ruc.edu.cn
[ Upstream commit 0381ac3ca2e727d4dfb7264d9416a8ba6bb6c18b ]
Similar to the handling of amdgpu_sa_bo_next_hole in commit 6a15f3ff19a8 ("drm/amdgpu: Initialize fences array entries in amdgpu_sa_bo_next_hole"), we thought a patch might be needed here as well.
The entries were only initialized once in radeon_sa_bo_new. If a fence wasn't signalled yet in the first radeon_sa_bo_next_hole call, but then got signalled before a later radeon_sa_bo_next_hole call, it could destroy the fence but leave its pointer in the array, resulting in use-after-free in radeon_sa_bo_new.
Signed-off-by: Xiaohui Zhang xiaohuizhang@ruc.edu.cn Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/radeon/radeon_sa.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/radeon/radeon_sa.c b/drivers/gpu/drm/radeon/radeon_sa.c index 310c322c7112..0981948bd9ed 100644 --- a/drivers/gpu/drm/radeon/radeon_sa.c +++ b/drivers/gpu/drm/radeon/radeon_sa.c @@ -267,6 +267,8 @@ static bool radeon_sa_bo_next_hole(struct radeon_sa_manager *sa_manager, for (i = 0; i < RADEON_NUM_RINGS; ++i) { struct radeon_sa_bo *sa_bo;
+ fences[i] = NULL; + if (list_empty(&sa_manager->flist[i])) { continue; } @@ -332,10 +334,8 @@ int radeon_sa_bo_new(struct radeon_device *rdev,
spin_lock(&sa_manager->wq.lock); do { - for (i = 0; i < RADEON_NUM_RINGS; ++i) { - fences[i] = NULL; + for (i = 0; i < RADEON_NUM_RINGS; ++i) tries[i] = 0; - }
do { radeon_sa_bo_try_free(sa_manager);
From: Vivek Kasireddy vivek.kasireddy@intel.com
[ Upstream commit 9e9fa6a9198b767b00f48160800128e83a038f9f ]
If the DMA mask is not set explicitly, the following warning occurs when the userspace tries to access the dma-buf via the CPU as reported by syzbot here:
WARNING: CPU: 1 PID: 3595 at kernel/dma/mapping.c:188 __dma_map_sg_attrs+0x181/0x1f0 kernel/dma/mapping.c:188 Modules linked in: CPU: 0 PID: 3595 Comm: syz-executor249 Not tainted 5.17.0-rc2-syzkaller-00316-g0457e5153e0e #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 RIP: 0010:__dma_map_sg_attrs+0x181/0x1f0 kernel/dma/mapping.c:188 Code: 00 00 00 00 00 fc ff df 48 c1 e8 03 80 3c 10 00 75 71 4c 8b 3d c0 83 b5 0d e9 db fe ff ff e8 b6 0f 13 00 0f 0b e8 af 0f 13 00 <0f> 0b 45 31 e4 e9 54 ff ff ff e8 a0 0f 13 00 49 8d 7f 50 48 b8 00 RSP: 0018:ffffc90002a07d68 EFLAGS: 00010293 RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000000 RDX: ffff88807e25e2c0 RSI: ffffffff81649e91 RDI: ffff88801b848408 RBP: ffff88801b848000 R08: 0000000000000002 R09: ffff88801d86c74f R10: ffffffff81649d72 R11: 0000000000000001 R12: 0000000000000002 R13: ffff88801d86c680 R14: 0000000000000001 R15: 0000000000000000 FS: 0000555556e30300(0000) GS:ffff8880b9d00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00000000200000cc CR3: 000000001d74a000 CR4: 00000000003506e0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 Call Trace: <TASK> dma_map_sgtable+0x70/0xf0 kernel/dma/mapping.c:264 get_sg_table.isra.0+0xe0/0x160 drivers/dma-buf/udmabuf.c:72 begin_cpu_udmabuf+0x130/0x1d0 drivers/dma-buf/udmabuf.c:126 dma_buf_begin_cpu_access+0xfd/0x1d0 drivers/dma-buf/dma-buf.c:1164 dma_buf_ioctl+0x259/0x2b0 drivers/dma-buf/dma-buf.c:363 vfs_ioctl fs/ioctl.c:51 [inline] __do_sys_ioctl fs/ioctl.c:874 [inline] __se_sys_ioctl fs/ioctl.c:860 [inline] __x64_sys_ioctl+0x193/0x200 fs/ioctl.c:860 do_syscall_x64 arch/x86/entry/common.c:50 [inline] do_syscall_64+0x35/0xb0 arch/x86/entry/common.c:80 entry_SYSCALL_64_after_hwframe+0x44/0xae RIP: 0033:0x7f62fcf530f9 Code: 28 c3 e8 2a 14 00 00 66 2e 0f 1f 84 00 00 00 00 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 c0 ff ff ff f7 d8 64 89 01 48 RSP: 002b:00007ffe3edab9b8 EFLAGS: 00000246 ORIG_RAX: 0000000000000010 RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007f62fcf530f9 RDX: 0000000020000200 RSI: 0000000040086200 RDI: 0000000000000006 RBP: 00007f62fcf170e0 R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000246 R12: 00007f62fcf17170 R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000 </TASK>
v2: Dont't forget to deregister if DMA mask setup fails.
Reported-by: syzbot+10e27961f4da37c443b2@syzkaller.appspotmail.com Cc: Gerd Hoffmann kraxel@redhat.com Signed-off-by: Vivek Kasireddy vivek.kasireddy@intel.com Link: http://patchwork.freedesktop.org/patch/msgid/20220520205235.3687336-1-vivek.... Signed-off-by: Gerd Hoffmann kraxel@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/dma-buf/udmabuf.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-)
diff --git a/drivers/dma-buf/udmabuf.c b/drivers/dma-buf/udmabuf.c index 9631f2fd2faf..38e8767ec371 100644 --- a/drivers/dma-buf/udmabuf.c +++ b/drivers/dma-buf/udmabuf.c @@ -368,7 +368,23 @@ static struct miscdevice udmabuf_misc = {
static int __init udmabuf_dev_init(void) { - return misc_register(&udmabuf_misc); + int ret; + + ret = misc_register(&udmabuf_misc); + if (ret < 0) { + pr_err("Could not initialize udmabuf device\n"); + return ret; + } + + ret = dma_coerce_mask_and_coherent(udmabuf_misc.this_device, + DMA_BIT_MASK(64)); + if (ret < 0) { + pr_err("Could not setup DMA mask for udmabuf device\n"); + misc_deregister(&udmabuf_misc); + return ret; + } + + return 0; }
static void __exit udmabuf_dev_exit(void)
From: Shijith Thotton sthotton@marvell.com
[ Upstream commit b03c0dc0788abccc7a25ef7dff5818f4123bb992 ]
Added missing checks to avoid null pointer dereference.
The patch fixes below issue reported by klocwork tool: . Pointer 'strsep( &val, ":" )' returned from call to function 'strsep' at line 1608 may be NULL and will be dereferenced at line 1608. Also there are 2 similar errors on lines 1620, 1632 in otx2_cptpf_ucode.c.
Signed-off-by: Shijith Thotton sthotton@marvell.com Signed-off-by: Herbert Xu herbert@gondor.apana.org.au Signed-off-by: Sasha Levin sashal@kernel.org --- .../crypto/marvell/octeontx2/otx2_cptpf_ucode.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/drivers/crypto/marvell/octeontx2/otx2_cptpf_ucode.c b/drivers/crypto/marvell/octeontx2/otx2_cptpf_ucode.c index 9cba2f714c7e..080cbfa093ec 100644 --- a/drivers/crypto/marvell/octeontx2/otx2_cptpf_ucode.c +++ b/drivers/crypto/marvell/octeontx2/otx2_cptpf_ucode.c @@ -1605,7 +1605,10 @@ int otx2_cpt_dl_custom_egrp_create(struct otx2_cptpf_dev *cptpf, if (!strncasecmp(val, "se", 2) && strchr(val, ':')) { if (has_se || ucode_idx) goto err_print; - tmp = strim(strsep(&val, ":")); + tmp = strsep(&val, ":"); + if (!tmp) + goto err_print; + tmp = strim(tmp); if (!val) goto err_print; if (strlen(tmp) != 2) @@ -1617,7 +1620,10 @@ int otx2_cpt_dl_custom_egrp_create(struct otx2_cptpf_dev *cptpf, } else if (!strncasecmp(val, "ae", 2) && strchr(val, ':')) { if (has_ae || ucode_idx) goto err_print; - tmp = strim(strsep(&val, ":")); + tmp = strsep(&val, ":"); + if (!tmp) + goto err_print; + tmp = strim(tmp); if (!val) goto err_print; if (strlen(tmp) != 2) @@ -1629,7 +1635,10 @@ int otx2_cpt_dl_custom_egrp_create(struct otx2_cptpf_dev *cptpf, } else if (!strncasecmp(val, "ie", 2) && strchr(val, ':')) { if (has_ie || ucode_idx) goto err_print; - tmp = strim(strsep(&val, ":")); + tmp = strsep(&val, ":"); + if (!tmp) + goto err_print; + tmp = strim(tmp); if (!val) goto err_print; if (strlen(tmp) != 2)
From: Saeed Mahameed saeedm@nvidia.com
[ Upstream commit 3e94e61bd44d90070dcda53b647fdc826097ef26 ]
total_q_under_processor_handle - number of queues in error state due to an async error or errored command.
send_queue_priority_update_flow - number of QP/SQ priority/SL update events.
cq_overrun - number of times CQ entered an error state due to an overflow.
async_eq_overrun -number of time an EQ mapped to async events was overrun.
comp_eq_overrun - number of time an EQ mapped to completion events was overrun.
quota_exceeded_command - number of commands issued and failed due to quota exceeded.
invalid_command - number of commands issued and failed dues to any reason other than quota exceeded.
Signed-off-by: Saeed Mahameed saeedm@nvidia.com Signed-off-by: Michael Guralnik michaelgur@nvidia.com Signed-off-by: Saeed Mahameed saeedm@nvidia.com Signed-off-by: Sasha Levin sashal@kernel.org --- include/linux/mlx5/mlx5_ifc.h | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-)
diff --git a/include/linux/mlx5/mlx5_ifc.h b/include/linux/mlx5/mlx5_ifc.h index fd7d083a34d3..f0b0bb67955e 100644 --- a/include/linux/mlx5/mlx5_ifc.h +++ b/include/linux/mlx5/mlx5_ifc.h @@ -1426,7 +1426,8 @@ struct mlx5_ifc_cmd_hca_cap_bits {
u8 reserved_at_120[0xa]; u8 log_max_ra_req_dc[0x6]; - u8 reserved_at_130[0xa]; + u8 reserved_at_130[0x9]; + u8 vnic_env_cq_overrun[0x1]; u8 log_max_ra_res_dc[0x6];
u8 reserved_at_140[0x5]; @@ -1621,7 +1622,11 @@ struct mlx5_ifc_cmd_hca_cap_bits { u8 nic_receive_steering_discard[0x1]; u8 receive_discard_vport_down[0x1]; u8 transmit_discard_vport_down[0x1]; - u8 reserved_at_343[0x5]; + u8 eq_overrun_count[0x1]; + u8 reserved_at_344[0x1]; + u8 invalid_command_count[0x1]; + u8 quota_exceeded_count[0x1]; + u8 reserved_at_347[0x1]; u8 log_max_flow_counter_bulk[0x8]; u8 max_flow_counter_15_0[0x10];
@@ -3391,11 +3396,21 @@ struct mlx5_ifc_vnic_diagnostic_statistics_bits {
u8 transmit_discard_vport_down[0x40];
- u8 reserved_at_140[0xa0]; + u8 async_eq_overrun[0x20]; + + u8 comp_eq_overrun[0x20]; + + u8 reserved_at_180[0x20]; + + u8 invalid_command[0x20]; + + u8 quota_exceeded_command[0x20];
u8 internal_rq_out_of_buffer[0x20];
- u8 reserved_at_200[0xe00]; + u8 cq_overrun[0x20]; + + u8 reserved_at_220[0xde0]; };
struct mlx5_ifc_traffic_counter_bits {
From: Yonghong Song yhs@fb.com
[ Upstream commit 3831cd1f9ff627734096f22d8e37f72a5cabf92e ]
Commit 704c91e59fe0 ('selftests/bpf: Test "bpftool gen min_core_btf"') added a test test_core_btfgen to test core relocation with btf generated with 'bpftool gen min_core_btf'. Currently, among 76 subtests, 25 are skipped.
... #46/69 core_reloc_btfgen/enumval:OK #46/70 core_reloc_btfgen/enumval___diff:OK #46/71 core_reloc_btfgen/enumval___val3_missing:OK #46/72 core_reloc_btfgen/enumval___err_missing:SKIP #46/73 core_reloc_btfgen/enum64val:OK #46/74 core_reloc_btfgen/enum64val___diff:OK #46/75 core_reloc_btfgen/enum64val___val3_missing:OK #46/76 core_reloc_btfgen/enum64val___err_missing:SKIP ... #46 core_reloc_btfgen:SKIP Summary: 1/51 PASSED, 25 SKIPPED, 0 FAILED
Alexei found that in the above core_reloc_btfgen/enum64val___err_missing should not be skipped.
Currently, the core_reloc tests have some negative tests. In Commit 704c91e59fe0, for core_reloc_btfgen, all negative tests are skipped with the following condition if (!test_case->btf_src_file || test_case->fails) { test__skip(); continue; } This is too conservative. Negative tests do not fail mkstemp() and run_btfgen() should not be skipped. There are a few negative tests indeed failing run_btfgen() and this patch added 'run_btfgen_fails' to mark these tests so that they can be skipped for btfgen tests. With this, we have ... #46/69 core_reloc_btfgen/enumval:OK #46/70 core_reloc_btfgen/enumval___diff:OK #46/71 core_reloc_btfgen/enumval___val3_missing:OK #46/72 core_reloc_btfgen/enumval___err_missing:OK #46/73 core_reloc_btfgen/enum64val:OK #46/74 core_reloc_btfgen/enum64val___diff:OK #46/75 core_reloc_btfgen/enum64val___val3_missing:OK #46/76 core_reloc_btfgen/enum64val___err_missing:OK ... Summary: 1/62 PASSED, 14 SKIPPED, 0 FAILED
Totally 14 subtests are skipped instead of 25.
Reported-by: Alexei Starovoitov ast@kernel.org Signed-off-by: Yonghong Song yhs@fb.com Link: https://lore.kernel.org/r/20220614055526.628299-1-yhs@fb.com Signed-off-by: Alexei Starovoitov ast@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- tools/testing/selftests/bpf/prog_tests/core_reloc.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/tools/testing/selftests/bpf/prog_tests/core_reloc.c b/tools/testing/selftests/bpf/prog_tests/core_reloc.c index 3712dfe1be59..ed85abd6782c 100644 --- a/tools/testing/selftests/bpf/prog_tests/core_reloc.c +++ b/tools/testing/selftests/bpf/prog_tests/core_reloc.c @@ -84,6 +84,7 @@ static int duration = 0; #define NESTING_ERR_CASE(name) { \ NESTING_CASE_COMMON(name), \ .fails = true, \ + .run_btfgen_fails = true, \ }
#define ARRAYS_DATA(struct_name) STRUCT_TO_CHAR_PTR(struct_name) { \ @@ -258,12 +259,14 @@ static int duration = 0; BITFIELDS_CASE_COMMON("test_core_reloc_bitfields_probed.o", \ "probed:", name), \ .fails = true, \ + .run_btfgen_fails = true, \ .raw_tp_name = "sys_enter", \ .prog_name = "test_core_bitfields", \ }, { \ BITFIELDS_CASE_COMMON("test_core_reloc_bitfields_direct.o", \ "direct:", name), \ .fails = true, \ + .run_btfgen_fails = true, \ .prog_name = "test_core_bitfields_direct", \ }
@@ -304,6 +307,7 @@ static int duration = 0; #define SIZE_ERR_CASE(name) { \ SIZE_CASE_COMMON(name), \ .fails = true, \ + .run_btfgen_fails = true, \ }
#define TYPE_BASED_CASE_COMMON(name) \ @@ -377,6 +381,7 @@ struct core_reloc_test_case { const char *output; int output_len; bool fails; + bool run_btfgen_fails; bool needs_testmod; bool relaxed_core_relocs; const char *prog_name; @@ -894,7 +899,7 @@ static void run_core_reloc_tests(bool use_btfgen) /* generate a "minimal" BTF file and use it as source */ if (use_btfgen) {
- if (!test_case->btf_src_file || test_case->fails) { + if (!test_case->btf_src_file || test_case->run_btfgen_fails) { test__skip(); continue; }
From: Shah Dharati dharshah@amd.com
[ Upstream commit b840b64bc8ed3fc46f6d6aa7f97c43862a33bea5 ]
[Why & How] For a some specific monitors, when connected on boot or hot plug, monitor flash for 1/2 seconds can happen during first HDCP query operation. Ading some delay in the init sequence for these monitors fixes the issue, so it is implemented as monitor specific patch.
Co-authored-by: Shah Dharati dharshah@amd.com Reviewed-by: Hansen Dsouza Hansen.Dsouza@amd.com Reviewed-by: Nicholas Kazlauskas Nicholas.Kazlauskas@amd.com Acked-by: Hamza Mahfooz hamza.mahfooz@amd.com Signed-off-by: Shah Dharati dharshah@amd.com Tested-by: Daniel Wheeler daniel.wheeler@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/amd/display/modules/hdcp/hdcp2_transition.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp2_transition.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp2_transition.c index 1f4095b26409..c5f6c11de7e5 100644 --- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp2_transition.c +++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp2_transition.c @@ -524,7 +524,7 @@ enum mod_hdcp_status mod_hdcp_hdcp2_dp_transition(struct mod_hdcp *hdcp, set_watchdog_in_ms(hdcp, 3000, output); set_state_id(hdcp, output, D2_A6_WAIT_FOR_RX_ID_LIST); } else { - callback_in_ms(0, output); + callback_in_ms(1, output); set_state_id(hdcp, output, D2_SEND_CONTENT_STREAM_TYPE); } break;
From: Ivan Bornyakov i.bornyakov@metrotek.ru
[ Upstream commit 9794ef5a68430946da2dfe7342be53b50bce9a41 ]
phydev->port was not set and always reported as PORT_TP. Set phydev->port according to inserted SFP module.
Signed-off-by: Ivan Bornyakov i.bornyakov@metrotek.ru Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/phy/marvell-88x2222.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/drivers/net/phy/marvell-88x2222.c b/drivers/net/phy/marvell-88x2222.c index d8b31d4d2a73..f070776ca904 100644 --- a/drivers/net/phy/marvell-88x2222.c +++ b/drivers/net/phy/marvell-88x2222.c @@ -490,6 +490,7 @@ static int mv2222_sfp_insert(void *upstream, const struct sfp_eeprom_id *id) dev = &phydev->mdio.dev;
sfp_parse_support(phydev->sfp_bus, id, sfp_supported); + phydev->port = sfp_parse_port(phydev->sfp_bus, id, sfp_supported); sfp_interface = sfp_select_interface(phydev->sfp_bus, sfp_supported);
dev_info(dev, "%s SFP module inserted\n", phy_modes(sfp_interface)); @@ -526,6 +527,7 @@ static void mv2222_sfp_remove(void *upstream)
priv->line_interface = PHY_INTERFACE_MODE_NA; linkmode_zero(priv->supported); + phydev->port = PORT_NONE; }
static void mv2222_sfp_link_up(void *upstream)
From: Petr Machata petrm@nvidia.com
[ Upstream commit 8cad339db339a39cb82b1188e4be4070a433abac ]
The scale tests are currently testing two things: that some number of instances of a given resource can actually be created; and that when an attempt is made to create more than the supported amount, the failures are noted and handled gracefully.
Sometimes the scale test depends on more than one resource. In particular, a following patch will add a RIF counter scale test, which depends on the number of RIF counters that can be bound, and also on the number of RIFs that can be created.
When the test is limited by the auxiliary resource and not by the primary one, there's no point trying to run the overflow test, because it would be testing exhaustion of the wrong resource.
To support this use case, when the $test_get_target yields 0, skip the test instead.
Signed-off-by: Petr Machata petrm@nvidia.com Reviewed-by: Amit Cohen amcohen@nvidia.com Signed-off-by: Ido Schimmel idosch@nvidia.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- .../selftests/drivers/net/mlxsw/spectrum-2/resource_scale.sh | 5 +++++ .../selftests/drivers/net/mlxsw/spectrum/resource_scale.sh | 4 ++++ 2 files changed, 9 insertions(+)
diff --git a/tools/testing/selftests/drivers/net/mlxsw/spectrum-2/resource_scale.sh b/tools/testing/selftests/drivers/net/mlxsw/spectrum-2/resource_scale.sh index e9f65bd2e299..df920b6ed7c4 100755 --- a/tools/testing/selftests/drivers/net/mlxsw/spectrum-2/resource_scale.sh +++ b/tools/testing/selftests/drivers/net/mlxsw/spectrum-2/resource_scale.sh @@ -36,6 +36,11 @@ for current_test in ${TESTS:-$ALL_TESTS}; do for should_fail in 0 1; do RET=0 target=$(${current_test}_get_target "$should_fail") + if ((target == 0)); then + log_test_skip "'$current_test' should_fail=$should_fail test" + continue + fi + ${current_test}_setup_prepare setup_wait $num_netifs ${current_test}_test "$target" "$should_fail" diff --git a/tools/testing/selftests/drivers/net/mlxsw/spectrum/resource_scale.sh b/tools/testing/selftests/drivers/net/mlxsw/spectrum/resource_scale.sh index dea33dc93790..b75d1fcd2db2 100755 --- a/tools/testing/selftests/drivers/net/mlxsw/spectrum/resource_scale.sh +++ b/tools/testing/selftests/drivers/net/mlxsw/spectrum/resource_scale.sh @@ -41,6 +41,10 @@ for current_test in ${TESTS:-$ALL_TESTS}; do for should_fail in 0 1; do RET=0 target=$(${current_test}_get_target "$should_fail") + if ((target == 0)); then + log_test_skip "'$current_test' [$profile] should_fail=$should_fail test" + continue + fi ${current_test}_setup_prepare setup_wait $num_netifs ${current_test}_test "$target" "$should_fail"
From: Ong Boon Leong boon.leong.ong@intel.com
[ Upstream commit fa9c562f9735d24c3253747eb21f3f0c0f6de48e ]
xpcs_config() has 'advertising' input that is required for C37 1000BASE-X AN in later patch series. So, we prepare xpcs_do_config() for it.
For sja1105, xpcs_do_config() is used for xpcs configuration without depending on advertising input, so set to NULL.
Reported-by: kernel test robot lkp@intel.com Signed-off-by: Ong Boon Leong boon.leong.ong@intel.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/dsa/sja1105/sja1105_main.c | 2 +- drivers/net/pcs/pcs-xpcs.c | 6 +++--- include/linux/pcs/pcs-xpcs.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c index 698c7d1fb45c..b03d0d0c3dbf 100644 --- a/drivers/net/dsa/sja1105/sja1105_main.c +++ b/drivers/net/dsa/sja1105/sja1105_main.c @@ -2330,7 +2330,7 @@ int sja1105_static_config_reload(struct sja1105_private *priv, else mode = MLO_AN_PHY;
- rc = xpcs_do_config(xpcs, priv->phy_mode[i], mode); + rc = xpcs_do_config(xpcs, priv->phy_mode[i], mode, NULL); if (rc < 0) goto out;
diff --git a/drivers/net/pcs/pcs-xpcs.c b/drivers/net/pcs/pcs-xpcs.c index d25fbb9caeba..b17908a0b27c 100644 --- a/drivers/net/pcs/pcs-xpcs.c +++ b/drivers/net/pcs/pcs-xpcs.c @@ -795,7 +795,7 @@ static int xpcs_config_2500basex(struct dw_xpcs *xpcs) }
int xpcs_do_config(struct dw_xpcs *xpcs, phy_interface_t interface, - unsigned int mode) + unsigned int mode, const unsigned long *advertising) { const struct xpcs_compat *compat; int ret; @@ -843,7 +843,7 @@ static int xpcs_config(struct phylink_pcs *pcs, unsigned int mode, { struct dw_xpcs *xpcs = phylink_pcs_to_xpcs(pcs);
- return xpcs_do_config(xpcs, interface, mode); + return xpcs_do_config(xpcs, interface, mode, advertising); }
static int xpcs_get_state_c73(struct dw_xpcs *xpcs, @@ -864,7 +864,7 @@ static int xpcs_get_state_c73(struct dw_xpcs *xpcs,
state->link = 0;
- return xpcs_do_config(xpcs, state->interface, MLO_AN_INBAND); + return xpcs_do_config(xpcs, state->interface, MLO_AN_INBAND, NULL); }
if (state->an_enabled && xpcs_aneg_done_c73(xpcs, state, compat)) { diff --git a/include/linux/pcs/pcs-xpcs.h b/include/linux/pcs/pcs-xpcs.h index 266eb26fb029..37eb97cc2283 100644 --- a/include/linux/pcs/pcs-xpcs.h +++ b/include/linux/pcs/pcs-xpcs.h @@ -30,7 +30,7 @@ int xpcs_get_an_mode(struct dw_xpcs *xpcs, phy_interface_t interface); void xpcs_link_up(struct phylink_pcs *pcs, unsigned int mode, phy_interface_t interface, int speed, int duplex); int xpcs_do_config(struct dw_xpcs *xpcs, phy_interface_t interface, - unsigned int mode); + unsigned int mode, const unsigned long *advertising); void xpcs_get_interfaces(struct dw_xpcs *xpcs, unsigned long *interfaces); int xpcs_config_eee(struct dw_xpcs *xpcs, int mult_fact_100ns, int enable);
Hi,
Why are the stable kernels picking up this development commit? I don't see you picking up the commits that actually make use of this new parameter.
Maybe stable folk can tell me which of the rules listed in Documentation/process/stable-kernel-rules.rst that this patch conforms with that makes it eligable for stable kernels. Thanks.
Russell.
On Thu, Aug 11, 2022 at 11:27:12AM -0400, Sasha Levin wrote:
From: Ong Boon Leong boon.leong.ong@intel.com
[ Upstream commit fa9c562f9735d24c3253747eb21f3f0c0f6de48e ]
xpcs_config() has 'advertising' input that is required for C37 1000BASE-X AN in later patch series. So, we prepare xpcs_do_config() for it.
For sja1105, xpcs_do_config() is used for xpcs configuration without depending on advertising input, so set to NULL.
Reported-by: kernel test robot lkp@intel.com Signed-off-by: Ong Boon Leong boon.leong.ong@intel.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org
drivers/net/dsa/sja1105/sja1105_main.c | 2 +- drivers/net/pcs/pcs-xpcs.c | 6 +++--- include/linux/pcs/pcs-xpcs.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c index 698c7d1fb45c..b03d0d0c3dbf 100644 --- a/drivers/net/dsa/sja1105/sja1105_main.c +++ b/drivers/net/dsa/sja1105/sja1105_main.c @@ -2330,7 +2330,7 @@ int sja1105_static_config_reload(struct sja1105_private *priv, else mode = MLO_AN_PHY;
rc = xpcs_do_config(xpcs, priv->phy_mode[i], mode);
if (rc < 0) goto out;rc = xpcs_do_config(xpcs, priv->phy_mode[i], mode, NULL);
diff --git a/drivers/net/pcs/pcs-xpcs.c b/drivers/net/pcs/pcs-xpcs.c index d25fbb9caeba..b17908a0b27c 100644 --- a/drivers/net/pcs/pcs-xpcs.c +++ b/drivers/net/pcs/pcs-xpcs.c @@ -795,7 +795,7 @@ static int xpcs_config_2500basex(struct dw_xpcs *xpcs) } int xpcs_do_config(struct dw_xpcs *xpcs, phy_interface_t interface,
unsigned int mode)
unsigned int mode, const unsigned long *advertising)
{ const struct xpcs_compat *compat; int ret; @@ -843,7 +843,7 @@ static int xpcs_config(struct phylink_pcs *pcs, unsigned int mode, { struct dw_xpcs *xpcs = phylink_pcs_to_xpcs(pcs);
- return xpcs_do_config(xpcs, interface, mode);
- return xpcs_do_config(xpcs, interface, mode, advertising);
} static int xpcs_get_state_c73(struct dw_xpcs *xpcs, @@ -864,7 +864,7 @@ static int xpcs_get_state_c73(struct dw_xpcs *xpcs, state->link = 0;
return xpcs_do_config(xpcs, state->interface, MLO_AN_INBAND);
}return xpcs_do_config(xpcs, state->interface, MLO_AN_INBAND, NULL);
if (state->an_enabled && xpcs_aneg_done_c73(xpcs, state, compat)) { diff --git a/include/linux/pcs/pcs-xpcs.h b/include/linux/pcs/pcs-xpcs.h index 266eb26fb029..37eb97cc2283 100644 --- a/include/linux/pcs/pcs-xpcs.h +++ b/include/linux/pcs/pcs-xpcs.h @@ -30,7 +30,7 @@ int xpcs_get_an_mode(struct dw_xpcs *xpcs, phy_interface_t interface); void xpcs_link_up(struct phylink_pcs *pcs, unsigned int mode, phy_interface_t interface, int speed, int duplex); int xpcs_do_config(struct dw_xpcs *xpcs, phy_interface_t interface,
unsigned int mode);
unsigned int mode, const unsigned long *advertising);
void xpcs_get_interfaces(struct dw_xpcs *xpcs, unsigned long *interfaces); int xpcs_config_eee(struct dw_xpcs *xpcs, int mult_fact_100ns, int enable); -- 2.35.1
From: Ong Boon Leong boon.leong.ong@intel.com
[ Upstream commit ab21cf920928a791aa70b8665b395294da17667c ]
stmmac_mdio_register() lacks fixed-link consideration and only skip PHY scanning if it has done DT style PHY discovery. So, for DT or ACPI _DSD setting of fixed-link, the PHY scanning should not happen.
v2: fix incorrect order related to fwnode that is not caught in non-DT platform.
Tested-by: Emilio Riva emilio.riva@ericsson.com Signed-off-by: Ong Boon Leong boon.leong.ong@intel.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 12 +++++++----- drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c | 14 ++++++++++++++ 2 files changed, 21 insertions(+), 5 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index c5f33630e771..306f03399f5e 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -1119,18 +1119,20 @@ static void stmmac_check_pcs_mode(struct stmmac_priv *priv) static int stmmac_init_phy(struct net_device *dev) { struct stmmac_priv *priv = netdev_priv(dev); - struct device_node *node; + struct fwnode_handle *fwnode; int ret;
- node = priv->plat->phylink_node; + fwnode = of_fwnode_handle(priv->plat->phylink_node); + if (!fwnode) + fwnode = dev_fwnode(priv->device);
- if (node) - ret = phylink_of_phy_connect(priv->phylink, node, 0); + if (fwnode) + ret = phylink_fwnode_phy_connect(priv->phylink, fwnode, 0);
/* Some DT bindings do not set-up the PHY handle. Let's try to * manually parse it */ - if (!node || ret) { + if (!fwnode || ret) { int addr = priv->plat->phy_addr; struct phy_device *phydev;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c index 03d3d1f7aa4b..5f177ea80725 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c @@ -434,9 +434,11 @@ int stmmac_mdio_register(struct net_device *ndev) int err = 0; struct mii_bus *new_bus; struct stmmac_priv *priv = netdev_priv(ndev); + struct fwnode_handle *fwnode = of_fwnode_handle(priv->plat->phylink_node); struct stmmac_mdio_bus_data *mdio_bus_data = priv->plat->mdio_bus_data; struct device_node *mdio_node = priv->plat->mdio_node; struct device *dev = ndev->dev.parent; + struct fwnode_handle *fixed_node; int addr, found, max_addr;
if (!mdio_bus_data) @@ -490,6 +492,18 @@ int stmmac_mdio_register(struct net_device *ndev) if (priv->plat->has_xgmac) stmmac_xgmac2_mdio_read(new_bus, 0, MII_ADDR_C45);
+ /* If fixed-link is set, skip PHY scanning */ + if (!fwnode) + fwnode = dev_fwnode(priv->device); + + if (fwnode) { + fixed_node = fwnode_get_named_child_node(fwnode, "fixed-link"); + if (fixed_node) { + fwnode_handle_put(fixed_node); + goto bus_register_done; + } + } + if (priv->plat->phy_node || mdio_node) goto bus_register_done;
From: Oleksij Rempel o.rempel@pengutronix.de
[ Upstream commit 7a49f2193063b7db60a964fc26774275a4c964cd ]
Rework MDIO locking to avoid potential circular locking:
WARNING: possible circular locking dependency detected 5.19.0-rc1-ar9331-00017-g3ab364c7c48c #5 Not tainted ------------------------------------------------------ kworker/u2:4/68 is trying to acquire lock: 81f3c83c (ar9331:1005:(&ar9331_mdio_regmap_config)->lock){+.+.}-{4:4}, at: regmap_write+0x50/0x8c
but task is already holding lock: 81f60494 (&bus->mdio_lock){+.+.}-{4:4}, at: mdiobus_read+0x40/0x78
which lock already depends on the new lock.
the existing dependency chain (in reverse order) is:
-> #1 (&bus->mdio_lock){+.+.}-{4:4}: lock_acquire+0x2d4/0x360 __mutex_lock+0xf8/0x384 mutex_lock_nested+0x2c/0x38 mdiobus_write+0x44/0x80 ar9331_sw_bus_write+0x50/0xe4 _regmap_raw_write_impl+0x604/0x724 _regmap_bus_raw_write+0x9c/0xb4 _regmap_write+0xdc/0x1a0 _regmap_update_bits+0xf4/0x118 _regmap_select_page+0x108/0x138 _regmap_raw_read+0x25c/0x288 _regmap_bus_read+0x60/0x98 _regmap_read+0xd4/0x1b0 _regmap_update_bits+0xc4/0x118 regmap_update_bits_base+0x64/0x8c ar9331_sw_irq_bus_sync_unlock+0x40/0x6c __irq_set_handler+0x7c/0xac ar9331_sw_irq_map+0x48/0x7c irq_domain_associate+0x174/0x208 irq_create_mapping_affinity+0x1a8/0x230 ar9331_sw_probe+0x22c/0x388 mdio_probe+0x44/0x70 really_probe+0x200/0x424 __driver_probe_device+0x290/0x298 driver_probe_device+0x54/0xe4 __device_attach_driver+0xe4/0x130 bus_for_each_drv+0xb4/0xd8 __device_attach+0x104/0x1a4 bus_probe_device+0x48/0xc4 device_add+0x600/0x800 mdio_device_register+0x68/0xa0 of_mdiobus_register+0x2bc/0x3c4 ag71xx_probe+0x6e4/0x984 platform_probe+0x78/0xd0 really_probe+0x200/0x424 __driver_probe_device+0x290/0x298 driver_probe_device+0x54/0xe4 __driver_attach+0x17c/0x190 bus_for_each_dev+0x8c/0xd0 bus_add_driver+0x110/0x228 driver_register+0xe4/0x12c do_one_initcall+0x104/0x2a0 kernel_init_freeable+0x250/0x288 kernel_init+0x34/0x130 ret_from_kernel_thread+0x14/0x1c
-> #0 (ar9331:1005:(&ar9331_mdio_regmap_config)->lock){+.+.}-{4:4}: check_noncircular+0x88/0xc0 __lock_acquire+0x10bc/0x18bc lock_acquire+0x2d4/0x360 __mutex_lock+0xf8/0x384 mutex_lock_nested+0x2c/0x38 regmap_write+0x50/0x8c ar9331_sw_mbus_read+0x74/0x1b8 __mdiobus_read+0x90/0xec mdiobus_read+0x50/0x78 get_phy_device+0xa0/0x18c fwnode_mdiobus_register_phy+0x120/0x1d4 of_mdiobus_register+0x244/0x3c4 devm_of_mdiobus_register+0xe8/0x100 ar9331_sw_setup+0x16c/0x3a0 dsa_register_switch+0x7dc/0xcc0 ar9331_sw_probe+0x370/0x388 mdio_probe+0x44/0x70 really_probe+0x200/0x424 __driver_probe_device+0x290/0x298 driver_probe_device+0x54/0xe4 __device_attach_driver+0xe4/0x130 bus_for_each_drv+0xb4/0xd8 __device_attach+0x104/0x1a4 bus_probe_device+0x48/0xc4 deferred_probe_work_func+0xf0/0x10c process_one_work+0x314/0x4d4 worker_thread+0x2a4/0x354 kthread+0x134/0x13c ret_from_kernel_thread+0x14/0x1c
other info that might help us debug this:
Possible unsafe locking scenario:
CPU0 CPU1 ---- ---- lock(&bus->mdio_lock); lock(ar9331:1005:(&ar9331_mdio_regmap_config)->lock); lock(&bus->mdio_lock); lock(ar9331:1005:(&ar9331_mdio_regmap_config)->lock);
*** DEADLOCK ***
5 locks held by kworker/u2:4/68: #0: 81c04eb4 ((wq_completion)events_unbound){+.+.}-{0:0}, at: process_one_work+0x1e4/0x4d4 #1: 81f0de78 (deferred_probe_work){+.+.}-{0:0}, at: process_one_work+0x1e4/0x4d4 #2: 81f0a880 (&dev->mutex){....}-{4:4}, at: __device_attach+0x40/0x1a4 #3: 80c8aee0 (dsa2_mutex){+.+.}-{4:4}, at: dsa_register_switch+0x5c/0xcc0 #4: 81f60494 (&bus->mdio_lock){+.+.}-{4:4}, at: mdiobus_read+0x40/0x78
stack backtrace: CPU: 0 PID: 68 Comm: kworker/u2:4 Not tainted 5.19.0-rc1-ar9331-00017-g3ab364c7c48c #5 Workqueue: events_unbound deferred_probe_work_func Stack : 00000056 800d4638 81f0d64c 00000004 00000018 00000000 80a20000 80a20000 80937590 81ef3858 81f0d760 3913578a 00000005 8045e824 81f0d600 a8db84cc 00000000 00000000 80937590 00000a44 00000000 00000002 00000001 ffffffff 81f0d6a4 80982d7c 0000000f 20202020 80a20000 00000001 80937590 81ef3858 81f0d760 3913578a 00000005 00000005 00000000 03bd0000 00000000 80e00000 ... Call Trace: [<80069db0>] show_stack+0x94/0x130 [<8045e824>] dump_stack_lvl+0x54/0x8c [<800c7fac>] check_noncircular+0x88/0xc0 [<800ca068>] __lock_acquire+0x10bc/0x18bc [<800cb478>] lock_acquire+0x2d4/0x360 [<807b84c4>] __mutex_lock+0xf8/0x384 [<807b877c>] mutex_lock_nested+0x2c/0x38 [<804ea640>] regmap_write+0x50/0x8c [<80501e38>] ar9331_sw_mbus_read+0x74/0x1b8 [<804fe9a0>] __mdiobus_read+0x90/0xec [<804feac4>] mdiobus_read+0x50/0x78 [<804fcf74>] get_phy_device+0xa0/0x18c [<804ffeb4>] fwnode_mdiobus_register_phy+0x120/0x1d4 [<805004f0>] of_mdiobus_register+0x244/0x3c4 [<804f0c50>] devm_of_mdiobus_register+0xe8/0x100 [<805017a0>] ar9331_sw_setup+0x16c/0x3a0 [<807355c8>] dsa_register_switch+0x7dc/0xcc0 [<80501468>] ar9331_sw_probe+0x370/0x388 [<804ff0c0>] mdio_probe+0x44/0x70 [<804d1848>] really_probe+0x200/0x424 [<804d1cfc>] __driver_probe_device+0x290/0x298 [<804d1d58>] driver_probe_device+0x54/0xe4 [<804d2298>] __device_attach_driver+0xe4/0x130 [<804cf048>] bus_for_each_drv+0xb4/0xd8 [<804d200c>] __device_attach+0x104/0x1a4 [<804d026c>] bus_probe_device+0x48/0xc4 [<804d108c>] deferred_probe_work_func+0xf0/0x10c [<800a0ffc>] process_one_work+0x314/0x4d4 [<800a17fc>] worker_thread+0x2a4/0x354 [<800a9a54>] kthread+0x134/0x13c [<8006306c>] ret_from_kernel_thread+0x14/0x1c [
Signed-off-by: Oleksij Rempel o.rempel@pengutronix.de Link: https://lore.kernel.org/r/20220616112550.877118-1-o.rempel@pengutronix.de Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/dsa/qca/ar9331.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-)
diff --git a/drivers/net/dsa/qca/ar9331.c b/drivers/net/dsa/qca/ar9331.c index e5098cfe44bc..f23ce56fa591 100644 --- a/drivers/net/dsa/qca/ar9331.c +++ b/drivers/net/dsa/qca/ar9331.c @@ -818,7 +818,7 @@ static int __ar9331_mdio_write(struct mii_bus *sbus, u8 mode, u16 reg, u16 val) FIELD_GET(AR9331_SW_LOW_ADDR_PHY, reg); r = FIELD_GET(AR9331_SW_LOW_ADDR_REG, reg);
- return mdiobus_write(sbus, p, r, val); + return __mdiobus_write(sbus, p, r, val); }
static int __ar9331_mdio_read(struct mii_bus *sbus, u16 reg) @@ -829,7 +829,7 @@ static int __ar9331_mdio_read(struct mii_bus *sbus, u16 reg) FIELD_GET(AR9331_SW_LOW_ADDR_PHY, reg); r = FIELD_GET(AR9331_SW_LOW_ADDR_REG, reg);
- return mdiobus_read(sbus, p, r); + return __mdiobus_read(sbus, p, r); }
static int ar9331_mdio_read(void *ctx, const void *reg_buf, size_t reg_len, @@ -849,6 +849,8 @@ static int ar9331_mdio_read(void *ctx, const void *reg_buf, size_t reg_len, return 0; }
+ mutex_lock_nested(&sbus->mdio_lock, MDIO_MUTEX_NESTED); + ret = __ar9331_mdio_read(sbus, reg); if (ret < 0) goto error; @@ -860,9 +862,13 @@ static int ar9331_mdio_read(void *ctx, const void *reg_buf, size_t reg_len,
*(u32 *)val_buf |= ret << 16;
+ mutex_unlock(&sbus->mdio_lock); + return 0; error: + mutex_unlock(&sbus->mdio_lock); dev_err_ratelimited(&sbus->dev, "Bus error. Failed to read register.\n"); + return ret; }
@@ -872,12 +878,15 @@ static int ar9331_mdio_write(void *ctx, u32 reg, u32 val) struct mii_bus *sbus = priv->sbus; int ret;
+ mutex_lock_nested(&sbus->mdio_lock, MDIO_MUTEX_NESTED); if (reg == AR9331_SW_REG_PAGE) { ret = __ar9331_mdio_write(sbus, AR9331_SW_MDIO_PHY_MODE_PAGE, 0, val); if (ret < 0) goto error;
+ mutex_unlock(&sbus->mdio_lock); + return 0; }
@@ -897,10 +906,14 @@ static int ar9331_mdio_write(void *ctx, u32 reg, u32 val) if (ret < 0) goto error;
+ mutex_unlock(&sbus->mdio_lock); + return 0;
error: + mutex_unlock(&sbus->mdio_lock); dev_err_ratelimited(&sbus->dev, "Bus error. Failed to write register.\n"); + return ret; }
From: Yang Yingliang yangyingliang@huawei.com
[ Upstream commit bb45f5433f23cf103ba29c9692ee553e061f2cb4 ]
of_graph_get_next_endpoint() returns an 'endpoint' node pointer with refcount incremented. The refcount should be decremented before returning from vpif_probe().
Reported-by: Hulk Robot hulkci@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com Signed-off-by: Hans Verkuil hverkuil-cisco@xs4all.nl Signed-off-by: Mauro Carvalho Chehab mchehab@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/media/platform/ti/davinci/vpif.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/media/platform/ti/davinci/vpif.c b/drivers/media/platform/ti/davinci/vpif.c index 97ef770266af..da27da4c165a 100644 --- a/drivers/media/platform/ti/davinci/vpif.c +++ b/drivers/media/platform/ti/davinci/vpif.c @@ -469,6 +469,7 @@ static int vpif_probe(struct platform_device *pdev) endpoint); if (!endpoint) return 0; + of_node_put(endpoint);
/* * For DT platforms, manually create platform_devices for
From: Yunfei Dong yunfei.dong@mediatek.com
[ Upstream commit 9223415d47e1efe939fcc791870db8ce5bb6cc03 ]
When SCP timeout during playing video, kernel crashes with following message. It's caused by accessing NULL pointer in vpu_dec_ipi_handler. This patch doesn't solve the root cause of NULL pointer, but merely prevent kernel crashed when encounter the NULL pointer.
After applied this patch, kernel keeps alive, only the video player turns to green screen.
[67242.065474] pc : vpu_dec_ipi_handler+0xa0/0xb20 [mtk_vcodec_dec] [67242.065485] [MTK_V4L2] level=0 fops_vcodec_open(),334: 18000000.vcodec_dec decoder [135] [67242.065523] lr : scp_ipi_handler+0x11c/0x244 [mtk_scp] [67242.065540] sp : ffffffbb4207fb10 [67242.065557] x29: ffffffbb4207fb30 x28: ffffffd00a1d5000 [67242.065592] x27: 1ffffffa0143aa24 x26: 0000000000000000 [67242.065625] x25: dfffffd000000000 x24: ffffffd0168bfdb0 [67242.065659] x23: 1ffffff76840ff74 x22: ffffffbb41fa8a88 [67242.065692] x21: ffffffbb4207fb9c x20: ffffffbb4207fba0 [67242.065725] x19: ffffffbb4207fb98 x18: 0000000000000000 [67242.065758] x17: 0000000000000000 x16: ffffffd042022094 [67242.065791] x15: 1ffffff77ed4b71a x14: 1ffffff77ed4b719 [67242.065824] x13: 0000000000000000 x12: 0000000000000000 [67242.065857] x11: 0000000000000000 x10: dfffffd000000001 [67242.065890] x9 : 0000000000000000 x8 : 0000000000000002 [67242.065923] x7 : 0000000000000000 x6 : 000000000000003f [67242.065956] x5 : 0000000000000040 x4 : ffffffffffffffe0 [67242.065989] x3 : ffffffd043b841b8 x2 : 0000000000000000 [67242.066021] x1 : 0000000000000010 x0 : 0000000000000010 [67242.066055] Call trace: [67242.066092] vpu_dec_ipi_handler+0xa0/0xb20 [mtk_vcodec_dec 12220d230d83a7426fc38c56b3e7bc6066955bae] [67242.066119] scp_ipi_handler+0x11c/0x244 [mtk_scp 8fb69c2ef141dd3192518b952b65aba35627b8bf] [67242.066145] mt8192_scp_irq_handler+0x70/0x128 [mtk_scp 8fb69c2ef141dd3192518b952b65aba35627b8bf] [67242.066172] scp_irq_handler+0xa0/0x114 [mtk_scp 8fb69c2ef141dd3192518b952b65aba35627b8bf] [67242.066200] irq_thread_fn+0x84/0xf8 [67242.066220] irq_thread+0x170/0x1ec [67242.066242] kthread+0x2f8/0x3b8 [67242.066264] ret_from_fork+0x10/0x30 [67242.066292] Code: 38f96908 35003628 91004340 d343fc08 (38f96908)
Signed-off-by: Tinghan Shen tinghan.shen@mediatek.com Signed-off-by: Yunfei Dong yunfei.dong@mediatek.com Reviewed-by: Macpaul Lin macpaul.lin@mediatek.com Signed-off-by: Hans Verkuil hverkuil-cisco@xs4all.nl Signed-off-by: Mauro Carvalho Chehab mchehab@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/media/platform/mediatek/vcodec/vdec_vpu_if.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/drivers/media/platform/mediatek/vcodec/vdec_vpu_if.c b/drivers/media/platform/mediatek/vcodec/vdec_vpu_if.c index 35f4d5583084..df309e8e9379 100644 --- a/drivers/media/platform/mediatek/vcodec/vdec_vpu_if.c +++ b/drivers/media/platform/mediatek/vcodec/vdec_vpu_if.c @@ -91,6 +91,11 @@ static void vpu_dec_ipi_handler(void *data, unsigned int len, void *priv) struct vdec_vpu_inst *vpu = (struct vdec_vpu_inst *) (unsigned long)msg->ap_inst_addr;
+ if (!vpu) { + mtk_v4l2_err("ap_inst_addr is NULL, did the SCP hang or crash?"); + return; + } + mtk_vcodec_debug(vpu, "+ id=%X", msg->msg_id);
vpu->failure = msg->status;
From: Oliver Neukum oneukum@suse.com
[ Upstream commit ca9dc8d06ab64543a6a31adac5003349c5671218 ]
If we want to avoid memory corruption on incoherent architectures, buffers for DMA must not reside - on the stack - embedded within other structures
Allocate them separately.
v2: fix uninitialized return value
Signed-off-by: Oliver Neukum oneukum@suse.com Signed-off-by: Hans Verkuil hverkuil-cisco@xs4all.nl Signed-off-by: Mauro Carvalho Chehab mchehab@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/media/usb/airspy/airspy.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-)
diff --git a/drivers/media/usb/airspy/airspy.c b/drivers/media/usb/airspy/airspy.c index d568452618d1..240a7cc56777 100644 --- a/drivers/media/usb/airspy/airspy.c +++ b/drivers/media/usb/airspy/airspy.c @@ -123,7 +123,7 @@ struct airspy {
/* USB control message buffer */ #define BUF_SIZE 128 - u8 buf[BUF_SIZE]; + u8 *buf;
/* Current configuration */ unsigned int f_adc; @@ -856,6 +856,7 @@ static void airspy_video_release(struct v4l2_device *v)
v4l2_ctrl_handler_free(&s->hdl); v4l2_device_unregister(&s->v4l2_dev); + kfree(s->buf); kfree(s); }
@@ -963,7 +964,10 @@ static int airspy_probe(struct usb_interface *intf, { struct airspy *s; int ret; - u8 u8tmp, buf[BUF_SIZE]; + u8 u8tmp, *buf; + + buf = NULL; + ret = -ENOMEM;
s = kzalloc(sizeof(struct airspy), GFP_KERNEL); if (s == NULL) { @@ -971,6 +975,13 @@ static int airspy_probe(struct usb_interface *intf, return -ENOMEM; }
+ s->buf = kzalloc(BUF_SIZE, GFP_KERNEL); + if (!s->buf) + goto err_free_mem; + buf = kzalloc(BUF_SIZE, GFP_KERNEL); + if (!buf) + goto err_free_mem; + mutex_init(&s->v4l2_lock); mutex_init(&s->vb_queue_lock); spin_lock_init(&s->queued_bufs_lock); @@ -1068,6 +1079,8 @@ static int airspy_probe(struct usb_interface *intf, v4l2_ctrl_handler_free(&s->hdl); v4l2_device_unregister(&s->v4l2_dev); err_free_mem: + kfree(buf); + kfree(s->buf); kfree(s); return ret; }
From: Dongliang Mu mudongliangabcd@gmail.com
[ Upstream commit 945a9a8e448b65bec055d37eba58f711b39f66f0 ]
The error handling code in pvr2_hdw_create forgets to unregister the v4l2 device. When pvr2_hdw_create returns back to pvr2_context_create, it calls pvr2_context_destroy to destroy context, but mp->hdw is NULL, which leads to that pvr2_hdw_destroy directly returns.
Fix this by adding v4l2_device_unregister to decrease the refcount of usb interface.
Reported-by: syzbot+77b432d57c4791183ed4@syzkaller.appspotmail.com Signed-off-by: Dongliang Mu mudongliangabcd@gmail.com Signed-off-by: Hans Verkuil hverkuil-cisco@xs4all.nl Signed-off-by: Mauro Carvalho Chehab mchehab@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/media/usb/pvrusb2/pvrusb2-hdw.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c index a9666373af6b..92d6db1ad00f 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c @@ -2610,6 +2610,7 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, del_timer_sync(&hdw->encoder_run_timer); del_timer_sync(&hdw->encoder_wait_timer); flush_work(&hdw->workpoll); + v4l2_device_unregister(&hdw->v4l2_dev); usb_free_urb(hdw->ctl_read_urb); usb_free_urb(hdw->ctl_write_urb); kfree(hdw->ctl_read_buffer);
From: "Paul E. McKenney" paulmck@kernel.org
[ Upstream commit ed4ae5eff4b38797607cbdd80da394149110fb37 ]
This commit applies the "noinstr" tag to the rcu_idle_enter() and rcu_idle_exit() functions, which are invoked from portions of the idle loop that cannot be instrumented. These tags require reworking the rcu_eqs_enter() and rcu_eqs_exit() functions that these two functions invoke in order to cause them to use normal assertions rather than lockdep. In addition, within rcu_idle_exit(), the raw versions of local_irq_save() and local_irq_restore() are used, again to avoid issues with lockdep in uninstrumented code.
This patch is based in part on an earlier patch by Jiri Olsa, discussions with Peter Zijlstra and Frederic Weisbecker, earlier changes by Thomas Gleixner, and off-list discussions with Yonghong Song.
Link: https://lore.kernel.org/lkml/20220515203653.4039075-1-jolsa@kernel.org/ Reported-by: Jiri Olsa jolsa@kernel.org Reported-by: Alexei Starovoitov ast@kernel.org Reported-by: Andrii Nakryiko andrii@kernel.org Signed-off-by: Paul E. McKenney paulmck@kernel.org Reviewed-by: Yonghong Song yhs@fb.com Signed-off-by: Sasha Levin sashal@kernel.org --- kernel/rcu/tree.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c index c25ba442044a..9a5edab5558c 100644 --- a/kernel/rcu/tree.c +++ b/kernel/rcu/tree.c @@ -631,8 +631,8 @@ static noinstr void rcu_eqs_enter(bool user) return; }
- lockdep_assert_irqs_disabled(); instrumentation_begin(); + lockdep_assert_irqs_disabled(); trace_rcu_dyntick(TPS("Start"), rdp->dynticks_nesting, 0, atomic_read(&rdp->dynticks)); WARN_ON_ONCE(IS_ENABLED(CONFIG_RCU_EQS_DEBUG) && !user && !is_idle_task(current)); rcu_preempt_deferred_qs(current); @@ -659,9 +659,9 @@ static noinstr void rcu_eqs_enter(bool user) * If you add or remove a call to rcu_idle_enter(), be sure to test with * CONFIG_RCU_EQS_DEBUG=y. */ -void rcu_idle_enter(void) +void noinstr rcu_idle_enter(void) { - lockdep_assert_irqs_disabled(); + WARN_ON_ONCE(IS_ENABLED(CONFIG_RCU_EQS_DEBUG) && !raw_irqs_disabled()); rcu_eqs_enter(false); } EXPORT_SYMBOL_GPL(rcu_idle_enter); @@ -861,7 +861,7 @@ static void noinstr rcu_eqs_exit(bool user) struct rcu_data *rdp; long oldval;
- lockdep_assert_irqs_disabled(); + WARN_ON_ONCE(IS_ENABLED(CONFIG_RCU_EQS_DEBUG) && !raw_irqs_disabled()); rdp = this_cpu_ptr(&rcu_data); oldval = rdp->dynticks_nesting; WARN_ON_ONCE(IS_ENABLED(CONFIG_RCU_EQS_DEBUG) && oldval < 0); @@ -896,13 +896,13 @@ static void noinstr rcu_eqs_exit(bool user) * If you add or remove a call to rcu_idle_exit(), be sure to test with * CONFIG_RCU_EQS_DEBUG=y. */ -void rcu_idle_exit(void) +void noinstr rcu_idle_exit(void) { unsigned long flags;
- local_irq_save(flags); + raw_local_irq_save(flags); rcu_eqs_exit(false); - local_irq_restore(flags); + raw_local_irq_restore(flags); } EXPORT_SYMBOL_GPL(rcu_idle_exit);
From: Ammar Faizi ammarfaizi2@gnuweeb.org
[ Upstream commit 1ef150cf40be986747c3fa0c0e75acaec412e85e ]
Previously, we used __builtin_mul_overflow() to check for overflow in the multiplication operation in the calloc() function. However, older compiler versions don't support this built-in. This patch changes the overflow checking mechanism to make it work on any compiler version by using a division method to check for overflow. No functional change intended. While in there, remove the unused variable `void *orig`.
Link: https://lore.kernel.org/lkml/20220330024114.GA18892@1wt.eu Suggested-by: Willy Tarreau w@1wt.eu Cc: Alviro Iskandar Setiawan alviro.iskandar@gnuweeb.org Signed-off-by: Ammar Faizi ammarfaizi2@gnuweeb.org Acked-by: Willy Tarreau w@1wt.eu Reviewed-by: Alviro Iskandar Setiawan alviro.iskandar@gnuweeb.org Signed-off-by: Paul E. McKenney paulmck@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- tools/include/nolibc/stdlib.h | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/tools/include/nolibc/stdlib.h b/tools/include/nolibc/stdlib.h index 8fd32eaf8037..92378c4b9660 100644 --- a/tools/include/nolibc/stdlib.h +++ b/tools/include/nolibc/stdlib.h @@ -128,10 +128,9 @@ void *malloc(size_t len) static __attribute__((unused)) void *calloc(size_t size, size_t nmemb) { - void *orig; - size_t res = 0; + size_t x = size * nmemb;
- if (__builtin_expect(__builtin_mul_overflow(nmemb, size, &res), 0)) { + if (__builtin_expect(size && ((x / size) != nmemb), 0)) { SET_ERRNO(ENOMEM); return NULL; } @@ -140,7 +139,7 @@ void *calloc(size_t size, size_t nmemb) * No need to zero the heap, the MAP_ANONYMOUS in malloc() * already does it. */ - return malloc(res); + return malloc(x); }
static __attribute__((unused))
From: Jiri Vanek jirivanek1@gmail.com
[ Upstream commit 993a87917c2af59efb0ee1ce43c878ca8790ba1c ]
Use the same PCLK divide option (divide DSI clock to generate pixel clock) which is set to LVDS Configuration Register (LVCFG) also for a VSync delay calculation. Without this change an auxiliary variable could underflow during the calculation for some dual-link LVDS panels and then calculated VSync delay is wrong. This leads to a shifted picture on a panel.
Tested-by: Jiri Vanek jirivanek1@gmail.com Signed-off-by: Jiri Vanek jirivanek1@gmail.com Reviewed-by: Vinay Simha BN simhavcs@gmail.com Signed-off-by: Robert Foss robert.foss@linaro.org Link: https://patchwork.freedesktop.org/patch/msgid/20220615222221.1501-3-jirivane... Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/bridge/tc358775.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/bridge/tc358775.c b/drivers/gpu/drm/bridge/tc358775.c index 62a7ef352daa..dd18be95207b 100644 --- a/drivers/gpu/drm/bridge/tc358775.c +++ b/drivers/gpu/drm/bridge/tc358775.c @@ -429,7 +429,7 @@ static void tc_bridge_enable(struct drm_bridge *bridge) val = TC358775_VPCTRL_MSF(1);
dsiclk = mode->crtc_clock * 3 * tc->bpc / tc->num_dsi_lanes / 1000; - clkdiv = dsiclk / DIVIDE_BY_3 * tc->lvds_link; + clkdiv = dsiclk / (tc->lvds_link == DUAL_LINK ? DIVIDE_BY_6 : DIVIDE_BY_3); byteclk = dsiclk / 4; t1 = hactive * (tc->bpc * 3 / 8) / tc->num_dsi_lanes; t2 = ((100000 / clkdiv)) * (hactive + hback_porch + hsync_len + hfront_porch) / 1000;
From: Delyan Kratunov delyank@fb.com
[ Upstream commit aca80dd95e20f1fa0daa212afc83c9fa0ad239e5 ]
The call into bpf from uprobes needs to be gated now that it doesn't use the trace_events.h helpers.
Randy found this as a randconfig build failure on linux-next [1].
[1]: https://lore.kernel.org/linux-next/2de99180-7d55-2fdf-134d-33198c27cc58@infr...
Reported-by: Randy Dunlap rdunlap@infradead.org Signed-off-by: Delyan Kratunov delyank@fb.com Tested-by: Randy Dunlap rdunlap@infradead.org Acked-by: Randy Dunlap rdunlap@infradead.org Link: https://lore.kernel.org/r/cb8bfbbcde87ed5d811227a393ef4925f2aadb7b.camel@fb.... Signed-off-by: Alexei Starovoitov ast@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- kernel/trace/trace_uprobe.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/kernel/trace/trace_uprobe.c b/kernel/trace/trace_uprobe.c index c3dc4f859a6b..687520c675fd 100644 --- a/kernel/trace/trace_uprobe.c +++ b/kernel/trace/trace_uprobe.c @@ -1342,6 +1342,7 @@ static void __uprobe_perf_func(struct trace_uprobe *tu, int size, esize; int rctx;
+#ifdef CONFIG_BPF_EVENTS if (bpf_prog_array_valid(call)) { u32 ret;
@@ -1351,6 +1352,7 @@ static void __uprobe_perf_func(struct trace_uprobe *tu, if (!ret) return; } +#endif /* CONFIG_BPF_EVENTS */
esize = SIZEOF_TRACE_ENTRY(is_ret_probe(tu));
From: Zqiang qiang1.zhang@intel.com
[ Upstream commit 98ea20328786372cbbc90c601be168f5fe1f8845 ]
The kernel memory leak detector located the following:
unreferenced object 0xffff95d941135b50 (size 16): comm "swapper/0", pid 1, jiffies 4294667610 (age 1367.451s) hex dump (first 16 bytes): f0 c6 c2 bd d9 95 ff ff 00 00 00 00 00 00 00 00 ................ backtrace: [<00000000bc81d9b1>] kmem_cache_alloc_trace+0x2f6/0x500 [<00000000d28be229>] rcu_torture_init+0x1235/0x1354 [<0000000032c3acd9>] do_one_initcall+0x51/0x210 [<000000003c117727>] kernel_init_freeable+0x205/0x259 [<000000003961f965>] kernel_init+0x1a/0x120 [<000000001998f890>] ret_from_fork+0x22/0x30
This is caused by the rcu_test_debug_objects() function allocating an rcu_head structure, then failing to free it. This commit therefore adds the needed kfree() after the last use of this structure.
Signed-off-by: Zqiang qiang1.zhang@intel.com Signed-off-by: Paul E. McKenney paulmck@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- kernel/rcu/rcutorture.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c index 7120165a9342..ca7b028f424b 100644 --- a/kernel/rcu/rcutorture.c +++ b/kernel/rcu/rcutorture.c @@ -3122,6 +3122,7 @@ static void rcu_test_debug_objects(void) pr_alert("%s: WARN: Duplicate call_rcu() test complete.\n", KBUILD_MODNAME); destroy_rcu_head_on_stack(&rh1); destroy_rcu_head_on_stack(&rh2); + kfree(rhp); #else /* #ifdef CONFIG_DEBUG_OBJECTS_RCU_HEAD */ pr_alert("%s: !CONFIG_DEBUG_OBJECTS_RCU_HEAD, not testing duplicate call_rcu()\n", KBUILD_MODNAME); #endif /* #else #ifdef CONFIG_DEBUG_OBJECTS_RCU_HEAD */
From: Zqiang qiang1.zhang@intel.com
[ Upstream commit 92366810644d5675043c792abb70eaf974a77384 ]
Systems built with CONFIG_DEBUG_PREEMPT=y can trigger the following BUG while running the rcuscale performance test:
BUG: using smp_processor_id() in preemptible [00000000] code: rcu_scale_write/69 CPU: 0 PID: 66 Comm: rcu_scale_write Not tainted 5.18.0-rc7-next-20220517-yoctodev-standard+ caller is debug_smp_processor_id+0x17/0x20 Call Trace: <TASK> dump_stack_lvl+0x49/0x5e dump_stack+0x10/0x12 check_preemption_disabled+0xdf/0xf0 debug_smp_processor_id+0x17/0x20 rcu_scale_writer+0x2b5/0x580 kthread+0x177/0x1b0 ret_from_fork+0x22/0x30 </TASK>
Reproduction method: runqemu kvm slirp nographic qemuparams="-m 4096 -smp 8" bootparams="isolcpus=2,3 nohz_full=2,3 rcu_nocbs=2,3 rcutree.dump_tree=1 rcuscale.shutdown=false rcuscale.gp_async=true" -d
The problem is that the rcu_scale_writer() kthreads fail to set the PF_NO_SETAFFINITY flags, which causes is_percpu_thread() to assume that the kthread's affinity might change at any time, thus the BUG noted above.
This commit therefore causes rcu_scale_writer() to set PF_NO_SETAFFINITY in its kthread's ->flags field, thus preventing this BUG.
Signed-off-by: Zqiang qiang1.zhang@intel.com Signed-off-by: Paul E. McKenney paulmck@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- kernel/rcu/rcuscale.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/kernel/rcu/rcuscale.c b/kernel/rcu/rcuscale.c index 277a5bfb37d4..3ef02d4a8108 100644 --- a/kernel/rcu/rcuscale.c +++ b/kernel/rcu/rcuscale.c @@ -419,6 +419,7 @@ rcu_scale_writer(void *arg) VERBOSE_SCALEOUT_STRING("rcu_scale_writer task started"); WARN_ON(!wdpp); set_cpus_allowed_ptr(current, cpumask_of(me % nr_cpu_ids)); + current->flags |= PF_NO_SETAFFINITY; sched_set_fifo_low(current);
if (holdoff)
From: Zqiang qiang1.zhang@intel.com
[ Upstream commit 7bf336fb8dac718febb7bf4fe79e1be0c5e4a631 ]
In kernels built with CONFIG_PREEMPT_RT=y, spinlocks are replaced by rt_mutex, which can sleep. This means that acquiring a non-raw spinlock in a critical section where preemption is disabled can trigger the following BUG:
BUG: scheduling while atomic: ref_scale_reade/76/0x00000002 Preemption disabled at: ref_lock_section+0x16/0x80 Call Trace: <TASK> dump_stack_lvl+0x5b/0x82 dump_stack+0x10/0x12 __schedule_bug.cold+0x9c/0xad __schedule+0x839/0xc00 schedule_rtlock+0x22/0x40 rtlock_slowlock_locked+0x460/0x1350 rt_spin_lock+0x61/0xe0 ref_lock_section+0x29/0x80 rcu_scale_one_reader+0x52/0x60 ref_scale_reader+0x28d/0x490 kthread+0x128/0x150 ret_from_fork+0x22/0x30 </TASK>
This commit therefore converts spinlock to raw_spinlock.
Signed-off-by: Zqiang qiang1.zhang@intel.com Signed-off-by: Paul E. McKenney paulmck@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- kernel/rcu/refscale.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/kernel/rcu/refscale.c b/kernel/rcu/refscale.c index 909644abee67..435c884c02b5 100644 --- a/kernel/rcu/refscale.c +++ b/kernel/rcu/refscale.c @@ -385,7 +385,7 @@ static struct ref_scale_ops rwsem_ops = { };
// Definitions for global spinlock -static DEFINE_SPINLOCK(test_lock); +static DEFINE_RAW_SPINLOCK(test_lock);
static void ref_lock_section(const int nloops) { @@ -393,8 +393,8 @@ static void ref_lock_section(const int nloops)
preempt_disable(); for (i = nloops; i >= 0; i--) { - spin_lock(&test_lock); - spin_unlock(&test_lock); + raw_spin_lock(&test_lock); + raw_spin_unlock(&test_lock); } preempt_enable(); } @@ -405,9 +405,9 @@ static void ref_lock_delay_section(const int nloops, const int udl, const int nd
preempt_disable(); for (i = nloops; i >= 0; i--) { - spin_lock(&test_lock); + raw_spin_lock(&test_lock); un_delay(udl, ndl); - spin_unlock(&test_lock); + raw_spin_unlock(&test_lock); } preempt_enable(); } @@ -427,8 +427,8 @@ static void ref_lock_irq_section(const int nloops)
preempt_disable(); for (i = nloops; i >= 0; i--) { - spin_lock_irqsave(&test_lock, flags); - spin_unlock_irqrestore(&test_lock, flags); + raw_spin_lock_irqsave(&test_lock, flags); + raw_spin_unlock_irqrestore(&test_lock, flags); } preempt_enable(); } @@ -440,9 +440,9 @@ static void ref_lock_irq_delay_section(const int nloops, const int udl, const in
preempt_disable(); for (i = nloops; i >= 0; i--) { - spin_lock_irqsave(&test_lock, flags); + raw_spin_lock_irqsave(&test_lock, flags); un_delay(udl, ndl); - spin_unlock_irqrestore(&test_lock, flags); + raw_spin_unlock_irqrestore(&test_lock, flags); } preempt_enable(); }
From: Amit Cohen amcohen@nvidia.com
[ Upstream commit 89df3c6261f271c550f120b5ccf4d9c5132e870c ]
Currently, the length of 'config_profile.flood_mode' is defined as 2 bits, while the correct length is 3 bits.
As preparation for unified bridge model, which will use the whole field length, fix it and increase the field to the correct size.
Signed-off-by: Amit Cohen amcohen@nvidia.com Signed-off-by: Ido Schimmel idosch@nvidia.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/mellanox/mlxsw/cmd.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/cmd.h b/drivers/net/ethernet/mellanox/mlxsw/cmd.h index 51b260d54237..0abd69040ba0 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/cmd.h +++ b/drivers/net/ethernet/mellanox/mlxsw/cmd.h @@ -745,7 +745,7 @@ MLXSW_ITEM32(cmd_mbox, config_profile, max_vid_flood_tables, 0x30, 8, 4); * max_fid_offset_flood_tables indicates the number of FID-offset tables. * max_fid_flood_tables indicates the number of per-FID tables. */ -MLXSW_ITEM32(cmd_mbox, config_profile, flood_mode, 0x30, 0, 2); +MLXSW_ITEM32(cmd_mbox, config_profile, flood_mode, 0x30, 0, 3);
/* cmd_mbox_config_profile_max_fid_offset_flood_tables * Maximum number of FID-offset flooding tables.
From: Philip Yang Philip.Yang@amd.com
[ Upstream commit ab8529b0cdb271d9b222cbbddb2641f3fca5df8f ]
After queue unmap or remove from MES successfully, free queue sysfs entries, doorbell and remove from queue list. Otherwise, application may destroy queue again, cause below kernel warning or crash backtrace.
For outstanding queues, either application forget to destroy or failed to destroy, kfd_process_notifier_release will remove queue sysfs entries, kfd_process_wq_release will free queue doorbell.
v2: decrement_queue_count for MES queue
refcount_t: underflow; use-after-free. WARNING: CPU: 7 PID: 3053 at lib/refcount.c:28 Call Trace: kobject_put+0xd6/0x1a0 kfd_procfs_del_queue+0x27/0x30 [amdgpu] pqm_destroy_queue+0xeb/0x240 [amdgpu] kfd_ioctl_destroy_queue+0x32/0x70 [amdgpu] kfd_ioctl+0x27d/0x500 [amdgpu] do_syscall_64+0x35/0x80
WARNING: CPU: 2 PID: 3053 at drivers/gpu/drm/amd/amdgpu/../amdkfd/kfd_device_queue_manager.c:400 Call Trace: deallocate_doorbell.isra.0+0x39/0x40 [amdgpu] destroy_queue_cpsch+0xb3/0x270 [amdgpu] pqm_destroy_queue+0x108/0x240 [amdgpu] kfd_ioctl_destroy_queue+0x32/0x70 [amdgpu] kfd_ioctl+0x27d/0x500 [amdgpu]
general protection fault, probably for non-canonical address 0xdead000000000108: Call Trace: pqm_destroy_queue+0xf0/0x200 [amdgpu] kfd_ioctl_destroy_queue+0x2f/0x60 [amdgpu] kfd_ioctl+0x19b/0x600 [amdgpu]
Signed-off-by: Philip Yang Philip.Yang@amd.com Reviewed-by: Graham Sider Graham.Sider@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Sasha Levin sashal@kernel.org --- .../drm/amd/amdkfd/kfd_device_queue_manager.c | 28 +++++++++++-------- .../amd/amdkfd/kfd_process_queue_manager.c | 2 +- 2 files changed, 18 insertions(+), 12 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c index e1797657b04c..e017b4240472 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c @@ -1873,6 +1873,22 @@ static int destroy_queue_cpsch(struct device_queue_manager *dqm,
}
+ if (q->properties.is_active) { + if (!dqm->dev->shared_resources.enable_mes) { + retval = execute_queues_cpsch(dqm, + KFD_UNMAP_QUEUES_FILTER_DYNAMIC_QUEUES, 0); + if (retval == -ETIME) + qpd->reset_wavefronts = true; + } else { + retval = remove_queue_mes(dqm, q, qpd); + } + + if (retval) + goto failed_unmap_queue; + + decrement_queue_count(dqm, qpd, q); + } + mqd_mgr = dqm->mqd_mgrs[get_mqd_type_from_queue_type( q->properties.type)];
@@ -1886,17 +1902,6 @@ static int destroy_queue_cpsch(struct device_queue_manager *dqm,
list_del(&q->list); qpd->queue_count--; - if (q->properties.is_active) { - if (!dqm->dev->shared_resources.enable_mes) { - decrement_queue_count(dqm, qpd, q); - retval = execute_queues_cpsch(dqm, - KFD_UNMAP_QUEUES_FILTER_DYNAMIC_QUEUES, 0); - if (retval == -ETIME) - qpd->reset_wavefronts = true; - } else { - retval = remove_queue_mes(dqm, q, qpd); - } - }
/* * Unconditionally decrement this counter, regardless of the queue's @@ -1913,6 +1918,7 @@ static int destroy_queue_cpsch(struct device_queue_manager *dqm,
return retval;
+failed_unmap_queue: failed_try_destroy_debugged_queue:
dqm_unlock(dqm); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c index dc00484ff484..99f2a6412201 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c @@ -419,7 +419,6 @@ int pqm_destroy_queue(struct process_queue_manager *pqm, unsigned int qid) }
if (pqn->q) { - kfd_procfs_del_queue(pqn->q); dqm = pqn->q->device->dqm; retval = dqm->ops.destroy_queue(dqm, &pdd->qpd, pqn->q); if (retval) { @@ -439,6 +438,7 @@ int pqm_destroy_queue(struct process_queue_manager *pqm, unsigned int qid) if (dev->shared_resources.enable_mes) amdgpu_amdkfd_free_gtt_mem(dev->adev, pqn->q->gang_ctx_bo); + kfd_procfs_del_queue(pqn->q); uninit_queue(pqn->q); }
From: Darren Powell darren.powell@amd.com
[ Upstream commit ceb180361e3851007547c55035cd1de03f108f75 ]
[v2] simplified fix after Lijo's feedback removed clocks.num_levels from calculation of loop count removed unsafe accesses to shim table freq_values retained corner case output only min,now if clocks.num_levels == 1 && now > min
[v1] added a check to populate and use SCLK shim table freq_values only if using dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL or AMD_DPM_FORCED_LEVEL_PERF_DETERMINISM removed clocks.num_levels from calculation of shim table size removed unsafe accesses to shim table freq_values output gfx_table values if using other dpm levels added check for freq_match when using freq_values for when now == min_clk
== Test == LOGFILE=aldebaran-sclk.test.log AMDGPU_PCI_ADDR=`lspci -nn | grep "VGA|Display" | cut -d " " -f 1` AMDGPU_HWMON=`ls -la /sys/class/hwmon | grep $AMDGPU_PCI_ADDR | awk '{print $9}'` HWMON_DIR=/sys/class/hwmon/${AMDGPU_HWMON}
lspci -nn | grep "VGA|Display" > $LOGFILE FILES="pp_od_clk_voltage pp_dpm_sclk"
for f in $FILES do echo === $f === >> $LOGFILE cat $HWMON_DIR/device/$f >> $LOGFILE done cat $LOGFILE
Signed-off-by: Darren Powell darren.powell@amd.com Reviewed-by: Kenneth Feng kenneth.feng@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Sasha Levin sashal@kernel.org --- .../drm/amd/pm/swsmu/smu13/aldebaran_ppt.c | 34 +++++++------------ 1 file changed, 12 insertions(+), 22 deletions(-)
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c index fb130409309c..f6ff7942e1b7 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c @@ -739,7 +739,7 @@ static int aldebaran_print_clk_levels(struct smu_context *smu, struct smu_13_0_dpm_table *single_dpm_table; struct smu_dpm_context *smu_dpm = &smu->smu_dpm; struct smu_13_0_dpm_context *dpm_context = NULL; - uint32_t display_levels; + int display_levels; uint32_t freq_values[3] = {0}; uint32_t min_clk, max_clk;
@@ -771,7 +771,7 @@ static int aldebaran_print_clk_levels(struct smu_context *smu, return ret; }
- display_levels = clocks.num_levels; + display_levels = (clocks.num_levels == 1) ? 1 : 2;
min_clk = pstate_table->gfxclk_pstate.curr.min; max_clk = pstate_table->gfxclk_pstate.curr.max; @@ -781,30 +781,20 @@ static int aldebaran_print_clk_levels(struct smu_context *smu,
/* fine-grained dpm has only 2 levels */ if (now > min_clk && now < max_clk) { - display_levels = clocks.num_levels + 1; + display_levels++; freq_values[2] = max_clk; freq_values[1] = now; }
- /* - * For DPM disabled case, there will be only one clock level. - * And it's safe to assume that is always the current clock. - */ - if (display_levels == clocks.num_levels) { - for (i = 0; i < clocks.num_levels; i++) - size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", i, - freq_values[i], - (clocks.num_levels == 1) ? - "*" : - (aldebaran_freqs_in_same_level( - freq_values[i], now) ? - "*" : - "")); - } else { - for (i = 0; i < display_levels; i++) - size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", i, - freq_values[i], i == 1 ? "*" : ""); - } + for (i = 0; i < display_levels; i++) + size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", i, + freq_values[i], + (display_levels == 1) ? + "*" : + (aldebaran_freqs_in_same_level( + freq_values[i], now) ? + "*" : + ""));
break;
From: KuoHsiang Chou kuohsiang_chou@aspeedtech.com
[ Upstream commit 232b95ba4e83ca0a77f19fc772ccc6581051e5cc ]
V1: 1.Fixed sparse:cast truncates bits form constant value ()cast truncates bits from constant value (ffffffffffffff00 becomes 0)
Reported-by: kernel test robot lkp@intel.com Signed-off-by: KuoHsiang Chou kuohsiang_chou@aspeedtech.com Signed-off-by: Thomas Zimmermann tzimmermann@suse.de Link: https://patchwork.freedesktop.org/patch/msgid/20220623083116.35365-1-kuohsia... Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/ast/ast_dp.c | 10 +++++----- drivers/gpu/drm/ast/ast_drv.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/drm/ast/ast_dp.c b/drivers/gpu/drm/ast/ast_dp.c index f573d582407e..56483860306b 100644 --- a/drivers/gpu/drm/ast/ast_dp.c +++ b/drivers/gpu/drm/ast/ast_dp.c @@ -34,7 +34,7 @@ int ast_astdp_read_edid(struct drm_device *dev, u8 *ediddata) * CRE4[7:0]: Read-Pointer for EDID (Unit: 4bytes); valid range: 0~64 */ ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE4, - (u8) ~ASTDP_EDID_READ_POINTER_MASK, (u8) i); + ASTDP_AND_CLEAR_MASK, (u8)i); j = 0;
/* @@ -274,8 +274,8 @@ void ast_dp_set_mode(struct drm_crtc *crtc, struct ast_vbios_mode_info *vbios_mo * CRE1[7:0]: MISC1 (default: 0x00) * CRE2[7:0]: video format index (0x00 ~ 0x20 or 0x40 ~ 0x50) */ - ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE0, (u8) ~ASTDP_CLEAR_MASK, - ASTDP_MISC0_24bpp); - ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE1, (u8) ~ASTDP_CLEAR_MASK, ASTDP_MISC1); - ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE2, (u8) ~ASTDP_CLEAR_MASK, ModeIdx); + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE0, ASTDP_AND_CLEAR_MASK, + ASTDP_MISC0_24bpp); + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE1, ASTDP_AND_CLEAR_MASK, ASTDP_MISC1); + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE2, ASTDP_AND_CLEAR_MASK, ModeIdx); } diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h index a34db4380f68..2e44b971c3a6 100644 --- a/drivers/gpu/drm/ast/ast_drv.h +++ b/drivers/gpu/drm/ast/ast_drv.h @@ -433,7 +433,7 @@ int ast_mode_config_init(struct ast_private *ast); */ #define ASTDP_MISC0_24bpp BIT(5) #define ASTDP_MISC1 0 -#define ASTDP_CLEAR_MASK GENMASK(7, 0) +#define ASTDP_AND_CLEAR_MASK 0x00
/* * ASTDP resoultion table:
From: Justin Green greenjustin@chromium.org
[ Upstream commit f5caaa47f55fa742f1a230e5b4258c139e223c74 ]
Modify vb2ops_vdec_buf_prepare to return EINVAL if the size of the plane is less than the size of the image. Currently we just log an error and return 0 anyway, which may cause a buffer overrun bug.
Signed-off-by: Justin Green greenjustin@chromium.org Suggested-by: Andres Calderon Jaramillo andrescj@chromium.org Reviewed-by: Nicolas Dufresne nicolas.dufresne@collabora.com Signed-off-by: Hans Verkuil hverkuil-cisco@xs4all.nl Signed-off-by: Mauro Carvalho Chehab mchehab@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec.c b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec.c index 52e5d36aa912..191e13344c53 100644 --- a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec.c +++ b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec.c @@ -735,6 +735,7 @@ int vb2ops_vdec_buf_prepare(struct vb2_buffer *vb) mtk_v4l2_err("data will not fit into plane %d (%lu < %d)", i, vb2_plane_size(vb, i), q_data->sizeimage[i]); + return -EINVAL; } if (!V4L2_TYPE_IS_OUTPUT(vb->type)) vb2_set_plane_payload(vb, i, q_data->sizeimage[i]);
From: Eugen Hristev eugen.hristev@microchip.com
[ Upstream commit aa63c5eaf7f7d2d3a4b1cc5782e7151b8ae3079f ]
When attempting to change the white balance (WB) ctrls before starting streaming, e.g.:
# v4l2-ctl -L
User Controls .. blue_component_gain 0x009819c1 (int) : min=0 max=8191 step=1 default=512 value=512 flags=slider .. # v4l2-ctl --set-ctrl=blue_component_gain=500 # v4l2-ctl -L .. blue_component_gain 0x009819c1 (int) : min=0 max=8191 step=1 default=512 value=500 flags=slider ..
These will not be written to the internal data struct and will not be written to the WB hardware module. Thus, after starting streaming, they will be reset to default:
# v4l2-ctl -L .. blue_component_gain 0x009819c1 (int) : min=0 max=8191 step=1 default=512 value=512 flags=slider ..
It does not make much sense to not be able to configure the WB controls at all times. Even if the sensor would not be RAW Bayer (and in this case the WB module is unavailable), the user could configure the ISC itself, as the ISC should not care about the sensor format. Thus, when WB module is available (if the sensor changes format e.g.) it will be already configured as be user's desires. In consequence, remove the check in isc_s_awb_ctrl that will return if ISC does not know the sensor format.
Signed-off-by: Eugen Hristev eugen.hristev@microchip.com Signed-off-by: Hans Verkuil hverkuil-cisco@xs4all.nl Signed-off-by: Mauro Carvalho Chehab mchehab@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/media/platform/atmel/atmel-isc-base.c | 4 ---- 1 file changed, 4 deletions(-)
diff --git a/drivers/media/platform/atmel/atmel-isc-base.c b/drivers/media/platform/atmel/atmel-isc-base.c index 2f07a50035c8..fce4a7ae43d7 100644 --- a/drivers/media/platform/atmel/atmel-isc-base.c +++ b/drivers/media/platform/atmel/atmel-isc-base.c @@ -1525,10 +1525,6 @@ static int isc_s_awb_ctrl(struct v4l2_ctrl *ctrl) else ctrls->awb = ISC_WB_NONE;
- /* we did not configure ISC yet */ - if (!isc->config.sd_format) - break; - /* configure the controls with new values from v4l2 */ if (ctrl->cluster[ISC_CTRL_R_GAIN]->is_new) ctrls->gain[ISC_HIS_CFG_MODE_R] = isc->r_gain_ctrl->val;
From: Hirokazu Honda hiroh@chromium.org
[ Upstream commit d8e8aa866ed8636fd6c1017c3d9453eab2922496 ]
The media driver supports constant bitrate mode only. The supported rate control mode is reported through querymenu() and s_ctrl() fails if non constant bitrate mode (e.g. VBR) is requested.
Signed-off-by: Hirokazu Honda hiroh@chromium.org Reviewed-by: Irui Wang irui.wang@mediatek.com Signed-off-by: Hans Verkuil hverkuil-cisco@xs4all.nl Signed-off-by: Mauro Carvalho Chehab mchehab@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- .../media/platform/mediatek/vcodec/mtk_vcodec_enc.c | 11 +++++++++++ 1 file changed, 11 insertions(+)
diff --git a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_enc.c b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_enc.c index c21367038c34..98d451ce2545 100644 --- a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_enc.c +++ b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_enc.c @@ -50,6 +50,14 @@ static int vidioc_venc_s_ctrl(struct v4l2_ctrl *ctrl) int ret = 0;
switch (ctrl->id) { + case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: + mtk_v4l2_debug(2, "V4L2_CID_MPEG_VIDEO_BITRATE_MODE val= %d", + ctrl->val); + if (ctrl->val != V4L2_MPEG_VIDEO_BITRATE_MODE_CBR) { + mtk_v4l2_err("Unsupported bitrate mode =%d", ctrl->val); + ret = -EINVAL; + } + break; case V4L2_CID_MPEG_VIDEO_BITRATE: mtk_v4l2_debug(2, "V4L2_CID_MPEG_VIDEO_BITRATE val = %d", ctrl->val); @@ -1373,6 +1381,9 @@ int mtk_vcodec_enc_ctrls_setup(struct mtk_vcodec_ctx *ctx) 0, V4L2_MPEG_VIDEO_H264_LEVEL_4_0); v4l2_ctrl_new_std_menu(handler, ops, V4L2_CID_MPEG_VIDEO_VP8_PROFILE, V4L2_MPEG_VIDEO_VP8_PROFILE_0, 0, V4L2_MPEG_VIDEO_VP8_PROFILE_0); + v4l2_ctrl_new_std_menu(handler, ops, V4L2_CID_MPEG_VIDEO_BITRATE_MODE, + V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, + 0, V4L2_MPEG_VIDEO_BITRATE_MODE_CBR);
if (handler->error) {
From: Gautam gautammenghani201@gmail.com
[ Upstream commit 3297a4df805d4263506b6dfec4d1bbeff8862dd8 ]
In the install section of the main Makefile of kselftests, the echo command is used with -n flag, which disables the printing of new line due to which the output contains "\n" chars as follows:
Emit Tests for alsa\nSkipping non-existent dir: arm64 Emit Tests for breakpoints\nEmit Tests for capabilities\n
This patch fixes the above bug by using the -e flag.
Signed-off-by: Gautam gautammenghani201@gmail.com Signed-off-by: Shuah Khan skhan@linuxfoundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- tools/testing/selftests/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile index de11992dc577..52e31437f1a3 100644 --- a/tools/testing/selftests/Makefile +++ b/tools/testing/selftests/Makefile @@ -253,7 +253,7 @@ ifdef INSTALL_PATH for TARGET in $(TARGETS); do \ BUILD_TARGET=$$BUILD/$$TARGET; \ [ ! -d $(INSTALL_PATH)/$$TARGET ] && echo "Skipping non-existent dir: $$TARGET" && continue; \ - echo -n "Emit Tests for $$TARGET\n"; \ + echo -ne "Emit Tests for $$TARGET\n"; \ $(MAKE) -s --no-print-directory OUTPUT=$$BUILD_TARGET COLLECTION=$$TARGET \ -C $$TARGET emit_tests >> $(TEST_LIST); \ done;
From: Sam Edwards cfsworks@gmail.com
[ Upstream commit 778964f2fdf05e5d2e6ca9bc3f450b3db454ba9c ]
The addrconf_verify_rtnl() function uses a big if/elseif/elseif/... block to categorize each address by what type of attention it needs. An about-to-expire (RFC 4941) temporary address is one such category, but the previous elseif branch catches addresses that have already run out their prefered_lft. This means that if addrconf_verify_rtnl() fails to run in the necessary time window (i.e. REGEN_ADVANCE time units before the end of the prefered_lft), the temporary address will never be regenerated, and no temporary addresses will be available until each one's valid_lft runs out and manage_tempaddrs() begins anew.
Fix this by moving the entire temporary address regeneration case out of that block. That block is supposed to implement the "destructive" part of an address's lifecycle, and regenerating a fresh temporary address is not, semantically speaking, actually tied to any particular lifecycle stage. The age test is also changed from `age >= prefered_lft - regen_advance` to `age + regen_advance >= prefered_lft` instead, to ensure no underflow occurs if the system administrator increases the regen_advance to a value greater than the already-set prefered_lft.
Note that this does not fix the problem of addrconf_verify_rtnl() sometimes not running in time, resulting in the race condition described in RFC 4941 section 3.4 - it only ensures that the address is regenerated. Fixing THAT problem may require either using jiffies instead of seconds for all time arithmetic here, or always rounding up when regen_advance is converted to seconds.
Signed-off-by: Sam Edwards CFSworks@gmail.com Link: https://lore.kernel.org/r/20220623181103.7033-1-CFSworks@gmail.com Signed-off-by: Paolo Abeni pabeni@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- net/ipv6/addrconf.c | 62 ++++++++++++++++++++++++--------------------- 1 file changed, 33 insertions(+), 29 deletions(-)
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 49cc6587dd77..8a28fe95aeb6 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -4520,6 +4520,39 @@ static void addrconf_verify_rtnl(struct net *net) /* We try to batch several events at once. */ age = (now - ifp->tstamp + ADDRCONF_TIMER_FUZZ_MINUS) / HZ;
+ if ((ifp->flags&IFA_F_TEMPORARY) && + !(ifp->flags&IFA_F_TENTATIVE) && + ifp->prefered_lft != INFINITY_LIFE_TIME && + !ifp->regen_count && ifp->ifpub) { + /* This is a non-regenerated temporary addr. */ + + unsigned long regen_advance = ifp->idev->cnf.regen_max_retry * + ifp->idev->cnf.dad_transmits * + max(NEIGH_VAR(ifp->idev->nd_parms, RETRANS_TIME), HZ/100) / HZ; + + if (age + regen_advance >= ifp->prefered_lft) { + struct inet6_ifaddr *ifpub = ifp->ifpub; + if (time_before(ifp->tstamp + ifp->prefered_lft * HZ, next)) + next = ifp->tstamp + ifp->prefered_lft * HZ; + + ifp->regen_count++; + in6_ifa_hold(ifp); + in6_ifa_hold(ifpub); + spin_unlock(&ifp->lock); + + spin_lock(&ifpub->lock); + ifpub->regen_count = 0; + spin_unlock(&ifpub->lock); + rcu_read_unlock_bh(); + ipv6_create_tempaddr(ifpub, true); + in6_ifa_put(ifpub); + in6_ifa_put(ifp); + rcu_read_lock_bh(); + goto restart; + } else if (time_before(ifp->tstamp + ifp->prefered_lft * HZ - regen_advance * HZ, next)) + next = ifp->tstamp + ifp->prefered_lft * HZ - regen_advance * HZ; + } + if (ifp->valid_lft != INFINITY_LIFE_TIME && age >= ifp->valid_lft) { spin_unlock(&ifp->lock); @@ -4553,35 +4586,6 @@ static void addrconf_verify_rtnl(struct net *net) in6_ifa_put(ifp); goto restart; } - } else if ((ifp->flags&IFA_F_TEMPORARY) && - !(ifp->flags&IFA_F_TENTATIVE)) { - unsigned long regen_advance = ifp->idev->cnf.regen_max_retry * - ifp->idev->cnf.dad_transmits * - max(NEIGH_VAR(ifp->idev->nd_parms, RETRANS_TIME), HZ/100) / HZ; - - if (age >= ifp->prefered_lft - regen_advance) { - struct inet6_ifaddr *ifpub = ifp->ifpub; - if (time_before(ifp->tstamp + ifp->prefered_lft * HZ, next)) - next = ifp->tstamp + ifp->prefered_lft * HZ; - if (!ifp->regen_count && ifpub) { - ifp->regen_count++; - in6_ifa_hold(ifp); - in6_ifa_hold(ifpub); - spin_unlock(&ifp->lock); - - spin_lock(&ifpub->lock); - ifpub->regen_count = 0; - spin_unlock(&ifpub->lock); - rcu_read_unlock_bh(); - ipv6_create_tempaddr(ifpub, true); - in6_ifa_put(ifpub); - in6_ifa_put(ifp); - rcu_read_lock_bh(); - goto restart; - } - } else if (time_before(ifp->tstamp + ifp->prefered_lft * HZ - regen_advance * HZ, next)) - next = ifp->tstamp + ifp->prefered_lft * HZ - regen_advance * HZ; - spin_unlock(&ifp->lock); } else { /* ifp->prefered_lft <= ifp->valid_lft */ if (time_before(ifp->tstamp + ifp->prefered_lft * HZ, next))
From: Rahul Kumar rahul.kumar1@amd.com
[ Upstream commit 1c4dae3e4639540fb567e570cc56a3c292afb6fe ]
We observed hard hang due to NULL derefrence This issue is seen after running system all the time after two or three days
struct dc *dc = plane_state->ctx->dc; Randomly in long run we found plane_state or plane_state->ctx is found NULL which causes exception.
BUG: kernel NULL pointer dereference, address: 0000000000000000 PF: supervisor read access in kernel mode PF: error_code(0x0000) - not-present page PGD 1dc7f2067 P4D 1dc7f2067 PUD 222c75067 PMD 0 Oops: 0000 [#1] SMP NOPTI CPU: 5 PID: 29855 Comm: kworker/u16:4 ... ... Workqueue: events_unbound commit_work [drm_kms_helper] RIP: 0010:dcn10_update_pending_status+0x1f/0xee [amdgpu] Code: 41 5f c3 0f 1f 44 00 00 b0 01 c3 0f 1f 44 00 00 41 55 41 54 55 53 48 8b 1f 4c 8b af f8 00 00 00 48 8b 83 88 03 00 00 48 85 db <4c> 8b 20 0f 84 bf 00 00 00 48 89 fd 48 8b bf b8 00 00 00 48 8b 07 RSP: 0018:ffff942941997ab8 EFLAGS: 00010286 RAX: 0000000000000000 RBX: ffff8d7fd98d2000 RCX: 0000000000000000 RDX: 0000000000000000 RSI: ffff8d7e3e87c708 RDI: ffff8d7f2d8c0690 RBP: ffff8d7f2d8c0000 R08: ffff942941997a34 R09: 00000000ffffffff R10: 0000000000005000 R11: 00000000000000f0 R12: ffff8d7f2d8c0690 R13: ffff8d8035a41680 R14: 00000000000186a0 R15: ffff8d7f2d8c1dd8 FS: 0000000000000000(0000) GS:ffff8d8037340000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000000000000000 CR3: 0000000148030000 CR4: 00000000003406e0 Call Trace: dc_commit_state+0x6a2/0x7f0 [amdgpu] amdgpu_dm_atomic_commit_tail+0x460/0x19bb [amdgpu]
Tested-by: Rodrigo Siqueira Rodrigo.Siqueira@amd.com Reviewed-by: Harry Wentland harry.wentland@amd.com Signed-off-by: Rahul Kumar rahul.kumar1@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index e3a62873c0e7..ffe496131635 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -3242,7 +3242,7 @@ void dcn10_update_pending_status(struct pipe_ctx *pipe_ctx) struct dc_plane_state *plane_state = pipe_ctx->plane_state; struct timing_generator *tg = pipe_ctx->stream_res.tg; bool flip_pending; - struct dc *dc = plane_state->ctx->dc; + struct dc *dc = pipe_ctx->stream->ctx->dc;
if (plane_state == NULL) return;
From: Andrii Nakryiko andrii@kernel.org
[ Upstream commit ab9a5a05dc480f8994eddd31093a8920b08ee71d ]
Seems like we missed to add 2 APIs to libbpf.map and another API was misspelled. Fix it in libbpf.map.
Signed-off-by: Andrii Nakryiko andrii@kernel.org Link: https://lore.kernel.org/r/20220627211527.2245459-16-andrii@kernel.org Signed-off-by: Alexei Starovoitov ast@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- tools/lib/bpf/libbpf.map | 3 ++- tools/lib/bpf/libbpf_legacy.h | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/tools/lib/bpf/libbpf.map b/tools/lib/bpf/libbpf.map index 52973cffc20c..b6592c93a9d4 100644 --- a/tools/lib/bpf/libbpf.map +++ b/tools/lib/bpf/libbpf.map @@ -434,10 +434,11 @@ LIBBPF_0.7.0 { bpf_xdp_detach; bpf_xdp_query; bpf_xdp_query_id; + btf_ext__raw_data; libbpf_probe_bpf_helper; libbpf_probe_bpf_map_type; libbpf_probe_bpf_prog_type; - libbpf_set_memlock_rlim_max; + libbpf_set_memlock_rlim; } LIBBPF_0.6.0;
LIBBPF_0.8.0 { diff --git a/tools/lib/bpf/libbpf_legacy.h b/tools/lib/bpf/libbpf_legacy.h index d7bcbd01f66f..a3503c02e4a9 100644 --- a/tools/lib/bpf/libbpf_legacy.h +++ b/tools/lib/bpf/libbpf_legacy.h @@ -71,8 +71,8 @@ enum libbpf_strict_mode { * first BPF program or map creation operation. This is done only if * kernel is too old to support memcg-based memory accounting for BPF * subsystem. By default, RLIMIT_MEMLOCK limit is set to RLIM_INFINITY, - * but it can be overriden with libbpf_set_memlock_rlim_max() API. - * Note that libbpf_set_memlock_rlim_max() needs to be called before + * but it can be overriden with libbpf_set_memlock_rlim() API. + * Note that libbpf_set_memlock_rlim() needs to be called before * the very first bpf_prog_load(), bpf_map_create() or bpf_object__load() * operation. */
From: Chris Mason clm@fb.com
[ Upstream commit d58562ca6c992fc5577838d010c8a37401c2a831 ]
iomap_do_writepage() sends pages past i_size through folio_redirty_for_writepage(), which normally isn't a problem because truncate and friends clean them very quickly.
When the system has cgroups configured, we can end up in situations where one cgroup has almost no dirty pages at all, and other cgroups consume the entire background dirty limit. This is especially common in our XFS workloads in production because they have cgroups using O_DIRECT for almost all of the IO mixed in with cgroups that do more traditional buffered IO work.
We've hit storms where the redirty path hits millions of times in a few seconds, on all a single file that's only ~40 pages long. This leads to long tail latencies for file writes because the pdflush workers are hogging the CPU from some kworkers bound to the same CPU.
Reproducing this on 5.18 was tricky because 869ae85dae ("xfs: flush new eof page on truncate...") ends up writing/waiting most of these dirty pages before truncate gets a chance to wait on them.
The actual repro looks like this:
/* * run me in a cgroup all alone. Start a second cgroup with dd * streaming IO into the block device. */ int main(int ac, char **av) { int fd; int ret; char buf[BUFFER_SIZE]; char *filename = av[1];
memset(buf, 0, BUFFER_SIZE);
if (ac != 2) { fprintf(stderr, "usage: looper filename\n"); exit(1); } fd = open(filename, O_WRONLY | O_CREAT, 0600); if (fd < 0) { err(errno, "failed to open"); } fprintf(stderr, "looping on %s\n", filename); while(1) { /* * skip past page 0 so truncate doesn't write and wait * on our extent before changing i_size */ ret = lseek(fd, 8192, SEEK_SET); if (ret < 0) err(errno, "lseek"); ret = write(fd, buf, BUFFER_SIZE); if (ret != BUFFER_SIZE) err(errno, "write failed"); /* start IO so truncate has to wait after i_size is 0 */ ret = sync_file_range(fd, 16384, 4095, SYNC_FILE_RANGE_WRITE); if (ret < 0) err(errno, "sync_file_range"); ret = ftruncate(fd, 0); if (ret < 0) err(errno, "truncate"); usleep(1000); } }
And this bpftrace script will show when you've hit a redirty storm:
kretprobe:xfs_vm_writepages { delete(@dirty[pid]); }
kprobe:xfs_vm_writepages { @dirty[pid] = 1; }
kprobe:folio_redirty_for_writepage /@dirty[pid] > 0/ { $inode = ((struct folio *)arg1)->mapping->host->i_ino; @inodes[$inode] = count(); @redirty++; if (@redirty > 90000) { printf("inode %d redirty was %d", $inode, @redirty); exit(); } }
This patch has the same number of failures on xfstests as unpatched 5.18: Failures: generic/648 xfs/019 xfs/050 xfs/168 xfs/299 xfs/348 xfs/506 xfs/543
I also ran it through a long stress of multiple fsx processes hammering.
(Johannes Weiner did significant tracing and debugging on this as well)
Signed-off-by: Chris Mason clm@fb.com Co-authored-by: Johannes Weiner hannes@cmpxchg.org Reviewed-by: Johannes Weiner hannes@cmpxchg.org Reported-by: Domas Mituzas domas@fb.com Reviewed-by: Darrick J. Wong djwong@kernel.org Signed-off-by: Darrick J. Wong djwong@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- fs/iomap/buffered-io.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c index d2a9f699e17e..02b8bb46e0b3 100644 --- a/fs/iomap/buffered-io.c +++ b/fs/iomap/buffered-io.c @@ -1478,10 +1478,10 @@ iomap_do_writepage(struct page *page, struct writeback_control *wbc, void *data) pgoff_t end_index = isize >> PAGE_SHIFT;
/* - * Skip the page if it's fully outside i_size, e.g. due to a - * truncate operation that's in progress. We must redirty the - * page so that reclaim stops reclaiming it. Otherwise - * iomap_release_folio() is called on it and gets confused. + * Skip the page if it's fully outside i_size, e.g. + * due to a truncate operation that's in progress. We've + * cleaned this page and truncate will finish things off for + * us. * * Note that the end_index is unsigned long. If the given * offset is greater than 16TB on a 32-bit system then if we @@ -1496,7 +1496,7 @@ iomap_do_writepage(struct page *page, struct writeback_control *wbc, void *data) */ if (folio->index > end_index || (folio->index == end_index && poff == 0)) - goto redirty; + goto unlock;
/* * The page straddles i_size. It must be zeroed out on each @@ -1514,6 +1514,7 @@ iomap_do_writepage(struct page *page, struct writeback_control *wbc, void *data)
redirty: folio_redirty_for_writepage(wbc, folio); +unlock: folio_unlock(folio); return 0; }
From: David Reaver me@davidreaver.com
[ Upstream commit 2bc6430884d5ee0e30ae18652d31f821d8e9ec32 ]
I tried running `make pdfdocs` on NixOS, but it failed because get_feat.pl uses a shebang line with /usr/bin/perl, and that file path doesn't exist on NixOS. Using the more portable /usr/bin/env perl fixes the problem.
Signed-off-by: David Reaver me@davidreaver.com Link: https://lore.kernel.org/r/20220625211548.1200198-1-me@davidreaver.com Signed-off-by: Jonathan Corbet corbet@lwn.net Signed-off-by: Sasha Levin sashal@kernel.org --- scripts/get_feat.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/scripts/get_feat.pl b/scripts/get_feat.pl index 76cfb96b59b6..5c5397eeb237 100755 --- a/scripts/get_feat.pl +++ b/scripts/get_feat.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # SPDX-License-Identifier: GPL-2.0
use strict;
From: Shijith Thotton sthotton@marvell.com
[ Upstream commit b14056914357beee6a84f6ff1b9195f4659fab9d ]
Made size of operands same in bitwise operations.
The patch fixes the klocwork issue, operands in a bitwise operation have different size at line 375 and 483.
Signed-off-by: Shijith Thotton sthotton@marvell.com Link: https://lore.kernel.org/r/f4fba33fe4f89b420b4da11d51255e7cc6ea1dbf.165658626... Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/marvell/octeontx2/af/rvu_cpt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_cpt.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_cpt.c index a9da85e418a4..38bbae5d9ae0 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_cpt.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_cpt.c @@ -17,7 +17,7 @@ #define PCI_DEVID_OTX2_CPT10K_PF 0xA0F2
/* Length of initial context fetch in 128 byte words */ -#define CPT_CTX_ILEN 2 +#define CPT_CTX_ILEN 2ULL
#define cpt_get_eng_sts(e_min, e_max, rsp, etype) \ ({ \ @@ -480,7 +480,7 @@ static int cpt_inline_ipsec_cfg_inbound(struct rvu *rvu, int blkaddr, u8 cptlf, */ if (!is_rvu_otx2(rvu)) { val = (ilog2(NIX_CHAN_CPT_X2P_MASK + 1) << 16); - val |= rvu->hw->cpt_chan_base; + val |= (u64)rvu->hw->cpt_chan_base;
rvu_write64(rvu, blkaddr, CPT_AF_X2PX_LINK_CFG(0), val); rvu_write64(rvu, blkaddr, CPT_AF_X2PX_LINK_CFG(1), val);
From: "Stanley.Yang" Stanley.Yang@amd.com
[ Upstream commit e0e146d5567317d6ba7d0169bed55d1d9ea05a61 ]
It should not init whole ras bad page framework on sriov guest side due to it is handled on host side.
Signed-off-by: Stanley.Yang Stanley.Yang@amd.com Reviewed-by: Hawking Zhang Hawking.Zhang@amd.com Reviewed-by: Tao Zhou tao.zhou1@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index dac202ae864d..465e7921bba1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -2148,7 +2148,7 @@ int amdgpu_ras_recovery_init(struct amdgpu_device *adev) bool exc_err_limit = false; int ret;
- if (!con) + if (!con || amdgpu_sriov_vf(adev)) return 0;
/* Allow access to RAS EEPROM via debugfs, when the ASIC
From: Nicholas Kazlauskas nicholas.kazlauskas@amd.com
[ Upstream commit bc19909f19fdc8253d720d11c948935786fbfa08 ]
[Why] In the case where we don't support DMUB aux but we have DPIA links in the configuration we might try to message AUX using the legacy path - where DDC pin is NULL. This causes a NULL pointer dereference.
[How] Guard against NULL DDC pin, return a failure for aux engine acquire.
Reviewed-by: Michael Strauss Michael.Strauss@amd.com Acked-by: Rodrigo Siqueira Rodrigo.Siqueira@amd.com Signed-off-by: Nicholas Kazlauskas nicholas.kazlauskas@amd.com Tested-by: Daniel Wheeler daniel.wheeler@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/amd/display/dc/dce/dce_aux.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c b/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c index 9e39cd7b203e..49d3145ae8fb 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c @@ -572,6 +572,11 @@ int dce_aux_transfer_raw(struct ddc_service *ddc,
memset(&aux_req, 0, sizeof(aux_req));
+ if (ddc_pin == NULL) { + *operation_result = AUX_RET_ERROR_ENGINE_ACQUIRE; + return -1; + } + aux_engine = ddc->ctx->dc->res_pool->engines[ddc_pin->pin_data->en]; if (!acquire(aux_engine, ddc_pin)) { *operation_result = AUX_RET_ERROR_ENGINE_ACQUIRE;
From: Fangzhi Zuo Jerry.Zuo@amd.com
[ Upstream commit 22676bc500c27d987a0b42cbe162aebf783f1c38 ]
[Why] Unexpected change of aux hw mapping causes dmub soft hang when initiate aux transation at wrong aux channel.
ddc_channel stands for hw dp aux index which is from vbios, but link_index is pure software concept for link count depending on which link is probed first. They are not interchangeable.
dmub aux transaction could pass if happens eDP link_index gets the same value as vbios ddc_channel, e.g., ddc_channel = 1, link_index = 1 if they gets different, e.g., ddc_channel = 2, link_index = 0, overwrite ddc_channel with link_index will have wrong ddc channel being used for aux transaction in dmub PSR, cause aux transaction soft hang.
[How] ddc_channel mapping to each link is determined by vbios and further parsed in dc. Such info. should not be touched in any kind, otherwise the mapping is screwed up leading to aux transaction timeout.
Reviewed-by: Aurabindo Jayamohanan Pillai Aurabindo.Pillai@amd.com Acked-by: Rodrigo Siqueira Rodrigo.Siqueira@amd.com Signed-off-by: Fangzhi Zuo Jerry.Zuo@amd.com Tested-by: Daniel Wheeler daniel.wheeler@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 3087dd1a1856..a6efd5c1fa2a 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -8538,7 +8538,7 @@ static int amdgpu_dm_i2c_xfer(struct i2c_adapter *i2c_adap,
if (dc_submit_i2c( ddc_service->ctx->dc, - ddc_service->ddc_pin->hw_info.ddc_channel, + ddc_service->link->link_index, &cmd)) result = num;
@@ -8574,8 +8574,6 @@ create_i2c(struct ddc_service *ddc_service, snprintf(i2c->base.name, sizeof(i2c->base.name), "AMDGPU DM i2c hw bus %d", link_index); i2c_set_adapdata(&i2c->base, i2c); i2c->ddc_service = ddc_service; - if (i2c->ddc_service->ddc_pin) - i2c->ddc_service->ddc_pin->hw_info.ddc_channel = link_index;
return i2c; }
From: Dmytro Laktyushkin Dmytro.Laktyushkin@amd.com
[ Upstream commit 8a077d9caa3a274de36ee2fe7b608041f5690343 ]
This w/a has a bad interaction with seamless boot toggling an active stream. Most panels recover, however some fail leading to display corruption.
Reviewed-by: Charlene Liu Charlene.Liu@amd.com Acked-by: Rodrigo Siqueira Rodrigo.Siqueira@amd.com Signed-off-by: Dmytro Laktyushkin Dmytro.Laktyushkin@amd.com Tested-by: Daniel Wheeler daniel.wheeler@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Sasha Levin sashal@kernel.org --- .../gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c index f4381725b210..36b0cd47c1c7 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c @@ -173,11 +173,14 @@ static void dcn315_update_clocks(struct clk_mgr *clk_mgr_base, }
if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz)) { - dcn315_disable_otg_wa(clk_mgr_base, true); + /* No need to apply the w/a if we haven't taken over from bios yet */ + if (clk_mgr_base->clks.dispclk_khz) + dcn315_disable_otg_wa(clk_mgr_base, true);
clk_mgr_base->clks.dispclk_khz = new_clocks->dispclk_khz; dcn315_smu_set_dispclk(clk_mgr, clk_mgr_base->clks.dispclk_khz); - dcn315_disable_otg_wa(clk_mgr_base, false); + if (clk_mgr_base->clks.dispclk_khz) + dcn315_disable_otg_wa(clk_mgr_base, false);
update_dispclk = true; }
From: Al Viro viro@zeniv.linux.org.uk
[ Upstream commit 7392ed1734c319150b5ddec3f192a6405728e8d0 ]
All callers can and should handle iov_iter_get_pages() returning fewer pages than requested. All in-kernel ones do. And it makes the arithmetical overflow analysis much simpler...
Reviewed-by: Jeff Layton jlayton@kernel.org Signed-off-by: Al Viro viro@zeniv.linux.org.uk Signed-off-by: Sasha Levin sashal@kernel.org --- lib/iov_iter.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/lib/iov_iter.c b/lib/iov_iter.c index 0b64695ab632..ea588628828b 100644 --- a/lib/iov_iter.c +++ b/lib/iov_iter.c @@ -1520,6 +1520,8 @@ ssize_t iov_iter_get_pages(struct iov_iter *i, maxsize = i->count; if (!maxsize) return 0; + if (maxsize > MAX_RW_COUNT) + maxsize = MAX_RW_COUNT;
if (likely(iter_is_iovec(i))) { unsigned int gup_flags = 0; @@ -1640,6 +1642,8 @@ ssize_t iov_iter_get_pages_alloc(struct iov_iter *i, maxsize = i->count; if (!maxsize) return 0; + if (maxsize > MAX_RW_COUNT) + maxsize = MAX_RW_COUNT;
if (likely(iter_is_iovec(i))) { unsigned int gup_flags = 0;
From: Rob Clark robdclark@chromium.org
[ Upstream commit a414fe3a2129b490e1e9b8ad66f0364f4f961887 ]
The only reason we grabbed the lock was to satisfy a bunch of places that WARN_ON() if called without the lock held. But this angers lockdep which doesn't realize no one else can be holding the lock by the time we end up destroying the object (and sees what would otherwise be a locking inversion between reservation_ww_class_mutex and fs_reclaim).
Closes: https://gitlab.freedesktop.org/drm/msm/-/issues/14 Signed-off-by: Rob Clark robdclark@chromium.org Patchwork: https://patchwork.freedesktop.org/patch/489364/ Link: https://lore.kernel.org/r/20220613205032.2652374-1-robdclark@gmail.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/msm/msm_gem.c | 8 -------- drivers/gpu/drm/msm/msm_gem.h | 14 +++++++++++++- 2 files changed, 13 insertions(+), 9 deletions(-)
diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c index 7f92231785a0..e171af15fb11 100644 --- a/drivers/gpu/drm/msm/msm_gem.c +++ b/drivers/gpu/drm/msm/msm_gem.c @@ -1020,8 +1020,6 @@ void msm_gem_free_object(struct drm_gem_object *obj) list_del(&msm_obj->mm_list); mutex_unlock(&priv->mm_lock);
- msm_gem_lock(obj); - /* object should not be on active list: */ GEM_WARN_ON(is_active(msm_obj));
@@ -1037,17 +1035,11 @@ void msm_gem_free_object(struct drm_gem_object *obj)
put_iova_vmas(obj);
- /* dma_buf_detach() grabs resv lock, so we need to unlock - * prior to drm_prime_gem_destroy - */ - msm_gem_unlock(obj); - drm_prime_gem_destroy(obj, msm_obj->sgt); } else { msm_gem_vunmap(obj); put_pages(obj); put_iova_vmas(obj); - msm_gem_unlock(obj); }
drm_gem_object_release(obj); diff --git a/drivers/gpu/drm/msm/msm_gem.h b/drivers/gpu/drm/msm/msm_gem.h index 6b7d5bb3b575..4b387c7a0779 100644 --- a/drivers/gpu/drm/msm/msm_gem.h +++ b/drivers/gpu/drm/msm/msm_gem.h @@ -230,7 +230,19 @@ msm_gem_unlock(struct drm_gem_object *obj) static inline bool msm_gem_is_locked(struct drm_gem_object *obj) { - return dma_resv_is_locked(obj->resv); + /* + * Destroying the object is a special case.. msm_gem_free_object() + * calls many things that WARN_ON if the obj lock is not held. But + * acquiring the obj lock in msm_gem_free_object() can cause a + * locking order inversion between reservation_ww_class_mutex and + * fs_reclaim. + * + * This deadlock is not actually possible, because no one should + * be already holding the lock when msm_gem_free_object() is called. + * Unfortunately lockdep is not aware of this detail. So when the + * refcount drops to zero, we pretend it is already locked. + */ + return dma_resv_is_locked(obj->resv) || (kref_read(&obj->refcount) == 0); }
static inline bool is_active(struct msm_gem_object *msm_obj)
From: Mauro Carvalho Chehab mchehab@kernel.org
[ Upstream commit 7c2d45a347c7933cbe0efff14fe96adeb13fd761 ]
The logic which checks if the venv version is good enough but was not activated is broken: it is checking against the wrong val, making it to recommend to re-create a venv every time. Fix it.
Signed-off-by: Mauro Carvalho Chehab mchehab@kernel.org Link: https://lore.kernel.org/r/afe01b7863fd655986d84ace8948f3d7aede796d.165675645... Signed-off-by: Jonathan Corbet corbet@lwn.net Signed-off-by: Sasha Levin sashal@kernel.org --- scripts/sphinx-pre-install | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/scripts/sphinx-pre-install b/scripts/sphinx-pre-install index f126ecbb0494..ae8c49734899 100755 --- a/scripts/sphinx-pre-install +++ b/scripts/sphinx-pre-install @@ -741,7 +741,7 @@ sub recommend_sphinx_upgrade()
# Get the highest version from sphinx_*/bin/sphinx-build and the # corresponding command to activate the venv/virtenv - $activate_cmd = get_virtenv(); + ($activate_cmd, $venv_ver) = get_virtenv();
# Store the highest version from Sphinx existing virtualenvs if (($activate_cmd ne "") && ($venv_ver gt $cur_version)) { @@ -759,10 +759,14 @@ sub recommend_sphinx_upgrade() # Either there are already a virtual env or a new one should be created $need_pip = 1;
+ return if (!$latest_avail_ver); + # Return if the reason is due to an upgrade or not if ($latest_avail_ver lt $rec_version) { $rec_sphinx_upgrade = 1; } + + return $latest_avail_ver; }
# @@ -820,7 +824,7 @@ sub recommend_sphinx_version($) }
# Suggest newer versions if current ones are too old - if ($latest_avail_ver && $cur_version ge $min_version) { + if ($latest_avail_ver && $latest_avail_ver ge $min_version) { # If there's a good enough version, ask the user to enable it if ($latest_avail_ver ge $rec_version) { printf "\nNeed to activate Sphinx (version $latest_avail_ver) on virtualenv with:\n"; @@ -897,7 +901,7 @@ sub check_needs() } }
- recommend_sphinx_upgrade(); + my $venv_ver = recommend_sphinx_upgrade();
my $virtualenv_cmd;
From: xinhui pan xinhui.pan@amd.com
[ Upstream commit cc3cb791f19ad0c4f951f38c98aa513b042ab329 ]
Queue would be freed when create_queue_cpsch fails So lets do queue cleanup otherwise various list and memory issues happen.
Signed-off-by: xinhui pan xinhui.pan@amd.com Reviewed-by: Philip Yang Philip.Yang@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c index e017b4240472..06417c7abca4 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c @@ -1666,14 +1666,13 @@ static int create_queue_cpsch(struct device_queue_manager *dqm, struct queue *q, if (q->properties.is_active) { increment_queue_count(dqm, qpd, q);
- if (!dqm->dev->shared_resources.enable_mes) { + if (!dqm->dev->shared_resources.enable_mes) retval = execute_queues_cpsch(dqm, - KFD_UNMAP_QUEUES_FILTER_DYNAMIC_QUEUES, 0); - } else { + KFD_UNMAP_QUEUES_FILTER_DYNAMIC_QUEUES, 0); + else retval = add_queue_mes(dqm, q, qpd); - if (retval) - goto cleanup_queue; - } + if (retval) + goto cleanup_queue; }
/*
From: Herbert Xu herbert@gondor.apana.org.au
[ Upstream commit cc8166bfc829043020b5cc3b7cdba02a17d03b6d ]
The compiler complains that p8_ghash_alg isn't declared which is because the header file aesp8-ppc.h isn't included in ghash.c. This patch fixes the warning.
Signed-off-by: Herbert Xu herbert@gondor.apana.org.au Acked-by: Breno Leitao leitao@debian.org Signed-off-by: Herbert Xu herbert@gondor.apana.org.au Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/crypto/vmx/ghash.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/crypto/vmx/ghash.c b/drivers/crypto/vmx/ghash.c index 5bc5710a6de0..77eca20bc7ac 100644 --- a/drivers/crypto/vmx/ghash.c +++ b/drivers/crypto/vmx/ghash.c @@ -23,6 +23,7 @@ #include <crypto/internal/hash.h> #include <crypto/internal/simd.h> #include <crypto/b128ops.h> +#include "aesp8-ppc.h"
void gcm_init_p8(u128 htable[16], const u64 Xi[2]); void gcm_gmult_p8(u64 Xi[2], const u128 htable[16]);
From: Hariprasad Kelam hkelam@marvell.com
[ Upstream commit 8e1514579246ddc36ba0b860fc8bdd03be085aee ]
Current implementation is such that driver first resets the existing PFC config before applying new pfc configuration. This creates a problem like once PF or VFs requests PFC config previous pfc config by other PFVfs is getting reset.
This patch fixes the problem by removing unnecessary resetting of PFC config. Also configure Pause quanta value to smaller as current value is too high.
Signed-off-by: Hariprasad Kelam hkelam@marvell.com Signed-off-by: Sunil Kovvuri Goutham sgoutham@marvell.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- .../net/ethernet/marvell/octeontx2/af/cgx.c | 15 +++++++++++---- .../net/ethernet/marvell/octeontx2/af/rpm.c | 18 +++++++++++------- .../net/ethernet/marvell/octeontx2/af/rpm.h | 3 +-- 3 files changed, 23 insertions(+), 13 deletions(-)
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c index 25491edc35ce..931a1a7ebf76 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c @@ -847,6 +847,11 @@ static void cgx_lmac_pause_frm_config(void *cgxd, int lmac_id, bool enable) cfg |= CGX_CMR_RX_OVR_BP_EN(lmac_id); cfg &= ~CGX_CMR_RX_OVR_BP_BP(lmac_id); cgx_write(cgx, 0, CGXX_CMR_RX_OVR_BP, cfg); + + /* Disable all PFC classes by default */ + cfg = cgx_read(cgx, lmac_id, CGXX_SMUX_CBFC_CTL); + cfg = FIELD_SET(CGX_PFC_CLASS_MASK, 0, cfg); + cgx_write(cgx, lmac_id, CGXX_SMUX_CBFC_CTL, cfg); }
int verify_lmac_fc_cfg(void *cgxd, int lmac_id, u8 tx_pause, u8 rx_pause, @@ -899,6 +904,7 @@ int cgx_lmac_pfc_config(void *cgxd, int lmac_id, u8 tx_pause, return 0;
cfg = cgx_read(cgx, lmac_id, CGXX_SMUX_CBFC_CTL); + pfc_en |= FIELD_GET(CGX_PFC_CLASS_MASK, cfg);
if (rx_pause) { cfg |= (CGXX_SMUX_CBFC_CTL_RX_EN | @@ -910,12 +916,13 @@ int cgx_lmac_pfc_config(void *cgxd, int lmac_id, u8 tx_pause, CGXX_SMUX_CBFC_CTL_DRP_EN); }
- if (tx_pause) + if (tx_pause) { cfg |= CGXX_SMUX_CBFC_CTL_TX_EN; - else + cfg = FIELD_SET(CGX_PFC_CLASS_MASK, pfc_en, cfg); + } else { cfg &= ~CGXX_SMUX_CBFC_CTL_TX_EN; - - cfg = FIELD_SET(CGX_PFC_CLASS_MASK, pfc_en, cfg); + cfg = FIELD_SET(CGX_PFC_CLASS_MASK, 0, cfg); + }
cgx_write(cgx, lmac_id, CGXX_SMUX_CBFC_CTL, cfg);
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rpm.c b/drivers/net/ethernet/marvell/octeontx2/af/rpm.c index 47e83d7a5804..05666922a45b 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rpm.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rpm.c @@ -276,6 +276,11 @@ void rpm_lmac_pause_frm_config(void *rpmd, int lmac_id, bool enable) cfg = rpm_read(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG); cfg |= RPMX_MTI_MAC100X_COMMAND_CONFIG_TX_P_DISABLE; rpm_write(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG, cfg); + + /* Disable all PFC classes */ + cfg = rpm_read(rpm, lmac_id, RPMX_CMRX_PRT_CBFC_CTL); + cfg = FIELD_SET(RPM_PFC_CLASS_MASK, 0, cfg); + rpm_write(rpm, lmac_id, RPMX_CMRX_PRT_CBFC_CTL, cfg); }
int rpm_get_rx_stats(void *rpmd, int lmac_id, int idx, u64 *rx_stat) @@ -387,15 +392,14 @@ void rpm_lmac_ptp_config(void *rpmd, int lmac_id, bool enable) int rpm_lmac_pfc_config(void *rpmd, int lmac_id, u8 tx_pause, u8 rx_pause, u16 pfc_en) { rpm_t *rpm = rpmd; - u64 cfg; + u64 cfg, class_en;
if (!is_lmac_valid(rpm, lmac_id)) return -ENODEV;
- /* reset PFC class quanta and threshold */ - rpm_cfg_pfc_quanta_thresh(rpm, lmac_id, 0xffff, false); - cfg = rpm_read(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG); + class_en = rpm_read(rpm, lmac_id, RPMX_CMRX_PRT_CBFC_CTL); + pfc_en |= FIELD_GET(RPM_PFC_CLASS_MASK, class_en);
if (rx_pause) { cfg &= ~(RPMX_MTI_MAC100X_COMMAND_CONFIG_RX_P_DISABLE | @@ -410,9 +414,11 @@ int rpm_lmac_pfc_config(void *rpmd, int lmac_id, u8 tx_pause, u8 rx_pause, u16 p if (tx_pause) { rpm_cfg_pfc_quanta_thresh(rpm, lmac_id, pfc_en, true); cfg &= ~RPMX_MTI_MAC100X_COMMAND_CONFIG_TX_P_DISABLE; + class_en = FIELD_SET(RPM_PFC_CLASS_MASK, pfc_en, class_en); } else { rpm_cfg_pfc_quanta_thresh(rpm, lmac_id, 0xfff, false); cfg |= RPMX_MTI_MAC100X_COMMAND_CONFIG_TX_P_DISABLE; + class_en = FIELD_SET(RPM_PFC_CLASS_MASK, 0, class_en); }
if (!rx_pause && !tx_pause) @@ -422,9 +428,7 @@ int rpm_lmac_pfc_config(void *rpmd, int lmac_id, u8 tx_pause, u8 rx_pause, u16 p
rpm_write(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG, cfg);
- cfg = rpm_read(rpm, lmac_id, RPMX_CMRX_PRT_CBFC_CTL); - cfg = FIELD_SET(RPM_PFC_CLASS_MASK, pfc_en, cfg); - rpm_write(rpm, lmac_id, RPMX_CMRX_PRT_CBFC_CTL, cfg); + rpm_write(rpm, lmac_id, RPMX_CMRX_PRT_CBFC_CTL, class_en);
return 0; } diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rpm.h b/drivers/net/ethernet/marvell/octeontx2/af/rpm.h index 9ab8d49dd180..8205f2626f61 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rpm.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/rpm.h @@ -48,7 +48,6 @@ #define RPMX_MTI_MAC100X_CL1011_QUANTA_THRESH 0x8130 #define RPMX_MTI_MAC100X_CL1213_QUANTA_THRESH 0x8138 #define RPMX_MTI_MAC100X_CL1415_QUANTA_THRESH 0x8140 -#define RPM_DEFAULT_PAUSE_TIME 0xFFFF #define RPMX_CMR_RX_OVR_BP 0x4120 #define RPMX_CMR_RX_OVR_BP_EN(x) BIT_ULL((x) + 8) #define RPMX_CMR_RX_OVR_BP_BP(x) BIT_ULL((x) + 4) @@ -70,7 +69,7 @@ #define RPMX_MTI_MAC100X_COMMAND_CONFIG_PAUSE_FWD BIT_ULL(7) #define RPMX_MTI_MAC100X_CL01_PAUSE_QUANTA 0x80A8 #define RPMX_MTI_MAC100X_CL89_PAUSE_QUANTA 0x8108 -#define RPM_DEFAULT_PAUSE_TIME 0xFFFF +#define RPM_DEFAULT_PAUSE_TIME 0x7FF
/* Function Declarations */ int rpm_get_nr_lmacs(void *rpmd);
From: James Hilliard james.hilliard1@gmail.com
[ Upstream commit 18410251f66aee7e82234073ce6656ca20a732a9 ]
It seems the gcc preprocessor breaks with pragmas when surrounding __attribute__.
Disable these pragmas on GCC due to upstream bugs see: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55578 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90400
Fixes errors like: error: expected identifier or '(' before '#pragma' 106 | SEC("cgroup/bind6") | ^~~
error: expected '=', ',', ';', 'asm' or '__attribute__' before '#pragma' 114 | char _license[] SEC("license") = "GPL"; | ^~~
Signed-off-by: James Hilliard james.hilliard1@gmail.com Signed-off-by: Andrii Nakryiko andrii@kernel.org Link: https://lore.kernel.org/bpf/20220706111839.1247911-1-james.hilliard1@gmail.c... Signed-off-by: Sasha Levin sashal@kernel.org --- tools/lib/bpf/bpf_helpers.h | 13 +++++++++++++ 1 file changed, 13 insertions(+)
diff --git a/tools/lib/bpf/bpf_helpers.h b/tools/lib/bpf/bpf_helpers.h index fb04eaf367f1..7349b16b8e2f 100644 --- a/tools/lib/bpf/bpf_helpers.h +++ b/tools/lib/bpf/bpf_helpers.h @@ -22,12 +22,25 @@ * To allow use of SEC() with externs (e.g., for extern .maps declarations), * make sure __attribute__((unused)) doesn't trigger compilation warning. */ +#if __GNUC__ && !__clang__ + +/* + * Pragma macros are broken on GCC + * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55578 + * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90400 + */ +#define SEC(name) __attribute__((section(name), used)) + +#else + #define SEC(name) \ _Pragma("GCC diagnostic push") \ _Pragma("GCC diagnostic ignored "-Wignored-attributes"") \ __attribute__((section(name), used)) \ _Pragma("GCC diagnostic pop") \
+#endif + /* Avoid 'linux/stddef.h' definition of '__always_inline'. */ #undef __always_inline #define __always_inline inline __attribute__((always_inline))
From: Yafang Shao laoar.shao@gmail.com
[ Upstream commit ace2bee839e08df324cb320763258dfd72e6120e ]
GFP_ATOMIC doesn't cooperate well with memcg pressure so far, especially if we allocate too much GFP_ATOMIC memory. For example, when we set the memcg limit to limit a non-preallocated bpf memory, the GFP_ATOMIC can easily break the memcg limit by force charge. So it is very dangerous to use GFP_ATOMIC in non-preallocated case. One way to make it safe is to remove __GFP_HIGH from GFP_ATOMIC, IOW, use (__GFP_ATOMIC | __GFP_KSWAPD_RECLAIM) instead, then it will be limited if we allocate too much memory. There's a plan to completely remove __GFP_ATOMIC in the mm side[1], so let's use GFP_NOWAIT instead.
We introduced BPF_F_NO_PREALLOC is because full map pre-allocation is too memory expensive for some cases. That means removing __GFP_HIGH doesn't break the rule of BPF_F_NO_PREALLOC, but has the same goal with it-avoiding issues caused by too much memory. So let's remove it.
This fix can also apply to other run-time allocations, for example, the allocation in lpm trie, local storage and devmap. So let fix it consistently over the bpf code
It also fixes a typo in the comment.
[1]. https://lore.kernel.org/linux-mm/163712397076.13692.4727608274002939094@nobl...
Cc: Roman Gushchin roman.gushchin@linux.dev Cc: Shakeel Butt shakeelb@google.com Cc: NeilBrown neilb@suse.de Signed-off-by: Yafang Shao laoar.shao@gmail.com Reviewed-by: Shakeel Butt shakeelb@google.com Link: https://lore.kernel.org/r/20220709154457.57379-2-laoar.shao@gmail.com Signed-off-by: Alexei Starovoitov ast@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- kernel/bpf/devmap.c | 2 +- kernel/bpf/hashtab.c | 6 +++--- kernel/bpf/local_storage.c | 2 +- kernel/bpf/lpm_trie.c | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/kernel/bpf/devmap.c b/kernel/bpf/devmap.c index c2867068e5bd..1400561efb15 100644 --- a/kernel/bpf/devmap.c +++ b/kernel/bpf/devmap.c @@ -845,7 +845,7 @@ static struct bpf_dtab_netdev *__dev_map_alloc_node(struct net *net, struct bpf_dtab_netdev *dev;
dev = bpf_map_kmalloc_node(&dtab->map, sizeof(*dev), - GFP_ATOMIC | __GFP_NOWARN, + GFP_NOWAIT | __GFP_NOWARN, dtab->map.numa_node); if (!dev) return ERR_PTR(-ENOMEM); diff --git a/kernel/bpf/hashtab.c b/kernel/bpf/hashtab.c index 17fb69c0e0dc..da7578426a46 100644 --- a/kernel/bpf/hashtab.c +++ b/kernel/bpf/hashtab.c @@ -61,7 +61,7 @@ * * As regular device interrupt handlers and soft interrupts are forced into * thread context, the existing code which does - * spin_lock*(); alloc(GPF_ATOMIC); spin_unlock*(); + * spin_lock*(); alloc(GFP_ATOMIC); spin_unlock*(); * just works. * * In theory the BPF locks could be converted to regular spinlocks as well, @@ -978,7 +978,7 @@ static struct htab_elem *alloc_htab_elem(struct bpf_htab *htab, void *key, goto dec_count; } l_new = bpf_map_kmalloc_node(&htab->map, htab->elem_size, - GFP_ATOMIC | __GFP_NOWARN, + GFP_NOWAIT | __GFP_NOWARN, htab->map.numa_node); if (!l_new) { l_new = ERR_PTR(-ENOMEM); @@ -996,7 +996,7 @@ static struct htab_elem *alloc_htab_elem(struct bpf_htab *htab, void *key, } else { /* alloc_percpu zero-fills */ pptr = bpf_map_alloc_percpu(&htab->map, size, 8, - GFP_ATOMIC | __GFP_NOWARN); + GFP_NOWAIT | __GFP_NOWARN); if (!pptr) { kfree(l_new); l_new = ERR_PTR(-ENOMEM); diff --git a/kernel/bpf/local_storage.c b/kernel/bpf/local_storage.c index 8654fc97f5fe..49ef0ce040c7 100644 --- a/kernel/bpf/local_storage.c +++ b/kernel/bpf/local_storage.c @@ -165,7 +165,7 @@ static int cgroup_storage_update_elem(struct bpf_map *map, void *key, }
new = bpf_map_kmalloc_node(map, struct_size(new, data, map->value_size), - __GFP_ZERO | GFP_ATOMIC | __GFP_NOWARN, + __GFP_ZERO | GFP_NOWAIT | __GFP_NOWARN, map->numa_node); if (!new) return -ENOMEM; diff --git a/kernel/bpf/lpm_trie.c b/kernel/bpf/lpm_trie.c index f0d05a3cc4b9..d789e3b831ad 100644 --- a/kernel/bpf/lpm_trie.c +++ b/kernel/bpf/lpm_trie.c @@ -285,7 +285,7 @@ static struct lpm_trie_node *lpm_trie_node_alloc(const struct lpm_trie *trie, if (value) size += trie->map.value_size;
- node = bpf_map_kmalloc_node(&trie->map, size, GFP_ATOMIC | __GFP_NOWARN, + node = bpf_map_kmalloc_node(&trie->map, size, GFP_NOWAIT | __GFP_NOWARN, trie->map.numa_node); if (!node) return NULL;
From: Ben Skeggs bskeggs@redhat.com
[ Upstream commit 61c1f340bc809a1ca1e3c8794207a91cde1a7c78 ]
Fixes resume from hibernate failing on (at least) TU102, where cursor channel init failed due to being performed before the core channel.
Not solid idea why suspend-to-ram worked, but, presumably HW being in an entirely clean state has something to do with it.
Signed-off-by: Ben Skeggs bskeggs@redhat.com Reviewed-by: Dave Airlie airlied@redhat.com Signed-off-by: Dave Airlie airlied@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/nouveau/nvkm/core/ioctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/nouveau/nvkm/core/ioctl.c b/drivers/gpu/drm/nouveau/nvkm/core/ioctl.c index 735cb6816f10..06b2f675f5da 100644 --- a/drivers/gpu/drm/nouveau/nvkm/core/ioctl.c +++ b/drivers/gpu/drm/nouveau/nvkm/core/ioctl.c @@ -128,7 +128,7 @@ nvkm_ioctl_new(struct nvkm_client *client, if (ret == 0) { ret = nvkm_object_init(object); if (ret == 0) { - list_add(&object->head, &parent->tree); + list_add_tail(&object->head, &parent->tree); if (nvkm_object_insert(object)) { client->data = object; return 0;
From: Alex Deucher alexander.deucher@amd.com
[ Upstream commit 0a94608f0f7de9b1135ffea3546afe68eafef57f ]
Drop execute.
Bug: https://gitlab.freedesktop.org/drm/amd/-/issues/2085 Reviewed-by: Guchun Chen guchun.chen@amd.com Reviewed-by: Christian König christian.koenig@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/amd/include/asic_reg/clk/clk_11_0_1_offset.h | 0 drivers/gpu/drm/amd/include/asic_reg/clk/clk_11_0_1_sh_mask.h | 0 drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_2_0_3_offset.h | 0 drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_2_0_3_sh_mask.h | 0 drivers/gpu/drm/amd/include/asic_reg/dpcs/dpcs_2_0_3_offset.h | 0 drivers/gpu/drm/amd/include/asic_reg/dpcs/dpcs_2_0_3_sh_mask.h | 0 6 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 drivers/gpu/drm/amd/include/asic_reg/clk/clk_11_0_1_offset.h mode change 100755 => 100644 drivers/gpu/drm/amd/include/asic_reg/clk/clk_11_0_1_sh_mask.h mode change 100755 => 100644 drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_2_0_3_offset.h mode change 100755 => 100644 drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_2_0_3_sh_mask.h mode change 100755 => 100644 drivers/gpu/drm/amd/include/asic_reg/dpcs/dpcs_2_0_3_offset.h mode change 100755 => 100644 drivers/gpu/drm/amd/include/asic_reg/dpcs/dpcs_2_0_3_sh_mask.h
diff --git a/drivers/gpu/drm/amd/include/asic_reg/clk/clk_11_0_1_offset.h b/drivers/gpu/drm/amd/include/asic_reg/clk/clk_11_0_1_offset.h old mode 100755 new mode 100644 diff --git a/drivers/gpu/drm/amd/include/asic_reg/clk/clk_11_0_1_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/clk/clk_11_0_1_sh_mask.h old mode 100755 new mode 100644 diff --git a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_2_0_3_offset.h b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_2_0_3_offset.h old mode 100755 new mode 100644 diff --git a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_2_0_3_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_2_0_3_sh_mask.h old mode 100755 new mode 100644 diff --git a/drivers/gpu/drm/amd/include/asic_reg/dpcs/dpcs_2_0_3_offset.h b/drivers/gpu/drm/amd/include/asic_reg/dpcs/dpcs_2_0_3_offset.h old mode 100755 new mode 100644 diff --git a/drivers/gpu/drm/amd/include/asic_reg/dpcs/dpcs_2_0_3_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/dpcs/dpcs_2_0_3_sh_mask.h old mode 100755 new mode 100644
From: Jiri Olsa jolsa@kernel.org
[ Upstream commit 7fb27a56b9ebd8a77d9dd188e8a42bff99bc3443 ]
Alexei reported crash by running test_progs -j on system with 32 cpus.
It turned out the kprobe_multi bench test that attaches all ftrace-able functions will race with bpf_dispatcher_update, that calls bpf_arch_text_poke on bpf_dispatcher_xdp_func, which is ftrace-able function.
Ftrace is not aware of this update so this will cause ftrace_bug with:
WARNING: CPU: 6 PID: 1985 at arch/x86/kernel/ftrace.c:94 ftrace_verify_code+0x27/0x50 ... ftrace_replace_code+0xa3/0x170 ftrace_modify_all_code+0xbd/0x150 ftrace_startup_enable+0x3f/0x50 ftrace_startup+0x98/0xf0 register_ftrace_function+0x20/0x60 register_fprobe_ips+0xbb/0xd0 bpf_kprobe_multi_link_attach+0x179/0x430 __sys_bpf+0x18a1/0x2440 ... ------------[ ftrace bug ]------------ ftrace failed to modify [<ffffffff818d9380>] bpf_dispatcher_xdp_func+0x0/0x10 actual: ffffffe9:7b:ffffff9c:77:1e Setting ftrace call site to call ftrace function
It looks like we need some way to hide some functions from ftrace, but meanwhile we workaround this by skipping bpf_dispatcher_xdp_func from kprobe_multi bench test.
Reported-by: Alexei Starovoitov ast@kernel.org Signed-off-by: Jiri Olsa jolsa@kernel.org Signed-off-by: Andrii Nakryiko andrii@kernel.org Acked-by: Yonghong Song yhs@fb.com Link: https://lore.kernel.org/bpf/20220714082316.479181-1-jolsa@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- tools/testing/selftests/bpf/prog_tests/kprobe_multi_test.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/tools/testing/selftests/bpf/prog_tests/kprobe_multi_test.c b/tools/testing/selftests/bpf/prog_tests/kprobe_multi_test.c index 5b93d5d0bd93..48681bf73e0b 100644 --- a/tools/testing/selftests/bpf/prog_tests/kprobe_multi_test.c +++ b/tools/testing/selftests/bpf/prog_tests/kprobe_multi_test.c @@ -364,6 +364,8 @@ static int get_syms(char ***symsp, size_t *cntp) continue; if (!strncmp(name, "rcu_", 4)) continue; + if (!strcmp(name, "bpf_dispatcher_xdp_func")) + continue; if (!strncmp(name, "__ftrace_invalid_address__", sizeof("__ftrace_invalid_address__") - 1)) continue;
From: Yuan Can yuancan@huawei.com
[ Upstream commit 30fb034361ff1b9bfc569b2d8d66b544ea3eb18f ]
Add clk_disable_unprepare() on error path in cc_pm_resume().
Reported-by: Hulk Robot hulkci@huawei.com Signed-off-by: Yuan Can yuancan@huawei.com Signed-off-by: Herbert Xu herbert@gondor.apana.org.au Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/crypto/ccree/cc_pm.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/drivers/crypto/ccree/cc_pm.c b/drivers/crypto/ccree/cc_pm.c index d5421b0c6831..6124fbbbed94 100644 --- a/drivers/crypto/ccree/cc_pm.c +++ b/drivers/crypto/ccree/cc_pm.c @@ -41,6 +41,7 @@ static int cc_pm_resume(struct device *dev) /* wait for Cryptocell reset completion */ if (!cc_wait_for_reset_completion(drvdata)) { dev_err(dev, "Cryptocell reset not completed"); + clk_disable_unprepare(drvdata->clk); return -EBUSY; }
@@ -48,6 +49,7 @@ static int cc_pm_resume(struct device *dev) rc = init_cc_regs(drvdata); if (rc) { dev_err(dev, "init_cc_regs (%x)\n", rc); + clk_disable_unprepare(drvdata->clk); return rc; } /* check if tee fips error occurred during power down */
From: Ben Dooks ben.dooks@sifive.com
[ Upstream commit a2a5580fcbf808e7c2310e4959b62f9d2157fdb6 ]
When checking with sparse, btf_show_type_value() is causing a warning about checking integer vs NULL when the macro is passed a pointer, due to the 'value != 0' check. Stop sparse complaining about any type-casting by adding a cast to the typeof(value).
This fixes the following sparse warnings:
kernel/bpf/btf.c:2579:17: warning: Using plain integer as NULL pointer kernel/bpf/btf.c:2581:17: warning: Using plain integer as NULL pointer kernel/bpf/btf.c:3407:17: warning: Using plain integer as NULL pointer kernel/bpf/btf.c:3758:9: warning: Using plain integer as NULL pointer
Signed-off-by: Ben Dooks ben.dooks@sifive.com Signed-off-by: Andrii Nakryiko andrii@kernel.org Acked-by: Yonghong Song yhs@fb.com Link: https://lore.kernel.org/bpf/20220714100322.260467-1-ben.dooks@sifive.com Signed-off-by: Sasha Levin sashal@kernel.org --- kernel/bpf/btf.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c index eb12d4f705cc..9a6e5f71bbd2 100644 --- a/kernel/bpf/btf.c +++ b/kernel/bpf/btf.c @@ -1108,7 +1108,8 @@ __printf(2, 3) static void btf_show(struct btf_show *show, const char *fmt, ...) */ #define btf_show_type_value(show, fmt, value) \ do { \ - if ((value) != 0 || (show->flags & BTF_SHOW_ZERO) || \ + if ((value) != (__typeof__(value))0 || \ + (show->flags & BTF_SHOW_ZERO) || \ show->state.depth == 0) { \ btf_show(show, "%s%s" fmt "%s%s", \ btf_show_indent(show), \
From: Laurent Pinchart laurent.pinchart@ideasonboard.com
[ Upstream commit 13c9810281f8b24af9b7712cd84a1fce61843e93 ]
If the v4l2_device_register() call fails, runtime PM is left enabled. Fix it.
Signed-off-by: Laurent Pinchart laurent.pinchart@ideasonboard.com Reviewed-by: Dafna Hirschfeld dafna@fastmail.com Reviewed-by: Paul Elder paul.elder@ideasonboard.com Signed-off-by: Mauro Carvalho Chehab mchehab@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c index 3f5cfa7eb937..471226d95dbf 100644 --- a/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c @@ -552,7 +552,7 @@ static int rkisp1_probe(struct platform_device *pdev)
ret = v4l2_device_register(rkisp1->dev, &rkisp1->v4l2_dev); if (ret) - return ret; + goto err_pm_runtime_disable;
ret = media_device_register(&rkisp1->media_dev); if (ret) { @@ -572,6 +572,7 @@ static int rkisp1_probe(struct platform_device *pdev) media_device_unregister(&rkisp1->media_dev); err_unreg_v4l2_dev: v4l2_device_unregister(&rkisp1->v4l2_dev); +err_pm_runtime_disable: pm_runtime_disable(&pdev->dev); return ret; }
From: lin cao lin.cao@amd.com
[ Upstream commit 748262eb400e809aa13e3485f4983c3db3d0ebb3 ]
In the case of SRIOV, the register smnMp1_PMI_3_FIFO will get an invalid value which will cause the "shift out of bound". In Ubuntu22.04, this issue will be checked an related call trace will be reported in dmesg.
Signed-off-by: lin cao lin.cao@amd.com Reviewed-by: Jingwen Chen Jingwen.Chen2@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c index 78f3d9e722bb..4db7e32efd08 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c @@ -886,6 +886,7 @@ static void sienna_cichlid_stb_init(struct smu_context *smu);
static int sienna_cichlid_init_smc_tables(struct smu_context *smu) { + struct amdgpu_device *adev = smu->adev; int ret = 0;
ret = sienna_cichlid_tables_init(smu); @@ -896,7 +897,8 @@ static int sienna_cichlid_init_smc_tables(struct smu_context *smu) if (ret) return ret;
- sienna_cichlid_stb_init(smu); + if (!amdgpu_sriov_vf(adev)) + sienna_cichlid_stb_init(smu);
return smu_v11_0_init_smc_tables(smu); }
From: Moshe Shemesh moshe@nvidia.com
[ Upstream commit e26fde2f5befad0951fe6345403616bf51e901be ]
Add a lock_class_key per devlink instance to avoid DEADLOCK warning by lockdep, while locking more than one devlink instance in driver code, for example in opening VFs flow.
Kernel log: [ 101.433802] ============================================ [ 101.433803] WARNING: possible recursive locking detected [ 101.433810] 5.19.0-rc1+ #35 Not tainted [ 101.433812] -------------------------------------------- [ 101.433813] bash/892 is trying to acquire lock: [ 101.433815] ffff888127bfc2f8 (&devlink->lock){+.+.}-{3:3}, at: probe_one+0x3c/0x690 [mlx5_core] [ 101.433909] but task is already holding lock: [ 101.433910] ffff888118f4c2f8 (&devlink->lock){+.+.}-{3:3}, at: mlx5_core_sriov_configure+0x62/0x280 [mlx5_core] [ 101.433989] other info that might help us debug this: [ 101.433990] Possible unsafe locking scenario:
[ 101.433991] CPU0 [ 101.433991] ---- [ 101.433992] lock(&devlink->lock); [ 101.433993] lock(&devlink->lock); [ 101.433995] *** DEADLOCK ***
[ 101.433996] May be due to missing lock nesting notation
[ 101.433996] 6 locks held by bash/892: [ 101.433998] #0: ffff88810eb50448 (sb_writers#3){.+.+}-{0:0}, at: ksys_write+0xf3/0x1d0 [ 101.434009] #1: ffff888114777c88 (&of->mutex){+.+.}-{3:3}, at: kernfs_fop_write_iter+0x20d/0x520 [ 101.434017] #2: ffff888102b58660 (kn->active#231){.+.+}-{0:0}, at: kernfs_fop_write_iter+0x230/0x520 [ 101.434023] #3: ffff888102d70198 (&dev->mutex){....}-{3:3}, at: sriov_numvfs_store+0x132/0x310 [ 101.434031] #4: ffff888118f4c2f8 (&devlink->lock){+.+.}-{3:3}, at: mlx5_core_sriov_configure+0x62/0x280 [mlx5_core] [ 101.434108] #5: ffff88812adce198 (&dev->mutex){....}-{3:3}, at: __device_attach+0x76/0x430 [ 101.434116] stack backtrace: [ 101.434118] CPU: 5 PID: 892 Comm: bash Not tainted 5.19.0-rc1+ #35 [ 101.434120] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.13.0-0-gf21b5a4aeb02-prebuilt.qemu.org 04/01/2014 [ 101.434130] Call Trace: [ 101.434133] <TASK> [ 101.434135] dump_stack_lvl+0x57/0x7d [ 101.434145] __lock_acquire.cold+0x1df/0x3e7 [ 101.434151] ? register_lock_class+0x1880/0x1880 [ 101.434157] lock_acquire+0x1c1/0x550 [ 101.434160] ? probe_one+0x3c/0x690 [mlx5_core] [ 101.434229] ? lockdep_hardirqs_on_prepare+0x400/0x400 [ 101.434232] ? __xa_alloc+0x1ed/0x2d0 [ 101.434236] ? ksys_write+0xf3/0x1d0 [ 101.434239] __mutex_lock+0x12c/0x14b0 [ 101.434243] ? probe_one+0x3c/0x690 [mlx5_core] [ 101.434312] ? probe_one+0x3c/0x690 [mlx5_core] [ 101.434380] ? devlink_alloc_ns+0x11b/0x910 [ 101.434385] ? mutex_lock_io_nested+0x1320/0x1320 [ 101.434388] ? lockdep_init_map_type+0x21a/0x7d0 [ 101.434391] ? lockdep_init_map_type+0x21a/0x7d0 [ 101.434393] ? __init_swait_queue_head+0x70/0xd0 [ 101.434397] probe_one+0x3c/0x690 [mlx5_core] [ 101.434467] pci_device_probe+0x1b4/0x480 [ 101.434471] really_probe+0x1e0/0xaa0 [ 101.434474] __driver_probe_device+0x219/0x480 [ 101.434478] driver_probe_device+0x49/0x130 [ 101.434481] __device_attach_driver+0x1b8/0x280 [ 101.434484] ? driver_allows_async_probing+0x140/0x140 [ 101.434487] bus_for_each_drv+0x123/0x1a0 [ 101.434489] ? bus_for_each_dev+0x1a0/0x1a0 [ 101.434491] ? lockdep_hardirqs_on_prepare+0x286/0x400 [ 101.434494] ? trace_hardirqs_on+0x2d/0x100 [ 101.434498] __device_attach+0x1a3/0x430 [ 101.434501] ? device_driver_attach+0x1e0/0x1e0 [ 101.434503] ? pci_bridge_d3_possible+0x1e0/0x1e0 [ 101.434506] ? pci_create_resource_files+0xeb/0x190 [ 101.434511] pci_bus_add_device+0x6c/0xa0 [ 101.434514] pci_iov_add_virtfn+0x9e4/0xe00 [ 101.434517] ? trace_hardirqs_on+0x2d/0x100 [ 101.434521] sriov_enable+0x64a/0xca0 [ 101.434524] ? pcibios_sriov_disable+0x10/0x10 [ 101.434528] mlx5_core_sriov_configure+0xab/0x280 [mlx5_core] [ 101.434602] sriov_numvfs_store+0x20a/0x310 [ 101.434605] ? sriov_totalvfs_show+0xc0/0xc0 [ 101.434608] ? sysfs_file_ops+0x170/0x170 [ 101.434611] ? sysfs_file_ops+0x117/0x170 [ 101.434614] ? sysfs_file_ops+0x170/0x170 [ 101.434616] kernfs_fop_write_iter+0x348/0x520 [ 101.434619] new_sync_write+0x2e5/0x520 [ 101.434621] ? new_sync_read+0x520/0x520 [ 101.434624] ? lock_acquire+0x1c1/0x550 [ 101.434626] ? lockdep_hardirqs_on_prepare+0x400/0x400 [ 101.434630] vfs_write+0x5cb/0x8d0 [ 101.434633] ksys_write+0xf3/0x1d0 [ 101.434635] ? __x64_sys_read+0xb0/0xb0 [ 101.434638] ? lockdep_hardirqs_on_prepare+0x286/0x400 [ 101.434640] ? syscall_enter_from_user_mode+0x1d/0x50 [ 101.434643] do_syscall_64+0x3d/0x90 [ 101.434647] entry_SYSCALL_64_after_hwframe+0x46/0xb0 [ 101.434650] RIP: 0033:0x7f5ff536b2f7 [ 101.434658] Code: 0d 00 f7 d8 64 89 02 48 c7 c0 ff ff ff ff eb b7 0f 1f 00 f3 0f 1e fa 64 8b 04 25 18 00 00 00 85 c0 75 10 b8 01 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 51 c3 48 83 ec 28 48 89 54 24 18 48 89 74 24 [ 101.434661] RSP: 002b:00007ffd9ea85d58 EFLAGS: 00000246 ORIG_RAX: 0000000000000001 [ 101.434664] RAX: ffffffffffffffda RBX: 0000000000000002 RCX: 00007f5ff536b2f7 [ 101.434666] RDX: 0000000000000002 RSI: 000055c4c279e230 RDI: 0000000000000001 [ 101.434668] RBP: 000055c4c279e230 R08: 000000000000000a R09: 0000000000000001 [ 101.434669] R10: 000055c4c283cbf0 R11: 0000000000000246 R12: 0000000000000002 [ 101.434670] R13: 00007f5ff543d500 R14: 0000000000000002 R15: 00007f5ff543d700 [ 101.434673] </TASK>
Signed-off-by: Moshe Shemesh moshe@nvidia.com Signed-off-by: Jiri Pirko jiri@nvidia.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- net/core/devlink.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/net/core/devlink.c b/net/core/devlink.c index 5cc88490f18f..e4c19692c792 100644 --- a/net/core/devlink.c +++ b/net/core/devlink.c @@ -66,6 +66,7 @@ struct devlink { * port, sb, dpipe, resource, params, region, traps and more. */ struct mutex lock; + struct lock_class_key lock_key; u8 reload_failed:1; refcount_t refcount; struct completion comp; @@ -9473,7 +9474,9 @@ struct devlink *devlink_alloc_ns(const struct devlink_ops *ops, INIT_LIST_HEAD(&devlink->trap_list); INIT_LIST_HEAD(&devlink->trap_group_list); INIT_LIST_HEAD(&devlink->trap_policer_list); + lockdep_register_key(&devlink->lock_key); mutex_init(&devlink->lock); + lockdep_set_class(&devlink->lock, &devlink->lock_key); mutex_init(&devlink->reporters_lock); mutex_init(&devlink->linecards_lock); refcount_set(&devlink->refcount, 1); @@ -9620,6 +9623,7 @@ void devlink_free(struct devlink *devlink) mutex_destroy(&devlink->linecards_lock); mutex_destroy(&devlink->reporters_lock); mutex_destroy(&devlink->lock); + lockdep_unregister_key(&devlink->lock_key); WARN_ON(!list_empty(&devlink->trap_policer_list)); WARN_ON(!list_empty(&devlink->trap_group_list)); WARN_ON(!list_empty(&devlink->trap_list));
On Thu, 11 Aug 2022 11:28:00 -0400 Sasha Levin wrote:
From: Moshe Shemesh moshe@nvidia.com
[ Upstream commit e26fde2f5befad0951fe6345403616bf51e901be ]
Add a lock_class_key per devlink instance to avoid DEADLOCK warning by lockdep, while locking more than one devlink instance in driver code, for example in opening VFs flow.
I think we can drop this one, no driver locks multiple instances in 5.19. The whole infra for that stuff is new. Not that adding a lockdep key can hurt in any way..
From: Zhengchao Shao shaozhengchao@huawei.com
[ Upstream commit fd1894224407c484f652ad456e1ce423e89bb3eb ]
Syzbot found an issue [1]: fq_codel_drop() try to drop a flow whitout any skbs, that is, the flow->head is null. The root cause, as the [2] says, is because that bpf_prog_test_run_skb() run a bpf prog which redirects empty skbs. So we should determine whether the length of the packet modified by bpf prog or others like bpf_prog_test is valid before forwarding it directly.
LINK: [1] https://syzkaller.appspot.com/bug?id=0b84da80c2917757915afa89f7738a9d16ec96c... LINK: [2] https://www.spinics.net/lists/netdev/msg777503.html
Reported-by: syzbot+7a12909485b94426aceb@syzkaller.appspotmail.com Signed-off-by: Zhengchao Shao shaozhengchao@huawei.com Reviewed-by: Stanislav Fomichev sdf@google.com Link: https://lore.kernel.org/r/20220715115559.139691-1-shaozhengchao@huawei.com Signed-off-by: Alexei Starovoitov ast@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- include/linux/skbuff.h | 8 ++++++++ net/bpf/test_run.c | 3 +++ net/core/dev.c | 1 + 3 files changed, 12 insertions(+)
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index d3d10556f0fa..2f41364a6791 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -2624,6 +2624,14 @@ static inline void skb_set_tail_pointer(struct sk_buff *skb, const int offset)
#endif /* NET_SKBUFF_DATA_USES_OFFSET */
+static inline void skb_assert_len(struct sk_buff *skb) +{ +#ifdef CONFIG_DEBUG_NET + if (WARN_ONCE(!skb->len, "%s\n", __func__)) + DO_ONCE_LITE(skb_dump, KERN_ERR, skb, false); +#endif /* CONFIG_DEBUG_NET */ +} + /* * Add data to an sk_buff */ diff --git a/net/bpf/test_run.c b/net/bpf/test_run.c index 56f059b3c242..42f8de4ebbd7 100644 --- a/net/bpf/test_run.c +++ b/net/bpf/test_run.c @@ -955,6 +955,9 @@ static int convert___skb_to_skb(struct sk_buff *skb, struct __sk_buff *__skb) { struct qdisc_skb_cb *cb = (struct qdisc_skb_cb *)skb->cb;
+ if (!skb->len) + return -EINVAL; + if (!__skb) return 0;
diff --git a/net/core/dev.c b/net/core/dev.c index 30a1603a7225..fe487dc6798e 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -4168,6 +4168,7 @@ int __dev_queue_xmit(struct sk_buff *skb, struct net_device *sb_dev) bool again = false;
skb_reset_mac_header(skb); + skb_assert_len(skb);
if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_SCHED_TSTAMP)) __skb_tstamp_tx(skb, NULL, NULL, skb->sk, SCM_TSTAMP_SCHED);
From: Patrick Wang patrick.wang.shcn@gmail.com
[ Upstream commit 48f8070f5dd8e13148ae4647780a452d53c457a2 ]
Stop-machine recently started calling additional functions while waiting:
---------------------------------------------------------------- Former stop machine wait loop: do { cpu_relax(); => macro ... } while (curstate != STOPMACHINE_EXIT); ----------------------------------------------------------------- Current stop machine wait loop: do { stop_machine_yield(cpumask); => function (notraced) ... touch_nmi_watchdog(); => function (notraced, inside calls also notraced) ... rcu_momentary_dyntick_idle(); => function (notraced, inside calls traced) } while (curstate != MULTI_STOP_EXIT); ------------------------------------------------------------------
These functions (and the functions that they call) must be marked notrace to prevent them from being updated while they are executing. The consequences of failing to mark these functions can be severe:
rcu: INFO: rcu_preempt detected stalls on CPUs/tasks: rcu: 1-...!: (0 ticks this GP) idle=14f/1/0x4000000000000000 softirq=3397/3397 fqs=0 rcu: 3-...!: (0 ticks this GP) idle=ee9/1/0x4000000000000000 softirq=5168/5168 fqs=0 (detected by 0, t=8137 jiffies, g=5889, q=2 ncpus=4) Task dump for CPU 1: task:migration/1 state:R running task stack: 0 pid: 19 ppid: 2 flags:0x00000000 Stopper: multi_cpu_stop+0x0/0x18c <- stop_machine_cpuslocked+0x128/0x174 Call Trace: Task dump for CPU 3: task:migration/3 state:R running task stack: 0 pid: 29 ppid: 2 flags:0x00000000 Stopper: multi_cpu_stop+0x0/0x18c <- stop_machine_cpuslocked+0x128/0x174 Call Trace: rcu: rcu_preempt kthread timer wakeup didn't happen for 8136 jiffies! g5889 f0x0 RCU_GP_WAIT_FQS(5) ->state=0x402 rcu: Possible timer handling issue on cpu=2 timer-softirq=594 rcu: rcu_preempt kthread starved for 8137 jiffies! g5889 f0x0 RCU_GP_WAIT_FQS(5) ->state=0x402 ->cpu=2 rcu: Unless rcu_preempt kthread gets sufficient CPU time, OOM is now expected behavior. rcu: RCU grace-period kthread stack dump: task:rcu_preempt state:I stack: 0 pid: 14 ppid: 2 flags:0x00000000 Call Trace: schedule+0x56/0xc2 schedule_timeout+0x82/0x184 rcu_gp_fqs_loop+0x19a/0x318 rcu_gp_kthread+0x11a/0x140 kthread+0xee/0x118 ret_from_exception+0x0/0x14 rcu: Stack dump where RCU GP kthread last ran: Task dump for CPU 2: task:migration/2 state:R running task stack: 0 pid: 24 ppid: 2 flags:0x00000000 Stopper: multi_cpu_stop+0x0/0x18c <- stop_machine_cpuslocked+0x128/0x174 Call Trace:
This commit therefore marks these functions notrace: rcu_preempt_deferred_qs() rcu_preempt_need_deferred_qs() rcu_preempt_deferred_qs_irqrestore()
[ paulmck: Apply feedback from Neeraj Upadhyay. ]
Signed-off-by: Patrick Wang patrick.wang.shcn@gmail.com Acked-by: Steven Rostedt (Google) rostedt@goodmis.org Signed-off-by: Paul E. McKenney paulmck@kernel.org Reviewed-by: Neeraj Upadhyay quic_neeraju@quicinc.com Signed-off-by: Sasha Levin sashal@kernel.org --- kernel/rcu/tree_plugin.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/kernel/rcu/tree_plugin.h b/kernel/rcu/tree_plugin.h index c8ba0fe17267..7a07f2ca153e 100644 --- a/kernel/rcu/tree_plugin.h +++ b/kernel/rcu/tree_plugin.h @@ -460,7 +460,7 @@ static bool rcu_preempt_has_tasks(struct rcu_node *rnp) * be quite short, for example, in the case of the call from * rcu_read_unlock_special(). */ -static void +static notrace void rcu_preempt_deferred_qs_irqrestore(struct task_struct *t, unsigned long flags) { bool empty_exp; @@ -581,7 +581,7 @@ rcu_preempt_deferred_qs_irqrestore(struct task_struct *t, unsigned long flags) * is disabled. This function cannot be expected to understand these * nuances, so the caller must handle them. */ -static bool rcu_preempt_need_deferred_qs(struct task_struct *t) +static notrace bool rcu_preempt_need_deferred_qs(struct task_struct *t) { return (__this_cpu_read(rcu_data.cpu_no_qs.b.exp) || READ_ONCE(t->rcu_read_unlock_special.s)) && @@ -595,7 +595,7 @@ static bool rcu_preempt_need_deferred_qs(struct task_struct *t) * evaluate safety in terms of interrupt, softirq, and preemption * disabling. */ -static void rcu_preempt_deferred_qs(struct task_struct *t) +static notrace void rcu_preempt_deferred_qs(struct task_struct *t) { unsigned long flags;
@@ -926,7 +926,7 @@ static bool rcu_preempt_has_tasks(struct rcu_node *rnp) * Because there is no preemptible RCU, there can be no deferred quiescent * states. */ -static bool rcu_preempt_need_deferred_qs(struct task_struct *t) +static notrace bool rcu_preempt_need_deferred_qs(struct task_struct *t) { return false; } @@ -935,7 +935,7 @@ static bool rcu_preempt_need_deferred_qs(struct task_struct *t) // period for a quiescent state from this CPU. Note that requests from // tasks are handled when removing the task from the blocked-tasks list // below. -static void rcu_preempt_deferred_qs(struct task_struct *t) +static notrace void rcu_preempt_deferred_qs(struct task_struct *t) { struct rcu_data *rdp = this_cpu_ptr(&rcu_data);
From: Biju Das biju.das.jz@bp.renesas.com
[ Upstream commit 2d99bfbf3386962692dcccd73931cb0db07a1a43 ]
As per Chapter 6.5.16 of the RZ/N1 Peripheral Manual, The SJA1000 CAN controller does not support Clock Divider Register compared to the reference Philips SJA1000 device.
This patch adds a device quirk to handle this difference.
Link: https://lore.kernel.org/all/20220710115248.190280-4-biju.das.jz@bp.renesas.c... Signed-off-by: Biju Das biju.das.jz@bp.renesas.com Signed-off-by: Marc Kleine-Budde mkl@pengutronix.de Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/can/sja1000/sja1000.c | 8 +++++--- drivers/net/can/sja1000/sja1000.h | 3 ++- 2 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/drivers/net/can/sja1000/sja1000.c b/drivers/net/can/sja1000/sja1000.c index 2e7638f98cf1..d9da471f1bb9 100644 --- a/drivers/net/can/sja1000/sja1000.c +++ b/drivers/net/can/sja1000/sja1000.c @@ -183,8 +183,9 @@ static void chipset_init(struct net_device *dev) { struct sja1000_priv *priv = netdev_priv(dev);
- /* set clock divider and output control register */ - priv->write_reg(priv, SJA1000_CDR, priv->cdr | CDR_PELICAN); + if (!(priv->flags & SJA1000_QUIRK_NO_CDR_REG)) + /* set clock divider and output control register */ + priv->write_reg(priv, SJA1000_CDR, priv->cdr | CDR_PELICAN);
/* set acceptance filter (accept all) */ priv->write_reg(priv, SJA1000_ACCC0, 0x00); @@ -209,7 +210,8 @@ static void sja1000_start(struct net_device *dev) set_reset_mode(dev);
/* Initialize chip if uninitialized at this stage */ - if (!(priv->read_reg(priv, SJA1000_CDR) & CDR_PELICAN)) + if (!(priv->flags & SJA1000_QUIRK_NO_CDR_REG || + priv->read_reg(priv, SJA1000_CDR) & CDR_PELICAN)) chipset_init(dev);
/* Clear error counters and error code capture */ diff --git a/drivers/net/can/sja1000/sja1000.h b/drivers/net/can/sja1000/sja1000.h index 9d46398f8154..7f736f1df547 100644 --- a/drivers/net/can/sja1000/sja1000.h +++ b/drivers/net/can/sja1000/sja1000.h @@ -145,7 +145,8 @@ /* * Flags for sja1000priv.flags */ -#define SJA1000_CUSTOM_IRQ_HANDLER 0x1 +#define SJA1000_CUSTOM_IRQ_HANDLER BIT(0) +#define SJA1000_QUIRK_NO_CDR_REG BIT(1)
/* * SJA1000 private data structure
From: Łukasz Spintzyk lukasz.spintzyk@synaptics.com
[ Upstream commit 5588d628027092e66195097bdf6835ddf64418b3 ]
DisplayLink ethernet devices require NTB buffers larger then 32kb in order to run with highest performance.
This patch is changing upper limit of the rx and tx buffers. Those buffers are initialized with CDC_NCM_NTB_DEF_SIZE_RX and CDC_NCM_NTB_DEF_SIZE_TX which is 16kb so by default no device is affected by increased limit.
Rx and tx buffer is increased under two conditions: - Device need to advertise that it supports higher buffer size in dwNtbMaxInMaxSize and dwNtbMaxOutMaxSize. - cdc_ncm/rx_max and cdc_ncm/tx_max driver parameters must be adjusted with udev rule or ethtool.
Summary of testing and performance results: Tests were performed on following devices: - DisplayLink DL-3xxx family device - DisplayLink DL-6xxx family device - ASUS USB-C2500 2.5G USB3 ethernet adapter - Plugable USB3 1G USB3 ethernet adapter - EDIMAX EU-4307 USB-C ethernet adapter - Dell DBQBCBC064 USB-C ethernet adapter
Performance measurements were done with: - iperf3 between two linux boxes - http://openspeedtest.com/ instance running on local test machine
Insights from tests results: - All except one from third party usb adapters were not affected by increased buffer size to their advertised dwNtbOutMaxSize and dwNtbInMaxSize. Devices were generally reaching 912-940Mbps both download and upload.
Only EDIMAX adapter experienced decreased download size from 929Mbps to 827Mbps with iper3, with openspeedtest decrease was from 968Mbps to 886Mbps.
- DisplayLink DL-3xxx family devices experienced performance increase with iperf3 download from 300Mbps to 870Mbps and upload from 782Mbps to 844Mbps. With openspeedtest download increased from 556Mbps to 873Mbps and upload from 727Mbps to 973Mbps
- DiplayLink DL-6xxx family devices are not affected by increased buffer size.
Signed-off-by: Łukasz Spintzyk lukasz.spintzyk@synaptics.com Acked-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Link: https://lore.kernel.org/r/20220720060518.541-2-lukasz.spintzyk@synaptics.com Signed-off-by: Paolo Abeni pabeni@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- include/linux/usb/cdc_ncm.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/include/linux/usb/cdc_ncm.h b/include/linux/usb/cdc_ncm.h index f7cb3ddce7fb..2d207cb4837d 100644 --- a/include/linux/usb/cdc_ncm.h +++ b/include/linux/usb/cdc_ncm.h @@ -53,8 +53,8 @@ #define USB_CDC_NCM_NDP32_LENGTH_MIN 0x20
/* Maximum NTB length */ -#define CDC_NCM_NTB_MAX_SIZE_TX 32768 /* bytes */ -#define CDC_NCM_NTB_MAX_SIZE_RX 32768 /* bytes */ +#define CDC_NCM_NTB_MAX_SIZE_TX 65536 /* bytes */ +#define CDC_NCM_NTB_MAX_SIZE_RX 65536 /* bytes */
/* Initial NTB length */ #define CDC_NCM_NTB_DEF_SIZE_TX 16384 /* bytes */
From: Ahmad Fatoum a.fatoum@pengutronix.de
[ Upstream commit 4f17c2b6694d0c4098f33b07ee3a696976940aa5 ]
The BCM4349B1, aka CYW/BCM89359, is a WiFi+BT chip and its Bluetooth portion can be controlled over serial.
Two subversions are added for the chip, because ROM firmware reports 002.002.013 (at least for the chips I have here), while depending on patchram firmware revision, either 002.002.013 or 002.002.014 is reported.
Signed-off-by: Ahmad Fatoum a.fatoum@pengutronix.de Reviewed-by: Linus Walleij linus.walleij@linaro.org Signed-off-by: Marcel Holtmann marcel@holtmann.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/bluetooth/btbcm.c | 2 ++ drivers/bluetooth/hci_bcm.c | 1 + 2 files changed, 3 insertions(+)
diff --git a/drivers/bluetooth/btbcm.c b/drivers/bluetooth/btbcm.c index 76fbb046bdbe..c9cda681c691 100644 --- a/drivers/bluetooth/btbcm.c +++ b/drivers/bluetooth/btbcm.c @@ -454,6 +454,8 @@ static const struct bcm_subver_table bcm_uart_subver_table[] = { { 0x6606, "BCM4345C5" }, /* 003.006.006 */ { 0x230f, "BCM4356A2" }, /* 001.003.015 */ { 0x220e, "BCM20702A1" }, /* 001.002.014 */ + { 0x420d, "BCM4349B1" }, /* 002.002.013 */ + { 0x420e, "BCM4349B1" }, /* 002.002.014 */ { 0x4217, "BCM4329B1" }, /* 002.002.023 */ { 0x6106, "BCM4359C0" }, /* 003.001.006 */ { 0x4106, "BCM4335A0" }, /* 002.001.006 */ diff --git a/drivers/bluetooth/hci_bcm.c b/drivers/bluetooth/hci_bcm.c index 785f445dd60d..d0a6f9ff4e08 100644 --- a/drivers/bluetooth/hci_bcm.c +++ b/drivers/bluetooth/hci_bcm.c @@ -1544,6 +1544,7 @@ static const struct of_device_id bcm_bluetooth_of_match[] = { { .compatible = "brcm,bcm43430a0-bt" }, { .compatible = "brcm,bcm43430a1-bt" }, { .compatible = "brcm,bcm43438-bt", .data = &bcm43438_device_data }, + { .compatible = "brcm,bcm4349-bt", .data = &bcm43438_device_data }, { .compatible = "brcm,bcm43540-bt", .data = &bcm4354_device_data }, { .compatible = "brcm,bcm4335a0" }, { },
From: Xiaohui Zhang xiaohuizhang@ruc.edu.cn
[ Upstream commit a5133fe87ed827ce94084eecb7830a6d451ef55c ]
Similar to the handling of l2cap_ecred_connect in commit d3715b2333e9 ("Bluetooth: use memset avoid memory leaks"), we thought a patch might be needed here as well.
Use memset to initialize structs to prevent memory leaks in l2cap_le_connect
Signed-off-by: Xiaohui Zhang xiaohuizhang@ruc.edu.cn Signed-off-by: Marcel Holtmann marcel@holtmann.org Signed-off-by: Sasha Levin sashal@kernel.org --- net/bluetooth/l2cap_core.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 52668662ae8d..77c0aac14539 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -1392,6 +1392,7 @@ static void l2cap_le_connect(struct l2cap_chan *chan)
l2cap_le_flowctl_init(chan, 0);
+ memset(&req, 0, sizeof(req)); req.psm = chan->psm; req.scid = cpu_to_le16(chan->scid); req.mtu = cpu_to_le16(chan->imtu);
From: Tamas Koczka poprdi@google.com
[ Upstream commit 9f30de9e0343da05ac621b5817e9b1ce303c6310 ]
Annotate hci_rx_work() with kcov_remote_start() and kcov_remote_stop() calls, so remote KCOV coverage is collected while processing the rx_q queue which is the main incoming Bluetooth packet queue.
Coverage is associated with the thread which created the packet skb.
The collected extra coverage helps kernel fuzzing efforts in finding vulnerabilities.
This change only has effect if the kernel is compiled with CONFIG_KCOV, otherwise kcov_ functions don't do anything.
Signed-off-by: Tamas Koczka poprdi@google.com Tested-by: Aleksandr Nogikh nogikh@google.com Reviewed-by: Dmitry Vyukov dvyukov@google.com Signed-off-by: Luiz Augusto von Dentz luiz.von.dentz@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- net/bluetooth/hci_core.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index a0f99baafd35..00d42ef705f4 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -29,6 +29,7 @@ #include <linux/rfkill.h> #include <linux/debugfs.h> #include <linux/crypto.h> +#include <linux/kcov.h> #include <linux/property.h> #include <linux/suspend.h> #include <linux/wait.h> @@ -3781,7 +3782,14 @@ static void hci_rx_work(struct work_struct *work)
BT_DBG("%s", hdev->name);
- while ((skb = skb_dequeue(&hdev->rx_q))) { + /* The kcov_remote functions used for collecting packet parsing + * coverage information from this background thread and associate + * the coverage with the syscall's thread which originally injected + * the packet. This helps fuzzing the kernel. + */ + for (; (skb = skb_dequeue(&hdev->rx_q)); kcov_remote_stop()) { + kcov_remote_start_common(skb_get_kcov_handle(skb)); + /* Send copy to monitor */ hci_send_to_monitor(hdev, skb);
From: Yuri D'Elia wavexx@thregr.org
[ Upstream commit e11523e97f474f8c7acc76fa912209900e2d3c69 ]
This sets HCI_QUIRK_BROKEN_ENHANCED_SETUP_SYNC_CONN for MTK controllers since SCO appear to not work when using HCI_OP_ENHANCED_SETUP_SYNC_CONN.
Link: https://bugzilla.kernel.org/show_bug.cgi?id=215576 Signed-off-by: Yuri D'Elia wavexx@thregr.org Signed-off-by: Luiz Augusto von Dentz luiz.von.dentz@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/bluetooth/btusb.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index e25fcd49db70..d5da862fabaf 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -3795,6 +3795,7 @@ static int btusb_probe(struct usb_interface *intf, hdev->manufacturer = 70; hdev->cmd_timeout = btusb_mtk_cmd_timeout; hdev->set_bdaddr = btmtk_set_bdaddr; + set_bit(HCI_QUIRK_BROKEN_ENHANCED_SETUP_SYNC_CONN, &hdev->quirks); set_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks); data->recv_acl = btusb_recv_acl_mtk; }
From: Zijun Hu quic_zijuhu@quicinc.com
[ Upstream commit 766ae2422b4312a73510ebee9266bc23b466fbbb ]
BT core driver should addtionally check LMP feature bit "Erroneous Data Reporting" instead of quirk HCI_QUIRK_BROKEN_ERR_DATA_REPORTING set by BT device driver to decide if HCI commands HCI_Read|Write_Default_Erroneous_Data_Reporting are broken.
BLUETOOTH CORE SPECIFICATION Version 5.3 | Vol 2, Part C | page 587 This feature indicates whether the device is able to support the Packet_Status_Flag and the HCI commands HCI_Write_Default_- Erroneous_Data_Reporting and HCI_Read_Default_Erroneous_- Data_Reporting.
the quirk was introduced by 'commit cde1a8a99287 ("Bluetooth: btusb: Fix and detect most of the Chinese Bluetooth controllers")' to mark HCI commands HCI_Read|Write_Default_Erroneous_Data_Reporting broken by BT device driver, but the reason why these two HCI commands are broken is that feature "Erroneous Data Reporting" is not enabled by firmware, this scenario is illustrated by below log of QCA controllers with USB I/F:
@ RAW Open: hcitool (privileged) version 2.22 < HCI Command: Read Local Supported Commands (0x04|0x0002) plen 0
HCI Event: Command Complete (0x0e) plen 68
Read Local Supported Commands (0x04|0x0002) ncmd 1 Status: Success (0x00) Commands: 288 entries ...... Read Default Erroneous Data Reporting (Octet 18 - Bit 2) Write Default Erroneous Data Reporting (Octet 18 - Bit 3) ......
< HCI Command: Read Default Erroneous Data Reporting (0x03|0x005a) plen 0
HCI Event: Command Complete (0x0e) plen 4
Read Default Erroneous Data Reporting (0x03|0x005a) ncmd 1 Status: Unknown HCI Command (0x01)
< HCI Command: Read Local Supported Features (0x04|0x0003) plen 0
HCI Event: Command Complete (0x0e) plen 12
Read Local Supported Features (0x04|0x0003) ncmd 1 Status: Success (0x00) Features: 0xff 0xfe 0x0f 0xfe 0xd8 0x3f 0x5b 0x87 3 slot packets ......
Signed-off-by: Zijun Hu quic_zijuhu@quicinc.com Tested-by: Zijun Hu quic_zijuhu@quicinc.com Signed-off-by: Luiz Augusto von Dentz luiz.von.dentz@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- include/net/bluetooth/hci.h | 1 + net/bluetooth/hci_sync.c | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index fe7935be7dc4..000c70e88aa8 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -496,6 +496,7 @@ enum { #define LMP_EXT_INQ 0x01 #define LMP_SIMUL_LE_BR 0x02 #define LMP_SIMPLE_PAIR 0x08 +#define LMP_ERR_DATA_REPORTING 0x20 #define LMP_NO_FLUSH 0x40
#define LMP_LSTO 0x01 diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c index c17021642234..a6418095b8d5 100644 --- a/net/bluetooth/hci_sync.c +++ b/net/bluetooth/hci_sync.c @@ -3191,7 +3191,7 @@ static int hci_read_page_scan_activity_sync(struct hci_dev *hdev) static int hci_read_def_err_data_reporting_sync(struct hci_dev *hdev) { if (!(hdev->commands[18] & 0x04) || - test_bit(HCI_QUIRK_BROKEN_ERR_DATA_REPORTING, &hdev->quirks)) + !(hdev->features[0][6] & LMP_ERR_DATA_REPORTING)) return 0;
return __hci_cmd_sync_status(hdev, HCI_OP_READ_DEF_ERR_DATA_REPORTING, @@ -3676,7 +3676,7 @@ static int hci_set_err_data_report_sync(struct hci_dev *hdev) bool enabled = hci_dev_test_flag(hdev, HCI_WIDEBAND_SPEECH_ENABLED);
if (!(hdev->commands[18] & 0x08) || - test_bit(HCI_QUIRK_BROKEN_ERR_DATA_REPORTING, &hdev->quirks)) + !(hdev->features[0][6] & LMP_ERR_DATA_REPORTING)) return 0;
if (enabled == hdev->err_data_reporting)
From: Zijun Hu quic_zijuhu@quicinc.com
[ Upstream commit 1172c59f451f524a14bac5e7b047781883dfe441 ]
Core driver addtionally checks LMP feature bit "Erroneous Data Reporting" instead of quirk HCI_QUIRK_BROKEN_ERR_DATA_REPORTING to decide if HCI commands HCI_Read|Write_Default_Erroneous_Data_Reporting are broken, so remove this unnecessary quirk for QCA controllers.
The reason why these two HCI commands are broken for QCA controllers is that feature "Erroneous Data Reporting" is not enabled by their firmware as shown by below log:
@ RAW Open: hcitool (privileged) version 2.22 < HCI Command: Read Local Supported Commands (0x04|0x0002) plen 0
HCI Event: Command Complete (0x0e) plen 68
Read Local Supported Commands (0x04|0x0002) ncmd 1 Status: Success (0x00) Commands: 288 entries ...... Read Default Erroneous Data Reporting (Octet 18 - Bit 2) Write Default Erroneous Data Reporting (Octet 18 - Bit 3) ......
< HCI Command: Read Default Erroneous Data Reporting (0x03|0x005a) plen 0
HCI Event: Command Complete (0x0e) plen 4
Read Default Erroneous Data Reporting (0x03|0x005a) ncmd 1 Status: Unknown HCI Command (0x01)
< HCI Command: Read Local Supported Features (0x04|0x0003) plen 0
HCI Event: Command Complete (0x0e) plen 12
Read Local Supported Features (0x04|0x0003) ncmd 1 Status: Success (0x00) Features: 0xff 0xfe 0x0f 0xfe 0xd8 0x3f 0x5b 0x87 3 slot packets ......
Signed-off-by: Zijun Hu quic_zijuhu@quicinc.com Tested-by: Zijun Hu quic_zijuhu@quicinc.com Signed-off-by: Luiz Augusto von Dentz luiz.von.dentz@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/bluetooth/btusb.c | 1 - 1 file changed, 1 deletion(-)
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index d5da862fabaf..53deca7b86c9 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -3352,7 +3352,6 @@ static int btusb_setup_qca(struct hci_dev *hdev) * work with the likes of HSP/HFP mSBC. */ set_bit(HCI_QUIRK_BROKEN_ENHANCED_SETUP_SYNC_CONN, &hdev->quirks); - set_bit(HCI_QUIRK_BROKEN_ERR_DATA_REPORTING, &hdev->quirks);
return 0; }
From: Zijun Hu quic_zijuhu@quicinc.com
[ Upstream commit e168f690087735ad12604ee6ee2db1b93e323072 ]
Core driver addtionally checks LMP feature bit "Erroneous Data Reporting" instead of quirk HCI_QUIRK_BROKEN_ERR_DATA_REPORTING to decide if HCI commands HCI_Read|Write_Default_Erroneous_Data_Reporting are broken, so remove this unnecessary quirk for fake CSR controllers.
Signed-off-by: Zijun Hu quic_zijuhu@quicinc.com Signed-off-by: Luiz Augusto von Dentz luiz.von.dentz@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/bluetooth/btusb.c | 1 - 1 file changed, 1 deletion(-)
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 53deca7b86c9..ad27119334fb 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -2069,7 +2069,6 @@ static int btusb_setup_csr(struct hci_dev *hdev) * without these the controller will lock up. */ set_bit(HCI_QUIRK_BROKEN_STORED_LINK_KEY, &hdev->quirks); - set_bit(HCI_QUIRK_BROKEN_ERR_DATA_REPORTING, &hdev->quirks); set_bit(HCI_QUIRK_BROKEN_FILTER_CLEAR_ALL, &hdev->quirks); set_bit(HCI_QUIRK_NO_SUSPEND_NOTIFIER, &hdev->quirks);
From: Zijun Hu quic_zijuhu@quicinc.com
[ Upstream commit 63b1a7dd38bfd4630e5f59a20a2b7b1f3d04f486 ]
Core driver addtionally checks LMP feature bit "Erroneous Data Reporting" instead of quirk HCI_QUIRK_BROKEN_ERR_DATA_REPORTING to decide if HCI commands HCI_Read|Write_Default_Erroneous_Data_Reporting are broken, so remove this unnecessary quirk.
Signed-off-by: Zijun Hu quic_zijuhu@quicinc.com Tested-by: Zijun Hu quic_zijuhu@quicinc.com Signed-off-by: Luiz Augusto von Dentz luiz.von.dentz@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- include/net/bluetooth/hci.h | 11 ----------- net/bluetooth/hci_sync.c | 3 --- 2 files changed, 14 deletions(-)
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 000c70e88aa8..a74535e2edef 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -228,17 +228,6 @@ enum { */ HCI_QUIRK_VALID_LE_STATES,
- /* When this quirk is set, then erroneous data reporting - * is ignored. This is mainly due to the fact that the HCI - * Read Default Erroneous Data Reporting command is advertised, - * but not supported; these controllers often reply with unknown - * command and tend to lock up randomly. Needing a hard reset. - * - * This quirk can be set before hci_register_dev is called or - * during the hdev->setup vendor callback. - */ - HCI_QUIRK_BROKEN_ERR_DATA_REPORTING, - /* * When this quirk is set, then the hci_suspend_notifier is not * registered. This is intended for devices which drop completely diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c index a6418095b8d5..9a3a7cc01345 100644 --- a/net/bluetooth/hci_sync.c +++ b/net/bluetooth/hci_sync.c @@ -3835,9 +3835,6 @@ static const struct { HCI_QUIRK_BROKEN(STORED_LINK_KEY, "HCI Delete Stored Link Key command is advertised, " "but not supported."), - HCI_QUIRK_BROKEN(ERR_DATA_REPORTING, - "HCI Read Default Erroneous Data Reporting command is " - "advertised, but not supported."), HCI_QUIRK_BROKEN(READ_TRANSMIT_POWER, "HCI Read Transmit Power Level command is advertised, " "but not supported."),
From: Luiz Augusto von Dentz luiz.von.dentz@intel.com
[ Upstream commit 1f7435c8f6558a94f75b408a74140bdcbd0f6dd1 ]
This fixes using hci_conn_abort instead of using hci_conn_abort_sync.
Signed-off-by: Luiz Augusto von Dentz luiz.von.dentz@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- include/net/bluetooth/hci_sync.h | 2 ++ net/bluetooth/hci_sync.c | 3 +-- net/bluetooth/mgmt.c | 38 +++++++++++++++++++++++++++++--- 3 files changed, 38 insertions(+), 5 deletions(-)
diff --git a/include/net/bluetooth/hci_sync.h b/include/net/bluetooth/hci_sync.h index 2492e3b46a8f..544e949b5dbf 100644 --- a/include/net/bluetooth/hci_sync.h +++ b/include/net/bluetooth/hci_sync.h @@ -105,4 +105,6 @@ int hci_resume_sync(struct hci_dev *hdev);
struct hci_conn;
+int hci_abort_conn_sync(struct hci_dev *hdev, struct hci_conn *conn, u8 reason); + int hci_le_create_conn_sync(struct hci_dev *hdev, struct hci_conn *conn); diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c index 9a3a7cc01345..ce7573182e81 100644 --- a/net/bluetooth/hci_sync.c +++ b/net/bluetooth/hci_sync.c @@ -4432,8 +4432,7 @@ static int hci_reject_conn_sync(struct hci_dev *hdev, struct hci_conn *conn, sizeof(cp), &cp, HCI_CMD_TIMEOUT); }
-static int hci_abort_conn_sync(struct hci_dev *hdev, struct hci_conn *conn, - u8 reason) +int hci_abort_conn_sync(struct hci_dev *hdev, struct hci_conn *conn, u8 reason) { int err;
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 2f91a8c2b678..c003a17d8814 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -2528,6 +2528,37 @@ static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr, skip_sk); }
+static void unpair_device_complete(struct hci_dev *hdev, void *data, int err) +{ + struct mgmt_pending_cmd *cmd = data; + struct mgmt_cp_unpair_device *cp = cmd->param; + + if (!err) + device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk); + + cmd->cmd_complete(cmd, err); + mgmt_pending_free(cmd); +} + +static int unpair_device_sync(struct hci_dev *hdev, void *data) +{ + struct mgmt_pending_cmd *cmd = data; + struct mgmt_cp_unpair_device *cp = cmd->param; + struct hci_conn *conn; + + if (cp->addr.type == BDADDR_BREDR) + conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, + &cp->addr.bdaddr); + else + conn = hci_conn_hash_lookup_le(hdev, &cp->addr.bdaddr, + le_addr_type(cp->addr.type)); + + if (!conn) + return 0; + + return hci_abort_conn_sync(hdev, conn, HCI_ERROR_REMOTE_USER_TERM); +} + static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) { @@ -2638,7 +2669,7 @@ static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data, goto unlock; }
- cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp, + cmd = mgmt_pending_new(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp, sizeof(*cp)); if (!cmd) { err = -ENOMEM; @@ -2647,9 +2678,10 @@ static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
cmd->cmd_complete = addr_cmd_complete;
- err = hci_abort_conn(conn, HCI_ERROR_REMOTE_USER_TERM); + err = hci_cmd_sync_queue(hdev, unpair_device_sync, cmd, + unpair_device_complete); if (err < 0) - mgmt_pending_remove(cmd); + mgmt_pending_free(cmd);
unlock: hci_dev_unlock(hdev);
From: Jie2x Zhou jie2x.zhou@intel.com
[ Upstream commit f664f9c6b4a1bb9a10af812df0fbbf6aac28fcc6 ]
Before change:
selftests: bpf: test_xdp_veth.sh Couldn't retrieve pinned program '/sys/fs/bpf/test_xdp_veth/progs/redirect_map_0': No such file or directory selftests: xdp_veth [SKIP] ok 20 selftests: bpf: test_xdp_veth.sh # SKIP
After change:
PING 10.1.1.33 (10.1.1.33) 56(84) bytes of data. 64 bytes from 10.1.1.33: icmp_seq=1 ttl=64 time=0.320 ms --- 10.1.1.33 ping statistics --- 1 packets transmitted, 1 received, 0% packet loss, time 0ms rtt min/avg/max/mdev = 0.320/0.320/0.320/0.000 ms selftests: xdp_veth [PASS]
For the test case, the following can be found:
ls /sys/fs/bpf/test_xdp_veth/progs/redirect_map_0 ls: cannot access '/sys/fs/bpf/test_xdp_veth/progs/redirect_map_0': No such file or directory ls /sys/fs/bpf/test_xdp_veth/progs/ xdp_redirect_map_0 xdp_redirect_map_1 xdp_redirect_map_2
Reported-by: kernel test robot lkp@intel.com Signed-off-by: Jie2x Zhou jie2x.zhou@intel.com Signed-off-by: Daniel Borkmann daniel@iogearbox.net Link: https://lore.kernel.org/bpf/20220719082430.9916-1-jie2x.zhou@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- tools/testing/selftests/bpf/test_xdp_veth.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/tools/testing/selftests/bpf/test_xdp_veth.sh b/tools/testing/selftests/bpf/test_xdp_veth.sh index 392d28cc4e58..49936c4c8567 100755 --- a/tools/testing/selftests/bpf/test_xdp_veth.sh +++ b/tools/testing/selftests/bpf/test_xdp_veth.sh @@ -106,9 +106,9 @@ bpftool prog loadall \ bpftool map update pinned $BPF_DIR/maps/tx_port key 0 0 0 0 value 122 0 0 0 bpftool map update pinned $BPF_DIR/maps/tx_port key 1 0 0 0 value 133 0 0 0 bpftool map update pinned $BPF_DIR/maps/tx_port key 2 0 0 0 value 111 0 0 0 -ip link set dev veth1 xdp pinned $BPF_DIR/progs/redirect_map_0 -ip link set dev veth2 xdp pinned $BPF_DIR/progs/redirect_map_1 -ip link set dev veth3 xdp pinned $BPF_DIR/progs/redirect_map_2 +ip link set dev veth1 xdp pinned $BPF_DIR/progs/xdp_redirect_map_0 +ip link set dev veth2 xdp pinned $BPF_DIR/progs/xdp_redirect_map_1 +ip link set dev veth3 xdp pinned $BPF_DIR/progs/xdp_redirect_map_2
ip -n ${NS1} link set dev veth11 xdp obj xdp_dummy.o sec xdp ip -n ${NS2} link set dev veth22 xdp obj xdp_tx.o sec xdp
From: Philip Yang Philip.Yang@amd.com
[ Upstream commit 0593ad215359d51514c1e6c81ce28ea598efed6b ]
If process has signal pending, mmu_notifier_get_locked fails and calls ops->free_notifier, kfd_process_free_notifier will schedule kfd_process_wq_release as process refcount is 1, but process structure is already freed. This use after free bug causes system crash with different backtrace.
The fix is to increase process refcount and then decrease the refcount after mmu_notifier_get success.
Signed-off-by: Philip Yang Philip.Yang@amd.com Reviewed-by: Felix Kuehling Felix.Kuehling@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/amd/amdkfd/kfd_process.c | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c index e3d64ec8c353..b8b185e242d3 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c @@ -1404,6 +1404,11 @@ static struct kfd_process *create_process(const struct task_struct *thread) hash_add_rcu(kfd_processes_table, &process->kfd_processes, (uintptr_t)process->mm);
+ /* Avoid free_notifier to start kfd_process_wq_release if + * mmu_notifier_get failed because of pending signal. + */ + kref_get(&process->ref); + /* MMU notifier registration must be the last call that can fail * because after this point we cannot unwind the process creation. * After this point, mmu_notifier_put will trigger the cleanup by @@ -1416,6 +1421,7 @@ static struct kfd_process *create_process(const struct task_struct *thread) } BUG_ON(mn != &process->mmu_notifier);
+ kfd_unref_process(process); get_task_struct(process->lead_thread);
return process;
From: Philip Yang Philip.Yang@amd.com
[ Upstream commit 74097f9fd2f5ebdae04fcba59da345386415cbf3 ]
Move process queues cleanup to deferred work kfd_process_wq_release, to avoid potential deadlock circular locking warning:
WARNING: possible circular locking dependency detected the existing dependency chain (in reverse order) is: -> #2 ((work_completion)(&svms->deferred_list_work)){+.+.}-{0:0}: __flush_work+0x343/0x4a0 svm_range_list_lock_and_flush_work+0x39/0xc0 svm_range_set_attr+0xe8/0x1080 [amdgpu] kfd_ioctl+0x19b/0x600 [amdgpu] __x64_sys_ioctl+0x81/0xb0 do_syscall_64+0x34/0x80 entry_SYSCALL_64_after_hwframe+0x44/0xae
-> #1 (&info->lock#2){+.+.}-{3:3}: __mutex_lock+0xa4/0x940 amdgpu_amdkfd_gpuvm_acquire_process_vm+0x2e3/0x590 kfd_process_device_init_vm+0x61/0x200 [amdgpu] kfd_ioctl_acquire_vm+0x83/0xb0 [amdgpu] kfd_ioctl+0x19b/0x600 [amdgpu] __x64_sys_ioctl+0x81/0xb0 do_syscall_64+0x34/0x80 entry_SYSCALL_64_after_hwframe+0x44/0xae
-> #0 (&process->mutex){+.+.}-{3:3}: __lock_acquire+0x1365/0x23d0 lock_acquire+0xc9/0x2e0 __mutex_lock+0xa4/0x940 kfd_process_notifier_release+0x96/0xe0 [amdgpu] __mmu_notifier_release+0x94/0x210 exit_mmap+0x35/0x1f0 mmput+0x63/0x120 svm_range_deferred_list_work+0x177/0x2c0 [amdgpu] process_one_work+0x2a4/0x600 worker_thread+0x39/0x3e0 kthread+0x16d/0x1a0
Possible unsafe locking scenario:
CPU0 CPU1 ---- ---- lock((work_completion)(&svms->deferred_list_work)); lock(&info->lock#2); lock((work_completion)(&svms->deferred_list_work)); lock(&process->mutex);
Signed-off-by: Philip Yang Philip.Yang@amd.com Reviewed-by: Felix Kuehling Felix.Kuehling@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/amd/amdkfd/kfd_process.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c index b8b185e242d3..9ad293fb95af 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c @@ -1114,6 +1114,15 @@ static void kfd_process_wq_release(struct work_struct *work) struct kfd_process *p = container_of(work, struct kfd_process, release_work);
+ kfd_process_dequeue_from_all_devices(p); + pqm_uninit(&p->pqm); + + /* Signal the eviction fence after user mode queues are + * destroyed. This allows any BOs to be freed without + * triggering pointless evictions or waiting for fences. + */ + dma_fence_signal(p->ef); + kfd_process_remove_sysfs(p); kfd_iommu_unbind_process(p);
@@ -1178,20 +1187,8 @@ static void kfd_process_notifier_release(struct mmu_notifier *mn, cancel_delayed_work_sync(&p->eviction_work); cancel_delayed_work_sync(&p->restore_work);
- mutex_lock(&p->mutex); - - kfd_process_dequeue_from_all_devices(p); - pqm_uninit(&p->pqm); - /* Indicate to other users that MM is no longer valid */ p->mm = NULL; - /* Signal the eviction fence after user mode queues are - * destroyed. This allows any BOs to be freed without - * triggering pointless evictions or waiting for fences. - */ - dma_fence_signal(p->ef); - - mutex_unlock(&p->mutex);
mmu_notifier_put(&p->mmu_notifier); }
From: Qu Wenruo wqu@suse.com
[ Upstream commit 8f0ed7d4e7bd87c9207a59d6d887777f632a5ed5 ]
When handling a real world transid mismatch image, it's hard to know which copy is corrupted, as the error messages just look like this:
BTRFS warning (device dm-3): checksum verify failed on 30408704 wanted 0xcdcdcdcd found 0x3c0adc8e level 0 BTRFS warning (device dm-3): checksum verify failed on 30408704 wanted 0xcdcdcdcd found 0x3c0adc8e level 0 BTRFS warning (device dm-3): checksum verify failed on 30408704 wanted 0xcdcdcdcd found 0x3c0adc8e level 0 BTRFS warning (device dm-3): checksum verify failed on 30408704 wanted 0xcdcdcdcd found 0x3c0adc8e level 0
We don't even know if the retry is caused by btrfs or the VFS retry.
To make things a little easier to read, add mirror number for all related tree block read errors.
So the above messages would look like this:
BTRFS warning (device dm-3): checksum verify failed on logical 30408704 mirror 1 wanted 0xcdcdcdcd found 0x3c0adc8e level 0 BTRFS warning (device dm-3): checksum verify failed on logical 30408704 mirror 2 wanted 0xcdcdcdcd found 0x3c0adc8e level 0 BTRFS warning (device dm-3): checksum verify failed on logical 30408704 mirror 1 wanted 0xcdcdcdcd found 0x3c0adc8e level 0 BTRFS warning (device dm-3): checksum verify failed on logical 30408704 mirror 2 wanted 0xcdcdcdcd found 0x3c0adc8e level 0
Signed-off-by: Qu Wenruo wqu@suse.com [ update messages, add "logical" ] Reviewed-by: David Sterba dsterba@suse.com Signed-off-by: David Sterba dsterba@suse.com Signed-off-by: Sasha Levin sashal@kernel.org --- fs/btrfs/disk-io.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-)
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index de440ebf5648..b9f335252113 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -256,8 +256,8 @@ static int verify_parent_transid(struct extent_io_tree *io_tree, goto out; } btrfs_err_rl(eb->fs_info, - "parent transid verify failed on %llu wanted %llu found %llu", - eb->start, +"parent transid verify failed on logical %llu mirror %u wanted %llu found %llu", + eb->start, eb->read_mirror, parent_transid, btrfs_header_generation(eb)); ret = 1; clear_extent_buffer_uptodate(eb); @@ -587,21 +587,23 @@ static int validate_extent_buffer(struct extent_buffer *eb)
found_start = btrfs_header_bytenr(eb); if (found_start != eb->start) { - btrfs_err_rl(fs_info, "bad tree block start, want %llu have %llu", - eb->start, found_start); + btrfs_err_rl(fs_info, + "bad tree block start, mirror %u want %llu have %llu", + eb->read_mirror, eb->start, found_start); ret = -EIO; goto out; } if (check_tree_block_fsid(eb)) { - btrfs_err_rl(fs_info, "bad fsid on block %llu", - eb->start); + btrfs_err_rl(fs_info, "bad fsid on logical %llu mirror %u", + eb->start, eb->read_mirror); ret = -EIO; goto out; } found_level = btrfs_header_level(eb); if (found_level >= BTRFS_MAX_LEVEL) { - btrfs_err(fs_info, "bad tree block level %d on %llu", - (int)btrfs_header_level(eb), eb->start); + btrfs_err(fs_info, + "bad tree block level, mirror %u level %d on logical %llu", + eb->read_mirror, btrfs_header_level(eb), eb->start); ret = -EIO; goto out; } @@ -612,8 +614,8 @@ static int validate_extent_buffer(struct extent_buffer *eb)
if (memcmp(result, header_csum, csum_size) != 0) { btrfs_warn_rl(fs_info, - "checksum verify failed on %llu wanted " CSUM_FMT " found " CSUM_FMT " level %d", - eb->start, +"checksum verify failed on logical %llu mirror %u wanted " CSUM_FMT " found " CSUM_FMT " level %d", + eb->start, eb->read_mirror, CSUM_FMT_VALUE(csum_size, header_csum), CSUM_FMT_VALUE(csum_size, result), btrfs_header_level(eb)); @@ -638,8 +640,8 @@ static int validate_extent_buffer(struct extent_buffer *eb) set_extent_buffer_uptodate(eb); else btrfs_err(fs_info, - "block=%llu read time tree block corruption detected", - eb->start); + "read time tree block corruption detected on logical %llu mirror %u", + eb->start, eb->read_mirror); out: return ret; }
From: Christoph Hellwig hch@lst.de
[ Upstream commit c144c63fd33a1fc0e43e0b851a35b09c9460d94d ]
When there is more than a single level of redundancy there can also be multiple bad mirrors, and the current read repair code only repairs the last bad one.
Restructure btrfs_repair_one_sector so that it records the originally failed mirror and the number of copies, and then repair all known bad copies until we reach the originally failed copy in clean_io_failure. Note that this also means the read repair reads will always start from the next bad mirror and not mirror 0.
This fixes btrfs/265 in xfstests.
Reviewed-by: Nikolay Borisov nborisov@suse.com Signed-off-by: Christoph Hellwig hch@lst.de Reviewed-by: David Sterba dsterba@suse.com Signed-off-by: David Sterba dsterba@suse.com Signed-off-by: Sasha Levin sashal@kernel.org --- fs/btrfs/extent_io.c | 126 +++++++++++++++++++++---------------------- fs/btrfs/extent_io.h | 1 + 2 files changed, 61 insertions(+), 66 deletions(-)
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index f03ab5dbda7a..48fff4801eb7 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -2418,6 +2418,20 @@ int btrfs_repair_eb_io_failure(const struct extent_buffer *eb, int mirror_num) return ret; }
+static int next_mirror(const struct io_failure_record *failrec, int cur_mirror) +{ + if (cur_mirror == failrec->num_copies) + return cur_mirror + 1 - failrec->num_copies; + return cur_mirror + 1; +} + +static int prev_mirror(const struct io_failure_record *failrec, int cur_mirror) +{ + if (cur_mirror == 1) + return failrec->num_copies; + return cur_mirror - 1; +} + /* * each time an IO finishes, we do a fast check in the IO failure tree * to see if we need to process or clean up an io_failure_record @@ -2430,7 +2444,7 @@ int clean_io_failure(struct btrfs_fs_info *fs_info, u64 private; struct io_failure_record *failrec; struct extent_state *state; - int num_copies; + int mirror; int ret;
private = 0; @@ -2454,20 +2468,19 @@ int clean_io_failure(struct btrfs_fs_info *fs_info, EXTENT_LOCKED); spin_unlock(&io_tree->lock);
- if (state && state->start <= failrec->start && - state->end >= failrec->start + failrec->len - 1) { - num_copies = btrfs_num_copies(fs_info, failrec->logical, - failrec->len); - if (num_copies > 1) { - repair_io_failure(fs_info, ino, start, failrec->len, - failrec->logical, page, pg_offset, - failrec->failed_mirror); - } - } + if (!state || state->start > failrec->start || + state->end < failrec->start + failrec->len - 1) + goto out; + + mirror = failrec->this_mirror; + do { + mirror = prev_mirror(failrec, mirror); + repair_io_failure(fs_info, ino, start, failrec->len, + failrec->logical, page, pg_offset, mirror); + } while (mirror != failrec->failed_mirror);
out: free_io_failure(failure_tree, io_tree, failrec); - return 0; }
@@ -2506,7 +2519,8 @@ void btrfs_free_io_failure_record(struct btrfs_inode *inode, u64 start, u64 end) }
static struct io_failure_record *btrfs_get_io_failure_record(struct inode *inode, - u64 start) + u64 start, + int failed_mirror) { struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); struct io_failure_record *failrec; @@ -2528,7 +2542,8 @@ static struct io_failure_record *btrfs_get_io_failure_record(struct inode *inode * (e.g. with a list for failed_mirror) to make * clean_io_failure() clean all those errors at once. */ - + ASSERT(failrec->this_mirror == failed_mirror); + ASSERT(failrec->len == fs_info->sectorsize); return failrec; }
@@ -2538,7 +2553,8 @@ static struct io_failure_record *btrfs_get_io_failure_record(struct inode *inode
failrec->start = start; failrec->len = sectorsize; - failrec->this_mirror = 0; + failrec->failed_mirror = failed_mirror; + failrec->this_mirror = failed_mirror; failrec->compress_type = BTRFS_COMPRESS_NONE;
read_lock(&em_tree->lock); @@ -2573,6 +2589,20 @@ static struct io_failure_record *btrfs_get_io_failure_record(struct inode *inode failrec->logical = logical; free_extent_map(em);
+ failrec->num_copies = btrfs_num_copies(fs_info, logical, sectorsize); + if (failrec->num_copies == 1) { + /* + * We only have a single copy of the data, so don't bother with + * all the retry and error correction code that follows. No + * matter what the error is, it is very likely to persist. + */ + btrfs_debug(fs_info, + "cannot repair logical %llu num_copies %d", + failrec->logical, failrec->num_copies); + kfree(failrec); + return ERR_PTR(-EIO); + } + /* Set the bits in the private failure tree */ ret = set_extent_bits(failure_tree, start, start + sectorsize - 1, EXTENT_LOCKED | EXTENT_DIRTY); @@ -2589,54 +2619,6 @@ static struct io_failure_record *btrfs_get_io_failure_record(struct inode *inode return failrec; }
-static bool btrfs_check_repairable(struct inode *inode, - struct io_failure_record *failrec, - int failed_mirror) -{ - struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); - int num_copies; - - num_copies = btrfs_num_copies(fs_info, failrec->logical, failrec->len); - if (num_copies == 1) { - /* - * we only have a single copy of the data, so don't bother with - * all the retry and error correction code that follows. no - * matter what the error is, it is very likely to persist. - */ - btrfs_debug(fs_info, - "Check Repairable: cannot repair, num_copies=%d, next_mirror %d, failed_mirror %d", - num_copies, failrec->this_mirror, failed_mirror); - return false; - } - - /* The failure record should only contain one sector */ - ASSERT(failrec->len == fs_info->sectorsize); - - /* - * There are two premises: - * a) deliver good data to the caller - * b) correct the bad sectors on disk - * - * Since we're only doing repair for one sector, we only need to get - * a good copy of the failed sector and if we succeed, we have setup - * everything for repair_io_failure to do the rest for us. - */ - ASSERT(failed_mirror); - failrec->failed_mirror = failed_mirror; - failrec->this_mirror++; - if (failrec->this_mirror == failed_mirror) - failrec->this_mirror++; - - if (failrec->this_mirror > num_copies) { - btrfs_debug(fs_info, - "Check Repairable: (fail) num_copies=%d, next_mirror %d, failed_mirror %d", - num_copies, failrec->this_mirror, failed_mirror); - return false; - } - - return true; -} - int btrfs_repair_one_sector(struct inode *inode, struct bio *failed_bio, u32 bio_offset, struct page *page, unsigned int pgoff, @@ -2657,12 +2639,24 @@ int btrfs_repair_one_sector(struct inode *inode,
BUG_ON(bio_op(failed_bio) == REQ_OP_WRITE);
- failrec = btrfs_get_io_failure_record(inode, start); + failrec = btrfs_get_io_failure_record(inode, start, failed_mirror); if (IS_ERR(failrec)) return PTR_ERR(failrec);
- - if (!btrfs_check_repairable(inode, failrec, failed_mirror)) { + /* + * There are two premises: + * a) deliver good data to the caller + * b) correct the bad sectors on disk + * + * Since we're only doing repair for one sector, we only need to get + * a good copy of the failed sector and if we succeed, we have setup + * everything for repair_io_failure to do the rest for us. + */ + failrec->this_mirror = next_mirror(failrec, failrec->this_mirror); + if (failrec->this_mirror == failrec->failed_mirror) { + btrfs_debug(fs_info, + "failed to repair num_copies %d this_mirror %d failed_mirror %d", + failrec->num_copies, failrec->this_mirror, failrec->failed_mirror); free_io_failure(failure_tree, tree, failrec); return -EIO; } diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h index 23d4103c8831..acee497bab7b 100644 --- a/fs/btrfs/extent_io.h +++ b/fs/btrfs/extent_io.h @@ -269,6 +269,7 @@ struct io_failure_record { enum btrfs_compression_type compress_type; int this_mirror; int failed_mirror; + int num_copies; };
int btrfs_repair_one_sector(struct inode *inode,
From: Christian Marangi ansuelsmth@gmail.com
[ Upstream commit 7028471edb646bfc532fec0973e50e784cdcb7c6 ]
Disable all queues and disconnect before tx_disable in stmmac_release to prevent a corner case where packet may be still queued at the same time tx_disable is called resulting in kernel panic if some packet still has to be processed.
Signed-off-by: Christian Marangi ansuelsmth@gmail.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 306f03399f5e..db2098cbe1fe 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -3764,8 +3764,6 @@ static int stmmac_release(struct net_device *dev) struct stmmac_priv *priv = netdev_priv(dev); u32 chan;
- netif_tx_disable(dev); - if (device_may_wakeup(priv->device)) phylink_speed_down(priv->phylink, false); /* Stop and disconnect the PHY */ @@ -3777,6 +3775,8 @@ static int stmmac_release(struct net_device *dev) for (chan = 0; chan < priv->plat->tx_queues_to_use; chan++) hrtimer_cancel(&priv->tx_queue[chan].txtimer);
+ netif_tx_disable(dev); + /* Free the IRQ lines */ stmmac_free_irq(dev, REQ_IRQ_ERR_ALL, 0);
From: Jiri Pirko jiri@nvidia.com
[ Upstream commit 30bab7cdb56da4819ff081ad658646f2df16c098 ]
Remove dependency on devlink_mutex during devlinks xarray iteration.
The reason is that devlink_register/unregister() functions taking devlink_mutex would deadlock during devlink reload operation of devlink instance which registers/unregisters nested devlink instances.
The devlinks xarray consistency is ensured internally by xarray. There is a reference taken when working with devlink using devlink_try_get(). But there is no guarantee that devlink pointer picked during xarray iteration is not freed before devlink_try_get() is called.
Make sure that devlink_try_get() works with valid pointer. Achieve it by: 1) Splitting devlink_put() so the completion is sent only after grace period. Completion unblocks the devlink_unregister() routine, which is followed-up by devlink_free() 2) During devlinks xa_array iteration, get devlink pointer from xa_array holding RCU read lock and taking reference using devlink_try_get() before unlock.
Signed-off-by: Jiri Pirko jiri@nvidia.com Reviewed-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- net/core/devlink.c | 171 +++++++++++++++++++++------------------------ 1 file changed, 80 insertions(+), 91 deletions(-)
diff --git a/net/core/devlink.c b/net/core/devlink.c index e4c19692c792..47ba3e255f14 100644 --- a/net/core/devlink.c +++ b/net/core/devlink.c @@ -70,6 +70,7 @@ struct devlink { u8 reload_failed:1; refcount_t refcount; struct completion comp; + struct rcu_head rcu; char priv[] __aligned(NETDEV_ALIGN); };
@@ -221,8 +222,6 @@ static DEFINE_XARRAY_FLAGS(devlinks, XA_FLAGS_ALLOC); /* devlink_mutex * * An overall lock guarding every operation coming from userspace. - * It also guards devlink devices list and it is taken when - * driver registers/unregisters it. */ static DEFINE_MUTEX(devlink_mutex);
@@ -232,10 +231,21 @@ struct net *devlink_net(const struct devlink *devlink) } EXPORT_SYMBOL_GPL(devlink_net);
+static void __devlink_put_rcu(struct rcu_head *head) +{ + struct devlink *devlink = container_of(head, struct devlink, rcu); + + complete(&devlink->comp); +} + void devlink_put(struct devlink *devlink) { if (refcount_dec_and_test(&devlink->refcount)) - complete(&devlink->comp); + /* Make sure unregister operation that may await the completion + * is unblocked only after all users are after the end of + * RCU grace period. + */ + call_rcu(&devlink->rcu, __devlink_put_rcu); }
struct devlink *__must_check devlink_try_get(struct devlink *devlink) @@ -272,12 +282,55 @@ void devl_unlock(struct devlink *devlink) } EXPORT_SYMBOL_GPL(devl_unlock);
+static struct devlink * +devlinks_xa_find_get(unsigned long *indexp, xa_mark_t filter, + void * (*xa_find_fn)(struct xarray *, unsigned long *, + unsigned long, xa_mark_t)) +{ + struct devlink *devlink; + + rcu_read_lock(); +retry: + devlink = xa_find_fn(&devlinks, indexp, ULONG_MAX, DEVLINK_REGISTERED); + if (!devlink) + goto unlock; + /* For a possible retry, the xa_find_after() should be always used */ + xa_find_fn = xa_find_after; + if (!devlink_try_get(devlink)) + goto retry; +unlock: + rcu_read_unlock(); + return devlink; +} + +static struct devlink *devlinks_xa_find_get_first(unsigned long *indexp, + xa_mark_t filter) +{ + return devlinks_xa_find_get(indexp, filter, xa_find); +} + +static struct devlink *devlinks_xa_find_get_next(unsigned long *indexp, + xa_mark_t filter) +{ + return devlinks_xa_find_get(indexp, filter, xa_find_after); +} + +/* Iterate over devlink pointers which were possible to get reference to. + * devlink_put() needs to be called for each iterated devlink pointer + * in loop body in order to release the reference. + */ +#define devlinks_xa_for_each_get(index, devlink, filter) \ + for (index = 0, devlink = devlinks_xa_find_get_first(&index, filter); \ + devlink; devlink = devlinks_xa_find_get_next(&index, filter)) + +#define devlinks_xa_for_each_registered_get(index, devlink) \ + devlinks_xa_for_each_get(index, devlink, DEVLINK_REGISTERED) + static struct devlink *devlink_get_from_attrs(struct net *net, struct nlattr **attrs) { struct devlink *devlink; unsigned long index; - bool found = false; char *busname; char *devname;
@@ -287,21 +340,15 @@ static struct devlink *devlink_get_from_attrs(struct net *net, busname = nla_data(attrs[DEVLINK_ATTR_BUS_NAME]); devname = nla_data(attrs[DEVLINK_ATTR_DEV_NAME]);
- lockdep_assert_held(&devlink_mutex); - - xa_for_each_marked(&devlinks, index, devlink, DEVLINK_REGISTERED) { + devlinks_xa_for_each_registered_get(index, devlink) { if (strcmp(devlink->dev->bus->name, busname) == 0 && strcmp(dev_name(devlink->dev), devname) == 0 && - net_eq(devlink_net(devlink), net)) { - found = true; - break; - } + net_eq(devlink_net(devlink), net)) + return devlink; + devlink_put(devlink); }
- if (!found || !devlink_try_get(devlink)) - devlink = ERR_PTR(-ENODEV); - - return devlink; + return ERR_PTR(-ENODEV); }
static struct devlink_port *devlink_port_get_by_index(struct devlink *devlink, @@ -1323,10 +1370,7 @@ static int devlink_nl_cmd_rate_get_dumpit(struct sk_buff *msg, int err = 0;
mutex_lock(&devlink_mutex); - xa_for_each_marked(&devlinks, index, devlink, DEVLINK_REGISTERED) { - if (!devlink_try_get(devlink)) - continue; - + devlinks_xa_for_each_registered_get(index, devlink) { if (!net_eq(devlink_net(devlink), sock_net(msg->sk))) goto retry;
@@ -1426,10 +1470,7 @@ static int devlink_nl_cmd_get_dumpit(struct sk_buff *msg, int err;
mutex_lock(&devlink_mutex); - xa_for_each_marked(&devlinks, index, devlink, DEVLINK_REGISTERED) { - if (!devlink_try_get(devlink)) - continue; - + devlinks_xa_for_each_registered_get(index, devlink) { if (!net_eq(devlink_net(devlink), sock_net(msg->sk))) { devlink_put(devlink); continue; @@ -1489,10 +1530,7 @@ static int devlink_nl_cmd_port_get_dumpit(struct sk_buff *msg, int err;
mutex_lock(&devlink_mutex); - xa_for_each_marked(&devlinks, index, devlink, DEVLINK_REGISTERED) { - if (!devlink_try_get(devlink)) - continue; - + devlinks_xa_for_each_registered_get(index, devlink) { if (!net_eq(devlink_net(devlink), sock_net(msg->sk))) goto retry;
@@ -2174,10 +2212,7 @@ static int devlink_nl_cmd_linecard_get_dumpit(struct sk_buff *msg, int err;
mutex_lock(&devlink_mutex); - xa_for_each_marked(&devlinks, index, devlink, DEVLINK_REGISTERED) { - if (!devlink_try_get(devlink)) - continue; - + devlinks_xa_for_each_registered_get(index, devlink) { if (!net_eq(devlink_net(devlink), sock_net(msg->sk))) goto retry;
@@ -2446,10 +2481,7 @@ static int devlink_nl_cmd_sb_get_dumpit(struct sk_buff *msg, int err;
mutex_lock(&devlink_mutex); - xa_for_each_marked(&devlinks, index, devlink, DEVLINK_REGISTERED) { - if (!devlink_try_get(devlink)) - continue; - + devlinks_xa_for_each_registered_get(index, devlink) { if (!net_eq(devlink_net(devlink), sock_net(msg->sk))) goto retry;
@@ -2598,10 +2630,7 @@ static int devlink_nl_cmd_sb_pool_get_dumpit(struct sk_buff *msg, int err = 0;
mutex_lock(&devlink_mutex); - xa_for_each_marked(&devlinks, index, devlink, DEVLINK_REGISTERED) { - if (!devlink_try_get(devlink)) - continue; - + devlinks_xa_for_each_registered_get(index, devlink) { if (!net_eq(devlink_net(devlink), sock_net(msg->sk)) || !devlink->ops->sb_pool_get) goto retry; @@ -2819,10 +2848,7 @@ static int devlink_nl_cmd_sb_port_pool_get_dumpit(struct sk_buff *msg, int err = 0;
mutex_lock(&devlink_mutex); - xa_for_each_marked(&devlinks, index, devlink, DEVLINK_REGISTERED) { - if (!devlink_try_get(devlink)) - continue; - + devlinks_xa_for_each_registered_get(index, devlink) { if (!net_eq(devlink_net(devlink), sock_net(msg->sk)) || !devlink->ops->sb_port_pool_get) goto retry; @@ -3068,10 +3094,7 @@ devlink_nl_cmd_sb_tc_pool_bind_get_dumpit(struct sk_buff *msg, int err = 0;
mutex_lock(&devlink_mutex); - xa_for_each_marked(&devlinks, index, devlink, DEVLINK_REGISTERED) { - if (!devlink_try_get(devlink)) - continue; - + devlinks_xa_for_each_registered_get(index, devlink) { if (!net_eq(devlink_net(devlink), sock_net(msg->sk)) || !devlink->ops->sb_tc_pool_bind_get) goto retry; @@ -5155,10 +5178,7 @@ static int devlink_nl_cmd_param_get_dumpit(struct sk_buff *msg, int err = 0;
mutex_lock(&devlink_mutex); - xa_for_each_marked(&devlinks, index, devlink, DEVLINK_REGISTERED) { - if (!devlink_try_get(devlink)) - continue; - + devlinks_xa_for_each_registered_get(index, devlink) { if (!net_eq(devlink_net(devlink), sock_net(msg->sk))) goto retry;
@@ -5390,10 +5410,7 @@ static int devlink_nl_cmd_port_param_get_dumpit(struct sk_buff *msg, int err = 0;
mutex_lock(&devlink_mutex); - xa_for_each_marked(&devlinks, index, devlink, DEVLINK_REGISTERED) { - if (!devlink_try_get(devlink)) - continue; - + devlinks_xa_for_each_registered_get(index, devlink) { if (!net_eq(devlink_net(devlink), sock_net(msg->sk))) goto retry;
@@ -5974,10 +5991,7 @@ static int devlink_nl_cmd_region_get_dumpit(struct sk_buff *msg, int err = 0;
mutex_lock(&devlink_mutex); - xa_for_each_marked(&devlinks, index, devlink, DEVLINK_REGISTERED) { - if (!devlink_try_get(devlink)) - continue; - + devlinks_xa_for_each_registered_get(index, devlink) { if (!net_eq(devlink_net(devlink), sock_net(msg->sk))) goto retry;
@@ -6508,10 +6522,7 @@ static int devlink_nl_cmd_info_get_dumpit(struct sk_buff *msg, int err = 0;
mutex_lock(&devlink_mutex); - xa_for_each_marked(&devlinks, index, devlink, DEVLINK_REGISTERED) { - if (!devlink_try_get(devlink)) - continue; - + devlinks_xa_for_each_registered_get(index, devlink) { if (!net_eq(devlink_net(devlink), sock_net(msg->sk))) goto retry;
@@ -7688,10 +7699,7 @@ devlink_nl_cmd_health_reporter_get_dumpit(struct sk_buff *msg, int err;
mutex_lock(&devlink_mutex); - xa_for_each_marked(&devlinks, index, devlink, DEVLINK_REGISTERED) { - if (!devlink_try_get(devlink)) - continue; - + devlinks_xa_for_each_registered_get(index, devlink) { if (!net_eq(devlink_net(devlink), sock_net(msg->sk))) goto retry_rep;
@@ -7718,10 +7726,7 @@ devlink_nl_cmd_health_reporter_get_dumpit(struct sk_buff *msg, devlink_put(devlink); }
- xa_for_each_marked(&devlinks, index, devlink, DEVLINK_REGISTERED) { - if (!devlink_try_get(devlink)) - continue; - + devlinks_xa_for_each_registered_get(index, devlink) { if (!net_eq(devlink_net(devlink), sock_net(msg->sk))) goto retry_port;
@@ -8284,10 +8289,7 @@ static int devlink_nl_cmd_trap_get_dumpit(struct sk_buff *msg, int err;
mutex_lock(&devlink_mutex); - xa_for_each_marked(&devlinks, index, devlink, DEVLINK_REGISTERED) { - if (!devlink_try_get(devlink)) - continue; - + devlinks_xa_for_each_registered_get(index, devlink) { if (!net_eq(devlink_net(devlink), sock_net(msg->sk))) goto retry;
@@ -8511,10 +8513,7 @@ static int devlink_nl_cmd_trap_group_get_dumpit(struct sk_buff *msg, int err;
mutex_lock(&devlink_mutex); - xa_for_each_marked(&devlinks, index, devlink, DEVLINK_REGISTERED) { - if (!devlink_try_get(devlink)) - continue; - + devlinks_xa_for_each_registered_get(index, devlink) { if (!net_eq(devlink_net(devlink), sock_net(msg->sk))) goto retry;
@@ -8825,10 +8824,7 @@ static int devlink_nl_cmd_trap_policer_get_dumpit(struct sk_buff *msg, int err;
mutex_lock(&devlink_mutex); - xa_for_each_marked(&devlinks, index, devlink, DEVLINK_REGISTERED) { - if (!devlink_try_get(devlink)) - continue; - + devlinks_xa_for_each_registered_get(index, devlink) { if (!net_eq(devlink_net(devlink), sock_net(msg->sk))) goto retry;
@@ -9584,10 +9580,8 @@ void devlink_register(struct devlink *devlink) ASSERT_DEVLINK_NOT_REGISTERED(devlink); /* Make sure that we are in .probe() routine */
- mutex_lock(&devlink_mutex); xa_set_mark(&devlinks, devlink->index, DEVLINK_REGISTERED); devlink_notify_register(devlink); - mutex_unlock(&devlink_mutex); } EXPORT_SYMBOL_GPL(devlink_register);
@@ -9604,10 +9598,8 @@ void devlink_unregister(struct devlink *devlink) devlink_put(devlink); wait_for_completion(&devlink->comp);
- mutex_lock(&devlink_mutex); devlink_notify_unregister(devlink); xa_clear_mark(&devlinks, devlink->index, DEVLINK_REGISTERED); - mutex_unlock(&devlink_mutex); } EXPORT_SYMBOL_GPL(devlink_unregister);
@@ -12118,10 +12110,7 @@ static void __net_exit devlink_pernet_pre_exit(struct net *net) * all devlink instances from this namespace into init_net. */ mutex_lock(&devlink_mutex); - xa_for_each_marked(&devlinks, index, devlink, DEVLINK_REGISTERED) { - if (!devlink_try_get(devlink)) - continue; - + devlinks_xa_for_each_registered_get(index, devlink) { if (!net_eq(devlink_net(devlink), net)) goto retry;
On Thu, 11 Aug 2022 11:28:20 -0400 Sasha Levin wrote:
Remove dependency on devlink_mutex during devlinks xarray iteration.
Prep for a later patch, please drop.
From: Kalle Valo quic_kvalo@quicinc.com
[ Upstream commit 169ede1f594809d1f0f46d95c071d672dbfc0eb1 ]
This reverts commit ec038c6127fa772d2c5604e329f22371830d5fa6. Tyler reported that on L390 Yoga Thinkpad with QCA6390 the suspend was failing because of this commit.
Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3.6510.9
Link: https://bugzilla.kernel.org/show_bug.cgi?id=215881 Signed-off-by: Kalle Valo quic_kvalo@quicinc.com Link: https://lore.kernel.org/r/20220708164656.29549-1-kvalo@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/wireless/ath/ath11k/core.c | 73 -------------------------- drivers/net/wireless/ath/ath11k/core.h | 4 -- drivers/net/wireless/ath/ath11k/hw.h | 3 -- drivers/net/wireless/ath/ath11k/mac.c | 58 -------------------- drivers/net/wireless/ath/ath11k/mac.h | 2 - drivers/net/wireless/ath/ath11k/wmi.c | 41 --------------- drivers/net/wireless/ath/ath11k/wmi.h | 25 --------- 7 files changed, 206 deletions(-)
diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c index 1e98ff9ff288..79eb035fec8a 100644 --- a/drivers/net/wireless/ath/ath11k/core.c +++ b/drivers/net/wireless/ath/ath11k/core.c @@ -54,9 +54,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = { .target_ce_count = 11, .svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_ipq8074, .svc_to_ce_map_len = 21, - .rfkill_pin = 0, - .rfkill_cfg = 0, - .rfkill_on_level = 0, .single_pdev_only = false, .rxdma1_enable = true, .num_rxmda_per_pdev = 1, @@ -133,9 +130,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = { .target_ce_count = 11, .svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_ipq6018, .svc_to_ce_map_len = 19, - .rfkill_pin = 0, - .rfkill_cfg = 0, - .rfkill_on_level = 0, .single_pdev_only = false, .rxdma1_enable = true, .num_rxmda_per_pdev = 1, @@ -209,9 +203,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = { .target_ce_count = 9, .svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_qca6390, .svc_to_ce_map_len = 14, - .rfkill_pin = 48, - .rfkill_cfg = 0, - .rfkill_on_level = 1, .single_pdev_only = true, .rxdma1_enable = false, .num_rxmda_per_pdev = 2, @@ -284,9 +275,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = { .target_ce_count = 9, .svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_qcn9074, .svc_to_ce_map_len = 18, - .rfkill_pin = 0, - .rfkill_cfg = 0, - .rfkill_on_level = 0, .rxdma1_enable = true, .num_rxmda_per_pdev = 1, .rx_mac_buf_ring = false, @@ -359,9 +347,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = { .target_ce_count = 9, .svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_qca6390, .svc_to_ce_map_len = 14, - .rfkill_pin = 0, - .rfkill_cfg = 0, - .rfkill_on_level = 0, .single_pdev_only = true, .rxdma1_enable = false, .num_rxmda_per_pdev = 2, @@ -434,9 +419,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = { .target_ce_count = 9, .svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_qca6390, .svc_to_ce_map_len = 14, - .rfkill_pin = 0, - .rfkill_cfg = 0, - .rfkill_on_level = 0, .single_pdev_only = true, .rxdma1_enable = false, .num_rxmda_per_pdev = 2, @@ -508,9 +490,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = { .target_ce_count = 9, .svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_qca6390, .svc_to_ce_map_len = 14, - .rfkill_pin = 0, - .rfkill_cfg = 0, - .rfkill_on_level = 0, .single_pdev_only = true, .rxdma1_enable = false, .num_rxmda_per_pdev = 1, @@ -1402,27 +1381,6 @@ static int ath11k_core_start_firmware(struct ath11k_base *ab, return ret; }
-static int ath11k_core_rfkill_config(struct ath11k_base *ab) -{ - struct ath11k *ar; - int ret = 0, i; - - if (!(ab->target_caps.sys_cap_info & WMI_SYS_CAP_INFO_RFKILL)) - return 0; - - for (i = 0; i < ab->num_radios; i++) { - ar = ab->pdevs[i].ar; - - ret = ath11k_mac_rfkill_config(ar); - if (ret && ret != -EOPNOTSUPP) { - ath11k_warn(ab, "failed to configure rfkill: %d", ret); - return ret; - } - } - - return ret; -} - int ath11k_core_qmi_firmware_ready(struct ath11k_base *ab) { int ret; @@ -1475,13 +1433,6 @@ int ath11k_core_qmi_firmware_ready(struct ath11k_base *ab) goto err_core_stop; } ath11k_hif_irq_enable(ab); - - ret = ath11k_core_rfkill_config(ab); - if (ret && ret != -EOPNOTSUPP) { - ath11k_err(ab, "failed to config rfkill: %d\n", ret); - goto err_core_stop; - } - mutex_unlock(&ab->core_lock);
return 0; @@ -1550,7 +1501,6 @@ void ath11k_core_halt(struct ath11k *ar) cancel_delayed_work_sync(&ar->scan.timeout); cancel_work_sync(&ar->regd_update_work); cancel_work_sync(&ab->update_11d_work); - cancel_work_sync(&ab->rfkill_work);
rcu_assign_pointer(ab->pdevs_active[ar->pdev_idx], NULL); synchronize_rcu(); @@ -1558,28 +1508,6 @@ void ath11k_core_halt(struct ath11k *ar) idr_init(&ar->txmgmt_idr); }
-static void ath11k_rfkill_work(struct work_struct *work) -{ - struct ath11k_base *ab = container_of(work, struct ath11k_base, rfkill_work); - struct ath11k *ar; - bool rfkill_radio_on; - int i; - - spin_lock_bh(&ab->base_lock); - rfkill_radio_on = ab->rfkill_radio_on; - spin_unlock_bh(&ab->base_lock); - - for (i = 0; i < ab->num_radios; i++) { - ar = ab->pdevs[i].ar; - if (!ar) - continue; - - /* notify cfg80211 radio state change */ - ath11k_mac_rfkill_enable_radio(ar, rfkill_radio_on); - wiphy_rfkill_set_hw_state(ar->hw->wiphy, !rfkill_radio_on); - } -} - static void ath11k_update_11d(struct work_struct *work) { struct ath11k_base *ab = container_of(work, struct ath11k_base, update_11d_work); @@ -1891,7 +1819,6 @@ struct ath11k_base *ath11k_core_alloc(struct device *dev, size_t priv_size, init_waitqueue_head(&ab->qmi.cold_boot_waitq); INIT_WORK(&ab->restart_work, ath11k_core_restart); INIT_WORK(&ab->update_11d_work, ath11k_update_11d); - INIT_WORK(&ab->rfkill_work, ath11k_rfkill_work); INIT_WORK(&ab->reset_work, ath11k_core_reset); timer_setup(&ab->rx_replenish_retry, ath11k_ce_rx_replenish_retry, 0); init_completion(&ab->htc_suspend); diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h index 95bca0b078b1..ae0651ded608 100644 --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h @@ -927,10 +927,6 @@ struct ath11k_base {
struct ath11k_dbring_cap *db_caps; u32 num_db_cap; - struct work_struct rfkill_work; - - /* true means radio is on */ - bool rfkill_radio_on;
/* To synchronize 11d scan vdev id */ struct mutex vdev_id_11d_lock; diff --git a/drivers/net/wireless/ath/ath11k/hw.h b/drivers/net/wireless/ath/ath11k/hw.h index 77dc5c851c9b..14c6d092fcdd 100644 --- a/drivers/net/wireless/ath/ath11k/hw.h +++ b/drivers/net/wireless/ath/ath11k/hw.h @@ -153,9 +153,6 @@ struct ath11k_hw_params { u32 svc_to_ce_map_len;
bool single_pdev_only; - u32 rfkill_pin; - u32 rfkill_cfg; - u32 rfkill_on_level;
bool rxdma1_enable; int num_rxmda_per_pdev; diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c index ee1590b16eff..47f6127e8736 100644 --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c @@ -5606,63 +5606,6 @@ static int ath11k_mac_mgmt_tx(struct ath11k *ar, struct sk_buff *skb, return 0; }
-int ath11k_mac_rfkill_config(struct ath11k *ar) -{ - struct ath11k_base *ab = ar->ab; - u32 param; - int ret; - - if (ab->hw_params.rfkill_pin == 0) - return -EOPNOTSUPP; - - ath11k_dbg(ab, ATH11K_DBG_MAC, - "mac rfkill_pin %d rfkill_cfg %d rfkill_on_level %d", - ab->hw_params.rfkill_pin, ab->hw_params.rfkill_cfg, - ab->hw_params.rfkill_on_level); - - param = FIELD_PREP(WMI_RFKILL_CFG_RADIO_LEVEL, - ab->hw_params.rfkill_on_level) | - FIELD_PREP(WMI_RFKILL_CFG_GPIO_PIN_NUM, - ab->hw_params.rfkill_pin) | - FIELD_PREP(WMI_RFKILL_CFG_PIN_AS_GPIO, - ab->hw_params.rfkill_cfg); - - ret = ath11k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_HW_RFKILL_CONFIG, - param, ar->pdev->pdev_id); - if (ret) { - ath11k_warn(ab, - "failed to set rfkill config 0x%x: %d\n", - param, ret); - return ret; - } - - return 0; -} - -int ath11k_mac_rfkill_enable_radio(struct ath11k *ar, bool enable) -{ - enum wmi_rfkill_enable_radio param; - int ret; - - if (enable) - param = WMI_RFKILL_ENABLE_RADIO_ON; - else - param = WMI_RFKILL_ENABLE_RADIO_OFF; - - ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac %d rfkill enable %d", - ar->pdev_idx, param); - - ret = ath11k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_RFKILL_ENABLE, - param, ar->pdev->pdev_id); - if (ret) { - ath11k_warn(ar->ab, "failed to set rfkill enable param %d: %d\n", - param, ret); - return ret; - } - - return 0; -} - static void ath11k_mac_op_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control, struct sk_buff *skb) @@ -5917,7 +5860,6 @@ static void ath11k_mac_op_stop(struct ieee80211_hw *hw) cancel_delayed_work_sync(&ar->scan.timeout); cancel_work_sync(&ar->regd_update_work); cancel_work_sync(&ar->ab->update_11d_work); - cancel_work_sync(&ar->ab->rfkill_work);
if (ar->state_11d == ATH11K_11D_PREPARING) { ar->state_11d = ATH11K_11D_IDLE; diff --git a/drivers/net/wireless/ath/ath11k/mac.h b/drivers/net/wireless/ath/ath11k/mac.h index 57ebfc592b00..2a0d3afb0c99 100644 --- a/drivers/net/wireless/ath/ath11k/mac.h +++ b/drivers/net/wireless/ath/ath11k/mac.h @@ -148,8 +148,6 @@ u8 ath11k_mac_hw_rate_to_idx(const struct ieee80211_supported_band *sband,
void __ath11k_mac_scan_finish(struct ath11k *ar); void ath11k_mac_scan_finish(struct ath11k *ar); -int ath11k_mac_rfkill_enable_radio(struct ath11k *ar, bool enable); -int ath11k_mac_rfkill_config(struct ath11k *ar);
struct ath11k_vif *ath11k_mac_get_arvif(struct ath11k *ar, u32 vdev_id); struct ath11k_vif *ath11k_mac_get_arvif_by_vdev_id(struct ath11k_base *ab, diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c index 7b1dc19c565e..53389a083606 100644 --- a/drivers/net/wireless/ath/ath11k/wmi.c +++ b/drivers/net/wireless/ath/ath11k/wmi.c @@ -129,8 +129,6 @@ static const struct wmi_tlv_policy wmi_tlv_policies[] = { = { .min_len = sizeof(struct wmi_peer_assoc_conf_event) }, [WMI_TAG_STATS_EVENT] = { .min_len = sizeof(struct wmi_stats_event) }, - [WMI_TAG_RFKILL_EVENT] = { - .min_len = sizeof(struct wmi_rfkill_state_change_ev) }, [WMI_TAG_PDEV_CTL_FAILSAFE_CHECK_EVENT] = { .min_len = sizeof(struct wmi_pdev_ctl_failsafe_chk_event) }, [WMI_TAG_HOST_SWFDA_EVENT] = { @@ -533,8 +531,6 @@ static int ath11k_pull_service_ready_tlv(struct ath11k_base *ab, cap->default_dbs_hw_mode_index = ev->default_dbs_hw_mode_index; cap->num_msdu_desc = ev->num_msdu_desc;
- ath11k_dbg(ab, ATH11K_DBG_WMI, "wmi sys cap info 0x%x\n", cap->sys_cap_info); - return 0; }
@@ -7566,40 +7562,6 @@ ath11k_wmi_pdev_dfs_radar_detected_event(struct ath11k_base *ab, struct sk_buff kfree(tb); }
-static void ath11k_rfkill_state_change_event(struct ath11k_base *ab, - struct sk_buff *skb) -{ - const struct wmi_rfkill_state_change_ev *ev; - const void **tb; - int ret; - - tb = ath11k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC); - if (IS_ERR(tb)) { - ret = PTR_ERR(tb); - ath11k_warn(ab, "failed to parse tlv: %d\n", ret); - return; - } - - ev = tb[WMI_TAG_RFKILL_EVENT]; - if (!ev) { - kfree(tb); - return; - } - - ath11k_dbg(ab, ATH11K_DBG_MAC, - "wmi tlv rfkill state change gpio %d type %d radio_state %d\n", - ev->gpio_pin_num, - ev->int_type, - ev->radio_state); - - spin_lock_bh(&ab->base_lock); - ab->rfkill_radio_on = (ev->radio_state == WMI_RFKILL_RADIO_STATE_ON); - spin_unlock_bh(&ab->base_lock); - - queue_work(ab->workqueue, &ab->rfkill_work); - kfree(tb); -} - static void ath11k_wmi_pdev_temperature_event(struct ath11k_base *ab, struct sk_buff *skb) @@ -7995,9 +7957,6 @@ static void ath11k_wmi_tlv_op_rx(struct ath11k_base *ab, struct sk_buff *skb) case WMI_11D_NEW_COUNTRY_EVENTID: ath11k_reg_11d_new_cc_event(ab, skb); break; - case WMI_RFKILL_STATE_CHANGE_EVENTID: - ath11k_rfkill_state_change_event(ab, skb); - break; case WMI_DIAG_EVENTID: ath11k_wmi_diag_event(ab, skb); break; diff --git a/drivers/net/wireless/ath/ath11k/wmi.h b/drivers/net/wireless/ath/ath11k/wmi.h index b1fad4707dc6..4da248ffa318 100644 --- a/drivers/net/wireless/ath/ath11k/wmi.h +++ b/drivers/net/wireless/ath/ath11k/wmi.h @@ -5328,31 +5328,6 @@ struct target_resource_config { u32 twt_ap_sta_count; };
-enum wmi_sys_cap_info_flags { - WMI_SYS_CAP_INFO_RXTX_LED = BIT(0), - WMI_SYS_CAP_INFO_RFKILL = BIT(1), -}; - -#define WMI_RFKILL_CFG_GPIO_PIN_NUM GENMASK(5, 0) -#define WMI_RFKILL_CFG_RADIO_LEVEL BIT(6) -#define WMI_RFKILL_CFG_PIN_AS_GPIO GENMASK(10, 7) - -enum wmi_rfkill_enable_radio { - WMI_RFKILL_ENABLE_RADIO_ON = 0, - WMI_RFKILL_ENABLE_RADIO_OFF = 1, -}; - -enum wmi_rfkill_radio_state { - WMI_RFKILL_RADIO_STATE_OFF = 1, - WMI_RFKILL_RADIO_STATE_ON = 2, -}; - -struct wmi_rfkill_state_change_ev { - u32 gpio_pin_num; - u32 int_type; - u32 radio_state; -} __packed; - enum wmi_debug_log_param { WMI_DEBUG_LOG_PARAM_LOG_LEVEL = 0x1, WMI_DEBUG_LOG_PARAM_VDEV_ENABLE,
From: Zheyu Ma zheyuma97@gmail.com
[ Upstream commit 13876f2a087ad352bf640a7a0a4a4229ea6e9e4f ]
When the driver fails at ieee80211_alloc_hw() at the probe time, the driver will free the 'hw' which is not allocated, causing a bug.
The following log can reveal it:
[ 15.981294] BUG: KASAN: user-memory-access in mutex_is_locked+0xe/0x40 [ 15.981558] Read of size 8 at addr 0000000000001ab0 by task modprobe/373 [ 15.982583] Call Trace: [ 15.984282] ieee80211_free_hw+0x22/0x390 [ 15.984446] rtl8xxxu_probe+0x3a1/0xab30 [rtl8xxxu]
Fix the bug by changing the order of the error handling.
Signed-off-by: Zheyu Ma zheyuma97@gmail.com Signed-off-by: Kalle Valo kvalo@kernel.org Link: https://lore.kernel.org/r/20220716130444.2950690-1-zheyuma97@gmail.com Signed-off-by: Sasha Levin sashal@kernel.org --- .../wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-)
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c index 8b2ca9e8eac6..567ada2e665a 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c @@ -6657,7 +6657,7 @@ static int rtl8xxxu_probe(struct usb_interface *interface, if (!hw) { ret = -ENOMEM; priv = NULL; - goto exit; + goto err_put_dev; }
priv = hw->priv; @@ -6679,24 +6679,24 @@ static int rtl8xxxu_probe(struct usb_interface *interface,
ret = rtl8xxxu_parse_usb(priv, interface); if (ret) - goto exit; + goto err_set_intfdata;
ret = rtl8xxxu_identify_chip(priv); if (ret) { dev_err(&udev->dev, "Fatal - failed to identify chip\n"); - goto exit; + goto err_set_intfdata; }
ret = rtl8xxxu_read_efuse(priv); if (ret) { dev_err(&udev->dev, "Fatal - failed to read EFuse\n"); - goto exit; + goto err_set_intfdata; }
ret = priv->fops->parse_efuse(priv); if (ret) { dev_err(&udev->dev, "Fatal - failed to parse EFuse\n"); - goto exit; + goto err_set_intfdata; }
rtl8xxxu_print_chipinfo(priv); @@ -6704,12 +6704,12 @@ static int rtl8xxxu_probe(struct usb_interface *interface, ret = priv->fops->load_firmware(priv); if (ret) { dev_err(&udev->dev, "Fatal - failed to load firmware\n"); - goto exit; + goto err_set_intfdata; }
ret = rtl8xxxu_init_device(hw); if (ret) - goto exit; + goto err_set_intfdata;
hw->wiphy->max_scan_ssids = 1; hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN; @@ -6759,12 +6759,12 @@ static int rtl8xxxu_probe(struct usb_interface *interface, if (ret) { dev_err(&udev->dev, "%s: Failed to register: %i\n", __func__, ret); - goto exit; + goto err_set_intfdata; }
return 0;
-exit: +err_set_intfdata: usb_set_intfdata(interface, NULL);
if (priv) { @@ -6772,9 +6772,10 @@ static int rtl8xxxu_probe(struct usb_interface *interface, mutex_destroy(&priv->usb_buf_mutex); mutex_destroy(&priv->h2c_mutex); } - usb_put_dev(udev);
ieee80211_free_hw(hw); +err_put_dev: + usb_put_dev(udev);
return ret; }
linux-stable-mirror@lists.linaro.org