From: Tian Tao tiantao6@hisilicon.com
[ Upstream commit 7d614ab2f20503ed8766363d41f8607337571adf ]
fixed the below warning: drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c:84:2-8: WARNING: NULL check before some freeing functions is not needed.
Signed-off-by: Tian Tao tiantao6@hisilicon.com Acked-by: Christian König christian.koenig@amd.com Signed-off-by: Lucas Stach l.stach@pengutronix.de Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c b/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c index b390dd4d60b7..d741b1d735f7 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c @@ -80,8 +80,7 @@ static void etnaviv_gem_prime_release(struct etnaviv_gem_object *etnaviv_obj) /* Don't drop the pages for imported dmabuf, as they are not * ours, just free the array we allocated: */ - if (etnaviv_obj->pages) - kvfree(etnaviv_obj->pages); + kvfree(etnaviv_obj->pages);
drm_prime_gem_destroy(&etnaviv_obj->base, etnaviv_obj->sgt); }
From: Thomas Zimmermann tzimmermann@suse.de
[ Upstream commit 13b29cc3a722c2c0bc9ab9f72f9047d55d08a2f9 ]
Selecting DRM_FBDEV_EMULATION will include the correct settings for fbdev emulation. Drivers should not override this.
Signed-off-by: Thomas Zimmermann tzimmermann@suse.de Acked-by: Stefan Agner stefan@agner.ch Acked-by: Daniel Vetter daniel.vetter@ffwll.ch Link: https://patchwork.freedesktop.org/patch/msgid/20210415110040.23525-3-tzimmer... Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/mxsfb/Kconfig | 1 - 1 file changed, 1 deletion(-)
diff --git a/drivers/gpu/drm/mxsfb/Kconfig b/drivers/gpu/drm/mxsfb/Kconfig index 0143d539f8f8..ee22cd25d3e3 100644 --- a/drivers/gpu/drm/mxsfb/Kconfig +++ b/drivers/gpu/drm/mxsfb/Kconfig @@ -10,7 +10,6 @@ config DRM_MXSFB depends on COMMON_CLK select DRM_MXS select DRM_KMS_HELPER - select DRM_KMS_FB_HELPER select DRM_KMS_CMA_HELPER select DRM_PANEL select DRM_PANEL_BRIDGE
From: Thomas Zimmermann tzimmermann@suse.de
[ Upstream commit a50e74bec1d17e95275909660c6b43ffe11ebcf0 ]
Selecting DRM_FBDEV_EMULATION will include the correct settings for fbdev emulation. Drivers should not override this.
Signed-off-by: Thomas Zimmermann tzimmermann@suse.de Acked-by: Daniel Vetter daniel.vetter@ffwll.ch Link: https://patchwork.freedesktop.org/patch/msgid/20210415110040.23525-4-tzimmer... Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/zte/Kconfig | 1 - 1 file changed, 1 deletion(-)
diff --git a/drivers/gpu/drm/zte/Kconfig b/drivers/gpu/drm/zte/Kconfig index 90ebaedc11fd..aa8594190b50 100644 --- a/drivers/gpu/drm/zte/Kconfig +++ b/drivers/gpu/drm/zte/Kconfig @@ -3,7 +3,6 @@ config DRM_ZTE tristate "DRM Support for ZTE SoCs" depends on DRM && ARCH_ZX select DRM_KMS_CMA_HELPER - select DRM_KMS_FB_HELPER select DRM_KMS_HELPER select SND_SOC_HDMI_CODEC if SND_SOC select VIDEOMODE_HELPERS
From: KuoHsiang Chou kuohsiang_chou@aspeedtech.com
[ Upstream commit ba4e0339a6a33e2ba341703ce14ae8ca203cb2f1 ]
[Bug][DP501] If ASPEED P2A (PCI to AHB) bridge is disabled and disallowed for CVE_2019_6260 item3, and then the monitor's EDID is unable read through Parade DP501. The reason is the DP501's FW is mapped to BMC addressing space rather than Host addressing space. The resolution is that using "pci_iomap_range()" maps to DP501's FW that stored on the end of FB (Frame Buffer). In this case, FrameBuffer reserves the last 2MB used for the image of DP501.
Signed-off-by: KuoHsiang Chou kuohsiang_chou@aspeedtech.com Reported-by: kernel test robot lkp@intel.com Signed-off-by: Thomas Zimmermann tzimmermann@suse.de Link: https://patchwork.freedesktop.org/patch/msgid/20210421085859.17761-1-kuohsia... Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/ast/ast_dp501.c | 139 +++++++++++++++++++++++--------- drivers/gpu/drm/ast/ast_drv.h | 12 +++ drivers/gpu/drm/ast/ast_main.c | 11 ++- 3 files changed, 125 insertions(+), 37 deletions(-)
diff --git a/drivers/gpu/drm/ast/ast_dp501.c b/drivers/gpu/drm/ast/ast_dp501.c index 88121c0e0d05..cd93c44f2662 100644 --- a/drivers/gpu/drm/ast/ast_dp501.c +++ b/drivers/gpu/drm/ast/ast_dp501.c @@ -189,6 +189,9 @@ bool ast_backup_fw(struct drm_device *dev, u8 *addr, u32 size) u32 i, data; u32 boot_address;
+ if (ast->config_mode != ast_use_p2a) + return false; + data = ast_mindwm(ast, 0x1e6e2100) & 0x01; if (data) { boot_address = get_fw_base(ast); @@ -207,6 +210,9 @@ static bool ast_launch_m68k(struct drm_device *dev) u8 *fw_addr = NULL; u8 jreg;
+ if (ast->config_mode != ast_use_p2a) + return false; + data = ast_mindwm(ast, 0x1e6e2100) & 0x01; if (!data) {
@@ -271,25 +277,55 @@ u8 ast_get_dp501_max_clk(struct drm_device *dev) struct ast_private *ast = to_ast_private(dev); u32 boot_address, offset, data; u8 linkcap[4], linkrate, linklanes, maxclk = 0xff; + u32 *plinkcap;
- boot_address = get_fw_base(ast); - - /* validate FW version */ - offset = 0xf000; - data = ast_mindwm(ast, boot_address + offset); - if ((data & 0xf0) != 0x10) /* version: 1x */ - return maxclk; - - /* Read Link Capability */ - offset = 0xf014; - *(u32 *)linkcap = ast_mindwm(ast, boot_address + offset); - if (linkcap[2] == 0) { - linkrate = linkcap[0]; - linklanes = linkcap[1]; - data = (linkrate == 0x0a) ? (90 * linklanes) : (54 * linklanes); - if (data > 0xff) - data = 0xff; - maxclk = (u8)data; + if (ast->config_mode == ast_use_p2a) { + boot_address = get_fw_base(ast); + + /* validate FW version */ + offset = AST_DP501_GBL_VERSION; + data = ast_mindwm(ast, boot_address + offset); + if ((data & AST_DP501_FW_VERSION_MASK) != AST_DP501_FW_VERSION_1) /* version: 1x */ + return maxclk; + + /* Read Link Capability */ + offset = AST_DP501_LINKRATE; + plinkcap = (u32 *)linkcap; + *plinkcap = ast_mindwm(ast, boot_address + offset); + if (linkcap[2] == 0) { + linkrate = linkcap[0]; + linklanes = linkcap[1]; + data = (linkrate == 0x0a) ? (90 * linklanes) : (54 * linklanes); + if (data > 0xff) + data = 0xff; + maxclk = (u8)data; + } + } else { + if (!ast->dp501_fw_buf) + return AST_DP501_DEFAULT_DCLK; /* 1024x768 as default */ + + /* dummy read */ + offset = 0x0000; + data = readl(ast->dp501_fw_buf + offset); + + /* validate FW version */ + offset = AST_DP501_GBL_VERSION; + data = readl(ast->dp501_fw_buf + offset); + if ((data & AST_DP501_FW_VERSION_MASK) != AST_DP501_FW_VERSION_1) /* version: 1x */ + return maxclk; + + /* Read Link Capability */ + offset = AST_DP501_LINKRATE; + plinkcap = (u32 *)linkcap; + *plinkcap = readl(ast->dp501_fw_buf + offset); + if (linkcap[2] == 0) { + linkrate = linkcap[0]; + linklanes = linkcap[1]; + data = (linkrate == 0x0a) ? (90 * linklanes) : (54 * linklanes); + if (data > 0xff) + data = 0xff; + maxclk = (u8)data; + } } return maxclk; } @@ -298,26 +334,57 @@ bool ast_dp501_read_edid(struct drm_device *dev, u8 *ediddata) { struct ast_private *ast = to_ast_private(dev); u32 i, boot_address, offset, data; + u32 *pEDIDidx;
- boot_address = get_fw_base(ast); - - /* validate FW version */ - offset = 0xf000; - data = ast_mindwm(ast, boot_address + offset); - if ((data & 0xf0) != 0x10) - return false; - - /* validate PnP Monitor */ - offset = 0xf010; - data = ast_mindwm(ast, boot_address + offset); - if (!(data & 0x01)) - return false; + if (ast->config_mode == ast_use_p2a) { + boot_address = get_fw_base(ast);
- /* Read EDID */ - offset = 0xf020; - for (i = 0; i < 128; i += 4) { - data = ast_mindwm(ast, boot_address + offset + i); - *(u32 *)(ediddata + i) = data; + /* validate FW version */ + offset = AST_DP501_GBL_VERSION; + data = ast_mindwm(ast, boot_address + offset); + if ((data & AST_DP501_FW_VERSION_MASK) != AST_DP501_FW_VERSION_1) + return false; + + /* validate PnP Monitor */ + offset = AST_DP501_PNPMONITOR; + data = ast_mindwm(ast, boot_address + offset); + if (!(data & AST_DP501_PNP_CONNECTED)) + return false; + + /* Read EDID */ + offset = AST_DP501_EDID_DATA; + for (i = 0; i < 128; i += 4) { + data = ast_mindwm(ast, boot_address + offset + i); + pEDIDidx = (u32 *)(ediddata + i); + *pEDIDidx = data; + } + } else { + if (!ast->dp501_fw_buf) + return false; + + /* dummy read */ + offset = 0x0000; + data = readl(ast->dp501_fw_buf + offset); + + /* validate FW version */ + offset = AST_DP501_GBL_VERSION; + data = readl(ast->dp501_fw_buf + offset); + if ((data & AST_DP501_FW_VERSION_MASK) != AST_DP501_FW_VERSION_1) + return false; + + /* validate PnP Monitor */ + offset = AST_DP501_PNPMONITOR; + data = readl(ast->dp501_fw_buf + offset); + if (!(data & AST_DP501_PNP_CONNECTED)) + return false; + + /* Read EDID */ + offset = AST_DP501_EDID_DATA; + for (i = 0; i < 128; i += 4) { + data = readl(ast->dp501_fw_buf + offset + i); + pEDIDidx = (u32 *)(ediddata + i); + *pEDIDidx = data; + } }
return true; diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h index e82ab8628770..911f9f414774 100644 --- a/drivers/gpu/drm/ast/ast_drv.h +++ b/drivers/gpu/drm/ast/ast_drv.h @@ -150,6 +150,7 @@ struct ast_private {
void __iomem *regs; void __iomem *ioregs; + void __iomem *dp501_fw_buf;
enum ast_chip chip; bool vga2_clone; @@ -325,6 +326,17 @@ int ast_mode_config_init(struct ast_private *ast); #define AST_MM_ALIGN_SHIFT 4 #define AST_MM_ALIGN_MASK ((1 << AST_MM_ALIGN_SHIFT) - 1)
+#define AST_DP501_FW_VERSION_MASK GENMASK(7, 4) +#define AST_DP501_FW_VERSION_1 BIT(4) +#define AST_DP501_PNP_CONNECTED BIT(1) + +#define AST_DP501_DEFAULT_DCLK 65 + +#define AST_DP501_GBL_VERSION 0xf000 +#define AST_DP501_PNPMONITOR 0xf010 +#define AST_DP501_LINKRATE 0xf014 +#define AST_DP501_EDID_DATA 0xf020 + int ast_mm_init(struct ast_private *ast);
/* ast post */ diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c index 0ac3c2039c4b..3976a258799f 100644 --- a/drivers/gpu/drm/ast/ast_main.c +++ b/drivers/gpu/drm/ast/ast_main.c @@ -99,7 +99,7 @@ static void ast_detect_config_mode(struct drm_device *dev, u32 *scu_rev) if (!(jregd0 & 0x80) || !(jregd1 & 0x10)) { /* Double check it's actually working */ data = ast_read32(ast, 0xf004); - if (data != 0xFFFFFFFF) { + if ((data != 0xFFFFFFFF) && (data != 0x00)) { /* P2A works, grab silicon revision */ ast->config_mode = ast_use_p2a;
@@ -411,6 +411,7 @@ struct ast_private *ast_device_create(const struct drm_driver *drv, return ast; dev = &ast->base;
+ dev->pdev = pdev; pci_set_drvdata(pdev, dev);
ast->regs = pci_iomap(pdev, 1, 0); @@ -450,6 +451,14 @@ struct ast_private *ast_device_create(const struct drm_driver *drv, if (ret) return ERR_PTR(ret);
+ /* map reserved buffer */ + ast->dp501_fw_buf = NULL; + if (dev->vram_mm->vram_size < pci_resource_len(dev->pdev, 0)) { + ast->dp501_fw_buf = pci_iomap_range(dev->pdev, 0, dev->vram_mm->vram_size, 0); + if (!ast->dp501_fw_buf) + drm_info(dev, "failed to map reserved buffer!\n"); + } + ret = ast_mode_config_init(ast); if (ret) return ERR_PTR(ret);
From: Brandon Syu Brandon.Syu@amd.com
[ Upstream commit 99c248c41c2199bd34232ce8e729d18c4b343b64 ]
[why] When setup is called after hdcp has already setup, it would cause to disable HDCP flow won’t execute.
[how] Don't clean up hdcp content to be 0.
Signed-off-by: Brandon Syu Brandon.Syu@amd.com Reviewed-by: Wenjing Liu Wenjing.Liu@amd.com Acked-by: Wayne Lin waynelin@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/hdcp.c | 1 - 1 file changed, 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.c index 68a6481d7f8f..b963226e8af4 100644 --- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.c +++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.c @@ -260,7 +260,6 @@ enum mod_hdcp_status mod_hdcp_setup(struct mod_hdcp *hdcp, struct mod_hdcp_output output; enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
- memset(hdcp, 0, sizeof(struct mod_hdcp)); memset(&output, 0, sizeof(output)); hdcp->config = *config; HDCP_TOP_INTERFACE_TRACE(hdcp);
From: Lewis Huang Lewis.Huang@amd.com
[ Upstream commit d5433a9f692f57c814286f8af2746c567ef79fc8 ]
[Why] This change only fix dpp clock switch to lower case. New solution later can fix both case, which is "dc: skip program clock when allow seamless boot"
[How] This reverts commit "dc: wait vblank when stream enabled and update dpp clock"
Signed-off-by: Lewis Huang Lewis.Huang@amd.com Reviewed-by: Eric Yang eric.yang2@amd.com Acked-by: Wayne Lin waynelin@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 --- .../drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c | 10 +--------- drivers/gpu/drm/amd/display/dc/core/dc.c | 13 ------------- drivers/gpu/drm/amd/display/dc/dc.h | 1 - 3 files changed, 1 insertion(+), 23 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c index a06e86853bb9..49d19fdd750b 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c @@ -128,7 +128,7 @@ void rn_update_clocks(struct clk_mgr *clk_mgr_base, struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); struct dc_clocks *new_clocks = &context->bw_ctx.bw.dcn.clk; struct dc *dc = clk_mgr_base->ctx->dc; - int display_count, i; + int display_count; bool update_dppclk = false; bool update_dispclk = false; bool dpp_clock_lowered = false; @@ -210,14 +210,6 @@ void rn_update_clocks(struct clk_mgr *clk_mgr_base, clk_mgr_base->clks.dppclk_khz, safe_to_lower);
- for (i = 0; i < context->stream_count; i++) { - if (context->streams[i]->signal == SIGNAL_TYPE_EDP && - context->streams[i]->apply_seamless_boot_optimization) { - dc_wait_for_vblank(dc, context->streams[i]); - break; - } - } - clk_mgr_base->clks.actual_dppclk_khz = rn_vbios_smu_set_dppclk(clk_mgr, clk_mgr_base->clks.dppclk_khz);
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 4713f09bcbf1..e57df2f6f824 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -3219,19 +3219,6 @@ void dc_link_remove_remote_sink(struct dc_link *link, struct dc_sink *sink) } }
-void dc_wait_for_vblank(struct dc *dc, struct dc_stream_state *stream) -{ - int i; - - for (i = 0; i < dc->res_pool->pipe_count; i++) - if (dc->current_state->res_ctx.pipe_ctx[i].stream == stream) { - struct timing_generator *tg = - dc->current_state->res_ctx.pipe_ctx[i].stream_res.tg; - tg->funcs->wait_for_state(tg, CRTC_STATE_VBLANK); - break; - } -} - void get_clock_requirements_for_state(struct dc_state *state, struct AsicStateEx *info) { info->displayClock = (unsigned int)state->bw_ctx.bw.dcn.clk.dispclk_khz; diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 100d434f7a03..65f801b50686 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -719,7 +719,6 @@ void dc_init_callbacks(struct dc *dc, void dc_deinit_callbacks(struct dc *dc); void dc_destroy(struct dc **dc);
-void dc_wait_for_vblank(struct dc *dc, struct dc_stream_state *stream); /******************************************************************************* * Surface Interfaces ******************************************************************************/
From: Chris Park Chris.Park@amd.com
[ Upstream commit b2d4b9f72fb14c1e6e4f0128964a84539a72d831 ]
[Why] CLK mgr is null for server settings.
[How] Guard the function with NULL check.
Signed-off-by: Chris Park Chris.Park@amd.com Reviewed-by: Nicholas Kazlauskas Nicholas.Kazlauskas@amd.com Acked-by: Wayne Lin waynelin@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/core/dc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index e57df2f6f824..a869702d77af 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -3274,7 +3274,7 @@ void dc_allow_idle_optimizations(struct dc *dc, bool allow) if (dc->debug.disable_idle_power_optimizations) return;
- if (dc->clk_mgr->funcs->is_smu_present) + if (dc->clk_mgr != NULL && dc->clk_mgr->funcs->is_smu_present) if (!dc->clk_mgr->funcs->is_smu_present(dc->clk_mgr)) return;
From: Jack Zhang Jack.Zhang1@amd.com
[ Upstream commit 95ea3dbc4e9548d35ab6fbf67675cef8c293e2f5 ]
Disable all ip's hw status to false before any hw_init. Only set it to true until its hw_init is executed.
The old 5.9 branch has this change but somehow the 5.11 kernrel does not have this fix.
Without this change, sriov tdr have gfx IB test fail.
Signed-off-by: Jack Zhang Jack.Zhang1@amd.com Review-by: Emily Deng Emily.Deng@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_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 57ec108b5972..f008f001951b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -2856,7 +2856,7 @@ static int amdgpu_device_ip_reinit_early_sriov(struct amdgpu_device *adev) AMD_IP_BLOCK_TYPE_IH, };
- for (i = 0; i < ARRAY_SIZE(ip_order); i++) { + for (i = 0; i < adev->num_ip_blocks; i++) { int j; struct amdgpu_ip_block *block;
From: Dan Carpenter dan.carpenter@oracle.com
[ Upstream commit e590c2b03a6143ba93ddad306bc9eaafa838c020 ]
Cppcheck complains that the declaration doesn't match the function definition. Obviously "left" should come before "right". The caller and the function implementation are done this way, it's just the declaration which is wrong so this doesn't affect runtime.
Reported-by: kernel test robot lkp@intel.com Signed-off-by: Dan Carpenter dan.carpenter@oracle.com Signed-off-by: Maxime Ripard maxime@cerno.tech Link: https://patchwork.freedesktop.org/patch/msgid/YH/720FD978TPhHp@mwanda Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/vc4/vc4_drv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h index a7500716cf3f..5dceadc61600 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.h +++ b/drivers/gpu/drm/vc4/vc4_drv.h @@ -825,7 +825,7 @@ void vc4_crtc_destroy_state(struct drm_crtc *crtc, void vc4_crtc_reset(struct drm_crtc *crtc); void vc4_crtc_handle_vblank(struct vc4_crtc *crtc); void vc4_crtc_get_margins(struct drm_crtc_state *state, - unsigned int *right, unsigned int *left, + unsigned int *left, unsigned int *right, unsigned int *top, unsigned int *bottom);
/* vc4_debugfs.c */
From: Liu Ying victor.liu@nxp.com
[ Upstream commit 3afb2a28fa2404d11cce1956a003f2aaca4da421 ]
This patch replaces ->mode_fixup() with ->atomic_check() so that a full modeset can be requested from there when crtc_state->active is changed to be true(which implies only connector's DPMS is brought out of "Off" status, though not necessarily). Bridge functions are added or changed to accommodate the ->atomic_check() callback. That full modeset is needed by the up-coming patch which gets MIPI DSI controller and PHY ready in ->mode_set(), because it makes sure ->mode_set() and ->atomic_disable() are called in pairs.
Cc: Andrzej Hajda a.hajda@samsung.com Cc: Neil Armstrong narmstrong@baylibre.com Cc: Robert Foss robert.foss@linaro.org Cc: Laurent Pinchart Laurent.pinchart@ideasonboard.com Cc: Jonas Karlman jonas@kwiboo.se Cc: Jernej Skrabec jernej.skrabec@siol.net Cc: David Airlie airlied@linux.ie Cc: Daniel Vetter daniel@ffwll.ch Cc: Guido Günther agx@sigxcpu.org Cc: Robert Chiras robert.chiras@nxp.com Cc: NXP Linux Team linux-imx@nxp.com Signed-off-by: Liu Ying victor.liu@nxp.com Reviewed-by: Neil Armstrong narmstrong@baylibre.com Signed-off-by: Neil Armstrong narmstrong@baylibre.com Link: https://patchwork.freedesktop.org/patch/msgid/1619170003-4817-2-git-send-ema... Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/bridge/nwl-dsi.c | 61 ++++++++++++++++++++------------ 1 file changed, 39 insertions(+), 22 deletions(-)
diff --git a/drivers/gpu/drm/bridge/nwl-dsi.c b/drivers/gpu/drm/bridge/nwl-dsi.c index 66b67402f1ac..c65ca860712d 100644 --- a/drivers/gpu/drm/bridge/nwl-dsi.c +++ b/drivers/gpu/drm/bridge/nwl-dsi.c @@ -21,6 +21,7 @@ #include <linux/sys_soc.h> #include <linux/time64.h>
+#include <drm/drm_atomic_state_helper.h> #include <drm/drm_bridge.h> #include <drm/drm_mipi_dsi.h> #include <drm/drm_of.h> @@ -742,7 +743,9 @@ static int nwl_dsi_disable(struct nwl_dsi *dsi) return 0; }
-static void nwl_dsi_bridge_disable(struct drm_bridge *bridge) +static void +nwl_dsi_bridge_atomic_disable(struct drm_bridge *bridge, + struct drm_bridge_state *old_bridge_state) { struct nwl_dsi *dsi = bridge_to_dsi(bridge); int ret; @@ -803,17 +806,6 @@ static int nwl_dsi_get_dphy_params(struct nwl_dsi *dsi, return 0; }
-static bool nwl_dsi_bridge_mode_fixup(struct drm_bridge *bridge, - const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - /* At least LCDIF + NWL needs active high sync */ - adjusted_mode->flags |= (DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC); - adjusted_mode->flags &= ~(DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC); - - return true; -} - static enum drm_mode_status nwl_dsi_bridge_mode_valid(struct drm_bridge *bridge, const struct drm_display_info *info, @@ -831,6 +823,24 @@ nwl_dsi_bridge_mode_valid(struct drm_bridge *bridge, return MODE_OK; }
+static int nwl_dsi_bridge_atomic_check(struct drm_bridge *bridge, + struct drm_bridge_state *bridge_state, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state) +{ + struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode; + + /* At least LCDIF + NWL needs active high sync */ + adjusted_mode->flags |= (DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC); + adjusted_mode->flags &= ~(DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC); + + /* Do a full modeset if crtc_state->active is changed to be true. */ + if (crtc_state->active_changed && crtc_state->active) + crtc_state->mode_changed = true; + + return 0; +} + static void nwl_dsi_bridge_mode_set(struct drm_bridge *bridge, const struct drm_display_mode *mode, @@ -862,7 +872,9 @@ nwl_dsi_bridge_mode_set(struct drm_bridge *bridge, drm_mode_debug_printmodeline(adjusted_mode); }
-static void nwl_dsi_bridge_pre_enable(struct drm_bridge *bridge) +static void +nwl_dsi_bridge_atomic_pre_enable(struct drm_bridge *bridge, + struct drm_bridge_state *old_bridge_state) { struct nwl_dsi *dsi = bridge_to_dsi(bridge); int ret; @@ -897,7 +909,9 @@ static void nwl_dsi_bridge_pre_enable(struct drm_bridge *bridge) } }
-static void nwl_dsi_bridge_enable(struct drm_bridge *bridge) +static void +nwl_dsi_bridge_atomic_enable(struct drm_bridge *bridge, + struct drm_bridge_state *old_bridge_state) { struct nwl_dsi *dsi = bridge_to_dsi(bridge); int ret; @@ -942,14 +956,17 @@ static void nwl_dsi_bridge_detach(struct drm_bridge *bridge) }
static const struct drm_bridge_funcs nwl_dsi_bridge_funcs = { - .pre_enable = nwl_dsi_bridge_pre_enable, - .enable = nwl_dsi_bridge_enable, - .disable = nwl_dsi_bridge_disable, - .mode_fixup = nwl_dsi_bridge_mode_fixup, - .mode_set = nwl_dsi_bridge_mode_set, - .mode_valid = nwl_dsi_bridge_mode_valid, - .attach = nwl_dsi_bridge_attach, - .detach = nwl_dsi_bridge_detach, + .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, + .atomic_reset = drm_atomic_helper_bridge_reset, + .atomic_check = nwl_dsi_bridge_atomic_check, + .atomic_pre_enable = nwl_dsi_bridge_atomic_pre_enable, + .atomic_enable = nwl_dsi_bridge_atomic_enable, + .atomic_disable = nwl_dsi_bridge_atomic_disable, + .mode_set = nwl_dsi_bridge_mode_set, + .mode_valid = nwl_dsi_bridge_mode_valid, + .attach = nwl_dsi_bridge_attach, + .detach = nwl_dsi_bridge_detach, };
static int nwl_dsi_parse_dt(struct nwl_dsi *dsi)
From: Philipp Zabel p.zabel@pengutronix.de
[ Upstream commit 06841148c570832d4d247b0f6befc1922a84120b ]
Only planes that are displayed via the Display Processor (DP) path support color space conversion. Limit formats on planes that are shown via the direct Display Controller (DC) path to RGB.
Reported-by: Fabio Estevam festevam@gmail.com Signed-off-by: Philipp Zabel p.zabel@pengutronix.de Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/imx/ipuv3-plane.c | 41 ++++++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/imx/ipuv3-plane.c b/drivers/gpu/drm/imx/ipuv3-plane.c index fa5009705365..fc8f4834ed7b 100644 --- a/drivers/gpu/drm/imx/ipuv3-plane.c +++ b/drivers/gpu/drm/imx/ipuv3-plane.c @@ -35,7 +35,7 @@ static inline struct ipu_plane *to_ipu_plane(struct drm_plane *p) return container_of(p, struct ipu_plane, base); }
-static const uint32_t ipu_plane_formats[] = { +static const uint32_t ipu_plane_all_formats[] = { DRM_FORMAT_ARGB1555, DRM_FORMAT_XRGB1555, DRM_FORMAT_ABGR1555, @@ -72,6 +72,31 @@ static const uint32_t ipu_plane_formats[] = { DRM_FORMAT_BGRX8888_A8, };
+static const uint32_t ipu_plane_rgb_formats[] = { + DRM_FORMAT_ARGB1555, + DRM_FORMAT_XRGB1555, + DRM_FORMAT_ABGR1555, + DRM_FORMAT_XBGR1555, + DRM_FORMAT_RGBA5551, + DRM_FORMAT_BGRA5551, + DRM_FORMAT_ARGB4444, + DRM_FORMAT_ARGB8888, + DRM_FORMAT_XRGB8888, + DRM_FORMAT_ABGR8888, + DRM_FORMAT_XBGR8888, + DRM_FORMAT_RGBA8888, + DRM_FORMAT_RGBX8888, + DRM_FORMAT_BGRA8888, + DRM_FORMAT_BGRX8888, + DRM_FORMAT_RGB565, + DRM_FORMAT_RGB565_A8, + DRM_FORMAT_BGR565_A8, + DRM_FORMAT_RGB888_A8, + DRM_FORMAT_BGR888_A8, + DRM_FORMAT_RGBX8888_A8, + DRM_FORMAT_BGRX8888_A8, +}; + static const uint64_t ipu_format_modifiers[] = { DRM_FORMAT_MOD_LINEAR, DRM_FORMAT_MOD_INVALID @@ -830,16 +855,24 @@ struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu, struct ipu_plane *ipu_plane; const uint64_t *modifiers = ipu_format_modifiers; unsigned int zpos = (type == DRM_PLANE_TYPE_PRIMARY) ? 0 : 1; + unsigned int format_count; + const uint32_t *formats; int ret;
DRM_DEBUG_KMS("channel %d, dp flow %d, possible_crtcs=0x%x\n", dma, dp, possible_crtcs);
+ if (dp == IPU_DP_FLOW_SYNC_BG || dp == IPU_DP_FLOW_SYNC_FG) { + formats = ipu_plane_all_formats; + format_count = ARRAY_SIZE(ipu_plane_all_formats); + } else { + formats = ipu_plane_rgb_formats; + format_count = ARRAY_SIZE(ipu_plane_rgb_formats); + } ipu_plane = drmm_universal_plane_alloc(dev, struct ipu_plane, base, possible_crtcs, &ipu_plane_funcs, - ipu_plane_formats, - ARRAY_SIZE(ipu_plane_formats), - modifiers, type, NULL); + formats, format_count, modifiers, + type, NULL); if (IS_ERR(ipu_plane)) { DRM_ERROR("failed to allocate and initialize %s plane\n", zpos ? "overlay" : "primary");
From: Sebastian Reichel sebastian.reichel@collabora.com
[ Upstream commit 94dfec48fca756cef90263a03e81f24dae24a5c6 ]
Some standard resolutions like 1366x768 do not work properly with i.MX6 SoCs, since the horizontal resolution needs to be aligned to 8 pixels (so 1360x768 or 1368x768 would work).
This patch allocates framebuffers allocated to 8 pixels. The extra time required to send the extra pixels are removed from the blank time. In order to expose the correct display size to userspace, the stride is increased without increasing the width.
Without this patch systems with this display resolution hang indefinitely during boot up.
Suggested-by: Boris Brezillon boris.brezillon@collabora.com Signed-off-by: Sebastian Reichel sebastian.reichel@collabora.com Link: https://lore.kernel.org/r/20210428222953.235280-3-sebastian.reichel@collabor... Signed-off-by: Philipp Zabel p.zabel@pengutronix.de Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/imx/imx-drm-core.c | 19 ++++++++++++++++++- drivers/gpu/drm/imx/imx-ldb.c | 5 +++++ drivers/gpu/drm/imx/ipuv3-crtc.c | 11 ++++++++++- drivers/gpu/drm/imx/ipuv3-plane.c | 19 +++++++++++++++---- drivers/gpu/ipu-v3/ipu-dc.c | 5 +++++ drivers/gpu/ipu-v3/ipu-di.c | 7 +++++++ 6 files changed, 60 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/drm/imx/imx-drm-core.c b/drivers/gpu/drm/imx/imx-drm-core.c index e6a88c8cbd69..8457b9788cda 100644 --- a/drivers/gpu/drm/imx/imx-drm-core.c +++ b/drivers/gpu/drm/imx/imx-drm-core.c @@ -145,9 +145,26 @@ static const struct drm_ioctl_desc imx_drm_ioctls[] = { /* none so far */ };
+static int imx_drm_dumb_create(struct drm_file *file_priv, + struct drm_device *drm, + struct drm_mode_create_dumb *args) +{ + u32 width = args->width; + int ret; + + args->width = ALIGN(width, 8); + + ret = drm_gem_cma_dumb_create(file_priv, drm, args); + if (ret) + return ret; + + args->width = width; + return ret; +} + static const struct drm_driver imx_drm_driver = { .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC, - DRM_GEM_CMA_DRIVER_OPS, + DRM_GEM_CMA_DRIVER_OPS_WITH_DUMB_CREATE(imx_drm_dumb_create), .ioctls = imx_drm_ioctls, .num_ioctls = ARRAY_SIZE(imx_drm_ioctls), .fops = &imx_drm_driver_fops, diff --git a/drivers/gpu/drm/imx/imx-ldb.c b/drivers/gpu/drm/imx/imx-ldb.c index ffdc492c5bc5..53132ddf9587 100644 --- a/drivers/gpu/drm/imx/imx-ldb.c +++ b/drivers/gpu/drm/imx/imx-ldb.c @@ -274,6 +274,11 @@ imx_ldb_encoder_atomic_mode_set(struct drm_encoder *encoder, "%s: mode exceeds 85 MHz pixel clock\n", __func__); }
+ if (!IS_ALIGNED(mode->hdisplay, 8)) { + dev_warn(ldb->dev, + "%s: hdisplay does not align to 8 byte\n", __func__); + } + if (dual) { serial_clk = 3500UL * mode->clock; imx_ldb_set_clock(ldb, mux, 0, serial_clk, di_clk); diff --git a/drivers/gpu/drm/imx/ipuv3-crtc.c b/drivers/gpu/drm/imx/ipuv3-crtc.c index e6431a227feb..9c8829f945b2 100644 --- a/drivers/gpu/drm/imx/ipuv3-crtc.c +++ b/drivers/gpu/drm/imx/ipuv3-crtc.c @@ -305,10 +305,19 @@ static void ipu_crtc_mode_set_nofb(struct drm_crtc *crtc) sig_cfg.vsync_pin = imx_crtc_state->di_vsync_pin;
drm_display_mode_to_videomode(mode, &sig_cfg.mode); + if (!IS_ALIGNED(sig_cfg.mode.hactive, 8)) { + unsigned int new_hactive = ALIGN(sig_cfg.mode.hactive, 8); + + dev_warn(ipu_crtc->dev, "8-pixel align hactive %d -> %d\n", + sig_cfg.mode.hactive, new_hactive); + + sig_cfg.mode.hfront_porch = new_hactive - sig_cfg.mode.hactive; + sig_cfg.mode.hactive = new_hactive; + }
ipu_dc_init_sync(ipu_crtc->dc, ipu_crtc->di, mode->flags & DRM_MODE_FLAG_INTERLACE, - imx_crtc_state->bus_format, mode->hdisplay); + imx_crtc_state->bus_format, sig_cfg.mode.hactive); ipu_di_init_sync_panel(ipu_crtc->di, &sig_cfg); }
diff --git a/drivers/gpu/drm/imx/ipuv3-plane.c b/drivers/gpu/drm/imx/ipuv3-plane.c index fc8f4834ed7b..9a7150ac34a6 100644 --- a/drivers/gpu/drm/imx/ipuv3-plane.c +++ b/drivers/gpu/drm/imx/ipuv3-plane.c @@ -30,6 +30,11 @@ to_ipu_plane_state(struct drm_plane_state *p) return container_of(p, struct ipu_plane_state, base); }
+static unsigned int ipu_src_rect_width(const struct drm_plane_state *state) +{ + return ALIGN(drm_rect_width(&state->src) >> 16, 8); +} + static inline struct ipu_plane *to_ipu_plane(struct drm_plane *p) { return container_of(p, struct ipu_plane, base); @@ -440,6 +445,12 @@ static int ipu_plane_atomic_check(struct drm_plane *plane, if (old_fb && fb->pitches[0] != old_fb->pitches[0]) crtc_state->mode_changed = true;
+ if (ALIGN(fb->width, 8) * fb->format->cpp[0] > + fb->pitches[0] + fb->offsets[0]) { + dev_warn(dev, "pitch is not big enough for 8 pixels alignment"); + return -EINVAL; + } + switch (fb->format->format) { case DRM_FORMAT_YUV420: case DRM_FORMAT_YVU420: @@ -615,7 +626,7 @@ static void ipu_plane_atomic_update(struct drm_plane *plane, if (ipu_state->use_pre) { axi_id = ipu_chan_assign_axi_id(ipu_plane->dma); ipu_prg_channel_configure(ipu_plane->ipu_ch, axi_id, - drm_rect_width(&new_state->src) >> 16, + ipu_src_rect_width(new_state), drm_rect_height(&new_state->src) >> 16, fb->pitches[0], fb->format->format, fb->modifier, &eba); @@ -648,9 +659,9 @@ static void ipu_plane_atomic_update(struct drm_plane *plane, break; }
- ipu_dmfc_config_wait4eot(ipu_plane->dmfc, drm_rect_width(dst)); + ipu_dmfc_config_wait4eot(ipu_plane->dmfc, ALIGN(drm_rect_width(dst), 8));
- width = drm_rect_width(&new_state->src) >> 16; + width = ipu_src_rect_width(new_state); height = drm_rect_height(&new_state->src) >> 16; info = drm_format_info(fb->format->format); ipu_calculate_bursts(width, info->cpp[0], fb->pitches[0], @@ -715,7 +726,7 @@ static void ipu_plane_atomic_update(struct drm_plane *plane,
ipu_cpmem_zero(ipu_plane->alpha_ch); ipu_cpmem_set_resolution(ipu_plane->alpha_ch, - drm_rect_width(&new_state->src) >> 16, + ipu_src_rect_width(new_state), drm_rect_height(&new_state->src) >> 16); ipu_cpmem_set_format_passthrough(ipu_plane->alpha_ch, 8); ipu_cpmem_set_high_priority(ipu_plane->alpha_ch); diff --git a/drivers/gpu/ipu-v3/ipu-dc.c b/drivers/gpu/ipu-v3/ipu-dc.c index 34b4075a6a8e..ca96b235491a 100644 --- a/drivers/gpu/ipu-v3/ipu-dc.c +++ b/drivers/gpu/ipu-v3/ipu-dc.c @@ -167,6 +167,11 @@ int ipu_dc_init_sync(struct ipu_dc *dc, struct ipu_di *di, bool interlaced,
dc->di = ipu_di_get_num(di);
+ if (!IS_ALIGNED(width, 8)) { + dev_warn(priv->dev, + "%s: hactive does not align to 8 byte\n", __func__); + } + map = ipu_bus_format_to_map(bus_format);
/* diff --git a/drivers/gpu/ipu-v3/ipu-di.c b/drivers/gpu/ipu-v3/ipu-di.c index e617f60afeea..666223c6bec4 100644 --- a/drivers/gpu/ipu-v3/ipu-di.c +++ b/drivers/gpu/ipu-v3/ipu-di.c @@ -506,6 +506,13 @@ int ipu_di_adjust_videomode(struct ipu_di *di, struct videomode *mode) { u32 diff;
+ if (!IS_ALIGNED(mode->hactive, 8) && + mode->hfront_porch < ALIGN(mode->hactive, 8) - mode->hactive) { + dev_err(di->ipu->dev, "hactive %d is not aligned to 8 and front porch is too small to compensate\n", + mode->hactive); + return -EINVAL; + } + if (mode->vfront_porch >= 2) return 0;
From: Andy Shevchenko andriy.shevchenko@linux.intel.com
[ Upstream commit 443ef39b499cc9c6635f83238101f1bb923e9326 ]
Sparse is not happy about handling of strict types in pch_ptp_match():
.../pch_gbe_main.c:158:33: warning: incorrect type in argument 2 (different base types) .../pch_gbe_main.c:158:33: expected unsigned short [usertype] uid_hi .../pch_gbe_main.c:158:33: got restricted __be16 [usertype] .../pch_gbe_main.c:158:45: warning: incorrect type in argument 3 (different base types) .../pch_gbe_main.c:158:45: expected unsigned int [usertype] uid_lo .../pch_gbe_main.c:158:45: got restricted __be32 [usertype] .../pch_gbe_main.c:158:56: warning: incorrect type in argument 4 (different base types) .../pch_gbe_main.c:158:56: expected unsigned short [usertype] seqid .../pch_gbe_main.c:158:56: got restricted __be16 [usertype]
Fix that by switching to use proper accessors to BE data.
Reported-by: kernel test robot lkp@intel.com Signed-off-by: Andy Shevchenko andriy.shevchenko@linux.intel.com Tested-by: Flavio Suligoi f.suligoi@asem.it Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- .../ethernet/oki-semi/pch_gbe/pch_gbe_main.c | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-)
diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c index 334af49e5add..a6bb5509963d 100644 --- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c +++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c @@ -108,7 +108,7 @@ static int pch_ptp_match(struct sk_buff *skb, u16 uid_hi, u32 uid_lo, u16 seqid) { u8 *data = skb->data; unsigned int offset; - u16 *hi, *id; + u16 hi, id; u32 lo;
if (ptp_classify_raw(skb) == PTP_CLASS_NONE) @@ -119,14 +119,11 @@ static int pch_ptp_match(struct sk_buff *skb, u16 uid_hi, u32 uid_lo, u16 seqid) if (skb->len < offset + OFF_PTP_SEQUENCE_ID + sizeof(seqid)) return 0;
- hi = (u16 *)(data + offset + OFF_PTP_SOURCE_UUID); - id = (u16 *)(data + offset + OFF_PTP_SEQUENCE_ID); + hi = get_unaligned_be16(data + offset + OFF_PTP_SOURCE_UUID + 0); + lo = get_unaligned_be32(data + offset + OFF_PTP_SOURCE_UUID + 2); + id = get_unaligned_be16(data + offset + OFF_PTP_SEQUENCE_ID);
- memcpy(&lo, &hi[1], sizeof(lo)); - - return (uid_hi == *hi && - uid_lo == lo && - seqid == *id); + return (uid_hi == hi && uid_lo == lo && seqid == id); }
static void @@ -136,7 +133,6 @@ pch_rx_timestamp(struct pch_gbe_adapter *adapter, struct sk_buff *skb) struct pci_dev *pdev; u64 ns; u32 hi, lo, val; - u16 uid, seq;
if (!adapter->hwts_rx_en) return; @@ -152,10 +148,7 @@ pch_rx_timestamp(struct pch_gbe_adapter *adapter, struct sk_buff *skb) lo = pch_src_uuid_lo_read(pdev); hi = pch_src_uuid_hi_read(pdev);
- uid = hi & 0xffff; - seq = (hi >> 16) & 0xffff; - - if (!pch_ptp_match(skb, htons(uid), htonl(lo), htons(seq))) + if (!pch_ptp_match(skb, hi, lo, hi >> 16)) goto out;
ns = pch_rx_snap_read(pdev);
From: Roman Li Roman.Li@amd.com
[ Upstream commit cf8b92a75646735136053ce51107bfa8cfc23191 ]
[Why] In gpu reset dc_lock acquired in dm_suspend(). Asynchronously handle_hpd_rx_irq can also be called through amdgpu_dm_irq_suspend->flush_work, which also tries to acquire dc_lock. That causes a deadlock.
[How] Check if amdgpu executing reset before acquiring dc_lock.
Signed-off-by: Lang Yu Lang.Yu@amd.com Signed-off-by: Roman Li Roman.Li@amd.com Reviewed-by: Qingqing Zhuo Qingqing.Zhuo@amd.com Acked-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 --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 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 652cc1a0e450..875fd187463e 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -2726,13 +2726,15 @@ static void handle_hpd_rx_irq(void *param) } }
- mutex_lock(&adev->dm.dc_lock); + if (!amdgpu_in_reset(adev)) + mutex_lock(&adev->dm.dc_lock); #ifdef CONFIG_DRM_AMD_DC_HDCP result = dc_link_handle_hpd_rx_irq(dc_link, &hpd_irq_data, NULL); #else result = dc_link_handle_hpd_rx_irq(dc_link, NULL, NULL); #endif - mutex_unlock(&adev->dm.dc_lock); + if (!amdgpu_in_reset(adev)) + mutex_unlock(&adev->dm.dc_lock);
out: if (result && !is_mst_root_connector) {
From: Alex Deucher alexander.deucher@amd.com
[ Upstream commit 67387dfe0f6630f2d4f412ce77debec23a49db7a ]
Change to 60s. This matches what we already do in virtualization. Infinite timeout can lead to deadlocks in the kernel.
Reviewed-by: Christian König christian.koenig@amd.com Acked-by: Daniel Vetter daniel.vetter@ffwll.ch Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 8 +++----- drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 4 ++-- 2 files changed, 5 insertions(+), 7 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index f008f001951b..d83f2ee150b8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -3181,8 +3181,8 @@ static int amdgpu_device_get_job_timeout_settings(struct amdgpu_device *adev) int ret = 0;
/* - * By default timeout for non compute jobs is 10000. - * And there is no timeout enforced on compute jobs. + * By default timeout for non compute jobs is 10000 + * and 60000 for compute jobs. * In SR-IOV or passthrough mode, timeout for compute * jobs are 60000 by default. */ @@ -3191,10 +3191,8 @@ static int amdgpu_device_get_job_timeout_settings(struct amdgpu_device *adev) if (amdgpu_sriov_vf(adev)) adev->compute_timeout = amdgpu_sriov_is_pp_one_vf(adev) ? msecs_to_jiffies(60000) : msecs_to_jiffies(10000); - else if (amdgpu_passthrough(adev)) - adev->compute_timeout = msecs_to_jiffies(60000); else - adev->compute_timeout = MAX_SCHEDULE_TIMEOUT; + adev->compute_timeout = msecs_to_jiffies(60000);
if (strnlen(input, AMDGPU_MAX_TIMEOUT_PARAM_LENGTH)) { while ((timeout_setting = strsep(&input, ",")) && diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index f93883db2b46..57a055aa854d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -287,9 +287,9 @@ module_param_named(msi, amdgpu_msi, int, 0444); * for SDMA and Video. * * By default(with no lockup_timeout settings), the timeout for all non-compute(GFX, SDMA and Video) - * jobs is 10000. And there is no timeout enforced on compute jobs. + * jobs is 10000. The timeout for compute is 60000. */ -MODULE_PARM_DESC(lockup_timeout, "GPU lockup timeout in ms (default: for bare metal 10000 for non-compute jobs and infinity timeout for compute jobs; " +MODULE_PARM_DESC(lockup_timeout, "GPU lockup timeout in ms (default: for bare metal 10000 for non-compute jobs and 60000 for compute jobs; " "for passthrough or sriov, 10000 for all jobs." " 0: keep default value. negative: infinity timeout), " "format: for bare metal [Non-Compute] or [GFX,Compute,SDMA,Video]; "
From: Ilya Bakoulin Ilya.Bakoulin@amd.com
[ Upstream commit c31bef1cb1203b26f901a511a3246204cfaf8a57 ]
[Why] Currently, the code that fills the clock table can miss filling information about some of the higher voltage states advertised by the SMU. This, in turn, may cause some of the higher pixel clock modes (e.g. 8k60) to fail validation.
[How] Fill the table with one entry per DCFCLK level instead of one entry per FCLK level. This is needed because the maximum FCLK does not necessarily need maximum voltage, whereas DCFCLK values from SMU cover the full voltage range.
Signed-off-by: Ilya Bakoulin Ilya.Bakoulin@amd.com Reviewed-by: Dmytro Laktyushkin Dmytro.Laktyushkin@amd.com Acked-by: Stylon Wang stylon.wang@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 --- .../amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c | 80 ++++++++++++------- .../drm/amd/display/dc/dcn21/dcn21_resource.c | 33 +++++--- 2 files changed, 74 insertions(+), 39 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c index 49d19fdd750b..1f56ceab5922 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c @@ -834,46 +834,67 @@ static struct wm_table lpddr4_wm_table_rn = { }, } }; -static unsigned int find_socclk_for_voltage(struct dpm_clocks *clock_table, unsigned int voltage) + +static unsigned int find_max_fclk_for_voltage(struct dpm_clocks *clock_table, + unsigned int voltage) { int i; + uint32_t max_clk = 0;
- for (i = 0; i < PP_SMU_NUM_SOCCLK_DPM_LEVELS; i++) { - if (clock_table->SocClocks[i].Vol == voltage) - return clock_table->SocClocks[i].Freq; + for (i = 0; i < PP_SMU_NUM_FCLK_DPM_LEVELS; i++) { + if (clock_table->FClocks[i].Vol <= voltage) { + max_clk = clock_table->FClocks[i].Freq > max_clk ? + clock_table->FClocks[i].Freq : max_clk; + } }
- ASSERT(0); - return 0; + return max_clk; } -static unsigned int find_dcfclk_for_voltage(struct dpm_clocks *clock_table, unsigned int voltage) + +static unsigned int find_max_memclk_for_voltage(struct dpm_clocks *clock_table, + unsigned int voltage) { int i; + uint32_t max_clk = 0;
- for (i = 0; i < PP_SMU_NUM_DCFCLK_DPM_LEVELS; i++) { - if (clock_table->DcfClocks[i].Vol == voltage) - return clock_table->DcfClocks[i].Freq; + for (i = 0; i < PP_SMU_NUM_MEMCLK_DPM_LEVELS; i++) { + if (clock_table->MemClocks[i].Vol <= voltage) { + max_clk = clock_table->MemClocks[i].Freq > max_clk ? + clock_table->MemClocks[i].Freq : max_clk; + } }
- ASSERT(0); - return 0; + return max_clk; +} + +static unsigned int find_max_socclk_for_voltage(struct dpm_clocks *clock_table, + unsigned int voltage) +{ + int i; + uint32_t max_clk = 0; + + for (i = 0; i < PP_SMU_NUM_SOCCLK_DPM_LEVELS; i++) { + if (clock_table->SocClocks[i].Vol <= voltage) { + max_clk = clock_table->SocClocks[i].Freq > max_clk ? + clock_table->SocClocks[i].Freq : max_clk; + } + } + + return max_clk; }
static void rn_clk_mgr_helper_populate_bw_params(struct clk_bw_params *bw_params, struct dpm_clocks *clock_table, struct integrated_info *bios_info) { int i, j = 0; + unsigned int volt;
j = -1;
- ASSERT(PP_SMU_NUM_FCLK_DPM_LEVELS <= MAX_NUM_DPM_LVL); - - /* Find lowest DPM, FCLK is filled in reverse order*/ - - for (i = PP_SMU_NUM_FCLK_DPM_LEVELS - 1; i >= 0; i--) { - if (clock_table->FClocks[i].Freq != 0 && clock_table->FClocks[i].Vol != 0) { + /* Find max DPM */ + for (i = 0; i < PP_SMU_NUM_DCFCLK_DPM_LEVELS; ++i) { + if (clock_table->DcfClocks[i].Freq != 0 && + clock_table->DcfClocks[i].Vol != 0) j = i; - break; - } }
if (j == -1) { @@ -884,13 +905,18 @@ static void rn_clk_mgr_helper_populate_bw_params(struct clk_bw_params *bw_params
bw_params->clk_table.num_entries = j + 1;
- for (i = 0; i < bw_params->clk_table.num_entries; i++, j--) { - bw_params->clk_table.entries[i].fclk_mhz = clock_table->FClocks[j].Freq; - bw_params->clk_table.entries[i].memclk_mhz = clock_table->MemClocks[j].Freq; - bw_params->clk_table.entries[i].voltage = clock_table->FClocks[j].Vol; - bw_params->clk_table.entries[i].dcfclk_mhz = find_dcfclk_for_voltage(clock_table, clock_table->FClocks[j].Vol); - bw_params->clk_table.entries[i].socclk_mhz = find_socclk_for_voltage(clock_table, - bw_params->clk_table.entries[i].voltage); + for (i = 0; i < bw_params->clk_table.num_entries; i++) { + volt = clock_table->DcfClocks[i].Vol; + + bw_params->clk_table.entries[i].voltage = volt; + bw_params->clk_table.entries[i].dcfclk_mhz = + clock_table->DcfClocks[i].Freq; + bw_params->clk_table.entries[i].fclk_mhz = + find_max_fclk_for_voltage(clock_table, volt); + bw_params->clk_table.entries[i].memclk_mhz = + find_max_memclk_for_voltage(clock_table, volt); + bw_params->clk_table.entries[i].socclk_mhz = + find_max_socclk_for_voltage(clock_table, volt); }
bw_params->vram_type = bios_info->memory_type; diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c index 8e3f1d0b4cc3..38a2aa87f5f5 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c @@ -1575,10 +1575,12 @@ static struct _vcs_dpi_voltage_scaling_st construct_low_pstate_lvl(struct clk_li low_pstate_lvl.phyclk_d18_mhz = dcn2_1_soc.clock_limits[high_voltage_lvl].phyclk_d18_mhz; low_pstate_lvl.phyclk_mhz = dcn2_1_soc.clock_limits[high_voltage_lvl].phyclk_mhz;
- for (i = clk_table->num_entries; i > 1; i--) - clk_table->entries[i] = clk_table->entries[i-1]; - clk_table->entries[1] = clk_table->entries[0]; - clk_table->num_entries++; + if (clk_table->num_entries < MAX_NUM_DPM_LVL) { + for (i = clk_table->num_entries; i > 1; i--) + clk_table->entries[i] = clk_table->entries[i-1]; + clk_table->entries[1] = clk_table->entries[0]; + clk_table->num_entries++; + }
return low_pstate_lvl; } @@ -1610,10 +1612,6 @@ static void update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_param } }
- /* clk_table[1] is reserved for min DF PState. skip here to fill in later. */ - if (i == 1) - k++; - clock_limits[k].state = k; clock_limits[k].dcfclk_mhz = clk_table->entries[i].dcfclk_mhz; clock_limits[k].fabricclk_mhz = clk_table->entries[i].fclk_mhz; @@ -1630,14 +1628,25 @@ static void update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_param
k++; } - for (i = 0; i < clk_table->num_entries + 1; i++) - dcn2_1_soc.clock_limits[i] = clock_limits[i]; + + if (clk_table->num_entries >= MAX_NUM_DPM_LVL) { + for (i = 0; i < clk_table->num_entries + 1; i++) + dcn2_1_soc.clock_limits[i] = clock_limits[i]; + } else { + dcn2_1_soc.clock_limits[0] = clock_limits[0]; + for (i = 2; i < clk_table->num_entries + 1; i++) { + dcn2_1_soc.clock_limits[i] = clock_limits[i - 1]; + dcn2_1_soc.clock_limits[i].state = i; + } + } + if (clk_table->num_entries) { - dcn2_1_soc.num_states = clk_table->num_entries + 1; /* fill in min DF PState */ dcn2_1_soc.clock_limits[1] = construct_low_pstate_lvl(clk_table, closest_clk_lvl); + dcn2_1_soc.num_states = clk_table->num_entries; /* duplicate last level */ - dcn2_1_soc.clock_limits[dcn2_1_soc.num_states] = dcn2_1_soc.clock_limits[dcn2_1_soc.num_states - 1]; + dcn2_1_soc.clock_limits[dcn2_1_soc.num_states] = + dcn2_1_soc.clock_limits[dcn2_1_soc.num_states - 1]; dcn2_1_soc.clock_limits[dcn2_1_soc.num_states].state = dcn2_1_soc.num_states; }
From: Dmytro Laktyushkin Dmytro.Laktyushkin@amd.com
[ Upstream commit 8809a7a4afe90ad9ffb42f72154d27e7c47551ae ]
Right now the flag simply selects memory config 0 when flag is true however 420 modes benefit more from memory config 3.
Signed-off-by: Dmytro Laktyushkin Dmytro.Laktyushkin@amd.com Reviewed-by: Aric Cyr Aric.Cyr@amd.com Acked-by: Stylon Wang stylon.wang@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/dcn10/dcn10_dpp_dscl.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c index efa86d5c6847..98ab4b776924 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c @@ -496,10 +496,13 @@ static enum lb_memory_config dpp1_dscl_find_lb_memory_config(struct dcn10_dpp *d int vtaps_c = scl_data->taps.v_taps_c; int ceil_vratio = dc_fixpt_ceil(scl_data->ratios.vert); int ceil_vratio_c = dc_fixpt_ceil(scl_data->ratios.vert_c); - enum lb_memory_config mem_cfg = LB_MEMORY_CONFIG_0;
- if (dpp->base.ctx->dc->debug.use_max_lb) - return mem_cfg; + if (dpp->base.ctx->dc->debug.use_max_lb) { + if (scl_data->format == PIXEL_FORMAT_420BPP8 + || scl_data->format == PIXEL_FORMAT_420BPP10) + return LB_MEMORY_CONFIG_3; + return LB_MEMORY_CONFIG_0; + }
dpp->base.caps->dscl_calc_lb_num_partitions( scl_data, LB_MEMORY_CONFIG_1, &num_part_y, &num_part_c);
From: Dinghao Liu dinghao.liu@zju.edu.cn
[ Upstream commit a20a40a8bbc2cf4b29d7248ea31e974e9103dd7f ]
The error handling paths after pm_runtime_get_sync() have no refcount decrement, which leads to refcount leak.
Signed-off-by: Dinghao Liu dinghao.liu@zju.edu.cn Link: https://lore.kernel.org/r/20210415073338.22287-1-dinghao.liu@zju.edu.cn [geert: Remove now unused variable priv] Signed-off-by: Geert Uytterhoeven geert+renesas@glider.be Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/clk/renesas/rcar-usb2-clock-sel.c | 24 ++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-)
diff --git a/drivers/clk/renesas/rcar-usb2-clock-sel.c b/drivers/clk/renesas/rcar-usb2-clock-sel.c index 34a85dc95beb..9fb79bd79435 100644 --- a/drivers/clk/renesas/rcar-usb2-clock-sel.c +++ b/drivers/clk/renesas/rcar-usb2-clock-sel.c @@ -128,10 +128,8 @@ static int rcar_usb2_clock_sel_resume(struct device *dev) static int rcar_usb2_clock_sel_remove(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct usb2_clock_sel_priv *priv = platform_get_drvdata(pdev);
of_clk_del_provider(dev->of_node); - clk_hw_unregister(&priv->hw); pm_runtime_put(dev); pm_runtime_disable(dev);
@@ -164,9 +162,6 @@ static int rcar_usb2_clock_sel_probe(struct platform_device *pdev) if (IS_ERR(priv->rsts)) return PTR_ERR(priv->rsts);
- pm_runtime_enable(dev); - pm_runtime_get_sync(dev); - clk = devm_clk_get(dev, "usb_extal"); if (!IS_ERR(clk) && !clk_prepare_enable(clk)) { priv->extal = !!clk_get_rate(clk); @@ -183,6 +178,8 @@ static int rcar_usb2_clock_sel_probe(struct platform_device *pdev) return -ENOENT; }
+ pm_runtime_enable(dev); + pm_runtime_get_sync(dev); platform_set_drvdata(pdev, priv); dev_set_drvdata(dev, priv);
@@ -190,11 +187,20 @@ static int rcar_usb2_clock_sel_probe(struct platform_device *pdev) init.ops = &usb2_clock_sel_clock_ops; priv->hw.init = &init;
- clk = clk_register(NULL, &priv->hw); - if (IS_ERR(clk)) - return PTR_ERR(clk); + ret = devm_clk_hw_register(NULL, &priv->hw); + if (ret) + goto pm_put; + + ret = of_clk_add_hw_provider(np, of_clk_hw_simple_get, &priv->hw); + if (ret) + goto pm_put; + + return 0;
- return of_clk_add_hw_provider(np, of_clk_hw_simple_get, &priv->hw); +pm_put: + pm_runtime_put(dev); + pm_runtime_disable(dev); + return ret; }
static const struct dev_pm_ops rcar_usb2_clock_sel_pm_ops = {
From: Youling Tang tangyouling@loongson.cn
[ Upstream commit 6a73022ee3fdf7e60f2ba0a3a835dd421c05b5b5 ]
On the Loongson64 platform, if CONFIG_SMP is not set, the following build error will occur: arch/mips/loongson64/reset.c:133:2: error:'secondary_kexec_args' undeclared
Because the definition and declaration of secondary_kexec_args are in the CONFIG_SMP, the secondary_kexec_args variable should be used in CONFIG_SMP.
Reported-by: kernel test robot lkp@intel.com Signed-off-by: Youling Tang tangyouling@loongson.cn Acked-by: Randy Dunlap rdunlap@infradead.org Signed-off-by: Thomas Bogendoerfer tsbogend@alpha.franken.de Signed-off-by: Sasha Levin sashal@kernel.org --- arch/mips/loongson64/reset.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/arch/mips/loongson64/reset.c b/arch/mips/loongson64/reset.c index c97bfdc8c922..758d5d26aaaa 100644 --- a/arch/mips/loongson64/reset.c +++ b/arch/mips/loongson64/reset.c @@ -126,11 +126,12 @@ static void loongson_kexec_shutdown(void) for_each_possible_cpu(cpu) if (!cpu_online(cpu)) cpu_device_up(get_cpu_device(cpu)); + + secondary_kexec_args[0] = TO_UNCAC(0x3ff01000); #endif kexec_args[0] = kexec_argc; kexec_args[1] = fw_arg1; kexec_args[2] = fw_arg2; - secondary_kexec_args[0] = TO_UNCAC(0x3ff01000); memcpy((void *)fw_arg1, kexec_argv, KEXEC_ARGV_SIZE); memcpy((void *)fw_arg2, kexec_envp, KEXEC_ENVP_SIZE); } @@ -141,7 +142,9 @@ static void loongson_crash_shutdown(struct pt_regs *regs) kexec_args[0] = kdump_argc; kexec_args[1] = fw_arg1; kexec_args[2] = fw_arg2; +#ifdef CONFIG_SMP secondary_kexec_args[0] = TO_UNCAC(0x3ff01000); +#endif memcpy((void *)fw_arg1, kdump_argv, KEXEC_ARGV_SIZE); memcpy((void *)fw_arg2, kexec_envp, KEXEC_ENVP_SIZE); }
From: Bibo Mao maobibo@loongson.cn
[ Upstream commit 33ae8f801ad8bec48e886d368739feb2816478f2 ]
If multiple threads are accessing the same huge page at the same time, hugetlb_cow will be called if one thread write the COW huge page. And function huge_ptep_clear_flush is called to notify other threads to clear the huge pte tlb entry. The other threads clear the huge pte tlb entry and reload it from page table, the reload huge pte entry may be old.
This patch fixes this issue on mips platform, and it clears huge pte entry before notifying other threads to flush current huge page entry, it is similar with other architectures.
Signed-off-by: Bibo Mao maobibo@loongson.cn Signed-off-by: Thomas Bogendoerfer tsbogend@alpha.franken.de Signed-off-by: Sasha Levin sashal@kernel.org --- arch/mips/include/asm/hugetlb.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/arch/mips/include/asm/hugetlb.h b/arch/mips/include/asm/hugetlb.h index 10e3be870df7..c2144409c0c4 100644 --- a/arch/mips/include/asm/hugetlb.h +++ b/arch/mips/include/asm/hugetlb.h @@ -46,7 +46,13 @@ static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm, static inline void huge_ptep_clear_flush(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep) { - flush_tlb_page(vma, addr & huge_page_mask(hstate_vma(vma))); + /* + * clear the huge pte entry firstly, so that the other smp threads will + * not get old pte entry after finishing flush_tlb_page and before + * setting new huge pte entry + */ + huge_ptep_get_and_clear(vma->vm_mm, addr, ptep); + flush_tlb_page(vma, addr); }
#define __HAVE_ARCH_HUGE_PTE_NONE
From: Zou Wei zou_wei@huawei.com
[ Upstream commit 1c72e6ab66b9598cac741ed397438a52065a8f1f ]
This module's remove path calls del_timer(). However, that function does not wait until the timer handler finishes. This means that the timer handler may still be running after the driver's remove function has finished, which would result in a use-after-free.
Fix by calling del_timer_sync(), which makes sure the timer handler has finished, and unable to re-schedule itself.
Reported-by: Hulk Robot hulkci@huawei.com Signed-off-by: Zou Wei zou_wei@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/atm/iphase.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/atm/iphase.c b/drivers/atm/iphase.c index 933e3ff2ee8d..3f2ebfb06afd 100644 --- a/drivers/atm/iphase.c +++ b/drivers/atm/iphase.c @@ -3279,7 +3279,7 @@ static void __exit ia_module_exit(void) { pci_unregister_driver(&ia_driver);
- del_timer(&ia_timer); + del_timer_sync(&ia_timer); }
module_init(ia_module_init);
From: Zou Wei zou_wei@huawei.com
[ Upstream commit 009fc857c5f6fda81f2f7dd851b2d54193a8e733 ]
This module's remove path calls del_timer(). However, that function does not wait until the timer handler finishes. This means that the timer handler may still be running after the driver's remove function has finished, which would result in a use-after-free.
Fix by calling del_timer_sync(), which makes sure the timer handler has finished, and unable to re-schedule itself.
Reported-by: Hulk Robot hulkci@huawei.com Signed-off-by: Zou Wei zou_wei@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/isdn/hardware/mISDN/hfcpci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/isdn/hardware/mISDN/hfcpci.c b/drivers/isdn/hardware/mISDN/hfcpci.c index 56bd2e9db6ed..e501cb03f211 100644 --- a/drivers/isdn/hardware/mISDN/hfcpci.c +++ b/drivers/isdn/hardware/mISDN/hfcpci.c @@ -2342,7 +2342,7 @@ static void __exit HFC_cleanup(void) { if (timer_pending(&hfc_tl)) - del_timer(&hfc_tl); + del_timer_sync(&hfc_tl);
pci_unregister_driver(&hfc_driver); }
From: Zou Wei zou_wei@huawei.com
[ Upstream commit 34e7434ba4e97f4b85c1423a59b2922ba7dff2ea ]
This module's remove path calls del_timer(). However, that function does not wait until the timer handler finishes. This means that the timer handler may still be running after the driver's remove function has finished, which would result in a use-after-free.
Fix by calling del_timer_sync(), which makes sure the timer handler has finished, and unable to re-schedule itself.
Reported-by: Hulk Robot hulkci@huawei.com Signed-off-by: Zou Wei zou_wei@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/atm/nicstar.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/atm/nicstar.c b/drivers/atm/nicstar.c index 5c7e4df159b9..b015c3e14336 100644 --- a/drivers/atm/nicstar.c +++ b/drivers/atm/nicstar.c @@ -299,7 +299,7 @@ static void __exit nicstar_cleanup(void) { XPRINTK("nicstar: nicstar_cleanup() called.\n");
- del_timer(&ns_timer); + del_timer_sync(&ns_timer);
pci_unregister_driver(&nicstar_driver);
From: Sebastian Andrzej Siewior bigeasy@linutronix.de
[ Upstream commit 8380c81d5c4fced6f4397795a5ae65758272bbfd ]
__napi_schedule_irqoff() is an optimized version of __napi_schedule() which can be used where it is known that interrupts are disabled, e.g. in interrupt-handlers, spin_lock_irq() sections or hrtimer callbacks.
On PREEMPT_RT enabled kernels this assumptions is not true. Force- threaded interrupt handlers and spinlocks are not disabling interrupts and the NAPI hrtimer callback is forced into softirq context which runs with interrupts enabled as well.
Chasing all usage sites of __napi_schedule_irqoff() is a whack-a-mole game so make __napi_schedule_irqoff() invoke __napi_schedule() for PREEMPT_RT kernels.
The callers of ____napi_schedule() in the networking core have been audited and are correct on PREEMPT_RT kernels as well.
Reported-by: Juri Lelli juri.lelli@redhat.com Signed-off-by: Sebastian Andrzej Siewior bigeasy@linutronix.de Reviewed-by: Thomas Gleixner tglx@linutronix.de Reviewed-by: Juri Lelli juri.lelli@redhat.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- net/core/dev.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/net/core/dev.c b/net/core/dev.c index ef8cf7619baf..50531a2d0b20 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -6520,11 +6520,18 @@ EXPORT_SYMBOL(napi_schedule_prep); * __napi_schedule_irqoff - schedule for receive * @n: entry to schedule * - * Variant of __napi_schedule() assuming hard irqs are masked + * Variant of __napi_schedule() assuming hard irqs are masked. + * + * On PREEMPT_RT enabled kernels this maps to __napi_schedule() + * because the interrupt disabled assumption might not be true + * due to force-threaded interrupts and spinlock substitution. */ void __napi_schedule_irqoff(struct napi_struct *n) { - ____napi_schedule(this_cpu_ptr(&softnet_data), n); + if (!IS_ENABLED(CONFIG_PREEMPT_RT)) + ____napi_schedule(this_cpu_ptr(&softnet_data), n); + else + __napi_schedule(n); } EXPORT_SYMBOL(__napi_schedule_irqoff);
From: Wang Li wangli74@huawei.com
[ Upstream commit 69777e6ca396f0a7e1baff40fcad4a9d3d445b7a ]
pm_runtime_get_sync will increment pm usage counter even it failed. Forgetting to putting operation will result in reference leak here. Fix it by replacing it with pm_runtime_resume_and_get to keep usage counter balanced.
Reported-by: Hulk Robot hulkci@huawei.com Signed-off-by: Wang Li wangli74@huawei.com Signed-off-by: Chun-Kuang Hu chunkuang.hu@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c index 40df2c823187..474efb844249 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c @@ -260,7 +260,7 @@ static int mtk_crtc_ddp_hw_init(struct mtk_drm_crtc *mtk_crtc) drm_connector_list_iter_end(&conn_iter); }
- ret = pm_runtime_get_sync(crtc->dev->dev); + ret = pm_runtime_resume_and_get(crtc->dev->dev); if (ret < 0) { DRM_ERROR("Failed to enable power domain: %d\n", ret); return ret;
From: Nicolas Boichat drinkcat@chromium.org
[ Upstream commit 09da3191827f2fd326205fb58881838e6ea36fb7 ]
GPUs with more than a single regulator (e.g. G72 on MT8183) will require platform-specific handling for devfreq, for 2 reasons: 1. The opp core (drivers/opp/core.c:_generic_set_opp_regulator) does not support multiple regulators, so we'll need custom handlers. 2. Generally, platforms with 2 regulators have platform-specific constraints on how the voltages should be set (e.g. minimum/maximum voltage difference between them), so we should not just create generic handlers that simply change the voltages without taking care of those constraints.
Disable devfreq for now on those GPUs.
Signed-off-by: Nicolas Boichat drinkcat@chromium.org Reviewed-by: Tomeu Vizoso tomeu.vizoso@collabora.com Reviewed-by: Steven Price steven.price@arm.com Signed-off-by: Steven Price steven.price@arm.com Link: https://patchwork.freedesktop.org/patch/msgid/20210421132841.v13.3.I3af068ab... Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/panfrost/panfrost_devfreq.c | 9 +++++++++ 1 file changed, 9 insertions(+)
diff --git a/drivers/gpu/drm/panfrost/panfrost_devfreq.c b/drivers/gpu/drm/panfrost/panfrost_devfreq.c index 47d27e54a34f..3644652f726f 100644 --- a/drivers/gpu/drm/panfrost/panfrost_devfreq.c +++ b/drivers/gpu/drm/panfrost/panfrost_devfreq.c @@ -92,6 +92,15 @@ int panfrost_devfreq_init(struct panfrost_device *pfdev) struct thermal_cooling_device *cooling; struct panfrost_devfreq *pfdevfreq = &pfdev->pfdevfreq;
+ if (pfdev->comp->num_supplies > 1) { + /* + * GPUs with more than 1 supply require platform-specific handling: + * continue without devfreq + */ + DRM_DEV_INFO(dev, "More than 1 supply is not supported yet\n"); + return 0; + } + ret = devm_pm_opp_set_regulators(dev, pfdev->comp->supply_names, pfdev->comp->num_supplies); if (ret) {
From: Ansuel Smith ansuelsmth@gmail.com
[ Upstream commit b097bea10215315e8ee17f88b4c1bbb521b1878c ]
mdio drivers should not use REGCHACHE. Also disable locking since it's handled by the mdio users and regmap is always accessed atomically.
Signed-off-by: Ansuel Smith ansuelsmth@gmail.com Reviewed-by: Florian Fainelli f.fainelli@gmail.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/mdio/mdio-ipq8064.c | 34 +++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-)
diff --git a/drivers/net/mdio/mdio-ipq8064.c b/drivers/net/mdio/mdio-ipq8064.c index 8fe8f0119fc1..8de11f35ac1e 100644 --- a/drivers/net/mdio/mdio-ipq8064.c +++ b/drivers/net/mdio/mdio-ipq8064.c @@ -7,10 +7,9 @@
#include <linux/delay.h> #include <linux/kernel.h> -#include <linux/mfd/syscon.h> #include <linux/module.h> #include <linux/of_mdio.h> -#include <linux/phy.h> +#include <linux/of_address.h> #include <linux/platform_device.h> #include <linux/regmap.h>
@@ -96,14 +95,34 @@ ipq8064_mdio_write(struct mii_bus *bus, int phy_addr, int reg_offset, u16 data) return ipq8064_mdio_wait_busy(priv); }
+static const struct regmap_config ipq8064_mdio_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .can_multi_write = false, + /* the mdio lock is used by any user of this mdio driver */ + .disable_locking = true, + + .cache_type = REGCACHE_NONE, +}; + static int ipq8064_mdio_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; struct ipq8064_mdio *priv; + struct resource res; struct mii_bus *bus; + void __iomem *base; int ret;
+ if (of_address_to_resource(np, 0, &res)) + return -ENOMEM; + + base = ioremap(res.start, resource_size(&res)); + if (!base) + return -ENOMEM; + bus = devm_mdiobus_alloc_size(&pdev->dev, sizeof(*priv)); if (!bus) return -ENOMEM; @@ -115,15 +134,10 @@ ipq8064_mdio_probe(struct platform_device *pdev) bus->parent = &pdev->dev;
priv = bus->priv; - priv->base = device_node_to_regmap(np); - if (IS_ERR(priv->base)) { - if (priv->base == ERR_PTR(-EPROBE_DEFER)) - return -EPROBE_DEFER; - - dev_err(&pdev->dev, "error getting device regmap, error=%pe\n", - priv->base); + priv->base = devm_regmap_init_mmio(&pdev->dev, base, + &ipq8064_mdio_regmap_config); + if (IS_ERR(priv->base)) return PTR_ERR(priv->base); - }
ret = of_mdiobus_register(bus, np); if (ret)
From: Zou Wei zou_wei@huawei.com
[ Upstream commit 8d0b1fe81e18eb66a2d4406386760795fe0d77d9 ]
This patch adds missing MODULE_DEVICE_TABLE definition which generates correct modalias for automatic loading of this driver when it is built as an external module.
Reported-by: Hulk Robot hulkci@huawei.com Signed-off-by: Zou Wei zou_wei@huawei.com Reviewed-by: Robert Foss robert.foss@linaro.org Signed-off-by: Robert Foss robert.foss@linaro.org Link: https://patchwork.freedesktop.org/patch/msgid/1620801955-19188-1-git-send-em... Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/bridge/lontium-lt9611.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/gpu/drm/bridge/lontium-lt9611.c b/drivers/gpu/drm/bridge/lontium-lt9611.c index e8eb8deb444b..29b1ce2140ab 100644 --- a/drivers/gpu/drm/bridge/lontium-lt9611.c +++ b/drivers/gpu/drm/bridge/lontium-lt9611.c @@ -1215,6 +1215,7 @@ static struct i2c_device_id lt9611_id[] = { { "lontium,lt9611", 0 }, {} }; +MODULE_DEVICE_TABLE(i2c, lt9611_id);
static const struct of_device_id lt9611_match_table[] = { { .compatible = "lontium,lt9611" },
From: Pavel Skripkin paskripkin@gmail.com
[ Upstream commit a149127be52fa7eaf5b3681a0317a2bbb772d5a9 ]
syzbot reported divide error in reiserfs. The problem was in incorrect journal 1st block.
Syzbot's reproducer manualy generated wrong superblock with incorrect 1st block. In journal_init() wasn't any checks about this particular case.
For example, if 1st journal block is before superblock 1st block, it can cause zeroing important superblock members in do_journal_end().
Link: https://lore.kernel.org/r/20210517121545.29645-1-paskripkin@gmail.com Reported-by: syzbot+0ba9909df31c6a36974d@syzkaller.appspotmail.com Signed-off-by: Pavel Skripkin paskripkin@gmail.com Signed-off-by: Jan Kara jack@suse.cz Signed-off-by: Sasha Levin sashal@kernel.org --- fs/reiserfs/journal.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+)
diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c index 9edc8e2b154e..0834b101c316 100644 --- a/fs/reiserfs/journal.c +++ b/fs/reiserfs/journal.c @@ -2758,6 +2758,20 @@ int journal_init(struct super_block *sb, const char *j_dev_name, goto free_and_return; }
+ /* + * Sanity check to see if journal first block is correct. + * If journal first block is invalid it can cause + * zeroing important superblock members. + */ + if (!SB_ONDISK_JOURNAL_DEVICE(sb) && + SB_ONDISK_JOURNAL_1st_BLOCK(sb) < SB_JOURNAL_1st_RESERVED_BLOCK(sb)) { + reiserfs_warning(sb, "journal-1393", + "journal 1st super block is invalid: 1st reserved block %d, but actual 1st block is %d", + SB_JOURNAL_1st_RESERVED_BLOCK(sb), + SB_ONDISK_JOURNAL_1st_BLOCK(sb)); + goto free_and_return; + } + if (journal_init_dev(sb, journal, j_dev_name) != 0) { reiserfs_warning(sb, "sh-462", "unable to initialize journal device");
From: Xie Yongji xieyongji@bytedance.com
[ Upstream commit 17f46f488a5d82c5568e6e786cd760bba1c2ee09 ]
The dev->dev_private might not be allocated if virtio_gpu_pci_quirk() or virtio_gpu_init() failed. In this case, we should avoid the cleanup in virtio_gpu_release().
Signed-off-by: Xie Yongji xieyongji@bytedance.com Link: http://patchwork.freedesktop.org/patch/msgid/20210517084913.403-1-xieyongji@... Signed-off-by: Gerd Hoffmann kraxel@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/virtio/virtgpu_kms.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/drivers/gpu/drm/virtio/virtgpu_kms.c b/drivers/gpu/drm/virtio/virtgpu_kms.c index b375394193be..aa532ad31a23 100644 --- a/drivers/gpu/drm/virtio/virtgpu_kms.c +++ b/drivers/gpu/drm/virtio/virtgpu_kms.c @@ -264,6 +264,9 @@ void virtio_gpu_release(struct drm_device *dev) { struct virtio_gpu_device *vgdev = dev->dev_private;
+ if (!vgdev) + return; + virtio_gpu_modeset_fini(vgdev); virtio_gpu_free_vbufs(vgdev); virtio_gpu_cleanup_cap_cache(vgdev);
From: Xie Yongji xieyongji@bytedance.com
[ Upstream commit cec7f1774605a5ef47c134af62afe7c75c30b0ee ]
The virtio_gpu_init() will free vgdev and vgdev->vbufs on failure. But such failure will be caught by virtio_gpu_probe() and then virtio_gpu_release() will be called to do some cleanup which will free vgdev and vgdev->vbufs again. So let's set dev->dev_private to NULL to avoid double free.
Signed-off-by: Xie Yongji xieyongji@bytedance.com Link: http://patchwork.freedesktop.org/patch/msgid/20210517084913.403-2-xieyongji@... Signed-off-by: Gerd Hoffmann kraxel@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/virtio/virtgpu_kms.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/gpu/drm/virtio/virtgpu_kms.c b/drivers/gpu/drm/virtio/virtgpu_kms.c index aa532ad31a23..f3379059f324 100644 --- a/drivers/gpu/drm/virtio/virtgpu_kms.c +++ b/drivers/gpu/drm/virtio/virtgpu_kms.c @@ -234,6 +234,7 @@ int virtio_gpu_init(struct drm_device *dev) err_vbufs: vgdev->vdev->config->del_vqs(vgdev->vdev); err_vqs: + dev->dev_private = NULL; kfree(vgdev); return ret; }
From: Dongseok Yi dseok.yi@samsung.com
[ Upstream commit fa7b83bf3b156c767f3e4a25bbf3817b08f3ff8e ]
In the forwarding path GRO -> BPF 6 to 4 -> GSO for TCP traffic, the coalesced packet payload can be > MSS, but < MSS + 20.
bpf_skb_proto_6_to_4() will upgrade the MSS and it can be > the payload length. After then tcp_gso_segment checks for the payload length if it is <= MSS. The condition is causing the packet to be dropped.
tcp_gso_segment(): [...] mss = skb_shinfo(skb)->gso_size; if (unlikely(skb->len <= mss)) goto out; [...]
Allow to upgrade/downgrade MSS only when BPF_F_ADJ_ROOM_FIXED_GSO is not set.
Signed-off-by: Dongseok Yi dseok.yi@samsung.com Signed-off-by: Daniel Borkmann daniel@iogearbox.net Acked-by: Willem de Bruijn willemb@google.com Link: https://lore.kernel.org/bpf/1620804453-57566-1-git-send-email-dseok.yi@samsu... Signed-off-by: Sasha Levin sashal@kernel.org --- net/core/filter.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-)
diff --git a/net/core/filter.c b/net/core/filter.c index 65ab4e21c087..239de1306de9 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -3235,7 +3235,7 @@ static int bpf_skb_net_hdr_pop(struct sk_buff *skb, u32 off, u32 len) return ret; }
-static int bpf_skb_proto_4_to_6(struct sk_buff *skb) +static int bpf_skb_proto_4_to_6(struct sk_buff *skb, u64 flags) { const u32 len_diff = sizeof(struct ipv6hdr) - sizeof(struct iphdr); u32 off = skb_mac_header_len(skb); @@ -3264,7 +3264,9 @@ static int bpf_skb_proto_4_to_6(struct sk_buff *skb) }
/* Due to IPv6 header, MSS needs to be downgraded. */ - skb_decrease_gso_size(shinfo, len_diff); + if (!(flags & BPF_F_ADJ_ROOM_FIXED_GSO)) + skb_decrease_gso_size(shinfo, len_diff); + /* Header must be checked, and gso_segs recomputed. */ shinfo->gso_type |= SKB_GSO_DODGY; shinfo->gso_segs = 0; @@ -3276,7 +3278,7 @@ static int bpf_skb_proto_4_to_6(struct sk_buff *skb) return 0; }
-static int bpf_skb_proto_6_to_4(struct sk_buff *skb) +static int bpf_skb_proto_6_to_4(struct sk_buff *skb, u64 flags) { const u32 len_diff = sizeof(struct ipv6hdr) - sizeof(struct iphdr); u32 off = skb_mac_header_len(skb); @@ -3305,7 +3307,9 @@ static int bpf_skb_proto_6_to_4(struct sk_buff *skb) }
/* Due to IPv4 header, MSS can be upgraded. */ - skb_increase_gso_size(shinfo, len_diff); + if (!(flags & BPF_F_ADJ_ROOM_FIXED_GSO)) + skb_increase_gso_size(shinfo, len_diff); + /* Header must be checked, and gso_segs recomputed. */ shinfo->gso_type |= SKB_GSO_DODGY; shinfo->gso_segs = 0; @@ -3317,17 +3321,17 @@ static int bpf_skb_proto_6_to_4(struct sk_buff *skb) return 0; }
-static int bpf_skb_proto_xlat(struct sk_buff *skb, __be16 to_proto) +static int bpf_skb_proto_xlat(struct sk_buff *skb, __be16 to_proto, u64 flags) { __be16 from_proto = skb->protocol;
if (from_proto == htons(ETH_P_IP) && to_proto == htons(ETH_P_IPV6)) - return bpf_skb_proto_4_to_6(skb); + return bpf_skb_proto_4_to_6(skb, flags);
if (from_proto == htons(ETH_P_IPV6) && to_proto == htons(ETH_P_IP)) - return bpf_skb_proto_6_to_4(skb); + return bpf_skb_proto_6_to_4(skb, flags);
return -ENOTSUPP; } @@ -3337,7 +3341,7 @@ BPF_CALL_3(bpf_skb_change_proto, struct sk_buff *, skb, __be16, proto, { int ret;
- if (unlikely(flags)) + if (unlikely(flags & ~(BPF_F_ADJ_ROOM_FIXED_GSO))) return -EINVAL;
/* General idea is that this helper does the basic groundwork @@ -3357,7 +3361,7 @@ BPF_CALL_3(bpf_skb_change_proto, struct sk_buff *, skb, __be16, proto, * that. For offloads, we mark packet as dodgy, so that headers * need to be verified first. */ - ret = bpf_skb_proto_xlat(skb, proto); + ret = bpf_skb_proto_xlat(skb, proto, flags); bpf_compute_data_pointers(skb); return ret; }
From: Vladimir Oltean olteanv@gmail.com
[ Upstream commit 86544c3de6a2185409c5a3d02f674ea223a14217 ]
Similar to the way in which of_mdiobus_register() has a fallback to the non-DT based mdiobus_register() when CONFIG_OF is not set, we can create a shim for the device-managed devm_of_mdiobus_register() which calls devm_mdiobus_register() and discards the struct device_node *.
In particular, this solves a build issue with the qca8k DSA driver which uses devm_of_mdiobus_register and can be compiled without CONFIG_OF.
Reported-by: Randy Dunlap rdunlap@infradead.org Signed-off-by: Vladimir Oltean olteanv@gmail.com Acked-by: Randy Dunlap rdunlap@infradead.org # build-tested Reviewed-by: Andrew Lunn andrew@lunn.ch Reviewed-by: Florian Fainelli f.fainelli@gmail.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- include/linux/of_mdio.h | 7 +++++++ 1 file changed, 7 insertions(+)
diff --git a/include/linux/of_mdio.h b/include/linux/of_mdio.h index 2b05e7f7c238..da633d34ab86 100644 --- a/include/linux/of_mdio.h +++ b/include/linux/of_mdio.h @@ -72,6 +72,13 @@ static inline int of_mdiobus_register(struct mii_bus *mdio, struct device_node * return mdiobus_register(mdio); }
+static inline int devm_of_mdiobus_register(struct device *dev, + struct mii_bus *mdio, + struct device_node *np) +{ + return devm_mdiobus_register(dev, mdio); +} + static inline struct mdio_device *of_mdio_find_device(struct device_node *np) { return NULL;
From: Davide Caratti dcaratti@redhat.com
[ Upstream commit 05ff8435e50569a0a6b95e5ceaea43696e8827ab ]
modern userspace applications, like OVN, can configure the TC datapath to "recirculate" packets several times. If more than 4 "recirculation" rules are configured, packets can be dropped by __tcf_classify(). Changing the maximum number of reclassifications (from 4 to 16) should be sufficient to prevent drops in most use cases, and guard against loops at the same time.
Signed-off-by: Davide Caratti dcaratti@redhat.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- net/sched/cls_api.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index 279f9e2a2319..d73b5c5514a9 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c @@ -1531,7 +1531,7 @@ static inline int __tcf_classify(struct sk_buff *skb, u32 *last_executed_chain) { #ifdef CONFIG_NET_CLS_ACT - const int max_reclassify_loop = 4; + const int max_reclassify_loop = 16; const struct tcf_proto *first_tp; int limit = 0;
From: Wei Yongjun weiyongjun1@huawei.com
[ Upstream commit 20e76d3d044d936998617f8acd7e77bebd9ca703 ]
In case of error, the function mdiobus_get_phy() returns NULL pointer not ERR_PTR(). The IS_ERR() test in the return value check should be replaced with NULL test.
Reported-by: Hulk Robot hulkci@huawei.com Signed-off-by: Wei Yongjun weiyongjun1@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/xscale/ixp4xx_eth.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/xscale/ixp4xx_eth.c b/drivers/net/ethernet/xscale/ixp4xx_eth.c index cb89323855d8..1ecceeb9700d 100644 --- a/drivers/net/ethernet/xscale/ixp4xx_eth.c +++ b/drivers/net/ethernet/xscale/ixp4xx_eth.c @@ -1531,8 +1531,8 @@ static int ixp4xx_eth_probe(struct platform_device *pdev) phydev = of_phy_get_and_connect(ndev, np, ixp4xx_adjust_link); } else { phydev = mdiobus_get_phy(mdio_bus, plat->phy); - if (IS_ERR(phydev)) { - err = PTR_ERR(phydev); + if (!phydev) { + err = -ENODEV; dev_err(dev, "could not connect phydev (%d)\n", err); goto err_free_mem; }
From: Bixuan Cui cuibixuan@huawei.com
[ Upstream commit d7f444499d6faf9a6ae3b27ec094109528d2b9a7 ]
This patch adds missing MODULE_DEVICE_TABLE definition which generates correct modalias for automatic loading of this driver when it is built as an external module.
Reported-by: Hulk Robot hulkci@huawei.com Signed-off-by: Bixuan Cui cuibixuan@huawei.com Link: https://lore.kernel.org/r/20210508031502.53637-1-cuibixuan@huawei.com Signed-off-by: Linus Walleij linus.walleij@linaro.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/pinctrl/pinctrl-equilibrium.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/pinctrl/pinctrl-equilibrium.c b/drivers/pinctrl/pinctrl-equilibrium.c index a194d8089b6f..38cc20fa9d5a 100644 --- a/drivers/pinctrl/pinctrl-equilibrium.c +++ b/drivers/pinctrl/pinctrl-equilibrium.c @@ -939,6 +939,7 @@ static const struct of_device_id eqbr_pinctrl_dt_match[] = { { .compatible = "intel,lgm-io" }, {} }; +MODULE_DEVICE_TABLE(of, eqbr_pinctrl_dt_match);
static struct platform_driver eqbr_pinctrl_driver = { .probe = eqbr_pinctrl_probe,
From: Alex Deucher alexander.deucher@amd.com
[ Upstream commit 7230362c78d441020a47d7d5ca81f8a3d07bd9f0 ]
To stay consistent with the user's setting.
v2: rebase on multi-eDP support
Bug: https://gitlab.freedesktop.org/drm/amd/-/issues/1337 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/amdgpu_dm/amdgpu_dm.c | 6 ++++++ 1 file changed, 6 insertions(+)
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 875fd187463e..62663e287b21 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -8967,6 +8967,12 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) /* Update audio instances for each connector. */ amdgpu_dm_commit_audio(dev, state);
+#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) || \ + defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE) + /* restore the backlight level */ + if (dm->backlight_dev) + amdgpu_dm_backlight_set_level(dm, dm->brightness[0]); +#endif /* * send vblank event on all events not handled in flip and * mark consumed event for drm_atomic_helper_commit_hw_done
From: Andrey Grodzovsky andrey.grodzovsky@amd.com
[ Upstream commit c61cdbdbffc169dc7f1e6fe94dfffaf574fe672a ]
Problem: If scheduler is already stopped by the time sched_entity is released and entity's job_queue not empty I encountred a hang in drm_sched_entity_flush. This is because drm_sched_entity_is_idle never becomes false.
Fix: In drm_sched_fini detach all sched_entities from the scheduler's run queues. This will satisfy drm_sched_entity_is_idle. Also wakeup all those processes stuck in sched_entity flushing as the scheduler main thread which wakes them up is stopped by now.
v2: Reverse order of drm_sched_rq_remove_entity and marking s_entity as stopped to prevent reinserion back to rq due to race.
v3: Drop drm_sched_rq_remove_entity, only modify entity->stopped and check for it in drm_sched_entity_is_idle
Signed-off-by: Andrey Grodzovsky andrey.grodzovsky@amd.com Reviewed-by: Christian König christian.koenig@amd.com Link: https://patchwork.freedesktop.org/patch/msgid/20210512142648.666476-14-andre... Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/scheduler/sched_entity.c | 3 ++- drivers/gpu/drm/scheduler/sched_main.c | 24 ++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/scheduler/sched_entity.c b/drivers/gpu/drm/scheduler/sched_entity.c index f0790e9471d1..cb58f692dad9 100644 --- a/drivers/gpu/drm/scheduler/sched_entity.c +++ b/drivers/gpu/drm/scheduler/sched_entity.c @@ -116,7 +116,8 @@ static bool drm_sched_entity_is_idle(struct drm_sched_entity *entity) rmb(); /* for list_empty to work without lock */
if (list_empty(&entity->list) || - spsc_queue_count(&entity->job_queue) == 0) + spsc_queue_count(&entity->job_queue) == 0 || + entity->stopped) return true;
return false; diff --git a/drivers/gpu/drm/scheduler/sched_main.c b/drivers/gpu/drm/scheduler/sched_main.c index 92d8de24d0a1..c105c807d7e5 100644 --- a/drivers/gpu/drm/scheduler/sched_main.c +++ b/drivers/gpu/drm/scheduler/sched_main.c @@ -888,9 +888,33 @@ EXPORT_SYMBOL(drm_sched_init); */ void drm_sched_fini(struct drm_gpu_scheduler *sched) { + struct drm_sched_entity *s_entity; + int i; + if (sched->thread) kthread_stop(sched->thread);
+ for (i = DRM_SCHED_PRIORITY_COUNT - 1; i >= DRM_SCHED_PRIORITY_MIN; i--) { + struct drm_sched_rq *rq = &sched->sched_rq[i]; + + if (!rq) + continue; + + spin_lock(&rq->lock); + list_for_each_entry(s_entity, &rq->entities, list) + /* + * Prevents reinsertion and marks job_queue as idle, + * it will removed from rq in drm_sched_entity_fini + * eventually + */ + s_entity->stopped = true; + spin_unlock(&rq->lock); + + } + + /* Wakeup everyone stuck in drm_sched_entity_flush for this scheduler */ + wake_up_all(&sched->job_scheduled); + /* Confirm no work left behind accessing device structures */ cancel_delayed_work_sync(&sched->work_tdr);
From: Andrey Grodzovsky andrey.grodzovsky@amd.com
[ Upstream commit 0b10ab80695d61422337ede6ff496552d8ace99d ]
Wait for all dependencies of a job to complete before killing it to avoid data corruptions.
Signed-off-by: Andrey Grodzovsky andrey.grodzovsky@amd.com Reviewed-by: Christian König christian.koenig@amd.com Link: https://patchwork.freedesktop.org/patch/msgid/20210519141407.88444-1-andrey.... Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/scheduler/sched_entity.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/drivers/gpu/drm/scheduler/sched_entity.c b/drivers/gpu/drm/scheduler/sched_entity.c index cb58f692dad9..86a4209d8c77 100644 --- a/drivers/gpu/drm/scheduler/sched_entity.c +++ b/drivers/gpu/drm/scheduler/sched_entity.c @@ -222,11 +222,16 @@ static void drm_sched_entity_kill_jobs_cb(struct dma_fence *f, static void drm_sched_entity_kill_jobs(struct drm_sched_entity *entity) { struct drm_sched_job *job; + struct dma_fence *f; int r;
while ((job = to_drm_sched_job(spsc_queue_pop(&entity->job_queue)))) { struct drm_sched_fence *s_fence = job->s_fence;
+ /* Wait for all dependencies to avoid data corruptions */ + while ((f = job->sched->ops->dependency(job, entity))) + dma_fence_wait(f, false); + drm_sched_fence_scheduled(s_fence); dma_fence_set_error(&s_fence->finished, -ESRCH);
From: Arturo Giusti koredump@protonmail.com
[ Upstream commit fa236c2b2d4436d9f19ee4e5d5924e90ffd7bb43 ]
In function udf_symlink, epos.bh is assigned with the value returned by udf_tgetblk. The function udf_tgetblk is defined in udf/misc.c and returns the value of sb_getblk function that could be NULL. Then, epos.bh is used without any check, causing a possible NULL pointer dereference when sb_getblk fails.
This fix adds a check to validate the value of epos.bh.
Link: https://bugzilla.kernel.org/show_bug.cgi?id=213083 Signed-off-by: Arturo Giusti koredump@protonmail.com Signed-off-by: Jan Kara jack@suse.cz Signed-off-by: Sasha Levin sashal@kernel.org --- fs/udf/namei.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/fs/udf/namei.c b/fs/udf/namei.c index 3ae9f1e91984..7c7c9bbbfa57 100644 --- a/fs/udf/namei.c +++ b/fs/udf/namei.c @@ -934,6 +934,10 @@ static int udf_symlink(struct user_namespace *mnt_userns, struct inode *dir, iinfo->i_location.partitionReferenceNum, 0); epos.bh = udf_tgetblk(sb, block); + if (unlikely(!epos.bh)) { + err = -ENOMEM; + goto out_no_entry; + } lock_buffer(epos.bh); memset(epos.bh->b_data, 0x00, bsize); set_buffer_uptodate(epos.bh);
From: YueHaibing yuehaibing@huawei.com
[ Upstream commit d0d62baa7f505bd4c59cd169692ff07ec49dde37 ]
Printing kernel pointers is discouraged because they might leak kernel memory layout. This fixes smatch warning:
drivers/net/ethernet/xilinx/xilinx_emaclite.c:1191 xemaclite_of_probe() warn: argument 4 to %08lX specifier is cast from pointer
Signed-off-by: YueHaibing yuehaibing@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/xilinx/xilinx_emaclite.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/xilinx/xilinx_emaclite.c b/drivers/net/ethernet/xilinx/xilinx_emaclite.c index d9d58a7dabee..b06377fe7293 100644 --- a/drivers/net/ethernet/xilinx/xilinx_emaclite.c +++ b/drivers/net/ethernet/xilinx/xilinx_emaclite.c @@ -1189,9 +1189,8 @@ static int xemaclite_of_probe(struct platform_device *ofdev) }
dev_info(dev, - "Xilinx EmacLite at 0x%08lX mapped to 0x%08lX, irq=%d\n", - (unsigned long __force)ndev->mem_start, - (unsigned long __force)lp->base_addr, ndev->irq); + "Xilinx EmacLite at 0x%08lX mapped to 0x%p, irq=%d\n", + (unsigned long __force)ndev->mem_start, lp->base_addr, ndev->irq); return 0;
error:
From: Feifei Xu Feifei.Xu@amd.com
[ Upstream commit 5051cb794ac5d92154e186d87cdc12cba613f4f6 ]
For default cases,we should return 0. Otherwise resume will abort because of the wrong return value.
Signed-off-by: Feifei Xu Feifei.Xu@amd.com Reviewed-by: Lijo Lazar lijo.lazar@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/smu13/aldebaran_ppt.c | 4 +--- 1 file changed, 1 insertion(+), 3 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 dcbe3a72da09..16ad4683eb69 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c @@ -1779,10 +1779,8 @@ static int aldebaran_set_mp1_state(struct smu_context *smu, case PP_MP1_STATE_UNLOAD: return smu_cmn_set_mp1_state(smu, mp1_state); default: - return -EINVAL; + return 0; } - - return 0; }
static const struct pptable_funcs aldebaran_ppt_funcs = {
From: Mateusz Kwiatkowski kfyatek+publicgit@gmail.com
[ Upstream commit fc7a8abcee2225d6279ff785d33e24d70c738c6e ]
On the BCM2711 (Raspberry Pi 4), the VEC is actually connected to output 2 of pixelvalve3.
NOTE: This contradicts the Broadcom docs, but has been empirically tested and confirmed by Raspberry Pi firmware devs.
Signed-off-by: Mateusz Kwiatkowski kfyatek+publicgit@gmail.com Signed-off-by: Maxime Ripard maxime@cerno.tech Reviewed-by: Dave Stevenson dave.stevenson@raspberrypi.com Link: https://patchwork.freedesktop.org/patch/msgid/20210520150344.273900-2-maxime... Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/vc4/vc4_crtc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index 76657dcdf9b0..665ddf8f347f 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -994,7 +994,7 @@ static const struct vc4_pv_data bcm2711_pv3_data = { .fifo_depth = 64, .pixels_per_clock = 1, .encoder_types = { - [0] = VC4_ENCODER_TYPE_VEC, + [PV_CONTROL_CLK_SELECT_VEC] = VC4_ENCODER_TYPE_VEC, }, };
From: Zou Wei zou_wei@huawei.com
[ Upstream commit 5e4322a8b266bc9f5ee7ea4895f661c01dbd7cb3 ]
pm_runtime_get_sync will increment pm usage counter even it failed. Forgetting to putting operation will result in reference leak here. Fix it by replacing it with pm_runtime_resume_and_get to keep usage counter balanced.
Reported-by: Hulk Robot hulkci@huawei.com Signed-off-by: Zou Wei zou_wei@huawei.com Signed-off-by: Maxime Ripard maxime@cerno.tech Link: https://patchwork.freedesktop.org/patch/msgid/1621840854-105978-1-git-send-e... Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/vc4/vc4_hdmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 8106b5634fe1..d1c9819ea9f9 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -745,7 +745,7 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder, unsigned long pixel_rate, hsm_rate; int ret;
- ret = pm_runtime_get_sync(&vc4_hdmi->pdev->dev); + ret = pm_runtime_resume_and_get(&vc4_hdmi->pdev->dev); if (ret < 0) { DRM_ERROR("Failed to retain power domain: %d\n", ret); return;
From: Jesse Brandeburg jesse.brandeburg@intel.com
[ Upstream commit d4ef55288aa2e1b76033717242728ac98ddc4721 ]
Sparse tool was warning on some implicit conversions from little endian data read from the EEPROM on the e100 cards.
Fix these by being explicit about the conversions using le16_to_cpu().
Signed-off-by: Jesse Brandeburg jesse.brandeburg@intel.com Signed-off-by: Tony Nguyen anthony.l.nguyen@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/intel/e100.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/net/ethernet/intel/e100.c b/drivers/net/ethernet/intel/e100.c index f8d78af76d7d..1b0958bd24f6 100644 --- a/drivers/net/ethernet/intel/e100.c +++ b/drivers/net/ethernet/intel/e100.c @@ -1395,7 +1395,7 @@ static int e100_phy_check_without_mii(struct nic *nic) u8 phy_type; int without_mii;
- phy_type = (nic->eeprom[eeprom_phy_iface] >> 8) & 0x0f; + phy_type = (le16_to_cpu(nic->eeprom[eeprom_phy_iface]) >> 8) & 0x0f;
switch (phy_type) { case NoSuchPhy: /* Non-MII PHY; UNTESTED! */ @@ -1515,7 +1515,7 @@ static int e100_phy_init(struct nic *nic) mdio_write(netdev, nic->mii.phy_id, MII_BMCR, bmcr); } else if ((nic->mac >= mac_82550_D102) || ((nic->flags & ich) && (mdio_read(netdev, nic->mii.phy_id, MII_TPISTATUS) & 0x8000) && - (nic->eeprom[eeprom_cnfg_mdix] & eeprom_mdix_enabled))) { + (le16_to_cpu(nic->eeprom[eeprom_cnfg_mdix]) & eeprom_mdix_enabled))) { /* enable/disable MDI/MDI-X auto-switching. */ mdio_write(netdev, nic->mii.phy_id, MII_NCONFIG, nic->mii.force_media ? 0 : NCONFIG_AUTO_SWITCH); @@ -2269,9 +2269,9 @@ static int e100_asf(struct nic *nic) { /* ASF can be enabled from eeprom */ return (nic->pdev->device >= 0x1050) && (nic->pdev->device <= 0x1057) && - (nic->eeprom[eeprom_config_asf] & eeprom_asf) && - !(nic->eeprom[eeprom_config_asf] & eeprom_gcl) && - ((nic->eeprom[eeprom_smbus_addr] & 0xFF) != 0xFE); + (le16_to_cpu(nic->eeprom[eeprom_config_asf]) & eeprom_asf) && + !(le16_to_cpu(nic->eeprom[eeprom_config_asf]) & eeprom_gcl) && + ((le16_to_cpu(nic->eeprom[eeprom_smbus_addr]) & 0xFF) != 0xFE); }
static int e100_up(struct nic *nic) @@ -2926,7 +2926,7 @@ static int e100_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
/* Wol magic packet can be enabled from eeprom */ if ((nic->mac >= mac_82558_D101_A4) && - (nic->eeprom[eeprom_id] & eeprom_id_wol)) { + (le16_to_cpu(nic->eeprom[eeprom_id]) & eeprom_id_wol)) { nic->flags |= wol_magic; device_set_wakeup_enable(&pdev->dev, true); }
From: Jesse Brandeburg jesse.brandeburg@intel.com
[ Upstream commit c7cbfb028b95360403d579c47aaaeef1ff140964 ]
The sparse build (C=2) finds some issues with how the driver dealt with the (very difficult) hardware that in some generations uses little-endian, and in others uses big endian, for the VLAN field. The code as written picks __le16 as a type and for some hardware revisions we override it to __be16 as done in this patch. This impacted the VF driver as well so fix it there too.
Also change the vlan_tci assignment to override the sparse warning without changing functionality.
Signed-off-by: Jesse Brandeburg jesse.brandeburg@intel.com Tested-by: Dave Switzer david.switzer@intel.com Signed-off-by: Tony Nguyen anthony.l.nguyen@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/intel/igb/igb_main.c | 5 +++-- drivers/net/ethernet/intel/igbvf/netdev.c | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index b2a042f825ff..b0232a8de343 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -2643,7 +2643,8 @@ static int igb_parse_cls_flower(struct igb_adapter *adapter, }
input->filter.match_flags |= IGB_FILTER_FLAG_VLAN_TCI; - input->filter.vlan_tci = match.key->vlan_priority; + input->filter.vlan_tci = + (__force __be16)match.key->vlan_priority; } }
@@ -8592,7 +8593,7 @@ static void igb_process_skb_fields(struct igb_ring *rx_ring,
if (igb_test_staterr(rx_desc, E1000_RXDEXT_STATERR_LB) && test_bit(IGB_RING_FLAG_RX_LB_VLAN_BSWAP, &rx_ring->flags)) - vid = be16_to_cpu(rx_desc->wb.upper.vlan); + vid = be16_to_cpu((__force __be16)rx_desc->wb.upper.vlan); else vid = le16_to_cpu(rx_desc->wb.upper.vlan);
diff --git a/drivers/net/ethernet/intel/igbvf/netdev.c b/drivers/net/ethernet/intel/igbvf/netdev.c index fb3fbcb13331..630c1155f196 100644 --- a/drivers/net/ethernet/intel/igbvf/netdev.c +++ b/drivers/net/ethernet/intel/igbvf/netdev.c @@ -83,14 +83,14 @@ static int igbvf_desc_unused(struct igbvf_ring *ring) static void igbvf_receive_skb(struct igbvf_adapter *adapter, struct net_device *netdev, struct sk_buff *skb, - u32 status, u16 vlan) + u32 status, __le16 vlan) { u16 vid;
if (status & E1000_RXD_STAT_VP) { if ((adapter->flags & IGBVF_FLAG_RX_LB_VLAN_BSWAP) && (status & E1000_RXDEXT_STATERR_LB)) - vid = be16_to_cpu(vlan) & E1000_RXD_SPC_VLAN_MASK; + vid = be16_to_cpu((__force __be16)vlan) & E1000_RXD_SPC_VLAN_MASK; else vid = le16_to_cpu(vlan) & E1000_RXD_SPC_VLAN_MASK; if (test_bit(vid, adapter->active_vlans))
From: Jesse Brandeburg jesse.brandeburg@intel.com
[ Upstream commit b514958dd1a3bd57638b0e63b8e5152b1960e6aa ]
The igb driver was trying hard to be sparse correct, but somehow ended up converting a variable into little endian order and then tries to OR something with it.
A much plainer way of doing things is to leave all variables and OR operations in CPU (non-endian) mode, and then convert to little endian only once, which is what this change does.
This probably fixes a bug that might have been seen only on big endian systems.
Signed-off-by: Jesse Brandeburg jesse.brandeburg@intel.com Tested-by: Dave Switzer david.switzer@intel.com Signed-off-by: Tony Nguyen anthony.l.nguyen@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/intel/igb/igb_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index b0232a8de343..7b1885f9ce03 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -6276,12 +6276,12 @@ int igb_xmit_xdp_ring(struct igb_adapter *adapter, cmd_type |= len | IGB_TXD_DCMD; tx_desc->read.cmd_type_len = cpu_to_le32(cmd_type);
- olinfo_status = cpu_to_le32(len << E1000_ADVTXD_PAYLEN_SHIFT); + olinfo_status = len << E1000_ADVTXD_PAYLEN_SHIFT; /* 82575 requires a unique index per ring */ if (test_bit(IGB_RING_FLAG_TX_CTX_IDX, &tx_ring->flags)) olinfo_status |= tx_ring->reg_idx << 4;
- tx_desc->read.olinfo_status = olinfo_status; + tx_desc->read.olinfo_status = cpu_to_le32(olinfo_status);
netdev_tx_sent_queue(txring_txq(tx_ring), tx_buffer->bytecount);
From: Zou Wei zou_wei@huawei.com
[ Upstream commit 33f90f27e1c5ccd648d3e78a1c28be9ee8791cf1 ]
pm_runtime_get_sync will increment pm usage counter even it failed. Forgetting to putting operation will result in reference leak here. Fix it by replacing it with pm_runtime_resume_and_get to keep usage counter balanced.
Reported-by: Hulk Robot hulkci@huawei.com Signed-off-by: Zou Wei zou_wei@huawei.com Reviewed-by: Robert Foss robert.foss@linaro.org Signed-off-by: Robert Foss robert.foss@linaro.org Link: https://patchwork.freedesktop.org/patch/msgid/1621840862-106024-1-git-send-e... Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/bridge/cdns-dsi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/bridge/cdns-dsi.c b/drivers/gpu/drm/bridge/cdns-dsi.c index 76373e31df92..b31281f76117 100644 --- a/drivers/gpu/drm/bridge/cdns-dsi.c +++ b/drivers/gpu/drm/bridge/cdns-dsi.c @@ -1028,7 +1028,7 @@ static ssize_t cdns_dsi_transfer(struct mipi_dsi_host *host, struct mipi_dsi_packet packet; int ret, i, tx_len, rx_len;
- ret = pm_runtime_get_sync(host->dev); + ret = pm_runtime_resume_and_get(host->dev); if (ret < 0) return ret;
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
[ Upstream commit 790c06cc5df263cdaff748670cc65958c81b0951 ]
R-Car D3 ZA2 clock is from PLL0D3 or S0, and it can be controlled by ZA2CKCR. It is needed for R-Car Sound, but is not used so far. Using default settings is very enough at this point. This patch adds it by DEF_FIXED().
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com Link: https://lore.kernel.org/r/87pmxclrmy.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Geert Uytterhoeven geert+renesas@glider.be Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/clk/renesas/r8a77995-cpg-mssr.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/clk/renesas/r8a77995-cpg-mssr.c b/drivers/clk/renesas/r8a77995-cpg-mssr.c index 9cfd00cf4e69..81c0bc1e78af 100644 --- a/drivers/clk/renesas/r8a77995-cpg-mssr.c +++ b/drivers/clk/renesas/r8a77995-cpg-mssr.c @@ -75,6 +75,7 @@ static const struct cpg_core_clk r8a77995_core_clks[] __initconst = { DEF_RATE(".oco", CLK_OCO, 8 * 1000 * 1000),
/* Core Clock Outputs */ + DEF_FIXED("za2", R8A77995_CLK_ZA2, CLK_PLL0D3, 2, 1), DEF_FIXED("z2", R8A77995_CLK_Z2, CLK_PLL0D3, 1, 1), DEF_FIXED("ztr", R8A77995_CLK_ZTR, CLK_PLL1, 6, 1), DEF_FIXED("zt", R8A77995_CLK_ZT, CLK_PLL1, 4, 1),
From: Dmytro Laktyushkin Dmytro.Laktyushkin@amd.com
[ Upstream commit 6566cae7aef30da8833f1fa0eb854baf33b96676 ]
There are two issues with scaling calculations, odm recout calculation and matching viewport to actual recout.
This change fixes both issues. Odm recout calculation via special casing and viewport matching issue by reworking the viewport calcualtion to use scaling ratios and recout to derrive the required offset and size.
Signed-off-by: Dmytro Laktyushkin Dmytro.Laktyushkin@amd.com Reviewed-by: Jun Lei Jun.Lei@amd.com Acked-by: Qingqing Zhuo qingqing.zhuo@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/core/dc_resource.c | 568 +++++++----------- drivers/gpu/drm/amd/display/dc/dc_types.h | 5 - .../drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c | 12 +- .../drm/amd/display/dc/dcn20/dcn20_resource.c | 14 +- .../amd/display/dc/dml/display_mode_structs.h | 2 + .../drm/amd/display/dc/dml/display_mode_vba.c | 13 + .../gpu/drm/amd/display/dc/inc/hw/transform.h | 4 - 7 files changed, 232 insertions(+), 386 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 8cb937c046aa..78278a10d899 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -695,124 +695,23 @@ static void calculate_split_count_and_index(struct pipe_ctx *pipe_ctx, int *spli } }
-static void calculate_viewport(struct pipe_ctx *pipe_ctx) +/* + * This is a preliminary vp size calculation to allow us to check taps support. + * The result is completely overridden afterwards. + */ +static void calculate_viewport_size(struct pipe_ctx *pipe_ctx) { - const struct dc_plane_state *plane_state = pipe_ctx->plane_state; - const struct dc_stream_state *stream = pipe_ctx->stream; struct scaler_data *data = &pipe_ctx->plane_res.scl_data; - struct rect surf_src = plane_state->src_rect; - struct rect clip, dest; - int vpc_div = (data->format == PIXEL_FORMAT_420BPP8 - || data->format == PIXEL_FORMAT_420BPP10) ? 2 : 1; - int split_count = 0; - int split_idx = 0; - bool orthogonal_rotation, flip_y_start, flip_x_start; - - calculate_split_count_and_index(pipe_ctx, &split_count, &split_idx);
- if (stream->view_format == VIEW_3D_FORMAT_SIDE_BY_SIDE || - stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) { - split_count = 0; - split_idx = 0; - } - - /* The actual clip is an intersection between stream - * source and surface clip - */ - dest = plane_state->dst_rect; - clip.x = stream->src.x > plane_state->clip_rect.x ? - stream->src.x : plane_state->clip_rect.x; - - clip.width = stream->src.x + stream->src.width < - plane_state->clip_rect.x + plane_state->clip_rect.width ? - stream->src.x + stream->src.width - clip.x : - plane_state->clip_rect.x + plane_state->clip_rect.width - clip.x ; - - clip.y = stream->src.y > plane_state->clip_rect.y ? - stream->src.y : plane_state->clip_rect.y; - - clip.height = stream->src.y + stream->src.height < - plane_state->clip_rect.y + plane_state->clip_rect.height ? - stream->src.y + stream->src.height - clip.y : - plane_state->clip_rect.y + plane_state->clip_rect.height - clip.y ; - - /* - * Need to calculate how scan origin is shifted in vp space - * to correctly rotate clip and dst - */ - get_vp_scan_direction( - plane_state->rotation, - plane_state->horizontal_mirror, - &orthogonal_rotation, - &flip_y_start, - &flip_x_start); - - if (orthogonal_rotation) { - swap(clip.x, clip.y); - swap(clip.width, clip.height); - swap(dest.x, dest.y); - swap(dest.width, dest.height); - } - if (flip_x_start) { - clip.x = dest.x + dest.width - clip.x - clip.width; - dest.x = 0; - } - if (flip_y_start) { - clip.y = dest.y + dest.height - clip.y - clip.height; - dest.y = 0; - } - - /* offset = surf_src.ofs + (clip.ofs - surface->dst_rect.ofs) * scl_ratio - * num_pixels = clip.num_pix * scl_ratio - */ - data->viewport.x = surf_src.x + (clip.x - dest.x) * surf_src.width / dest.width; - data->viewport.width = clip.width * surf_src.width / dest.width; - - data->viewport.y = surf_src.y + (clip.y - dest.y) * surf_src.height / dest.height; - data->viewport.height = clip.height * surf_src.height / dest.height; - - /* Handle split */ - if (split_count) { - /* extra pixels in the division remainder need to go to pipes after - * the extra pixel index minus one(epimo) defined here as: - */ - int epimo = 0; - - if (orthogonal_rotation) { - if (flip_y_start) - split_idx = split_count - split_idx; - - epimo = split_count - data->viewport.height % (split_count + 1); - - data->viewport.y += (data->viewport.height / (split_count + 1)) * split_idx; - if (split_idx > epimo) - data->viewport.y += split_idx - epimo - 1; - data->viewport.height = data->viewport.height / (split_count + 1) + (split_idx > epimo ? 1 : 0); - } else { - if (flip_x_start) - split_idx = split_count - split_idx; - - epimo = split_count - data->viewport.width % (split_count + 1); - - data->viewport.x += (data->viewport.width / (split_count + 1)) * split_idx; - if (split_idx > epimo) - data->viewport.x += split_idx - epimo - 1; - data->viewport.width = data->viewport.width / (split_count + 1) + (split_idx > epimo ? 1 : 0); - } + data->viewport.width = dc_fixpt_ceil(dc_fixpt_mul_int(data->ratios.horz, data->recout.width)); + data->viewport.height = dc_fixpt_ceil(dc_fixpt_mul_int(data->ratios.vert, data->recout.height)); + data->viewport_c.width = dc_fixpt_ceil(dc_fixpt_mul_int(data->ratios.horz_c, data->recout.width)); + data->viewport_c.height = dc_fixpt_ceil(dc_fixpt_mul_int(data->ratios.vert_c, data->recout.height)); + if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90 || + pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270) { + swap(data->viewport.width, data->viewport.height); + swap(data->viewport_c.width, data->viewport_c.height); } - - /* Round down, compensate in init */ - data->viewport_c.x = data->viewport.x / vpc_div; - data->viewport_c.y = data->viewport.y / vpc_div; - data->inits.h_c = (data->viewport.x % vpc_div) != 0 ? dc_fixpt_half : dc_fixpt_zero; - data->inits.v_c = (data->viewport.y % vpc_div) != 0 ? dc_fixpt_half : dc_fixpt_zero; - - /* Round up, assume original video size always even dimensions */ - data->viewport_c.width = (data->viewport.width + vpc_div - 1) / vpc_div; - data->viewport_c.height = (data->viewport.height + vpc_div - 1) / vpc_div; - - data->viewport_unadjusted = data->viewport; - data->viewport_c_unadjusted = data->viewport_c; }
static void calculate_recout(struct pipe_ctx *pipe_ctx) @@ -821,26 +720,21 @@ static void calculate_recout(struct pipe_ctx *pipe_ctx) const struct dc_stream_state *stream = pipe_ctx->stream; struct scaler_data *data = &pipe_ctx->plane_res.scl_data; struct rect surf_clip = plane_state->clip_rect; - bool pri_split_tb = pipe_ctx->bottom_pipe && - pipe_ctx->bottom_pipe->plane_state == pipe_ctx->plane_state && - stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM; - bool sec_split_tb = pipe_ctx->top_pipe && - pipe_ctx->top_pipe->plane_state == pipe_ctx->plane_state && - stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM; - int split_count = 0; - int split_idx = 0; + bool split_tb = stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM; + int split_count, split_idx;
calculate_split_count_and_index(pipe_ctx, &split_count, &split_idx); + if (stream->view_format == VIEW_3D_FORMAT_SIDE_BY_SIDE) + split_idx = 0;
/* * Only the leftmost ODM pipe should be offset by a nonzero distance */ - if (!pipe_ctx->prev_odm_pipe) { + if (!pipe_ctx->prev_odm_pipe || split_idx == split_count) { data->recout.x = stream->dst.x; if (stream->src.x < surf_clip.x) data->recout.x += (surf_clip.x - stream->src.x) * stream->dst.width / stream->src.width; - } else data->recout.x = 0;
@@ -861,26 +755,31 @@ static void calculate_recout(struct pipe_ctx *pipe_ctx) if (data->recout.height + data->recout.y > stream->dst.y + stream->dst.height) data->recout.height = stream->dst.y + stream->dst.height - data->recout.y;
- /* Handle h & v split, handle rotation using viewport */ - if (sec_split_tb) { - data->recout.y += data->recout.height / 2; - /* Floor primary pipe, ceil 2ndary pipe */ - data->recout.height = (data->recout.height + 1) / 2; - } else if (pri_split_tb) + /* Handle h & v split */ + if (split_tb) { + ASSERT(data->recout.height % 2 == 0); data->recout.height /= 2; - else if (split_count) { - /* extra pixels in the division remainder need to go to pipes after - * the extra pixel index minus one(epimo) defined here as: - */ - int epimo = split_count - data->recout.width % (split_count + 1); - - /*no recout offset due to odm */ + } else if (split_count) { if (!pipe_ctx->next_odm_pipe && !pipe_ctx->prev_odm_pipe) { + /* extra pixels in the division remainder need to go to pipes after + * the extra pixel index minus one(epimo) defined here as: + */ + int epimo = split_count - data->recout.width % (split_count + 1); + data->recout.x += (data->recout.width / (split_count + 1)) * split_idx; if (split_idx > epimo) data->recout.x += split_idx - epimo - 1; + ASSERT(stream->view_format != VIEW_3D_FORMAT_SIDE_BY_SIDE || data->recout.width % 2 == 0); + data->recout.width = data->recout.width / (split_count + 1) + (split_idx > epimo ? 1 : 0); + } else { + /* odm */ + if (split_idx == split_count) { + /* rightmost pipe is the remainder recout */ + data->recout.width -= data->h_active * split_count - data->recout.x; + data->recout.x = 0; + } else + data->recout.width = data->h_active - data->recout.x; } - data->recout.width = data->recout.width / (split_count + 1) + (split_idx > epimo ? 1 : 0); } }
@@ -934,9 +833,15 @@ static void calculate_scaling_ratios(struct pipe_ctx *pipe_ctx) pipe_ctx->plane_res.scl_data.ratios.vert_c, 19); }
-static inline void adjust_vp_and_init_for_seamless_clip( + +/* + * We completely calculate vp offset, size and inits here based entirely on scaling + * ratios and recout for pixel perfect pipe combine. + */ +static void calculate_init_and_vp( bool flip_scan_dir, - int recout_skip, + int recout_offset_within_recout_full, + int recout_size, int src_size, int taps, struct fixed31_32 ratio, @@ -944,91 +849,87 @@ static inline void adjust_vp_and_init_for_seamless_clip( int *vp_offset, int *vp_size) { - if (!flip_scan_dir) { - /* Adjust for viewport end clip-off */ - if ((*vp_offset + *vp_size) < src_size) { - int vp_clip = src_size - *vp_size - *vp_offset; - int int_part = dc_fixpt_floor(dc_fixpt_sub(*init, ratio)); - - int_part = int_part > 0 ? int_part : 0; - *vp_size += int_part < vp_clip ? int_part : vp_clip; - } - - /* Adjust for non-0 viewport offset */ - if (*vp_offset) { - int int_part; - - *init = dc_fixpt_add(*init, dc_fixpt_mul_int(ratio, recout_skip)); - int_part = dc_fixpt_floor(*init) - *vp_offset; - if (int_part < taps) { - int int_adj = *vp_offset >= (taps - int_part) ? - (taps - int_part) : *vp_offset; - *vp_offset -= int_adj; - *vp_size += int_adj; - int_part += int_adj; - } else if (int_part > taps) { - *vp_offset += int_part - taps; - *vp_size -= int_part - taps; - int_part = taps; - } - init->value &= 0xffffffff; - *init = dc_fixpt_add_int(*init, int_part); - } - } else { - /* Adjust for non-0 viewport offset */ - if (*vp_offset) { - int int_part = dc_fixpt_floor(dc_fixpt_sub(*init, ratio)); - - int_part = int_part > 0 ? int_part : 0; - *vp_size += int_part < *vp_offset ? int_part : *vp_offset; - *vp_offset -= int_part < *vp_offset ? int_part : *vp_offset; - } + struct fixed31_32 temp; + int int_part;
- /* Adjust for viewport end clip-off */ - if ((*vp_offset + *vp_size) < src_size) { - int int_part; - int end_offset = src_size - *vp_offset - *vp_size; - - /* - * this is init if vp had no offset, keep in mind this is from the - * right side of vp due to scan direction - */ - *init = dc_fixpt_add(*init, dc_fixpt_mul_int(ratio, recout_skip)); - /* - * this is the difference between first pixel of viewport available to read - * and init position, takning into account scan direction - */ - int_part = dc_fixpt_floor(*init) - end_offset; - if (int_part < taps) { - int int_adj = end_offset >= (taps - int_part) ? - (taps - int_part) : end_offset; - *vp_size += int_adj; - int_part += int_adj; - } else if (int_part > taps) { - *vp_size += int_part - taps; - int_part = taps; - } - init->value &= 0xffffffff; - *init = dc_fixpt_add_int(*init, int_part); - } + /* + * First of the taps starts sampling pixel number <init_int_part> corresponding to recout + * pixel 1. Next recout pixel samples int part of <init + scaling ratio> and so on. + * All following calculations are based on this logic. + * + * Init calculated according to formula: + * init = (scaling_ratio + number_of_taps + 1) / 2 + * init_bot = init + scaling_ratio + * to get pixel perfect combine add the fraction from calculating vp offset + */ + temp = dc_fixpt_mul_int(ratio, recout_offset_within_recout_full); + *vp_offset = dc_fixpt_floor(temp); + temp.value &= 0xffffffff; + *init = dc_fixpt_truncate(dc_fixpt_add(dc_fixpt_div_int( + dc_fixpt_add_int(ratio, taps + 1), 2), temp), 19); + /* + * If viewport has non 0 offset and there are more taps than covered by init then + * we should decrease the offset and increase init so we are never sampling + * outside of viewport. + */ + int_part = dc_fixpt_floor(*init); + if (int_part < taps) { + int_part = taps - int_part; + if (int_part > *vp_offset) + int_part = *vp_offset; + *vp_offset -= int_part; + *init = dc_fixpt_add_int(*init, int_part); } + /* + * If taps are sampling outside of viewport at end of recout and there are more pixels + * available in the surface we should increase the viewport size, regardless set vp to + * only what is used. + */ + temp = dc_fixpt_add(*init, dc_fixpt_mul_int(ratio, recout_size - 1)); + *vp_size = dc_fixpt_floor(temp); + if (*vp_size + *vp_offset > src_size) + *vp_size = src_size - *vp_offset; + + /* We did all the math assuming we are scanning same direction as display does, + * however mirror/rotation changes how vp scans vs how it is offset. If scan direction + * is flipped we simply need to calculate offset from the other side of plane. + * Note that outside of viewport all scaling hardware works in recout space. + */ + if (flip_scan_dir) + *vp_offset = src_size - *vp_offset - *vp_size; }
-static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx) +static void calculate_inits_and_viewports(struct pipe_ctx *pipe_ctx) { const struct dc_plane_state *plane_state = pipe_ctx->plane_state; const struct dc_stream_state *stream = pipe_ctx->stream; - struct pipe_ctx *odm_pipe = pipe_ctx; struct scaler_data *data = &pipe_ctx->plane_res.scl_data; - struct rect src = pipe_ctx->plane_state->src_rect; - int recout_skip_h, recout_skip_v, surf_size_h, surf_size_v; + struct rect src = plane_state->src_rect; int vpc_div = (data->format == PIXEL_FORMAT_420BPP8 - || data->format == PIXEL_FORMAT_420BPP10) ? 2 : 1; + || data->format == PIXEL_FORMAT_420BPP10) ? 2 : 1; + int split_count, split_idx, ro_lb, ro_tb, recout_full_x, recout_full_y; bool orthogonal_rotation, flip_vert_scan_dir, flip_horz_scan_dir; - int odm_idx = 0;
+ calculate_split_count_and_index(pipe_ctx, &split_count, &split_idx); /* - * Need to calculate the scan direction for viewport to make adjustments + * recout full is what the recout would have been if we didnt clip + * the source plane at all. We only care about left(ro_lb) and top(ro_tb) + * offsets of recout within recout full because those are the directions + * we scan from and therefore the only ones that affect inits. + */ + recout_full_x = stream->dst.x + (plane_state->dst_rect.x - stream->src.x) + * stream->dst.width / stream->src.width; + recout_full_y = stream->dst.y + (plane_state->dst_rect.y - stream->src.y) + * stream->dst.height / stream->src.height; + if (pipe_ctx->prev_odm_pipe && split_idx) + ro_lb = data->h_active * split_idx - recout_full_x; + else + ro_lb = data->recout.x - recout_full_x; + ro_tb = data->recout.y - recout_full_y; + ASSERT(ro_lb >= 0 && ro_tb >= 0); + + /* + * Work in recout rotation since that requires less transformations */ get_vp_scan_direction( plane_state->rotation, @@ -1037,145 +938,62 @@ static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx) &flip_vert_scan_dir, &flip_horz_scan_dir);
- /* Calculate src rect rotation adjusted to recout space */ - surf_size_h = src.x + src.width; - surf_size_v = src.y + src.height; - if (flip_horz_scan_dir) - src.x = 0; - if (flip_vert_scan_dir) - src.y = 0; if (orthogonal_rotation) { - swap(src.x, src.y); swap(src.width, src.height); + swap(flip_vert_scan_dir, flip_horz_scan_dir); }
- /*modified recout_skip_h calculation due to odm having no recout offset*/ - while (odm_pipe->prev_odm_pipe) { - odm_idx++; - odm_pipe = odm_pipe->prev_odm_pipe; - } - /*odm_pipe is the leftmost pipe in the ODM group*/ - recout_skip_h = odm_idx * data->recout.width; - - /* Recout matching initial vp offset = recout_offset - (stream dst offset + - * ((surf dst offset - stream src offset) * 1/ stream scaling ratio) - * - (surf surf_src offset * 1/ full scl ratio)) - */ - recout_skip_h += odm_pipe->plane_res.scl_data.recout.x - - (stream->dst.x + (plane_state->dst_rect.x - stream->src.x) - * stream->dst.width / stream->src.width - - src.x * plane_state->dst_rect.width / src.width - * stream->dst.width / stream->src.width); - - - recout_skip_v = data->recout.y - (stream->dst.y + (plane_state->dst_rect.y - stream->src.y) - * stream->dst.height / stream->src.height - - src.y * plane_state->dst_rect.height / src.height - * stream->dst.height / stream->src.height); - if (orthogonal_rotation) - swap(recout_skip_h, recout_skip_v); - /* - * Init calculated according to formula: - * init = (scaling_ratio + number_of_taps + 1) / 2 - * init_bot = init + scaling_ratio - * init_c = init + truncated_vp_c_offset(from calculate viewport) - */ - data->inits.h = dc_fixpt_truncate(dc_fixpt_div_int( - dc_fixpt_add_int(data->ratios.horz, data->taps.h_taps + 1), 2), 19); - - data->inits.h_c = dc_fixpt_truncate(dc_fixpt_add(data->inits.h_c, dc_fixpt_div_int( - dc_fixpt_add_int(data->ratios.horz_c, data->taps.h_taps_c + 1), 2)), 19); - - data->inits.v = dc_fixpt_truncate(dc_fixpt_div_int( - dc_fixpt_add_int(data->ratios.vert, data->taps.v_taps + 1), 2), 19); - - data->inits.v_c = dc_fixpt_truncate(dc_fixpt_add(data->inits.v_c, dc_fixpt_div_int( - dc_fixpt_add_int(data->ratios.vert_c, data->taps.v_taps_c + 1), 2)), 19); - - /* - * Taps, inits and scaling ratios are in recout space need to rotate - * to viewport rotation before adjustment - */ - adjust_vp_and_init_for_seamless_clip( + calculate_init_and_vp( flip_horz_scan_dir, - recout_skip_h, - surf_size_h, - orthogonal_rotation ? data->taps.v_taps : data->taps.h_taps, - orthogonal_rotation ? data->ratios.vert : data->ratios.horz, - orthogonal_rotation ? &data->inits.v : &data->inits.h, + ro_lb, + data->recout.width, + src.width, + data->taps.h_taps, + data->ratios.horz, + &data->inits.h, &data->viewport.x, &data->viewport.width); - adjust_vp_and_init_for_seamless_clip( + calculate_init_and_vp( flip_horz_scan_dir, - recout_skip_h, - surf_size_h / vpc_div, - orthogonal_rotation ? data->taps.v_taps_c : data->taps.h_taps_c, - orthogonal_rotation ? data->ratios.vert_c : data->ratios.horz_c, - orthogonal_rotation ? &data->inits.v_c : &data->inits.h_c, + ro_lb, + data->recout.width, + src.width / vpc_div, + data->taps.h_taps_c, + data->ratios.horz_c, + &data->inits.h_c, &data->viewport_c.x, &data->viewport_c.width); - adjust_vp_and_init_for_seamless_clip( + calculate_init_and_vp( flip_vert_scan_dir, - recout_skip_v, - surf_size_v, - orthogonal_rotation ? data->taps.h_taps : data->taps.v_taps, - orthogonal_rotation ? data->ratios.horz : data->ratios.vert, - orthogonal_rotation ? &data->inits.h : &data->inits.v, + ro_tb, + data->recout.height, + src.height, + data->taps.v_taps, + data->ratios.vert, + &data->inits.v, &data->viewport.y, &data->viewport.height); - adjust_vp_and_init_for_seamless_clip( + calculate_init_and_vp( flip_vert_scan_dir, - recout_skip_v, - surf_size_v / vpc_div, - orthogonal_rotation ? data->taps.h_taps_c : data->taps.v_taps_c, - orthogonal_rotation ? data->ratios.horz_c : data->ratios.vert_c, - orthogonal_rotation ? &data->inits.h_c : &data->inits.v_c, + ro_tb, + data->recout.height, + src.height / vpc_div, + data->taps.v_taps_c, + data->ratios.vert_c, + &data->inits.v_c, &data->viewport_c.y, &data->viewport_c.height); - - /* Interlaced inits based on final vert inits */ - data->inits.v_bot = dc_fixpt_add(data->inits.v, data->ratios.vert); - data->inits.v_c_bot = dc_fixpt_add(data->inits.v_c, data->ratios.vert_c); - -} - -/* - * When handling 270 rotation in mixed SLS mode, we have - * stream->timing.h_border_left that is non zero. If we are doing - * pipe-splitting, this h_border_left value gets added to recout.x and when it - * calls calculate_inits_and_adj_vp() and - * adjust_vp_and_init_for_seamless_clip(), it can cause viewport.height for a - * pipe to be incorrect. - * - * To fix this, instead of using stream->timing.h_border_left, we can use - * stream->dst.x to represent the border instead. So we will set h_border_left - * to 0 and shift the appropriate amount in stream->dst.x. We will then - * perform all calculations in resource_build_scaling_params() based on this - * and then restore the h_border_left and stream->dst.x to their original - * values. - * - * shift_border_left_to_dst() will shift the amount of h_border_left to - * stream->dst.x and set h_border_left to 0. restore_border_left_from_dst() - * will restore h_border_left and stream->dst.x back to their original values - * We also need to make sure pipe_ctx->plane_res.scl_data.h_active uses the - * original h_border_left value in its calculation. - */ -static int shift_border_left_to_dst(struct pipe_ctx *pipe_ctx) -{ - int store_h_border_left = pipe_ctx->stream->timing.h_border_left; - - if (store_h_border_left) { - pipe_ctx->stream->timing.h_border_left = 0; - pipe_ctx->stream->dst.x += store_h_border_left; + if (orthogonal_rotation) { + swap(data->viewport.x, data->viewport.y); + swap(data->viewport.width, data->viewport.height); + swap(data->viewport_c.x, data->viewport_c.y); + swap(data->viewport_c.width, data->viewport_c.height); } - return store_h_border_left; -} - -static void restore_border_left_from_dst(struct pipe_ctx *pipe_ctx, - int store_h_border_left) -{ - pipe_ctx->stream->dst.x -= store_h_border_left; - pipe_ctx->stream->timing.h_border_left = store_h_border_left; + data->viewport.x += src.x; + data->viewport.y += src.y; + ASSERT(src.x % vpc_div == 0 && src.y % vpc_div == 0); + data->viewport_c.x += src.x / vpc_div; + data->viewport_c.y += src.y / vpc_div; }
bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) @@ -1183,48 +1001,42 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) const struct dc_plane_state *plane_state = pipe_ctx->plane_state; struct dc_crtc_timing *timing = &pipe_ctx->stream->timing; bool res = false; - int store_h_border_left = shift_border_left_to_dst(pipe_ctx); DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger); - /* Important: scaling ratio calculation requires pixel format, - * lb depth calculation requires recout and taps require scaling ratios. - * Inits require viewport, taps, ratios and recout of split pipe - */ + pipe_ctx->plane_res.scl_data.format = convert_pixel_format_to_dalsurface( pipe_ctx->plane_state->format);
- calculate_scaling_ratios(pipe_ctx); - - calculate_viewport(pipe_ctx); + /* Timing borders are part of vactive that we are also supposed to skip in addition + * to any stream dst offset. Since dm logic assumes dst is in addressable + * space we need to add the the left and top borders to dst offsets temporarily. + * TODO: fix in DM, stream dst is supposed to be in vactive + */ + pipe_ctx->stream->dst.x += timing->h_border_left; + pipe_ctx->stream->dst.y += timing->v_border_top;
- if (pipe_ctx->plane_res.scl_data.viewport.height < MIN_VIEWPORT_SIZE || - pipe_ctx->plane_res.scl_data.viewport.width < MIN_VIEWPORT_SIZE) { - if (store_h_border_left) { - restore_border_left_from_dst(pipe_ctx, - store_h_border_left); - } - return false; - } + /* Calculate H and V active size */ + pipe_ctx->plane_res.scl_data.h_active = timing->h_addressable + + timing->h_border_left + timing->h_border_right; + pipe_ctx->plane_res.scl_data.v_active = timing->v_addressable + + timing->v_border_top + timing->v_border_bottom; + if (pipe_ctx->next_odm_pipe || pipe_ctx->prev_odm_pipe) + pipe_ctx->plane_res.scl_data.h_active /= get_num_odm_splits(pipe_ctx) + 1;
+ /* depends on h_active */ calculate_recout(pipe_ctx); + /* depends on pixel format */ + calculate_scaling_ratios(pipe_ctx); + /* depends on scaling ratios and recout, does not calculate offset yet */ + calculate_viewport_size(pipe_ctx);
- /** + /* + * LB calculations depend on vp size, h/v_active and scaling ratios * Setting line buffer pixel depth to 24bpp yields banding * on certain displays, such as the Sharp 4k */ pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP; pipe_ctx->plane_res.scl_data.lb_params.alpha_en = plane_state->per_pixel_alpha;
- pipe_ctx->plane_res.scl_data.recout.x += timing->h_border_left; - pipe_ctx->plane_res.scl_data.recout.y += timing->v_border_top; - - pipe_ctx->plane_res.scl_data.h_active = timing->h_addressable + - store_h_border_left + timing->h_border_right; - pipe_ctx->plane_res.scl_data.v_active = timing->v_addressable + - timing->v_border_top + timing->v_border_bottom; - if (pipe_ctx->next_odm_pipe || pipe_ctx->prev_odm_pipe) - pipe_ctx->plane_res.scl_data.h_active /= get_num_odm_splits(pipe_ctx) + 1; - - /* Taps calculations */ if (pipe_ctx->plane_res.xfm != NULL) res = pipe_ctx->plane_res.xfm->funcs->transform_get_optimal_number_of_taps( pipe_ctx->plane_res.xfm, &pipe_ctx->plane_res.scl_data, &plane_state->scaling_quality); @@ -1251,9 +1063,31 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) &plane_state->scaling_quality); }
+ /* + * Depends on recout, scaling ratios, h_active and taps + * May need to re-check lb size after this in some obscure scenario + */ if (res) - /* May need to re-check lb size after this in some obscure scenario */ - calculate_inits_and_adj_vp(pipe_ctx); + calculate_inits_and_viewports(pipe_ctx); + + /* + * Handle side by side and top bottom 3d recout offsets after vp calculation + * since 3d is special and needs to calculate vp as if there is no recout offset + * This may break with rotation, good thing we aren't mixing hw rotation and 3d + */ + if (pipe_ctx->top_pipe && pipe_ctx->top_pipe->plane_state == plane_state) { + ASSERT(plane_state->rotation == ROTATION_ANGLE_0 || + (pipe_ctx->stream->view_format != VIEW_3D_FORMAT_TOP_AND_BOTTOM && + pipe_ctx->stream->view_format != VIEW_3D_FORMAT_SIDE_BY_SIDE)); + if (pipe_ctx->stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) + pipe_ctx->plane_res.scl_data.recout.y += pipe_ctx->plane_res.scl_data.recout.height; + else if (pipe_ctx->stream->view_format == VIEW_3D_FORMAT_SIDE_BY_SIDE) + pipe_ctx->plane_res.scl_data.recout.x += pipe_ctx->plane_res.scl_data.recout.width; + } + + if (pipe_ctx->plane_res.scl_data.viewport.height < MIN_VIEWPORT_SIZE || + pipe_ctx->plane_res.scl_data.viewport.width < MIN_VIEWPORT_SIZE) + res = false;
DC_LOG_SCALER("%s pipe %d:\nViewport: height:%d width:%d x:%d y:%d Recout: height:%d width:%d x:%d y:%d HACTIVE:%d VACTIVE:%d\n" "src_rect: height:%d width:%d x:%d y:%d dst_rect: height:%d width:%d x:%d y:%d clip_rect: height:%d width:%d x:%d y:%d\n", @@ -1282,8 +1116,8 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) plane_state->clip_rect.x, plane_state->clip_rect.y);
- if (store_h_border_left) - restore_border_left_from_dst(pipe_ctx, store_h_border_left); + pipe_ctx->stream->dst.x -= timing->h_border_left; + pipe_ctx->stream->dst.y -= timing->v_border_top;
return res; } diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index 432754eaf10b..a6f21f9de6e4 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -271,11 +271,6 @@ struct dc_edid_caps { struct dc_panel_patch panel_patch; };
-struct view { - uint32_t width; - uint32_t height; -}; - struct dc_mode_flags { /* note: part of refresh rate flag*/ uint32_t INTERLACE :1; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c index 98ab4b776924..a33f522a2648 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c @@ -631,8 +631,10 @@ static void dpp1_dscl_set_manual_ratio_init( SCL_V_INIT_INT, init_int);
if (REG(SCL_VERT_FILTER_INIT_BOT)) { - init_frac = dc_fixpt_u0d19(data->inits.v_bot) << 5; - init_int = dc_fixpt_floor(data->inits.v_bot); + struct fixed31_32 bot = dc_fixpt_add(data->inits.v, data->ratios.vert); + + init_frac = dc_fixpt_u0d19(bot) << 5; + init_int = dc_fixpt_floor(bot); REG_SET_2(SCL_VERT_FILTER_INIT_BOT, 0, SCL_V_INIT_FRAC_BOT, init_frac, SCL_V_INIT_INT_BOT, init_int); @@ -645,8 +647,10 @@ static void dpp1_dscl_set_manual_ratio_init( SCL_V_INIT_INT_C, init_int);
if (REG(SCL_VERT_FILTER_INIT_BOT_C)) { - init_frac = dc_fixpt_u0d19(data->inits.v_c_bot) << 5; - init_int = dc_fixpt_floor(data->inits.v_c_bot); + struct fixed31_32 bot = dc_fixpt_add(data->inits.v_c, data->ratios.vert_c); + + init_frac = dc_fixpt_u0d19(bot) << 5; + init_int = dc_fixpt_floor(bot); REG_SET_2(SCL_VERT_FILTER_INIT_BOT_C, 0, SCL_V_INIT_FRAC_BOT_C, init_frac, SCL_V_INIT_INT_BOT_C, init_int); diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c index 8357aa3c41d5..d7d70b9bb387 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c @@ -2289,12 +2289,14 @@ int dcn20_populate_dml_pipes_from_context(
pipes[pipe_cnt].pipe.src.source_scan = pln->rotation == ROTATION_ANGLE_90 || pln->rotation == ROTATION_ANGLE_270 ? dm_vert : dm_horz; - pipes[pipe_cnt].pipe.src.viewport_y_y = scl->viewport_unadjusted.y; - pipes[pipe_cnt].pipe.src.viewport_y_c = scl->viewport_c_unadjusted.y; - pipes[pipe_cnt].pipe.src.viewport_width = scl->viewport_unadjusted.width; - pipes[pipe_cnt].pipe.src.viewport_width_c = scl->viewport_c_unadjusted.width; - pipes[pipe_cnt].pipe.src.viewport_height = scl->viewport_unadjusted.height; - pipes[pipe_cnt].pipe.src.viewport_height_c = scl->viewport_c_unadjusted.height; + pipes[pipe_cnt].pipe.src.viewport_y_y = scl->viewport.y; + pipes[pipe_cnt].pipe.src.viewport_y_c = scl->viewport_c.y; + pipes[pipe_cnt].pipe.src.viewport_width = scl->viewport.width; + pipes[pipe_cnt].pipe.src.viewport_width_c = scl->viewport_c.width; + pipes[pipe_cnt].pipe.src.viewport_height = scl->viewport.height; + pipes[pipe_cnt].pipe.src.viewport_height_c = scl->viewport_c.height; + pipes[pipe_cnt].pipe.src.viewport_width_max = pln->src_rect.width; + pipes[pipe_cnt].pipe.src.viewport_height_max = pln->src_rect.height; pipes[pipe_cnt].pipe.src.surface_width_y = pln->plane_size.surface_size.width; pipes[pipe_cnt].pipe.src.surface_height_y = pln->plane_size.surface_size.height; pipes[pipe_cnt].pipe.src.surface_width_c = pln->plane_size.chroma_size.width; diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h index 2ece3690bfa3..a0f0c54c863b 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h @@ -253,6 +253,8 @@ struct _vcs_dpi_display_pipe_source_params_st { unsigned int viewport_y_c; unsigned int viewport_width_c; unsigned int viewport_height_c; + unsigned int viewport_width_max; + unsigned int viewport_height_max; unsigned int data_pitch; unsigned int data_pitch_c; unsigned int meta_pitch; diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c index 2a967458065b..8e5c9d22b364 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c @@ -630,6 +630,19 @@ static void fetch_pipe_params(struct display_mode_lib *mode_lib) } } } + if (src->viewport_width_max) { + int hdiv_c = src->source_format >= dm_420_8 && src->source_format <= dm_422_10 ? 2 : 1; + int vdiv_c = src->source_format >= dm_420_8 && src->source_format <= dm_420_12 ? 2 : 1; + + if (mode_lib->vba.ViewportWidth[mode_lib->vba.NumberOfActivePlanes] > src->viewport_width_max) + mode_lib->vba.ViewportWidth[mode_lib->vba.NumberOfActivePlanes] = src->viewport_width_max; + if (mode_lib->vba.ViewportHeight[mode_lib->vba.NumberOfActivePlanes] > src->viewport_height_max) + mode_lib->vba.ViewportHeight[mode_lib->vba.NumberOfActivePlanes] = src->viewport_height_max; + if (mode_lib->vba.ViewportWidthChroma[mode_lib->vba.NumberOfActivePlanes] > src->viewport_width_max / hdiv_c) + mode_lib->vba.ViewportWidthChroma[mode_lib->vba.NumberOfActivePlanes] = src->viewport_width_max / hdiv_c; + if (mode_lib->vba.ViewportHeightChroma[mode_lib->vba.NumberOfActivePlanes] > src->viewport_height_max / vdiv_c) + mode_lib->vba.ViewportHeightChroma[mode_lib->vba.NumberOfActivePlanes] = src->viewport_height_max / vdiv_c; + }
if (pipes[k].pipe.src.immediate_flip) { mode_lib->vba.ImmediateFlipSupport = true; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h index 2947d1b15512..2a0db2b03047 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h @@ -162,9 +162,7 @@ struct scl_inits { struct fixed31_32 h; struct fixed31_32 h_c; struct fixed31_32 v; - struct fixed31_32 v_bot; struct fixed31_32 v_c; - struct fixed31_32 v_c_bot; };
struct scaler_data { @@ -173,8 +171,6 @@ struct scaler_data { struct scaling_taps taps; struct rect viewport; struct rect viewport_c; - struct rect viewport_unadjusted; - struct rect viewport_c_unadjusted; struct rect recout; struct scaling_ratios ratios; struct scl_inits inits;
From: Alex Deucher alexander.deucher@amd.com
[ Upstream commit dd1d82c04e111b5a864638ede8965db2fe6d8653 ]
If smu_cmn_get_enabled_mask() fails, return false to be consistent with other asics.
Reviewed-by: Lijo Lazar lijo.lazar@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Cc: Lee Jones lee.jones@linaro.org Reviewed-by: Lee Jones lee.jones@linaro.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
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 16ad4683eb69..0d2f61f56f45 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c @@ -1290,10 +1290,13 @@ static int aldebaran_usr_edit_dpm_table(struct smu_context *smu, enum PP_OD_DPM_
static bool aldebaran_is_dpm_running(struct smu_context *smu) { - int ret = 0; + int ret; uint32_t feature_mask[2]; unsigned long feature_enabled; + ret = smu_cmn_get_enabled_mask(smu, feature_mask, 2); + if (ret) + return false; feature_enabled = (unsigned long)((uint64_t)feature_mask[0] | ((uint64_t)feature_mask[1] << 32)); return !!(feature_enabled & SMC_DPM_FEATURE);
From: Huy Nguyen huyn@nvidia.com
[ Upstream commit c07274ab1ab2c38fb128e32643c22c89cb319384 ]
rep_tc copy REG_C1 to REG_B. IPsec crypto utilizes the whole REG_B register with BIT31 as IPsec marker. rep_tc_update_skb drops IPsec because it thought REG_B contains bad value.
In previous patch, BIT 31 of REG_C1 is reserved for IPsec. Skip the rep_tc_update_skb if BIT31 of REG_B is set.
Signed-off-by: Huy Nguyen huyn@nvidia.com Signed-off-by: Raed Salem raeds@nvidia.com Signed-off-by: Saeed Mahameed saeedm@nvidia.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/mellanox/mlx5/core/en_rx.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c index f90894eea9e0..5346271974f5 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c @@ -1310,7 +1310,8 @@ static void mlx5e_handle_rx_cqe_rep(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe) if (rep->vlan && skb_vlan_tag_present(skb)) skb_vlan_pop(skb);
- if (!mlx5e_rep_tc_update_skb(cqe, skb, &tc_priv)) { + if (unlikely(!mlx5_ipsec_is_rx_flow(cqe) && + !mlx5e_rep_tc_update_skb(cqe, skb, &tc_priv))) { dev_kfree_skb_any(skb); goto free_wqe; } @@ -1367,7 +1368,8 @@ static void mlx5e_handle_rx_cqe_mpwrq_rep(struct mlx5e_rq *rq, struct mlx5_cqe64
mlx5e_complete_rx_cqe(rq, cqe, cqe_bcnt, skb);
- if (!mlx5e_rep_tc_update_skb(cqe, skb, &tc_priv)) { + if (unlikely(!mlx5_ipsec_is_rx_flow(cqe) && + !mlx5e_rep_tc_update_skb(cqe, skb, &tc_priv))) { dev_kfree_skb_any(skb); goto mpwrq_cqe_out; }
From: Eli Cohen elic@nvidia.com
[ Upstream commit 8613641063617c1dfc731b403b3ee4935ef15f87 ]
Fix the logic so that if both ports netdevices are enabled or disabled, use the trivial mapping without swapping.
If only one of the netdevice's tx is enabled, use it to remap traffic to that port.
Signed-off-by: Eli Cohen elic@nvidia.com Signed-off-by: Saeed Mahameed saeedm@nvidia.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/mellanox/mlx5/core/lag.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag.c b/drivers/net/ethernet/mellanox/mlx5/core/lag.c index b8748390335f..9ce144ef8326 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lag.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lag.c @@ -118,17 +118,24 @@ static bool __mlx5_lag_is_sriov(struct mlx5_lag *ldev) static void mlx5_infer_tx_affinity_mapping(struct lag_tracker *tracker, u8 *port1, u8 *port2) { + bool p1en; + bool p2en; + + p1en = tracker->netdev_state[MLX5_LAG_P1].tx_enabled && + tracker->netdev_state[MLX5_LAG_P1].link_up; + + p2en = tracker->netdev_state[MLX5_LAG_P2].tx_enabled && + tracker->netdev_state[MLX5_LAG_P2].link_up; + *port1 = 1; *port2 = 2; - if (!tracker->netdev_state[MLX5_LAG_P1].tx_enabled || - !tracker->netdev_state[MLX5_LAG_P1].link_up) { - *port1 = 2; + if ((!p1en && !p2en) || (p1en && p2en)) return; - }
- if (!tracker->netdev_state[MLX5_LAG_P2].tx_enabled || - !tracker->netdev_state[MLX5_LAG_P2].link_up) + if (p1en) *port2 = 1; + else + *port1 = 2; }
void mlx5_modify_lag(struct mlx5_lag *ldev,
From: Alex Bee knaerzche@gmail.com
[ Upstream commit ab64b448a175b8a5a4bd323b8f74758c2574482c ]
Add dither_up, dsp_lut_en and data_blank registers to enable their respective functionality for RK3188's VOP. While at that also fix .dsp_blank register which is (only) set with BIT24 (same as RK3066)
Signed-off-by: Alex Bee knaerzche@gmail.com Signed-off-by: Heiko Stuebner heiko@sntech.de Link: https://patchwork.freedesktop.org/patch/msgid/20210528130554.72191-3-knaerzc... Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c index 80053d91a301..b8dcee64a1f7 100644 --- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c @@ -505,7 +505,10 @@ static const struct vop_common rk3188_common = { .dither_down_sel = VOP_REG(RK3188_DSP_CTRL0, 0x1, 27), .dither_down_en = VOP_REG(RK3188_DSP_CTRL0, 0x1, 11), .dither_down_mode = VOP_REG(RK3188_DSP_CTRL0, 0x1, 10), - .dsp_blank = VOP_REG(RK3188_DSP_CTRL1, 0x3, 24), + .dsp_blank = VOP_REG(RK3188_DSP_CTRL1, 0x1, 24), + .dither_up = VOP_REG(RK3188_DSP_CTRL0, 0x1, 9), + .dsp_lut_en = VOP_REG(RK3188_SYS_CTRL, 0x1, 28), + .data_blank = VOP_REG(RK3188_DSP_CTRL1, 0x1, 25), };
static const struct vop_win_data rk3188_vop_win_data[] = {
From: Alex Bee knaerzche@gmail.com
[ Upstream commit 742203cd56d150eb7884eb45abb7d9dbc2bdbf04 ]
Add dither_up, dsp_lut_en and data_blank registers to enable their respective functionality for RK3066's VOP.
While at that also fix .rb_swap and .format registers for all windows, which have to be set though RK3066_SYS_CTRL1 register. Also remove .scl from win1: Scaling is only supported on the primary plane.
Signed-off-by: Alex Bee knaerzche@gmail.com Signed-off-by: Heiko Stuebner heiko@sntech.de Link: https://patchwork.freedesktop.org/patch/msgid/20210528130554.72191-4-knaerzc... Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-)
diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c index b8dcee64a1f7..a6fe03c3748a 100644 --- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c @@ -349,8 +349,8 @@ static const struct vop_win_phy rk3066_win0_data = { .nformats = ARRAY_SIZE(formats_win_full), .format_modifiers = format_modifiers_win_full, .enable = VOP_REG(RK3066_SYS_CTRL1, 0x1, 0), - .format = VOP_REG(RK3066_SYS_CTRL0, 0x7, 4), - .rb_swap = VOP_REG(RK3066_SYS_CTRL0, 0x1, 19), + .format = VOP_REG(RK3066_SYS_CTRL1, 0x7, 4), + .rb_swap = VOP_REG(RK3066_SYS_CTRL1, 0x1, 19), .act_info = VOP_REG(RK3066_WIN0_ACT_INFO, 0x1fff1fff, 0), .dsp_info = VOP_REG(RK3066_WIN0_DSP_INFO, 0x0fff0fff, 0), .dsp_st = VOP_REG(RK3066_WIN0_DSP_ST, 0x1fff1fff, 0), @@ -361,13 +361,12 @@ static const struct vop_win_phy rk3066_win0_data = { };
static const struct vop_win_phy rk3066_win1_data = { - .scl = &rk3066_win_scl, .data_formats = formats_win_full, .nformats = ARRAY_SIZE(formats_win_full), .format_modifiers = format_modifiers_win_full, .enable = VOP_REG(RK3066_SYS_CTRL1, 0x1, 1), - .format = VOP_REG(RK3066_SYS_CTRL0, 0x7, 7), - .rb_swap = VOP_REG(RK3066_SYS_CTRL0, 0x1, 23), + .format = VOP_REG(RK3066_SYS_CTRL1, 0x7, 7), + .rb_swap = VOP_REG(RK3066_SYS_CTRL1, 0x1, 23), .act_info = VOP_REG(RK3066_WIN1_ACT_INFO, 0x1fff1fff, 0), .dsp_info = VOP_REG(RK3066_WIN1_DSP_INFO, 0x0fff0fff, 0), .dsp_st = VOP_REG(RK3066_WIN1_DSP_ST, 0x1fff1fff, 0), @@ -382,8 +381,8 @@ static const struct vop_win_phy rk3066_win2_data = { .nformats = ARRAY_SIZE(formats_win_lite), .format_modifiers = format_modifiers_win_lite, .enable = VOP_REG(RK3066_SYS_CTRL1, 0x1, 2), - .format = VOP_REG(RK3066_SYS_CTRL0, 0x7, 10), - .rb_swap = VOP_REG(RK3066_SYS_CTRL0, 0x1, 27), + .format = VOP_REG(RK3066_SYS_CTRL1, 0x7, 10), + .rb_swap = VOP_REG(RK3066_SYS_CTRL1, 0x1, 27), .dsp_info = VOP_REG(RK3066_WIN2_DSP_INFO, 0x0fff0fff, 0), .dsp_st = VOP_REG(RK3066_WIN2_DSP_ST, 0x1fff1fff, 0), .yrgb_mst = VOP_REG(RK3066_WIN2_MST, 0xffffffff, 0), @@ -408,6 +407,9 @@ static const struct vop_common rk3066_common = { .dither_down_en = VOP_REG(RK3066_DSP_CTRL0, 0x1, 11), .dither_down_mode = VOP_REG(RK3066_DSP_CTRL0, 0x1, 10), .dsp_blank = VOP_REG(RK3066_DSP_CTRL1, 0x1, 24), + .dither_up = VOP_REG(RK3066_DSP_CTRL0, 0x1, 9), + .dsp_lut_en = VOP_REG(RK3066_SYS_CTRL1, 0x1, 31), + .data_blank = VOP_REG(RK3066_DSP_CTRL1, 0x1, 25), };
static const struct vop_win_data rk3066_vop_win_data[] = {
From: Vladimir Oltean vladimir.oltean@nxp.com
[ Upstream commit 4751d2aa321f2828d8c5d2f7ce4ed18a01e47f46 ]
stmmac_mdio_register() has logic to search for PHYs on the MDIO bus and assign them IRQ lines, as well as to set priv->plat->phy_addr.
If no PHY is found, the "found" variable remains set to 0 and the function errors out.
After the introduction of commit f213bbe8a9d6 ("net: stmmac: Integrate it with DesignWare XPCS"), the "found" variable was immediately reused for searching for a PCS on the same MDIO bus.
This can result in 2 types of potential problems (none of them seems to be seen on the only Intel system that sets has_xpcs = true, otherwise it would have been reported):
1. If a PCS is found but a PHY is not, then the code happily exits with no error. One might say "yes, but this is not possible, because of_mdiobus_register will probe a PHY for all MDIO addresses, including for the XPCS, so if an XPCS exists, then a PHY certainly exists too". Well, that is not true, see intel_mgbe_common_data():
/* Ensure mdio bus scan skips intel serdes and pcs-xpcs */ plat->mdio_bus_data->phy_mask = 1 << INTEL_MGBE_ADHOC_ADDR; plat->mdio_bus_data->phy_mask |= 1 << INTEL_MGBE_XPCS_ADDR;
2. A PHY is found but an MDIO device with the XPCS PHY ID isn't, and in that case, the error message will be "No PHY found". Confusing.
Signed-off-by: Vladimir Oltean vladimir.oltean@nxp.com Link: https://lore.kernel.org/r/20210527155959.3270478-1-olteanv@gmail.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- .../net/ethernet/stmicro/stmmac/stmmac_mdio.c | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c index b750074f8f9c..e293bf1ce9f3 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c @@ -503,6 +503,12 @@ int stmmac_mdio_register(struct net_device *ndev) found = 1; }
+ if (!found && !mdio_node) { + dev_warn(dev, "No PHY found\n"); + err = -ENODEV; + goto no_phy_found; + } + /* Try to probe the XPCS by scanning all addresses. */ if (priv->hw->xpcs) { struct mdio_xpcs_args *xpcs = &priv->hw->xpcs_args; @@ -511,6 +517,7 @@ int stmmac_mdio_register(struct net_device *ndev)
xpcs->bus = new_bus;
+ found = 0; for (addr = 0; addr < max_addr; addr++) { xpcs->addr = addr;
@@ -520,13 +527,12 @@ int stmmac_mdio_register(struct net_device *ndev) break; } } - }
- if (!found && !mdio_node) { - dev_warn(dev, "No PHY found\n"); - mdiobus_unregister(new_bus); - mdiobus_free(new_bus); - return -ENODEV; + if (!found && !mdio_node) { + dev_warn(dev, "No XPCS found\n"); + err = -ENODEV; + goto no_xpcs_found; + } }
bus_register_done: @@ -534,6 +540,9 @@ int stmmac_mdio_register(struct net_device *ndev)
return 0;
+no_xpcs_found: +no_phy_found: + mdiobus_unregister(new_bus); bus_register_fail: mdiobus_free(new_bus); return err;
From: Gioh Kim gi-oh.kim@cloud.ionos.com
[ Upstream commit 3a98ea7041b7d18ac356da64823c2ba2f8391b3e ]
Max IB immediate data size is 2^28 (MAX_IMM_PAYL_BITS) and the minimum chunk size is 4096 (2^12). Therefore the maximum sess_queue_depth is 65536 (2^16).
Link: https://lore.kernel.org/r/20210528113018.52290-6-jinpu.wang@ionos.com Signed-off-by: Gioh Kim gi-oh.kim@ionos.com Signed-off-by: Jack Wang jinpu.wang@ionos.com Reported-by: kernel test robot lkp@intel.com Signed-off-by: Jason Gunthorpe jgg@nvidia.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/infiniband/ulp/rtrs/rtrs-pri.h | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/drivers/infiniband/ulp/rtrs/rtrs-pri.h b/drivers/infiniband/ulp/rtrs/rtrs-pri.h index 86e65cf30cab..d957bbf1ddd3 100644 --- a/drivers/infiniband/ulp/rtrs/rtrs-pri.h +++ b/drivers/infiniband/ulp/rtrs/rtrs-pri.h @@ -47,12 +47,15 @@ enum { MAX_PATHS_NUM = 128,
/* - * With the size of struct rtrs_permit allocated on the client, 4K - * is the maximum number of rtrs_permits we can allocate. This number is - * also used on the client to allocate the IU for the user connection - * to receive the RDMA addresses from the server. + * Max IB immediate data size is 2^28 (MAX_IMM_PAYL_BITS) + * and the minimum chunk size is 4096 (2^12). + * So the maximum sess_queue_depth is 65536 (2^16) in theory. + * But mempool_create, create_qp and ib_post_send fail with + * "cannot allocate memory" error if sess_queue_depth is too big. + * Therefore the pratical max value of sess_queue_depth is + * somewhere between 1 and 65536 and it depends on the system. */ - MAX_SESS_QUEUE_DEPTH = 4096, + MAX_SESS_QUEUE_DEPTH = 65536,
RTRS_HB_INTERVAL_MS = 5000, RTRS_HB_MISSED_MAX = 5,
From: Thierry Reding treding@nvidia.com
[ Upstream commit e16efff4e5f490ce34a8c60d9ae7297dca5eb616 ]
The driver currently exposes several YUV formats but fails to properly program all the registers needed to display such formats. Add the right programming sequences so that overlay windows can be used to accelerate color format conversions in multimedia playback use-cases.
Signed-off-by: Thierry Reding treding@nvidia.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/tegra/dc.c | 2 +- drivers/gpu/drm/tegra/dc.h | 7 +++++ drivers/gpu/drm/tegra/hub.c | 52 +++++++++++++++++++++++++++++++---- drivers/gpu/drm/tegra/plane.c | 23 ++++++++++++++-- drivers/gpu/drm/tegra/plane.h | 3 +- 5 files changed, 78 insertions(+), 9 deletions(-)
diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index f9120dc24682..c5ea88a686d1 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c @@ -348,7 +348,7 @@ static void tegra_dc_setup_window(struct tegra_plane *plane, * For YUV planar modes, the number of bytes per pixel takes into * account only the luma component and therefore is 1. */ - yuv = tegra_plane_format_is_yuv(window->format, &planar); + yuv = tegra_plane_format_is_yuv(window->format, &planar, NULL); if (!yuv) bpp = window->bits_per_pixel / 8; else diff --git a/drivers/gpu/drm/tegra/dc.h b/drivers/gpu/drm/tegra/dc.h index 29f19c3c6149..455c3fdef8dc 100644 --- a/drivers/gpu/drm/tegra/dc.h +++ b/drivers/gpu/drm/tegra/dc.h @@ -696,6 +696,9 @@ int tegra_dc_rgb_exit(struct tegra_dc *dc);
#define DC_WINBUF_START_ADDR_HI 0x80d
+#define DC_WINBUF_START_ADDR_HI_U 0x80f +#define DC_WINBUF_START_ADDR_HI_V 0x811 + #define DC_WINBUF_CDE_CONTROL 0x82f #define ENABLE_SURFACE (1 << 0)
@@ -720,6 +723,10 @@ int tegra_dc_rgb_exit(struct tegra_dc *dc); #define DC_WIN_PLANAR_STORAGE 0x709 #define PITCH(x) (((x) >> 6) & 0x1fff)
+#define DC_WIN_PLANAR_STORAGE_UV 0x70a +#define PITCH_U(x) ((((x) >> 6) & 0x1fff) << 0) +#define PITCH_V(x) ((((x) >> 6) & 0x1fff) << 16) + #define DC_WIN_SET_PARAMS 0x70d #define CLAMP_BEFORE_BLEND (1 << 15) #define DEGAMMA_NONE (0 << 13) diff --git a/drivers/gpu/drm/tegra/hub.c b/drivers/gpu/drm/tegra/hub.c index bfae8a02f55b..94e1ccfb6235 100644 --- a/drivers/gpu/drm/tegra/hub.c +++ b/drivers/gpu/drm/tegra/hub.c @@ -454,7 +454,9 @@ static void tegra_shared_plane_atomic_update(struct drm_plane *plane, unsigned int zpos = new_state->normalized_zpos; struct drm_framebuffer *fb = new_state->fb; struct tegra_plane *p = to_tegra_plane(plane); - dma_addr_t base; + dma_addr_t base, addr_flag = 0; + unsigned int bpc; + bool yuv, planar; u32 value; int err;
@@ -473,6 +475,8 @@ static void tegra_shared_plane_atomic_update(struct drm_plane *plane, return; }
+ yuv = tegra_plane_format_is_yuv(tegra_plane_state->format, &planar, &bpc); + tegra_dc_assign_shared_plane(dc, p);
tegra_plane_writel(p, VCOUNTER, DC_WIN_CORE_ACT_CONTROL); @@ -501,8 +505,6 @@ static void tegra_shared_plane_atomic_update(struct drm_plane *plane, /* disable compression */ tegra_plane_writel(p, 0, DC_WINBUF_CDE_CONTROL);
- base = tegra_plane_state->iova[0] + fb->offsets[0]; - #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT /* * Physical address bit 39 in Tegra194 is used as a switch for special @@ -510,9 +512,12 @@ static void tegra_shared_plane_atomic_update(struct drm_plane *plane, * dGPU sector layout. */ if (tegra_plane_state->tiling.sector_layout == TEGRA_BO_SECTOR_LAYOUT_GPU) - base |= BIT_ULL(39); + addr_flag = BIT_ULL(39); #endif
+ base = tegra_plane_state->iova[0] + fb->offsets[0]; + base |= addr_flag; + tegra_plane_writel(p, tegra_plane_state->format, DC_WIN_COLOR_DEPTH); tegra_plane_writel(p, 0, DC_WIN_PRECOMP_WGRP_PARAMS);
@@ -535,7 +540,44 @@ static void tegra_shared_plane_atomic_update(struct drm_plane *plane, value = PITCH(fb->pitches[0]); tegra_plane_writel(p, value, DC_WIN_PLANAR_STORAGE);
- value = CLAMP_BEFORE_BLEND | DEGAMMA_SRGB | INPUT_RANGE_FULL; + if (yuv && planar) { + base = tegra_plane_state->iova[1] + fb->offsets[1]; + base |= addr_flag; + + tegra_plane_writel(p, upper_32_bits(base), DC_WINBUF_START_ADDR_HI_U); + tegra_plane_writel(p, lower_32_bits(base), DC_WINBUF_START_ADDR_U); + + base = tegra_plane_state->iova[2] + fb->offsets[2]; + base |= addr_flag; + + tegra_plane_writel(p, upper_32_bits(base), DC_WINBUF_START_ADDR_HI_V); + tegra_plane_writel(p, lower_32_bits(base), DC_WINBUF_START_ADDR_V); + + value = PITCH_U(fb->pitches[2]) | PITCH_V(fb->pitches[2]); + tegra_plane_writel(p, value, DC_WIN_PLANAR_STORAGE_UV); + } else { + tegra_plane_writel(p, 0, DC_WINBUF_START_ADDR_U); + tegra_plane_writel(p, 0, DC_WINBUF_START_ADDR_HI_U); + tegra_plane_writel(p, 0, DC_WINBUF_START_ADDR_V); + tegra_plane_writel(p, 0, DC_WINBUF_START_ADDR_HI_V); + tegra_plane_writel(p, 0, DC_WIN_PLANAR_STORAGE_UV); + } + + value = CLAMP_BEFORE_BLEND | INPUT_RANGE_FULL; + + if (yuv) { + if (bpc < 12) + value |= DEGAMMA_YUV8_10; + else + value |= DEGAMMA_YUV12; + + /* XXX parameterize */ + value |= COLOR_SPACE_YUV_2020; + } else { + if (!tegra_plane_format_is_indexed(tegra_plane_state->format)) + value |= DEGAMMA_SRGB; + } + tegra_plane_writel(p, value, DC_WIN_SET_PARAMS);
value = OFFSET_X(new_state->src_y >> 16) | diff --git a/drivers/gpu/drm/tegra/plane.c b/drivers/gpu/drm/tegra/plane.c index 2e11b4b1f702..2e65b4075ce6 100644 --- a/drivers/gpu/drm/tegra/plane.c +++ b/drivers/gpu/drm/tegra/plane.c @@ -375,7 +375,20 @@ int tegra_plane_format(u32 fourcc, u32 *format, u32 *swap) return 0; }
-bool tegra_plane_format_is_yuv(unsigned int format, bool *planar) +bool tegra_plane_format_is_indexed(unsigned int format) +{ + switch (format) { + case WIN_COLOR_DEPTH_P1: + case WIN_COLOR_DEPTH_P2: + case WIN_COLOR_DEPTH_P4: + case WIN_COLOR_DEPTH_P8: + return true; + } + + return false; +} + +bool tegra_plane_format_is_yuv(unsigned int format, bool *planar, unsigned int *bpc) { switch (format) { case WIN_COLOR_DEPTH_YCbCr422: @@ -383,6 +396,9 @@ bool tegra_plane_format_is_yuv(unsigned int format, bool *planar) if (planar) *planar = false;
+ if (bpc) + *bpc = 8; + return true;
case WIN_COLOR_DEPTH_YCbCr420P: @@ -396,6 +412,9 @@ bool tegra_plane_format_is_yuv(unsigned int format, bool *planar) if (planar) *planar = true;
+ if (bpc) + *bpc = 8; + return true; }
@@ -421,7 +440,7 @@ static bool __drm_format_has_alpha(u32 format) static int tegra_plane_format_get_alpha(unsigned int opaque, unsigned int *alpha) { - if (tegra_plane_format_is_yuv(opaque, NULL)) { + if (tegra_plane_format_is_yuv(opaque, NULL, NULL)) { *alpha = opaque; return 0; } diff --git a/drivers/gpu/drm/tegra/plane.h b/drivers/gpu/drm/tegra/plane.h index c691dd79b27b..1785c1559c0c 100644 --- a/drivers/gpu/drm/tegra/plane.h +++ b/drivers/gpu/drm/tegra/plane.h @@ -74,7 +74,8 @@ int tegra_plane_state_add(struct tegra_plane *plane, struct drm_plane_state *state);
int tegra_plane_format(u32 fourcc, u32 *format, u32 *swap); -bool tegra_plane_format_is_yuv(unsigned int format, bool *planar); +bool tegra_plane_format_is_indexed(unsigned int format); +bool tegra_plane_format_is_yuv(unsigned int format, bool *planar, unsigned int *bpc); int tegra_plane_setup_legacy_state(struct tegra_plane *tegra, struct tegra_plane_state *state);
From: Dmitry Osipenko digetx@gmail.com
[ Upstream commit c592c8a28f5821e880ac6675781cd8a151b0737c ]
The refcounting of the gate clocks has a bug causing the enable_refcnt to underflow when unused clocks are disabled. This happens because clk provider erroneously bumps the refcount if clock is enabled at a boot time, which it shouldn't be doing, and it does this only for the gate clocks, while peripheral clocks are using the same gate ops and the peripheral clocks are missing the initial bump. Hence the refcount of the peripheral clocks is 0 when unused clocks are disabled and then the counter is decremented further by the gate ops, causing the integer underflow.
Fix this problem by removing the erroneous bump and by implementing the disable_unused() callback, which disables the unused gates properly.
The visible effect of the bug is such that the unused clocks are never gated if a loaded kernel module grabs the unused clocks and starts to use them. In practice this shouldn't cause any real problems for the drivers and boards supported by the kernel today.
Acked-by: Thierry Reding treding@nvidia.com Signed-off-by: Dmitry Osipenko digetx@gmail.com Signed-off-by: Thierry Reding treding@nvidia.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/clk/tegra/clk-periph-gate.c | 72 +++++++++++++++++++---------- drivers/clk/tegra/clk-periph.c | 11 +++++ 2 files changed, 58 insertions(+), 25 deletions(-)
diff --git a/drivers/clk/tegra/clk-periph-gate.c b/drivers/clk/tegra/clk-periph-gate.c index 4b31beefc9fc..dc3f92678407 100644 --- a/drivers/clk/tegra/clk-periph-gate.c +++ b/drivers/clk/tegra/clk-periph-gate.c @@ -48,18 +48,9 @@ static int clk_periph_is_enabled(struct clk_hw *hw) return state; }
-static int clk_periph_enable(struct clk_hw *hw) +static void clk_periph_enable_locked(struct clk_hw *hw) { struct tegra_clk_periph_gate *gate = to_clk_periph_gate(hw); - unsigned long flags = 0; - - spin_lock_irqsave(&periph_ref_lock, flags); - - gate->enable_refcnt[gate->clk_num]++; - if (gate->enable_refcnt[gate->clk_num] > 1) { - spin_unlock_irqrestore(&periph_ref_lock, flags); - return 0; - }
write_enb_set(periph_clk_to_bit(gate), gate); udelay(2); @@ -78,6 +69,32 @@ static int clk_periph_enable(struct clk_hw *hw) udelay(1); writel_relaxed(0, gate->clk_base + LVL2_CLK_GATE_OVRE); } +} + +static void clk_periph_disable_locked(struct clk_hw *hw) +{ + struct tegra_clk_periph_gate *gate = to_clk_periph_gate(hw); + + /* + * If peripheral is in the APB bus then read the APB bus to + * flush the write operation in apb bus. This will avoid the + * peripheral access after disabling clock + */ + if (gate->flags & TEGRA_PERIPH_ON_APB) + tegra_read_chipid(); + + write_enb_clr(periph_clk_to_bit(gate), gate); +} + +static int clk_periph_enable(struct clk_hw *hw) +{ + struct tegra_clk_periph_gate *gate = to_clk_periph_gate(hw); + unsigned long flags = 0; + + spin_lock_irqsave(&periph_ref_lock, flags); + + if (!gate->enable_refcnt[gate->clk_num]++) + clk_periph_enable_locked(hw);
spin_unlock_irqrestore(&periph_ref_lock, flags);
@@ -91,21 +108,28 @@ static void clk_periph_disable(struct clk_hw *hw)
spin_lock_irqsave(&periph_ref_lock, flags);
- gate->enable_refcnt[gate->clk_num]--; - if (gate->enable_refcnt[gate->clk_num] > 0) { - spin_unlock_irqrestore(&periph_ref_lock, flags); - return; - } + WARN_ON(!gate->enable_refcnt[gate->clk_num]); + + if (--gate->enable_refcnt[gate->clk_num] == 0) + clk_periph_disable_locked(hw); + + spin_unlock_irqrestore(&periph_ref_lock, flags); +} + +static void clk_periph_disable_unused(struct clk_hw *hw) +{ + struct tegra_clk_periph_gate *gate = to_clk_periph_gate(hw); + unsigned long flags = 0; + + spin_lock_irqsave(&periph_ref_lock, flags);
/* - * If peripheral is in the APB bus then read the APB bus to - * flush the write operation in apb bus. This will avoid the - * peripheral access after disabling clock + * Some clocks are duplicated and some of them are marked as critical, + * like fuse and fuse_burn for example, thus the enable_refcnt will + * be non-zero here if the "unused" duplicate is disabled by CCF. */ - if (gate->flags & TEGRA_PERIPH_ON_APB) - tegra_read_chipid(); - - write_enb_clr(periph_clk_to_bit(gate), gate); + if (!gate->enable_refcnt[gate->clk_num]) + clk_periph_disable_locked(hw);
spin_unlock_irqrestore(&periph_ref_lock, flags); } @@ -114,6 +138,7 @@ const struct clk_ops tegra_clk_periph_gate_ops = { .is_enabled = clk_periph_is_enabled, .enable = clk_periph_enable, .disable = clk_periph_disable, + .disable_unused = clk_periph_disable_unused, };
struct clk *tegra_clk_register_periph_gate(const char *name, @@ -148,9 +173,6 @@ struct clk *tegra_clk_register_periph_gate(const char *name, gate->enable_refcnt = enable_refcnt; gate->regs = pregs;
- if (read_enb(gate) & periph_clk_to_bit(gate)) - enable_refcnt[clk_num]++; - /* Data in .init is copied by clk_register(), so stack variable OK */ gate->hw.init = &init;
diff --git a/drivers/clk/tegra/clk-periph.c b/drivers/clk/tegra/clk-periph.c index 67620c7ecd9e..79ca3aa072b7 100644 --- a/drivers/clk/tegra/clk-periph.c +++ b/drivers/clk/tegra/clk-periph.c @@ -100,6 +100,15 @@ static void clk_periph_disable(struct clk_hw *hw) gate_ops->disable(gate_hw); }
+static void clk_periph_disable_unused(struct clk_hw *hw) +{ + struct tegra_clk_periph *periph = to_clk_periph(hw); + const struct clk_ops *gate_ops = periph->gate_ops; + struct clk_hw *gate_hw = &periph->gate.hw; + + gate_ops->disable_unused(gate_hw); +} + static void clk_periph_restore_context(struct clk_hw *hw) { struct tegra_clk_periph *periph = to_clk_periph(hw); @@ -126,6 +135,7 @@ const struct clk_ops tegra_clk_periph_ops = { .is_enabled = clk_periph_is_enabled, .enable = clk_periph_enable, .disable = clk_periph_disable, + .disable_unused = clk_periph_disable_unused, .restore_context = clk_periph_restore_context, };
@@ -135,6 +145,7 @@ static const struct clk_ops tegra_clk_periph_nodiv_ops = { .is_enabled = clk_periph_is_enabled, .enable = clk_periph_enable, .disable = clk_periph_disable, + .disable_unused = clk_periph_disable_unused, .restore_context = clk_periph_restore_context, };
From: Dmitry Osipenko digetx@gmail.com
[ Upstream commit a7196048cd5168096c2c4f44a3939d7a6dcd06b9 ]
The PLLU (USB) consists of the PLL configuration itself and configuration of the PLLU outputs. The PLLU programming is inconsistent on T30 vs T114, where T114 immediately bails out if PLLU is enabled and T30 re-enables a potentially already enabled PLL (left after bootloader) and then fully reprograms it, which could be unsafe to do. The correct way should be to skip enabling of the PLL if it's already enabled and then apply configuration to the outputs. This patch doesn't fix any known problems, it's a minor improvement.
Acked-by: Thierry Reding treding@nvidia.com Signed-off-by: Dmitry Osipenko digetx@gmail.com Signed-off-by: Thierry Reding treding@nvidia.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/clk/tegra/clk-pll.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c index 0193cebe8c5a..823a567f2adc 100644 --- a/drivers/clk/tegra/clk-pll.c +++ b/drivers/clk/tegra/clk-pll.c @@ -1131,7 +1131,8 @@ static int clk_pllu_enable(struct clk_hw *hw) if (pll->lock) spin_lock_irqsave(pll->lock, flags);
- _clk_pll_enable(hw); + if (!clk_pll_is_enabled(hw)) + _clk_pll_enable(hw);
ret = clk_pll_wait_for_lock(pll); if (ret < 0) @@ -1748,15 +1749,13 @@ static int clk_pllu_tegra114_enable(struct clk_hw *hw) return -EINVAL; }
- if (clk_pll_is_enabled(hw)) - return 0; - input_rate = clk_hw_get_rate(__clk_get_hw(osc));
if (pll->lock) spin_lock_irqsave(pll->lock, flags);
- _clk_pll_enable(hw); + if (!clk_pll_is_enabled(hw)) + _clk_pll_enable(hw);
ret = clk_pll_wait_for_lock(pll); if (ret < 0)
From: Yu Kuai yukuai3@huawei.com
[ Upstream commit f674555ee5444c8987dfea0922f1cf6bf0c12847 ]
pm_runtime_get_sync will increment pm usage counter even it failed. Forgetting to putting operation will result in reference leak here. Fix it by replacing it with pm_runtime_resume_and_get to keep usage counter balanced.
Reported-by: Hulk Robot hulkci@huawei.com Signed-off-by: Yu Kuai yukuai3@huawei.com Reviewed-by: Robert Foss robert.foss@linaro.org Signed-off-by: Robert Foss robert.foss@linaro.org Link: https://patchwork.freedesktop.org/patch/msgid/20210531135622.3348252-1-yukua... Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c index 989a05bc8197..ddcd5b6ad37a 100644 --- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c +++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c @@ -2369,9 +2369,9 @@ static int cdns_mhdp_probe(struct platform_device *pdev) clk_prepare_enable(clk);
pm_runtime_enable(dev); - ret = pm_runtime_get_sync(dev); + ret = pm_runtime_resume_and_get(dev); if (ret < 0) { - dev_err(dev, "pm_runtime_get_sync failed\n"); + dev_err(dev, "pm_runtime_resume_and_get failed\n"); pm_runtime_disable(dev); goto clk_disable; }
From: Xie Yongji xieyongji@bytedance.com
[ Upstream commit ad993a95c508417acdeb15244109e009e50d8758 ]
This adds validation for used length (might come from an untrusted device) to avoid data corruption or loss.
Signed-off-by: Xie Yongji xieyongji@bytedance.com Acked-by: Jason Wang jasowang@redhat.com Link: https://lore.kernel.org/r/20210531135852.113-1-xieyongji@bytedance.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/virtio_net.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-)
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 78a01c71a17c..252f6718d730 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -721,6 +721,12 @@ static struct sk_buff *receive_small(struct net_device *dev, len -= vi->hdr_len; stats->bytes += len;
+ if (unlikely(len > GOOD_PACKET_LEN)) { + pr_debug("%s: rx error: len %u exceeds max size %d\n", + dev->name, len, GOOD_PACKET_LEN); + dev->stats.rx_length_errors++; + goto err_len; + } rcu_read_lock(); xdp_prog = rcu_dereference(rq->xdp_prog); if (xdp_prog) { @@ -824,6 +830,7 @@ static struct sk_buff *receive_small(struct net_device *dev, err_xdp: rcu_read_unlock(); stats->xdp_drops++; +err_len: stats->drops++; put_page(page); xdp_xmit: @@ -877,6 +884,12 @@ static struct sk_buff *receive_mergeable(struct net_device *dev, head_skb = NULL; stats->bytes += len - vi->hdr_len;
+ if (unlikely(len > truesize)) { + pr_debug("%s: rx error: len %u exceeds truesize %lu\n", + dev->name, len, (unsigned long)ctx); + dev->stats.rx_length_errors++; + goto err_skb; + } rcu_read_lock(); xdp_prog = rcu_dereference(rq->xdp_prog); if (xdp_prog) { @@ -1004,13 +1017,6 @@ static struct sk_buff *receive_mergeable(struct net_device *dev, } rcu_read_unlock();
- if (unlikely(len > truesize)) { - pr_debug("%s: rx error: len %u exceeds truesize %lu\n", - dev->name, len, (unsigned long)ctx); - dev->stats.rx_length_errors++; - goto err_skb; - } - head_skb = page_to_skb(vi, rq, page, offset, len, truesize, !xdp_prog, metasize, headroom); curr_skb = head_skb;
From: Willy Tarreau w@1wt.eu
[ Upstream commit 62f20e068ccc50d6ab66fdb72ba90da2b9418c99 ]
This is a complement to commit aa6dd211e4b1 ("inet: use bigger hash table for IP ID generation"), but focusing on some specific aspects of IPv6.
Contary to IPv4, IPv6 only uses packet IDs with fragments, and with a minimum MTU of 1280, it's much less easy to force a remote peer to produce many fragments to explore its ID sequence. In addition packet IDs are 32-bit in IPv6, which further complicates their analysis. On the other hand, it is often easier to choose among plenty of possible source addresses and partially work around the bigger hash table the commit above permits, which leaves IPv6 partially exposed to some possibilities of remote analysis at the risk of weakening some protocols like DNS if some IDs can be predicted with a good enough probability.
Given the wide range of permitted IDs, the risk of collision is extremely low so there's no need to rely on the positive increment algorithm that is shared with the IPv4 code via ip_idents_reserve(). We have a fast PRNG, so let's simply call prandom_u32() and be done with it.
Performance measurements at 10 Gbps couldn't show any difference with the previous code, even when using a single core, because due to the large fragments, we're limited to only ~930 kpps at 10 Gbps and the cost of the random generation is completely offset by other operations and by the network transfer time. In addition, this change removes the need to update a shared entry in the idents table so it may even end up being slightly faster on large scale systems where this matters.
The risk of at least one collision here is about 1/80 million among 10 IDs, 1/850k among 100 IDs, and still only 1/8.5k among 1000 IDs, which remains very low compared to IPv4 where all IDs are reused every 4 to 80ms on a 10 Gbps flow depending on packet sizes.
Reported-by: Amit Klein aksecurity@gmail.com Signed-off-by: Willy Tarreau w@1wt.eu Reviewed-by: Eric Dumazet edumazet@google.com Link: https://lore.kernel.org/r/20210529110746.6796-1-w@1wt.eu Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- net/ipv6/output_core.c | 28 +++++----------------------- 1 file changed, 5 insertions(+), 23 deletions(-)
diff --git a/net/ipv6/output_core.c b/net/ipv6/output_core.c index af36acc1a644..2880dc7d9a49 100644 --- a/net/ipv6/output_core.c +++ b/net/ipv6/output_core.c @@ -15,29 +15,11 @@ static u32 __ipv6_select_ident(struct net *net, const struct in6_addr *dst, const struct in6_addr *src) { - const struct { - struct in6_addr dst; - struct in6_addr src; - } __aligned(SIPHASH_ALIGNMENT) combined = { - .dst = *dst, - .src = *src, - }; - u32 hash, id; - - /* Note the following code is not safe, but this is okay. */ - if (unlikely(siphash_key_is_zero(&net->ipv4.ip_id_key))) - get_random_bytes(&net->ipv4.ip_id_key, - sizeof(net->ipv4.ip_id_key)); - - hash = siphash(&combined, sizeof(combined), &net->ipv4.ip_id_key); - - /* Treat id of 0 as unset and if we get 0 back from ip_idents_reserve, - * set the hight order instead thus minimizing possible future - * collisions. - */ - id = ip_idents_reserve(hash, 1); - if (unlikely(!id)) - id = 1 << 31; + u32 id; + + do { + id = prandom_u32(); + } while (!id);
return id; }
From: Paul Cercueil paul@crapouillou.net
[ Upstream commit fc52f92a653215fbd6bc522ac5311857b335e589 ]
Ingenic JZ4760 and JZ4760B do have a FPU, but the config registers don't report it. Force the FPU detection in case the processor ID match the JZ4760(B) one.
Signed-off-by: Paul Cercueil paul@crapouillou.net Signed-off-by: Thomas Bogendoerfer tsbogend@alpha.franken.de Signed-off-by: Sasha Levin sashal@kernel.org --- arch/mips/kernel/cpu-probe.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index 0ef240adefb5..630fcb4cb30e 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -1840,6 +1840,11 @@ static inline void cpu_probe_ingenic(struct cpuinfo_mips *c, unsigned int cpu) */ case PRID_COMP_INGENIC_D0: c->isa_level &= ~MIPS_CPU_ISA_M32R2; + + /* FPU is not properly detected on JZ4760(B). */ + if (c->processor_id == 0x2ed0024f) + c->options |= MIPS_CPU_FPU; + fallthrough;
/*
From: Paul Cercueil paul@crapouillou.net
[ Upstream commit eb3849370ae32b571e1f9a63ba52c61adeaf88f7 ]
The clock driving the XBurst CPUs in Ingenic SoCs is integer divided from the main PLL. As such, it is possible to control the frequency of the CPU, either by changing the divider, or by changing the rate of the main PLL.
The XBurst CPUs also lack the CP0 timer; the TCU, a separate piece of hardware in the SoC, provides this functionality.
Signed-off-by: Paul Cercueil paul@crapouillou.net Signed-off-by: Thomas Bogendoerfer tsbogend@alpha.franken.de Signed-off-by: Sasha Levin sashal@kernel.org --- arch/mips/Kconfig | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index ed51970c08e7..344e6c622efd 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -428,6 +428,8 @@ config MACH_INGENIC_SOC select MIPS_GENERIC select MACH_INGENIC select SYS_SUPPORTS_ZBOOT_UART16550 + select CPU_SUPPORTS_CPUFREQ + select MIPS_EXTERNAL_TIMER
config LANTIQ bool "Lantiq based platforms"
From: Shiwu Zhang shiwu.zhang@amd.com
[ Upstream commit eba98523724be7ad3539f2c975de1527e0c99dd6 ]
Although the kfd_ioctl_get_dmabuf_info() still fail it will indicate the caller right metadat_size useful for the same kfd ioctl next time.
Signed-off-by: Shiwu Zhang shiwu.zhang@amd.com Reviewed-by: Nirmoy Das nirmoy.das@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_object.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index f9434bc2f9b2..db00de33caa3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -1246,6 +1246,9 @@ int amdgpu_bo_get_metadata(struct amdgpu_bo *bo, void *buffer,
BUG_ON(bo->tbo.type == ttm_bo_type_kernel); ubo = to_amdgpu_bo_user(bo); + if (metadata_size) + *metadata_size = ubo->metadata_size; + if (buffer) { if (buffer_size < ubo->metadata_size) return -EINVAL; @@ -1254,8 +1257,6 @@ int amdgpu_bo_get_metadata(struct amdgpu_bo *bo, void *buffer, memcpy(buffer, ubo->metadata, ubo->metadata_size); }
- if (metadata_size) - *metadata_size = ubo->metadata_size; if (flags) *flags = ubo->metadata_flags;
From: Kevin Wang kevin1.wang@amd.com
[ Upstream commit 2b8f731849800e3948763ccaff31cceac526789b ]
Re-adjust the function return order to avoid empty sdma version in the sriov environment. (read amdgpu_firmware_info)
Signed-off-by: Kevin Wang kevin1.wang@amd.com Reviewed-by: Stanley.Yang Stanley.Yang@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c b/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c index 240596b25fe4..9ab23947a151 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c @@ -145,9 +145,6 @@ static int sdma_v5_2_init_microcode(struct amdgpu_device *adev) struct amdgpu_firmware_info *info = NULL; const struct common_firmware_header *header = NULL;
- if (amdgpu_sriov_vf(adev) && (adev->asic_type == CHIP_SIENNA_CICHLID)) - return 0; - DRM_DEBUG("\n");
switch (adev->asic_type) { @@ -182,6 +179,9 @@ static int sdma_v5_2_init_microcode(struct amdgpu_device *adev) (void *)&adev->sdma.instance[0], sizeof(struct amdgpu_sdma_instance));
+ if (amdgpu_sriov_vf(adev) && (adev->asic_type == CHIP_SIENNA_CICHLID)) + return 0; + DRM_DEBUG("psp_load == '%s'\n", adev->firmware.load_type == AMDGPU_FW_LOAD_PSP ? "true" : "false");
From: Kees Cook keescook@chromium.org
[ Upstream commit 06888d571b513cbfc0b41949948def6cb81021b2 ]
Instead of reading the desired 5 bytes of the actual target field, the code was reading 8. This could result in a corrupted value if the trailing 3 bytes were non-zero, so instead use an appropriately sized and zero-initialized bounce buffer, and read only 5 bytes before casting to u64.
Signed-off-by: Kees Cook keescook@chromium.org Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_execution.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_execution.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_execution.c index 2cbd931363bd..6d26d9c63ab2 100644 --- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_execution.c +++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_execution.c @@ -29,8 +29,10 @@ static inline enum mod_hdcp_status validate_bksv(struct mod_hdcp *hdcp) { uint64_t n = 0; uint8_t count = 0; + u8 bksv[sizeof(n)] = { };
- memcpy(&n, hdcp->auth.msg.hdcp1.bksv, sizeof(uint64_t)); + memcpy(bksv, hdcp->auth.msg.hdcp1.bksv, sizeof(hdcp->auth.msg.hdcp1.bksv)); + n = *(uint64_t *)bksv;
while (n) { count++;
From: Jiansong Chen Jiansong.Chen@amd.com
[ Upstream commit 7d9c70d23550eb86a1bec1954ccaa8d6ec3a3328 ]
Take the situation with gfxoff, the optimization may cause corrupt CE ram contents. In addition emit_cntxcntl callback has similar optimization which firmware can handle properly even for power feature.
Signed-off-by: Jiansong Chen Jiansong.Chen@amd.com Reviewed-by: Hawking Zhang Hawking.Zhang@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_ib.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c index a2fe2dac32c1..98906a43fda3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c @@ -130,7 +130,7 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs, struct amdgpu_device *adev = ring->adev; struct amdgpu_ib *ib = &ibs[0]; struct dma_fence *tmp = NULL; - bool skip_preamble, need_ctx_switch; + bool need_ctx_switch; unsigned patch_offset = ~0; struct amdgpu_vm *vm; uint64_t fence_ctx; @@ -227,7 +227,6 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs, if (need_ctx_switch) status |= AMDGPU_HAVE_CTX_SWITCH;
- skip_preamble = ring->current_ctx == fence_ctx; if (job && ring->funcs->emit_cntxcntl) { status |= job->preamble_status; status |= job->preemption_status; @@ -245,14 +244,6 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs, for (i = 0; i < num_ibs; ++i) { ib = &ibs[i];
- /* drop preamble IBs if we don't have a context switch */ - if ((ib->flags & AMDGPU_IB_FLAG_PREAMBLE) && - skip_preamble && - !(status & AMDGPU_PREAMBLE_IB_PRESENT_FIRST) && - !amdgpu_mcbp && - !amdgpu_sriov_vf(adev)) /* for SRIOV preemption, Preamble CE ib must be inserted anyway */ - continue; - if (job && ring->funcs->emit_frame_cntl) { if (secure != !!(ib->flags & AMDGPU_IB_FLAGS_SECURE)) { amdgpu_ring_emit_frame_cntl(ring, false, secure);
From: Yang Yingliang yangyingliang@huawei.com
[ Upstream commit f13570e7e830ca4fbf4869015af8492b8918445e ]
After calling clk_prepare_enable(), clk_disable_unprepare() needs be called when prepare_timing_change() failed.
Reported-by: Hulk Robot hulkci@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com Signed-off-by: Thierry Reding treding@nvidia.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/clk/tegra/clk-tegra124-emc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/clk/tegra/clk-tegra124-emc.c b/drivers/clk/tegra/clk-tegra124-emc.c index bdf6f4a51617..74c1d894cca8 100644 --- a/drivers/clk/tegra/clk-tegra124-emc.c +++ b/drivers/clk/tegra/clk-tegra124-emc.c @@ -249,8 +249,10 @@ static int emc_set_timing(struct tegra_clk_emc *tegra, div = timing->parent_rate / (timing->rate / 2) - 2;
err = tegra->prepare_timing_change(emc, timing->rate); - if (err) + if (err) { + clk_disable_unprepare(timing->parent); return err; + }
spin_lock_irqsave(tegra->lock, flags);
From: Yuchung Cheng ycheng@google.com
[ Upstream commit a29cb6914681a55667436a9eb7a42e28da8cf387 ]
This patch aims to improve the situation when reordering and loss are ocurring in the same flight of packets.
Previously the reordering would first induce a spurious recovery, then the subsequent ACK may undo the cwnd (based on the timestamps e.g.). However the current loss recovery does not proceed to invoke RACK to install a reordering timer. If some packets are also lost, this may lead to a long RTO-based recovery. An example is https://groups.google.com/g/bbr-dev/c/OFHADvJbTEI
The solution is to after reverting the recovery, always invoke RACK to either mount the RACK timer to fast retransmit after the reordering window, or restarts the recovery if new loss is identified. Hence it is possible the sender may go from Recovery to Disorder/Open to Recovery again in one ACK.
Reported-by: mingkun bian bianmingkun@gmail.com Signed-off-by: Yuchung Cheng ycheng@google.com Signed-off-by: Neal Cardwell ncardwell@google.com Signed-off-by: Eric Dumazet edumazet@google.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- net/ipv4/tcp_input.c | 45 +++++++++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 19 deletions(-)
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 4cf4dd532d1c..bc266514ce58 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -2816,8 +2816,17 @@ static void tcp_process_loss(struct sock *sk, int flag, int num_dupack, *rexmit = REXMIT_LOST; }
+static bool tcp_force_fast_retransmit(struct sock *sk) +{ + struct tcp_sock *tp = tcp_sk(sk); + + return after(tcp_highest_sack_seq(tp), + tp->snd_una + tp->reordering * tp->mss_cache); +} + /* Undo during fast recovery after partial ACK. */ -static bool tcp_try_undo_partial(struct sock *sk, u32 prior_snd_una) +static bool tcp_try_undo_partial(struct sock *sk, u32 prior_snd_una, + bool *do_lost) { struct tcp_sock *tp = tcp_sk(sk);
@@ -2842,7 +2851,9 @@ static bool tcp_try_undo_partial(struct sock *sk, u32 prior_snd_una) tcp_undo_cwnd_reduction(sk, true); NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPPARTIALUNDO); tcp_try_keep_open(sk); - return true; + } else { + /* Partial ACK arrived. Force fast retransmit. */ + *do_lost = tcp_force_fast_retransmit(sk); } return false; } @@ -2866,14 +2877,6 @@ static void tcp_identify_packet_loss(struct sock *sk, int *ack_flag) } }
-static bool tcp_force_fast_retransmit(struct sock *sk) -{ - struct tcp_sock *tp = tcp_sk(sk); - - return after(tcp_highest_sack_seq(tp), - tp->snd_una + tp->reordering * tp->mss_cache); -} - /* Process an event, which can update packets-in-flight not trivially. * Main goal of this function is to calculate new estimate for left_out, * taking into account both packets sitting in receiver's buffer and @@ -2943,17 +2946,21 @@ static void tcp_fastretrans_alert(struct sock *sk, const u32 prior_snd_una, if (!(flag & FLAG_SND_UNA_ADVANCED)) { if (tcp_is_reno(tp)) tcp_add_reno_sack(sk, num_dupack, ece_ack); - } else { - if (tcp_try_undo_partial(sk, prior_snd_una)) - return; - /* Partial ACK arrived. Force fast retransmit. */ - do_lost = tcp_force_fast_retransmit(sk); - } - if (tcp_try_undo_dsack(sk)) { - tcp_try_keep_open(sk); + } else if (tcp_try_undo_partial(sk, prior_snd_una, &do_lost)) return; - } + + if (tcp_try_undo_dsack(sk)) + tcp_try_keep_open(sk); + tcp_identify_packet_loss(sk, ack_flag); + if (icsk->icsk_ca_state != TCP_CA_Recovery) { + if (!tcp_time_to_recover(sk, flag)) + return; + /* Undo reverts the recovery state. If loss is evident, + * starts a new recovery (e.g. reordering then loss); + */ + tcp_enter_recovery(sk, ece_ack); + } break; case TCP_CA_Loss: tcp_process_loss(sk, flag, num_dupack, rexmit);
From: Andreas Roeseler andreas.a.roeseler@gmail.com
[ Upstream commit e32ea44c7ae476f4c90e35ab0a29dc8ff082bc11 ]
Including <linux/in.h> and <netinet/in.h> in the dependencies breaks compilation of trinity due to multiple definitions. <linux/in.h> is only used in <linux/icmp.h> to provide the definition of the struct in_addr, but this can be substituted out by using the datatype __be32.
Signed-off-by: Andreas Roeseler andreas.a.roeseler@gmail.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- include/uapi/linux/icmp.h | 3 +-- net/ipv4/icmp.c | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-)
diff --git a/include/uapi/linux/icmp.h b/include/uapi/linux/icmp.h index c1da8244c5e1..163c0998aec9 100644 --- a/include/uapi/linux/icmp.h +++ b/include/uapi/linux/icmp.h @@ -20,7 +20,6 @@
#include <linux/types.h> #include <asm/byteorder.h> -#include <linux/in.h> #include <linux/if.h> #include <linux/in6.h>
@@ -154,7 +153,7 @@ struct icmp_ext_echo_iio { struct { struct icmp_ext_echo_ctype3_hdr ctype3_hdr; union { - struct in_addr ipv4_addr; + __be32 ipv4_addr; struct in6_addr ipv6_addr; } ip_addr; } addr; diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index 752e392083e6..0a57f1892e7e 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c @@ -1066,7 +1066,7 @@ static bool icmp_echo(struct sk_buff *skb) if (ident_len != sizeof(iio->ident.addr.ctype3_hdr) + sizeof(struct in_addr)) goto send_mal_query; - dev = ip_dev_find(net, iio->ident.addr.ip_addr.ipv4_addr.s_addr); + dev = ip_dev_find(net, iio->ident.addr.ip_addr.ipv4_addr); break; #if IS_ENABLED(CONFIG_IPV6) case ICMP_AFI_IP6:
From: Jiapeng Chong jiapeng.chong@linux.alibaba.com
[ Upstream commit aeb27bb76ad8197eb47890b1ff470d5faf8ec9a5 ]
The error code is missing in this code scenario so 0 will be returned. Add the error code '-EINVAL' to the return value 'ret'.
Eliminates the follow smatch warning:
drivers/infiniband/hw/cxgb4/qp.c:298 create_qp() warn: missing error code 'ret'.
Link: https://lore.kernel.org/r/1622545669-20625-1-git-send-email-jiapeng.chong@li... Reported-by: Abaci Robot abaci@linux.alibaba.com Signed-off-by: Jiapeng Chong jiapeng.chong@linux.alibaba.com Signed-off-by: Jason Gunthorpe jgg@nvidia.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/infiniband/hw/cxgb4/qp.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/infiniband/hw/cxgb4/qp.c b/drivers/infiniband/hw/cxgb4/qp.c index d109bb3822a5..c9403743346e 100644 --- a/drivers/infiniband/hw/cxgb4/qp.c +++ b/drivers/infiniband/hw/cxgb4/qp.c @@ -295,6 +295,7 @@ static int create_qp(struct c4iw_rdev *rdev, struct t4_wq *wq, if (user && (!wq->sq.bar2_pa || (need_rq && !wq->rq.bar2_pa))) { pr_warn("%s: sqid %u or rqid %u not in BAR2 range\n", pci_name(rdev->lldi.pdev), wq->sq.qid, wq->rq.qid); + ret = -EINVAL; goto free_dma; }
From: Joe Thornber ejt@redhat.com
[ Upstream commit 5faafc77f7de69147d1e818026b9a0cbf036a7b2 ]
Current commit code resets the place where the search for free blocks will begin back to the start of the metadata device. There are a couple of repercussions to this:
- The first allocation after the commit is likely to take longer than normal as it searches for a free block in an area that is likely to have very few free blocks (if any).
- Any free blocks it finds will have been recently freed. Reusing them means we have fewer old copies of the metadata to aid recovery from hardware error.
Fix these issues by leaving the cursor alone, only resetting when the search hits the end of the metadata device.
Signed-off-by: Joe Thornber ejt@redhat.com Signed-off-by: Mike Snitzer snitzer@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/md/persistent-data/dm-space-map-disk.c | 9 ++++++++- drivers/md/persistent-data/dm-space-map-metadata.c | 9 ++++++++- 2 files changed, 16 insertions(+), 2 deletions(-)
diff --git a/drivers/md/persistent-data/dm-space-map-disk.c b/drivers/md/persistent-data/dm-space-map-disk.c index 61f56909e00b..4f8069bb0481 100644 --- a/drivers/md/persistent-data/dm-space-map-disk.c +++ b/drivers/md/persistent-data/dm-space-map-disk.c @@ -171,6 +171,14 @@ static int sm_disk_new_block(struct dm_space_map *sm, dm_block_t *b) * Any block we allocate has to be free in both the old and current ll. */ r = sm_ll_find_common_free_block(&smd->old_ll, &smd->ll, smd->begin, smd->ll.nr_blocks, b); + if (r == -ENOSPC) { + /* + * There's no free block between smd->begin and the end of the metadata device. + * We search before smd->begin in case something has been freed. + */ + r = sm_ll_find_common_free_block(&smd->old_ll, &smd->ll, 0, smd->begin, b); + } + if (r) return r;
@@ -194,7 +202,6 @@ static int sm_disk_commit(struct dm_space_map *sm) return r;
memcpy(&smd->old_ll, &smd->ll, sizeof(smd->old_ll)); - smd->begin = 0; smd->nr_allocated_this_transaction = 0;
return 0; diff --git a/drivers/md/persistent-data/dm-space-map-metadata.c b/drivers/md/persistent-data/dm-space-map-metadata.c index 9e3c64ec2026..da439ac85796 100644 --- a/drivers/md/persistent-data/dm-space-map-metadata.c +++ b/drivers/md/persistent-data/dm-space-map-metadata.c @@ -452,6 +452,14 @@ static int sm_metadata_new_block_(struct dm_space_map *sm, dm_block_t *b) * Any block we allocate has to be free in both the old and current ll. */ r = sm_ll_find_common_free_block(&smm->old_ll, &smm->ll, smm->begin, smm->ll.nr_blocks, b); + if (r == -ENOSPC) { + /* + * There's no free block between smm->begin and the end of the metadata device. + * We search before smm->begin in case something has been freed. + */ + r = sm_ll_find_common_free_block(&smm->old_ll, &smm->ll, 0, smm->begin, b); + } + if (r) return r;
@@ -503,7 +511,6 @@ static int sm_metadata_commit(struct dm_space_map *sm) return r;
memcpy(&smm->old_ll, &smm->ll, sizeof(smm->old_ll)); - smm->begin = 0; smm->allocated_this_transaction = 0;
return 0;
From: Mikulas Patocka mpatocka@redhat.com
[ Upstream commit ee50cc19d80e9b9a8283d1fb517a778faf2f6899 ]
If dm-writecache overwrites existing cached data, it splits the incoming bio into many block-sized bios. The I/O scheduler does merge these bios into one large request but this needless splitting and merging causes performance degradation.
Fix this by avoiding bio splitting if the cache target area that is being overwritten is contiguous.
Signed-off-by: Mikulas Patocka mpatocka@redhat.com Signed-off-by: Mike Snitzer snitzer@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/md/dm-writecache.c | 38 ++++++++++++++++++++++++++++++-------- 1 file changed, 30 insertions(+), 8 deletions(-)
diff --git a/drivers/md/dm-writecache.c b/drivers/md/dm-writecache.c index aecc246ade26..a44007297e63 100644 --- a/drivers/md/dm-writecache.c +++ b/drivers/md/dm-writecache.c @@ -1360,14 +1360,18 @@ static int writecache_map(struct dm_target *ti, struct bio *bio) } else { do { bool found_entry = false; + bool search_used = false; if (writecache_has_error(wc)) goto unlock_error; e = writecache_find_entry(wc, bio->bi_iter.bi_sector, 0); if (e) { - if (!writecache_entry_is_committed(wc, e)) + if (!writecache_entry_is_committed(wc, e)) { + search_used = true; goto bio_copy; + } if (!WC_MODE_PMEM(wc) && !e->write_in_progress) { wc->overwrote_committed = true; + search_used = true; goto bio_copy; } found_entry = true; @@ -1404,13 +1408,31 @@ static int writecache_map(struct dm_target *ti, struct bio *bio) sector_t current_cache_sec = start_cache_sec + (bio_size >> SECTOR_SHIFT);
while (bio_size < bio->bi_iter.bi_size) { - struct wc_entry *f = writecache_pop_from_freelist(wc, current_cache_sec); - if (!f) - break; - write_original_sector_seq_count(wc, f, bio->bi_iter.bi_sector + - (bio_size >> SECTOR_SHIFT), wc->seq_count); - writecache_insert_entry(wc, f); - wc->uncommitted_blocks++; + if (!search_used) { + struct wc_entry *f = writecache_pop_from_freelist(wc, current_cache_sec); + if (!f) + break; + write_original_sector_seq_count(wc, f, bio->bi_iter.bi_sector + + (bio_size >> SECTOR_SHIFT), wc->seq_count); + writecache_insert_entry(wc, f); + wc->uncommitted_blocks++; + } else { + struct wc_entry *f; + struct rb_node *next = rb_next(&e->rb_node); + if (!next) + break; + f = container_of(next, struct wc_entry, rb_node); + if (f != e + 1) + break; + if (read_original_sector(wc, f) != + read_original_sector(wc, e) + (wc->block_size >> SECTOR_SHIFT)) + break; + if (unlikely(f->write_in_progress)) + break; + if (writecache_entry_is_committed(wc, f)) + wc->overwrote_committed = true; + e = f; + } bio_size += wc->block_size; current_cache_sec += wc->block_size >> SECTOR_SHIFT; }
From: Damien Le Moal damien.lemoal@wdc.com
[ Upstream commit 6842d264aa5205da338b6dcc6acfa2a6732558f1 ]
Fix dm_accept_partial_bio() to actually check that zone management commands are not passed as explained in the function documentation comment. Also, since a zone append operation cannot be split, add REQ_OP_ZONE_APPEND as a forbidden command.
White lines are added around the group of BUG_ON() calls to make the code more legible.
Signed-off-by: Damien Le Moal damien.lemoal@wdc.com Signed-off-by: Mike Snitzer snitzer@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/md/dm.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/md/dm.c b/drivers/md/dm.c index ca2aedd8ee7d..11af20080639 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -1237,8 +1237,8 @@ static int dm_dax_zero_page_range(struct dax_device *dax_dev, pgoff_t pgoff,
/* * A target may call dm_accept_partial_bio only from the map routine. It is - * allowed for all bio types except REQ_PREFLUSH, REQ_OP_ZONE_RESET, - * REQ_OP_ZONE_OPEN, REQ_OP_ZONE_CLOSE and REQ_OP_ZONE_FINISH. + * allowed for all bio types except REQ_PREFLUSH, REQ_OP_ZONE_* zone management + * operations and REQ_OP_ZONE_APPEND (zone append writes). * * dm_accept_partial_bio informs the dm that the target only wants to process * additional n_sectors sectors of the bio and the rest of the data should be @@ -1268,9 +1268,13 @@ void dm_accept_partial_bio(struct bio *bio, unsigned n_sectors) { struct dm_target_io *tio = container_of(bio, struct dm_target_io, clone); unsigned bi_size = bio->bi_iter.bi_size >> SECTOR_SHIFT; + BUG_ON(bio->bi_opf & REQ_PREFLUSH); + BUG_ON(op_is_zone_mgmt(bio_op(bio))); + BUG_ON(bio_op(bio) == REQ_OP_ZONE_APPEND); BUG_ON(bi_size > *tio->len_ptr); BUG_ON(n_sectors > bi_size); + *tio->len_ptr -= bi_size - n_sectors; bio->bi_iter.bi_size = n_sectors << SECTOR_SHIFT; }
From: Damien Le Moal damien.lemoal@wdc.com
[ Upstream commit 9ffbbb435d8f566a0924ce4b5dc7fc1bceb6dbf8 ]
Introduce the BIO flag BIO_ZONE_WRITE_LOCKED to indicate that a BIO owns the write lock of the zone it is targeting. This is the counterpart of the struct request flag RQF_ZONE_WRITE_LOCKED.
This new BIO flag is reserved for now for zone write locking control for device mapper targets exposing a zoned block device. Since in this case, the lock flag must not be propagated to the struct request that will be used to process the BIO, a BIO private flag is used rather than changing the RQF_ZONE_WRITE_LOCKED request flag into a common REQ_XXX flag that could be used for both BIO and request. This avoids conflicts down the stack with the block IO scheduler zone write locking (in mq-deadline).
Signed-off-by: Damien Le Moal damien.lemoal@wdc.com Reviewed-by: Christoph Hellwig hch@lst.de Reviewed-by: Hannes Reinecke hare@suse.de Reviewed-by: Chaitanya Kulkarni chaitanya.kulkarni@wdc.com Reviewed-by: Himanshu Madhani himanshu.madhani@oracle.com Acked-by: Jens Axboe axboe@kernel.dk Signed-off-by: Mike Snitzer snitzer@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- include/linux/blk_types.h | 1 + 1 file changed, 1 insertion(+)
diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h index db026b6ec15a..e5cf12f102a2 100644 --- a/include/linux/blk_types.h +++ b/include/linux/blk_types.h @@ -304,6 +304,7 @@ enum { BIO_CGROUP_ACCT, /* has been accounted to a cgroup */ BIO_TRACKED, /* set if bio goes through the rq_qos path */ BIO_REMAPPED, + BIO_ZONE_WRITE_LOCKED, /* Owns a zoned device zone write lock */ BIO_FLAG_LAST };
From: Horatiu Vultur horatiu.vultur@microchip.com
[ Upstream commit fcb34635854a5a5814227628867ea914a9805384 ]
According to the standard IEC 62439-2, the number of transitions needs to be counted for each transition 'between' ring state open and ring state closed and not from open state to closed state.
Therefore fix this for both ring and interconnect ring.
Signed-off-by: Horatiu Vultur horatiu.vultur@microchip.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- net/bridge/br_mrp.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/net/bridge/br_mrp.c b/net/bridge/br_mrp.c index cd2b1e424e54..f7012b7d7ce4 100644 --- a/net/bridge/br_mrp.c +++ b/net/bridge/br_mrp.c @@ -627,8 +627,7 @@ int br_mrp_set_ring_state(struct net_bridge *br, if (!mrp) return -EINVAL;
- if (mrp->ring_state == BR_MRP_RING_STATE_CLOSED && - state->ring_state != BR_MRP_RING_STATE_CLOSED) + if (mrp->ring_state != state->ring_state) mrp->ring_transitions++;
mrp->ring_state = state->ring_state; @@ -715,8 +714,7 @@ int br_mrp_set_in_state(struct net_bridge *br, struct br_mrp_in_state *state) if (!mrp) return -EINVAL;
- if (mrp->in_state == BR_MRP_IN_STATE_CLOSED && - state->in_state != BR_MRP_IN_STATE_CLOSED) + if (mrp->in_state != state->in_state) mrp->in_transitions++;
mrp->in_state = state->in_state;
From: Radim Pavlik radim.pavlik@tbs-biometrics.com
[ Upstream commit 897120d41e7afd9da435cb00041a142aeeb53c07 ]
Checking value of MCP_INTF in mcp23s08_irq suggests that the handler may be called even when there is no interrupt pending.
But the actual interrupt could happened between reading MCP_INTF and MCP_GPIO. In this situation we got nothing from MCP_INTF, but the event gets acknowledged on the expander by reading MCP_GPIO. This leads to losing events.
Fix the problem by not reading any register until we see something in MCP_INTF.
The error was reproduced and fix tested on MCP23017.
Signed-off-by: Radim Pavlik radim.pavlik@tbs-biometrics.com Link: https://lore.kernel.org/r/AM7PR06MB6769E1183F68DEBB252F665ABA3E9@AM7PR06MB67... Signed-off-by: Linus Walleij linus.walleij@linaro.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/pinctrl/pinctrl-mcp23s08.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/drivers/pinctrl/pinctrl-mcp23s08.c b/drivers/pinctrl/pinctrl-mcp23s08.c index ce2d8014b7e0..799d596a1a4b 100644 --- a/drivers/pinctrl/pinctrl-mcp23s08.c +++ b/drivers/pinctrl/pinctrl-mcp23s08.c @@ -351,6 +351,11 @@ static irqreturn_t mcp23s08_irq(int irq, void *data) if (mcp_read(mcp, MCP_INTF, &intf)) goto unlock;
+ if (intf == 0) { + /* There is no interrupt pending */ + return IRQ_HANDLED; + } + if (mcp_read(mcp, MCP_INTCAP, &intcap)) goto unlock;
@@ -368,11 +373,6 @@ static irqreturn_t mcp23s08_irq(int irq, void *data) mcp->cached_gpio = gpio; mutex_unlock(&mcp->lock);
- if (intf == 0) { - /* There is no interrupt pending */ - return IRQ_HANDLED; - } - dev_dbg(mcp->chip.parent, "intcap 0x%04X intf 0x%04X gpio_orig 0x%04X gpio 0x%04X\n", intcap, intf, gpio_orig, gpio);
From: Liwei Song liwei.song@windriver.com
[ Upstream commit fb3612840d4f587a0af9511a11d7989d1fa48206 ]
It may need hold Global Config Lock a longer time when download DDP package file, extend the timeout value to 5000ms to ensure that download can be finished before other AQ command got time to run, this will fix the issue below when probe the device, 5000ms is a test value that work with both Backplane and BreakoutCable NVM image:
ice 0000:f4:00.0: VSI 12 failed lan queue config, error ICE_ERR_CFG ice 0000:f4:00.0: Failed to delete VSI 12 in FW - error: ICE_ERR_AQ_TIMEOUT ice 0000:f4:00.0: probe failed due to setup PF switch: -12 ice: probe of 0000:f4:00.0 failed with error -12
Signed-off-by: Liwei Song liwei.song@windriver.com Tested-by: Tony Brelinski tonyx.brelinski@intel.com Signed-off-by: Tony Nguyen anthony.l.nguyen@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/intel/ice/ice_type.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/intel/ice/ice_type.h b/drivers/net/ethernet/intel/ice/ice_type.h index 4474dd6a7ba1..a925273c2cca 100644 --- a/drivers/net/ethernet/intel/ice/ice_type.h +++ b/drivers/net/ethernet/intel/ice/ice_type.h @@ -63,7 +63,7 @@ enum ice_aq_res_ids { /* FW update timeout definitions are in milliseconds */ #define ICE_NVM_TIMEOUT 180000 #define ICE_CHANGE_LOCK_TIMEOUT 1000 -#define ICE_GLOBAL_CFG_LOCK_TIMEOUT 3000 +#define ICE_GLOBAL_CFG_LOCK_TIMEOUT 5000
enum ice_aq_res_access_type { ICE_RES_READ = 1,
From: Paul M Stillwell Jr paul.m.stillwell.jr@intel.com
[ Upstream commit 7e94090ae13e1ae5fe8bd3a9cd08136260bb7039 ]
clang generates deadcode.DeadStores warnings when a variable is used to read a value, but then that value isn't used later in the code. Fix this warning.
Signed-off-by: Paul M Stillwell Jr paul.m.stillwell.jr@intel.com Tested-by: Tony Brelinski tonyx.brelinski@intel.com Signed-off-by: Tony Nguyen anthony.l.nguyen@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/intel/ice/ice_ethtool.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool.c b/drivers/net/ethernet/intel/ice/ice_ethtool.c index 99301ad95290..1f30f24648d8 100644 --- a/drivers/net/ethernet/intel/ice/ice_ethtool.c +++ b/drivers/net/ethernet/intel/ice/ice_ethtool.c @@ -3462,13 +3462,9 @@ static int ice_get_rc_coalesce(struct ethtool_coalesce *ec, enum ice_container_type c_type, struct ice_ring_container *rc) { - struct ice_pf *pf; - if (!rc->ring) return -EINVAL;
- pf = rc->ring->vsi->back; - switch (c_type) { case ICE_RX_CONTAINER: ec->use_adaptive_rx_coalesce = ITR_IS_DYNAMIC(rc); @@ -3480,7 +3476,7 @@ ice_get_rc_coalesce(struct ethtool_coalesce *ec, enum ice_container_type c_type, ec->tx_coalesce_usecs = rc->itr_setting; break; default: - dev_dbg(ice_pf_to_dev(pf), "Invalid c_type %d\n", c_type); + dev_dbg(ice_pf_to_dev(rc->ring->vsi->back), "Invalid c_type %d\n", c_type); return -EINVAL; }
From: Xianting Tian xianting.tian@linux.alibaba.com
[ Upstream commit 85eb1389458d134bdb75dad502cc026c3753a619 ]
We should not directly BUG() when there is hdr error, it is better to output a print when such error happens. Currently, the caller of xmit_skb() already did it.
Signed-off-by: Xianting Tian xianting.tian@linux.alibaba.com Reviewed-by: Leon Romanovsky leonro@nvidia.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/virtio_net.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 252f6718d730..2debb32a1813 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -1625,7 +1625,7 @@ static int xmit_skb(struct send_queue *sq, struct sk_buff *skb) if (virtio_net_hdr_from_skb(skb, &hdr->hdr, virtio_is_little_endian(vi->vdev), false, 0)) - BUG(); + return -EPROTO;
if (vi->mergeable_rx_bufs) hdr->num_buffers = 0;
From: Yang Yingliang yangyingliang@huawei.com
[ Upstream commit f1fe19c2cb3fdc92a614cf330ced1613f8f1a681 ]
It will cause null-ptr-deref if platform_get_resource() returns NULL, we need check the return value.
Signed-off-by: Yang Yingliang yangyingliang@huawei.com Reviewed-by: Vladimir Oltean vladimir.oltean@nxp.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/dsa/ocelot/seville_vsc9953.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/drivers/net/dsa/ocelot/seville_vsc9953.c b/drivers/net/dsa/ocelot/seville_vsc9953.c index 84f93a874d50..deae923c8b7a 100644 --- a/drivers/net/dsa/ocelot/seville_vsc9953.c +++ b/drivers/net/dsa/ocelot/seville_vsc9953.c @@ -1206,6 +1206,11 @@ static int seville_probe(struct platform_device *pdev) felix->info = &seville_info_vsc9953;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + err = -EINVAL; + dev_err(&pdev->dev, "Invalid resource\n"); + goto err_alloc_felix; + } felix->switch_base = res->start;
ds = kzalloc(sizeof(struct dsa_switch), GFP_KERNEL);
From: Yang Yingliang yangyingliang@huawei.com
[ Upstream commit 74325bf0104573c6dfce42837139aeef3f34be76 ]
It will cause null-ptr-deref if platform_get_resource() returns NULL, we need check the return value.
Signed-off-by: Yang Yingliang yangyingliang@huawei.com Acked-by: Florian Fainelli f.fainelli@gmail.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/broadcom/genet/bcmmii.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/drivers/net/ethernet/broadcom/genet/bcmmii.c b/drivers/net/ethernet/broadcom/genet/bcmmii.c index 5335244e4577..89d16c587bb7 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmmii.c +++ b/drivers/net/ethernet/broadcom/genet/bcmmii.c @@ -423,6 +423,10 @@ static int bcmgenet_mii_register(struct bcmgenet_priv *priv) int id, ret;
pres = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!pres) { + dev_err(&pdev->dev, "Invalid resource\n"); + return -EINVAL; + } memset(&res, 0, sizeof(res)); memset(&ppd, 0, sizeof(ppd));
From: Yang Yingliang yangyingliang@huawei.com
[ Upstream commit 0bb51a3a385790a4be20085494cf78f70dadf646 ]
It will cause null-ptr-deref if platform_get_resource() returns NULL, we need check the return value.
Signed-off-by: Yang Yingliang yangyingliang@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c index d39c7639cdba..f1010fe14096 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c @@ -7387,6 +7387,10 @@ static int mvpp2_probe(struct platform_device *pdev) return PTR_ERR(priv->lms_base); } else { res = platform_get_resource(pdev, IORESOURCE_MEM, 1); + if (!res) { + dev_err(&pdev->dev, "Invalid resource\n"); + return -EINVAL; + } if (has_acpi_companion(&pdev->dev)) { /* In case the MDIO memory region is declared in * the ACPI, it can already appear as 'in-use'
From: Yang Yingliang yangyingliang@huawei.com
[ Upstream commit 20f1932e2282c58cb5ac59517585206cf5b385ae ]
It will cause null-ptr-deref if platform_get_resource() returns NULL, we need check the return value.
Signed-off-by: Yang Yingliang yangyingliang@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/micrel/ks8842.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/drivers/net/ethernet/micrel/ks8842.c b/drivers/net/ethernet/micrel/ks8842.c index caa251d0e381..b27713906d3a 100644 --- a/drivers/net/ethernet/micrel/ks8842.c +++ b/drivers/net/ethernet/micrel/ks8842.c @@ -1135,6 +1135,10 @@ static int ks8842_probe(struct platform_device *pdev) unsigned i;
iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!iomem) { + dev_err(&pdev->dev, "Invalid resource\n"); + return -EINVAL; + } if (!request_mem_region(iomem->start, resource_size(iomem), DRV_NAME)) goto err_mem_region;
From: Yang Yingliang yangyingliang@huawei.com
[ Upstream commit 35cba15a504bf4f585bb9d78f47b22b28a1a06b2 ]
Use devm_platform_get_and_ioremap_resource() to simplify code and avoid a null-ptr-deref by checking 'res' in it.
Signed-off-by: Yang Yingliang yangyingliang@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/moxa/moxart_ether.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/moxa/moxart_ether.c b/drivers/net/ethernet/moxa/moxart_ether.c index b85733942053..5249b64f4fc5 100644 --- a/drivers/net/ethernet/moxa/moxart_ether.c +++ b/drivers/net/ethernet/moxa/moxart_ether.c @@ -481,13 +481,12 @@ static int moxart_mac_probe(struct platform_device *pdev) priv->ndev = ndev; priv->pdev = pdev;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - ndev->base_addr = res->start; - priv->base = devm_ioremap_resource(p_dev, res); + priv->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); if (IS_ERR(priv->base)) { ret = PTR_ERR(priv->base); goto init_fail; } + ndev->base_addr = res->start;
spin_lock_init(&priv->txlock);
From: Nikola Cornij nikola.cornij@amd.com
[ Upstream commit 346cf627fb27c0fea63a041cedbaa4f31784e504 ]
[why] DSCCLK validation is not necessary because DSCCLK is derrived from DISPCLK, therefore if DISPCLK validation passes, DSCCLK is valid, too. Doing DSCLK validation in addition to DISPCLK leads to modes being wrongly rejected when DSCCLK was incorrectly set outside of DML.
[how] Remove DSCCLK validation because it's implicitly validated under DISPCLK
Signed-off-by: Nikola Cornij nikola.cornij@amd.com Reviewed-by: Dmytro Laktyushkin Dmytro.Laktyushkin@amd.com Acked-by: Stylon Wang stylon.wang@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 --- .../dc/dml/dcn30/display_mode_vba_30.c | 64 ++++++------------- 1 file changed, 21 insertions(+), 43 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c index cb3f70a71b51..af7d57602b2c 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c @@ -64,6 +64,7 @@ typedef struct { #define BPP_INVALID 0 #define BPP_BLENDED_PIPE 0xffffffff #define DCN30_MAX_DSC_IMAGE_WIDTH 5184 +#define DCN30_MAX_FMT_420_BUFFER_WIDTH 4096
static void DisplayPipeConfiguration(struct display_mode_lib *mode_lib); static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerformanceCalculation( @@ -3987,19 +3988,30 @@ void dml30_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l } else if (v->PlaneRequiredDISPCLKWithoutODMCombine > v->MaxDispclkRoundedDownToDFSGranularity) { v->ODMCombineEnablePerState[i][k] = dm_odm_combine_mode_2to1; v->PlaneRequiredDISPCLK = v->PlaneRequiredDISPCLKWithODMCombine2To1; - } else if (v->DSCEnabled[k] && (v->HActive[k] > DCN30_MAX_DSC_IMAGE_WIDTH)) { - v->ODMCombineEnablePerState[i][k] = dm_odm_combine_mode_2to1; - v->PlaneRequiredDISPCLK = v->PlaneRequiredDISPCLKWithODMCombine2To1; } else { v->ODMCombineEnablePerState[i][k] = dm_odm_combine_mode_disabled; v->PlaneRequiredDISPCLK = v->PlaneRequiredDISPCLKWithoutODMCombine; - /*420 format workaround*/ - if (v->HActive[k] > 4096 && v->OutputFormat[k] == dm_420) { + } + if (v->DSCEnabled[k] && v->HActive[k] > DCN30_MAX_DSC_IMAGE_WIDTH + && v->ODMCombineEnablePerState[i][k] != dm_odm_combine_mode_4to1) { + if (v->HActive[k] / 2 > DCN30_MAX_DSC_IMAGE_WIDTH) { + v->ODMCombineEnablePerState[i][k] = dm_odm_combine_mode_4to1; + v->PlaneRequiredDISPCLK = v->PlaneRequiredDISPCLKWithODMCombine4To1; + } else { + v->ODMCombineEnablePerState[i][k] = dm_odm_combine_mode_2to1; + v->PlaneRequiredDISPCLK = v->PlaneRequiredDISPCLKWithODMCombine2To1; + } + } + if (v->OutputFormat[k] == dm_420 && v->HActive[k] > DCN30_MAX_FMT_420_BUFFER_WIDTH + && v->ODMCombineEnablePerState[i][k] != dm_odm_combine_mode_4to1) { + if (v->HActive[k] / 2 > DCN30_MAX_FMT_420_BUFFER_WIDTH) { + v->ODMCombineEnablePerState[i][k] = dm_odm_combine_mode_4to1; + v->PlaneRequiredDISPCLK = v->PlaneRequiredDISPCLKWithODMCombine4To1; + } else { v->ODMCombineEnablePerState[i][k] = dm_odm_combine_mode_2to1; v->PlaneRequiredDISPCLK = v->PlaneRequiredDISPCLKWithODMCombine2To1; } } - if (v->ODMCombineEnablePerState[i][k] == dm_odm_combine_mode_4to1) { v->MPCCombine[i][j][k] = false; v->NoOfDPP[i][j][k] = 4; @@ -4281,42 +4293,8 @@ void dml30_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l } }
- for (i = 0; i < v->soc.num_states; i++) { - v->DSCCLKRequiredMoreThanSupported[i] = false; - for (k = 0; k <= v->NumberOfActivePlanes - 1; k++) { - if (v->BlendingAndTiming[k] == k) { - if (v->Output[k] == dm_dp || v->Output[k] == dm_edp) { - if (v->OutputFormat[k] == dm_420) { - v->DSCFormatFactor = 2; - } else if (v->OutputFormat[k] == dm_444) { - v->DSCFormatFactor = 1; - } else if (v->OutputFormat[k] == dm_n422) { - v->DSCFormatFactor = 2; - } else { - v->DSCFormatFactor = 1; - } - if (v->RequiresDSC[i][k] == true) { - if (v->ODMCombineEnablePerState[i][k] == dm_odm_combine_mode_4to1) { - if (v->PixelClockBackEnd[k] / 12.0 / v->DSCFormatFactor - > (1.0 - v->DISPCLKDPPCLKDSCCLKDownSpreading / 100.0) * v->MaxDSCCLK[i]) { - v->DSCCLKRequiredMoreThanSupported[i] = true; - } - } else if (v->ODMCombineEnablePerState[i][k] == dm_odm_combine_mode_2to1) { - if (v->PixelClockBackEnd[k] / 6.0 / v->DSCFormatFactor - > (1.0 - v->DISPCLKDPPCLKDSCCLKDownSpreading / 100.0) * v->MaxDSCCLK[i]) { - v->DSCCLKRequiredMoreThanSupported[i] = true; - } - } else { - if (v->PixelClockBackEnd[k] / 3.0 / v->DSCFormatFactor - > (1.0 - v->DISPCLKDPPCLKDSCCLKDownSpreading / 100.0) * v->MaxDSCCLK[i]) { - v->DSCCLKRequiredMoreThanSupported[i] = true; - } - } - } - } - } - } - } + /* Skip dscclk validation: as long as dispclk is supported, dscclk is also implicitly supported */ + for (i = 0; i < v->soc.num_states; i++) { v->NotEnoughDSCUnits[i] = false; v->TotalDSCUnitsRequired = 0.0; @@ -5319,7 +5297,7 @@ void dml30_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l for (j = 0; j < 2; j++) { if (v->ScaleRatioAndTapsSupport == 1 && v->SourceFormatPixelAndScanSupport == 1 && v->ViewportSizeSupport[i][j] == 1 && v->DIOSupport[i] == 1 && v->ODMCombine4To1SupportCheckOK[i] == 1 - && v->NotEnoughDSCUnits[i] == 0 && v->DSCCLKRequiredMoreThanSupported[i] == 0 + && v->NotEnoughDSCUnits[i] == 0 && v->DTBCLKRequiredMoreThanSupported[i] == 0 && v->ROBSupport[i][j] == 1 && v->DISPCLK_DPPCLK_Support[i][j] == 1 && v->TotalAvailablePipesSupport[i][j] == 1 && EnoughWritebackUnits == 1 && WritebackModeSupport == 1
From: Ilya Bakoulin Ilya.Bakoulin@amd.com
[ Upstream commit ae88357c7966ec2a52cb1e70fd42f74a40c9dfcb ]
[Why] This change was found to break some high-refresh modes. Reverting to unblock mainline.
Signed-off-by: Ilya Bakoulin Ilya.Bakoulin@amd.com Reviewed-by: Sung Lee Sung.Lee@amd.com Acked-by: Stylon Wang stylon.wang@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 --- .../amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c | 78 +++++++------------ .../drm/amd/display/dc/dcn21/dcn21_resource.c | 33 +++----- 2 files changed, 39 insertions(+), 72 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c index 1f56ceab5922..75ba86f951f8 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c @@ -835,66 +835,47 @@ static struct wm_table lpddr4_wm_table_rn = { } };
-static unsigned int find_max_fclk_for_voltage(struct dpm_clocks *clock_table, - unsigned int voltage) +static unsigned int find_socclk_for_voltage(struct dpm_clocks *clock_table, unsigned int voltage) { int i; - uint32_t max_clk = 0;
- for (i = 0; i < PP_SMU_NUM_FCLK_DPM_LEVELS; i++) { - if (clock_table->FClocks[i].Vol <= voltage) { - max_clk = clock_table->FClocks[i].Freq > max_clk ? - clock_table->FClocks[i].Freq : max_clk; - } - } - - return max_clk; -} - -static unsigned int find_max_memclk_for_voltage(struct dpm_clocks *clock_table, - unsigned int voltage) -{ - int i; - uint32_t max_clk = 0; - - for (i = 0; i < PP_SMU_NUM_MEMCLK_DPM_LEVELS; i++) { - if (clock_table->MemClocks[i].Vol <= voltage) { - max_clk = clock_table->MemClocks[i].Freq > max_clk ? - clock_table->MemClocks[i].Freq : max_clk; - } + for (i = 0; i < PP_SMU_NUM_SOCCLK_DPM_LEVELS; i++) { + if (clock_table->SocClocks[i].Vol == voltage) + return clock_table->SocClocks[i].Freq; }
- return max_clk; + ASSERT(0); + return 0; }
-static unsigned int find_max_socclk_for_voltage(struct dpm_clocks *clock_table, - unsigned int voltage) +static unsigned int find_dcfclk_for_voltage(struct dpm_clocks *clock_table, unsigned int voltage) { int i; - uint32_t max_clk = 0;
- for (i = 0; i < PP_SMU_NUM_SOCCLK_DPM_LEVELS; i++) { - if (clock_table->SocClocks[i].Vol <= voltage) { - max_clk = clock_table->SocClocks[i].Freq > max_clk ? - clock_table->SocClocks[i].Freq : max_clk; - } + for (i = 0; i < PP_SMU_NUM_DCFCLK_DPM_LEVELS; i++) { + if (clock_table->DcfClocks[i].Vol == voltage) + return clock_table->DcfClocks[i].Freq; }
- return max_clk; + ASSERT(0); + return 0; }
static void rn_clk_mgr_helper_populate_bw_params(struct clk_bw_params *bw_params, struct dpm_clocks *clock_table, struct integrated_info *bios_info) { int i, j = 0; - unsigned int volt;
j = -1;
- /* Find max DPM */ - for (i = 0; i < PP_SMU_NUM_DCFCLK_DPM_LEVELS; ++i) { - if (clock_table->DcfClocks[i].Freq != 0 && - clock_table->DcfClocks[i].Vol != 0) + ASSERT(PP_SMU_NUM_FCLK_DPM_LEVELS <= MAX_NUM_DPM_LVL); + + /* Find lowest DPM, FCLK is filled in reverse order*/ + + for (i = PP_SMU_NUM_FCLK_DPM_LEVELS - 1; i >= 0; i--) { + if (clock_table->FClocks[i].Freq != 0 && clock_table->FClocks[i].Vol != 0) { j = i; + break; + } }
if (j == -1) { @@ -905,18 +886,13 @@ static void rn_clk_mgr_helper_populate_bw_params(struct clk_bw_params *bw_params
bw_params->clk_table.num_entries = j + 1;
- for (i = 0; i < bw_params->clk_table.num_entries; i++) { - volt = clock_table->DcfClocks[i].Vol; - - bw_params->clk_table.entries[i].voltage = volt; - bw_params->clk_table.entries[i].dcfclk_mhz = - clock_table->DcfClocks[i].Freq; - bw_params->clk_table.entries[i].fclk_mhz = - find_max_fclk_for_voltage(clock_table, volt); - bw_params->clk_table.entries[i].memclk_mhz = - find_max_memclk_for_voltage(clock_table, volt); - bw_params->clk_table.entries[i].socclk_mhz = - find_max_socclk_for_voltage(clock_table, volt); + for (i = 0; i < bw_params->clk_table.num_entries; i++, j--) { + bw_params->clk_table.entries[i].fclk_mhz = clock_table->FClocks[j].Freq; + bw_params->clk_table.entries[i].memclk_mhz = clock_table->MemClocks[j].Freq; + bw_params->clk_table.entries[i].voltage = clock_table->FClocks[j].Vol; + bw_params->clk_table.entries[i].dcfclk_mhz = find_dcfclk_for_voltage(clock_table, clock_table->FClocks[j].Vol); + bw_params->clk_table.entries[i].socclk_mhz = find_socclk_for_voltage(clock_table, + bw_params->clk_table.entries[i].voltage); }
bw_params->vram_type = bios_info->memory_type; diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c index 38a2aa87f5f5..8e3f1d0b4cc3 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c @@ -1575,12 +1575,10 @@ static struct _vcs_dpi_voltage_scaling_st construct_low_pstate_lvl(struct clk_li low_pstate_lvl.phyclk_d18_mhz = dcn2_1_soc.clock_limits[high_voltage_lvl].phyclk_d18_mhz; low_pstate_lvl.phyclk_mhz = dcn2_1_soc.clock_limits[high_voltage_lvl].phyclk_mhz;
- if (clk_table->num_entries < MAX_NUM_DPM_LVL) { - for (i = clk_table->num_entries; i > 1; i--) - clk_table->entries[i] = clk_table->entries[i-1]; - clk_table->entries[1] = clk_table->entries[0]; - clk_table->num_entries++; - } + for (i = clk_table->num_entries; i > 1; i--) + clk_table->entries[i] = clk_table->entries[i-1]; + clk_table->entries[1] = clk_table->entries[0]; + clk_table->num_entries++;
return low_pstate_lvl; } @@ -1612,6 +1610,10 @@ static void update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_param } }
+ /* clk_table[1] is reserved for min DF PState. skip here to fill in later. */ + if (i == 1) + k++; + clock_limits[k].state = k; clock_limits[k].dcfclk_mhz = clk_table->entries[i].dcfclk_mhz; clock_limits[k].fabricclk_mhz = clk_table->entries[i].fclk_mhz; @@ -1628,25 +1630,14 @@ static void update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_param
k++; } - - if (clk_table->num_entries >= MAX_NUM_DPM_LVL) { - for (i = 0; i < clk_table->num_entries + 1; i++) - dcn2_1_soc.clock_limits[i] = clock_limits[i]; - } else { - dcn2_1_soc.clock_limits[0] = clock_limits[0]; - for (i = 2; i < clk_table->num_entries + 1; i++) { - dcn2_1_soc.clock_limits[i] = clock_limits[i - 1]; - dcn2_1_soc.clock_limits[i].state = i; - } - } - + for (i = 0; i < clk_table->num_entries + 1; i++) + dcn2_1_soc.clock_limits[i] = clock_limits[i]; if (clk_table->num_entries) { + dcn2_1_soc.num_states = clk_table->num_entries + 1; /* fill in min DF PState */ dcn2_1_soc.clock_limits[1] = construct_low_pstate_lvl(clk_table, closest_clk_lvl); - dcn2_1_soc.num_states = clk_table->num_entries; /* duplicate last level */ - dcn2_1_soc.clock_limits[dcn2_1_soc.num_states] = - dcn2_1_soc.clock_limits[dcn2_1_soc.num_states - 1]; + dcn2_1_soc.clock_limits[dcn2_1_soc.num_states] = dcn2_1_soc.clock_limits[dcn2_1_soc.num_states - 1]; dcn2_1_soc.clock_limits[dcn2_1_soc.num_states].state = dcn2_1_soc.num_states; }
From: Roman Li roman.li@amd.com
[ Upstream commit c521fc316d12fb9ea7b7680e301d673bceda922e ]
[Why] We update scaling settings when scaling mode has been changed. However when changing mode from native resolution the scaling mode previously set gets ignored.
[How] Perform scaling settings update on modeset.
Signed-off-by: Roman Li roman.li@amd.com Reviewed-by: Nicholas Kazlauskas Nicholas.Kazlauskas@amd.com Acked-by: Stylon Wang stylon.wang@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 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
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 62663e287b21..58577f7a57c1 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -9472,7 +9472,8 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm, BUG_ON(dm_new_crtc_state->stream == NULL);
/* Scaling or underscan settings */ - if (is_scaling_state_different(dm_old_conn_state, dm_new_conn_state)) + if (is_scaling_state_different(dm_old_conn_state, dm_new_conn_state) || + drm_atomic_crtc_needs_modeset(new_crtc_state)) update_stream_scaling_settings( &new_crtc_state->mode, dm_new_conn_state, dm_new_crtc_state->stream);
From: Vladimir Stempen vladimir.stempen@amd.com
[ Upstream commit 3f8518b60c10aa96f3efa38a967a0b4eb9211ac0 ]
[why] When OS overrides training link training parameters for MST device to SST mode, MST resources are not released and leak of the resource may result crash and incorrect MST discovery during following hot plugs.
[how] Retaining sink object to be reused by SST link and releasing MST resources.
Signed-off-by: Vladimir Stempen vladimir.stempen@amd.com Reviewed-by: Wenjing Liu Wenjing.Liu@amd.com Acked-by: Stylon Wang stylon.wang@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/core/dc_link_dp.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 3ff3d9e90983..f26ed50a9660 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -1784,6 +1784,8 @@ static void set_dp_mst_mode(struct dc_link *link, bool mst_enable) link->type = dc_connection_single; link->local_sink = link->remote_sinks[0]; link->local_sink->sink_signal = SIGNAL_TYPE_DISPLAY_PORT; + dc_sink_retain(link->local_sink); + dm_helpers_dp_mst_stop_top_mgr(link->ctx, link); } else if (mst_enable == true && link->type == dc_connection_single && link->remote_sinks[0] != NULL) {
From: Wesley Chalmers Wesley.Chalmers@amd.com
[ Upstream commit 3577e1678772ce3ede92af3a75b44a4b76f9b4ad ]
[WHY] DISPCLK_MAX_ERRDET_CYCLES must be 7 to prevent connection loss when changing DENTIST_DISPCLK_WDIVIDER from 126 to 127 and back.
Signed-off-by: Wesley Chalmers Wesley.Chalmers@amd.com Reviewed-by: Dmytro Laktyushkin Dmytro.Laktyushkin@amd.com Acked-by: Stylon Wang stylon.wang@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 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
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 6a10daec15cc..793554e61c52 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c @@ -243,7 +243,7 @@ void dcn20_dccg_init(struct dce_hwseq *hws) REG_WRITE(MILLISECOND_TIME_BASE_DIV, 0x1186a0);
/* This value is dependent on the hardware pipeline delay so set once per SOC */ - REG_WRITE(DISPCLK_FREQ_CHANGE_CNTL, 0x801003c); + REG_WRITE(DISPCLK_FREQ_CHANGE_CNTL, 0xe01003c); }
void dcn20_disable_vga(
From: Wesley Chalmers Wesley.Chalmers@amd.com
[ Upstream commit e4e3678260e9734f6f41b4325aac0b171833a618 ]
[WHY] For DCN30 and later, there is no data in DML arrays indexed by state at index num_states.
Signed-off-by: Wesley Chalmers Wesley.Chalmers@amd.com Reviewed-by: Dmytro Laktyushkin Dmytro.Laktyushkin@amd.com Acked-by: Stylon Wang stylon.wang@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 --- .../amd/display/dc/dml/dcn30/display_mode_vba_30.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c index af7d57602b2c..db6bb7ea5316 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c @@ -2053,7 +2053,7 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman v->DISPCLKWithoutRamping, v->DISPCLKDPPCLKVCOSpeed); v->MaxDispclkRoundedToDFSGranularity = RoundToDFSGranularityDown( - v->soc.clock_limits[mode_lib->soc.num_states].dispclk_mhz, + v->soc.clock_limits[mode_lib->soc.num_states - 1].dispclk_mhz, v->DISPCLKDPPCLKVCOSpeed); if (v->DISPCLKWithoutRampingRoundedToDFSGranularity > v->MaxDispclkRoundedToDFSGranularity) { @@ -3958,20 +3958,20 @@ void dml30_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l for (k = 0; k <= v->NumberOfActivePlanes - 1; k++) { v->PlaneRequiredDISPCLKWithoutODMCombine = v->PixelClock[k] * (1.0 + v->DISPCLKDPPCLKDSCCLKDownSpreading / 100.0) * (1.0 + v->DISPCLKRampingMargin / 100.0); - if ((v->PlaneRequiredDISPCLKWithoutODMCombine >= v->MaxDispclk[i] && v->MaxDispclk[i] == v->MaxDispclk[mode_lib->soc.num_states] - && v->MaxDppclk[i] == v->MaxDppclk[mode_lib->soc.num_states])) { + if ((v->PlaneRequiredDISPCLKWithoutODMCombine >= v->MaxDispclk[i] && v->MaxDispclk[i] == v->MaxDispclk[mode_lib->soc.num_states - 1] + && v->MaxDppclk[i] == v->MaxDppclk[mode_lib->soc.num_states - 1])) { v->PlaneRequiredDISPCLKWithoutODMCombine = v->PixelClock[k] * (1 + v->DISPCLKDPPCLKDSCCLKDownSpreading / 100.0); } v->PlaneRequiredDISPCLKWithODMCombine2To1 = v->PixelClock[k] / 2 * (1 + v->DISPCLKDPPCLKDSCCLKDownSpreading / 100.0) * (1 + v->DISPCLKRampingMargin / 100.0); - if ((v->PlaneRequiredDISPCLKWithODMCombine2To1 >= v->MaxDispclk[i] && v->MaxDispclk[i] == v->MaxDispclk[mode_lib->soc.num_states] - && v->MaxDppclk[i] == v->MaxDppclk[mode_lib->soc.num_states])) { + if ((v->PlaneRequiredDISPCLKWithODMCombine2To1 >= v->MaxDispclk[i] && v->MaxDispclk[i] == v->MaxDispclk[mode_lib->soc.num_states - 1] + && v->MaxDppclk[i] == v->MaxDppclk[mode_lib->soc.num_states - 1])) { v->PlaneRequiredDISPCLKWithODMCombine2To1 = v->PixelClock[k] / 2 * (1 + v->DISPCLKDPPCLKDSCCLKDownSpreading / 100.0); } v->PlaneRequiredDISPCLKWithODMCombine4To1 = v->PixelClock[k] / 4 * (1 + v->DISPCLKDPPCLKDSCCLKDownSpreading / 100.0) * (1 + v->DISPCLKRampingMargin / 100.0); - if ((v->PlaneRequiredDISPCLKWithODMCombine4To1 >= v->MaxDispclk[i] && v->MaxDispclk[i] == v->MaxDispclk[mode_lib->soc.num_states] - && v->MaxDppclk[i] == v->MaxDppclk[mode_lib->soc.num_states])) { + if ((v->PlaneRequiredDISPCLKWithODMCombine4To1 >= v->MaxDispclk[i] && v->MaxDispclk[i] == v->MaxDispclk[mode_lib->soc.num_states - 1] + && v->MaxDppclk[i] == v->MaxDppclk[mode_lib->soc.num_states - 1])) { v->PlaneRequiredDISPCLKWithODMCombine4To1 = v->PixelClock[k] / 4 * (1 + v->DISPCLKDPPCLKDSCCLKDownSpreading / 100.0); }
From: Aric Cyr aric.cyr@amd.com
[ Upstream commit 665f28507a2a3d8d72ed9afa9a2b9b17fd43add1 ]
[Why] When calculating recout width for an MPO plane on a mode that's using ODM combine, driver can calculate a negative value, resulting in a crash.
[How] For negative widths, use zero such that validation will prune the configuration correctly and disallow MPO.
Signed-off-by: Aric Cyr aric.cyr@amd.com Reviewed-by: Krunoslav Kovac Krunoslav.Kovac@amd.com Acked-by: Stylon Wang stylon.wang@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/core/dc_resource.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 78278a10d899..3b1068a09095 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -776,6 +776,11 @@ static void calculate_recout(struct pipe_ctx *pipe_ctx) if (split_idx == split_count) { /* rightmost pipe is the remainder recout */ data->recout.width -= data->h_active * split_count - data->recout.x; + + /* ODM combine cases with MPO we can get negative widths */ + if (data->recout.width < 0) + data->recout.width = 0; + data->recout.x = 0; } else data->recout.width = data->h_active - data->recout.x;
From: Joakim Zhang qiangqing.zhang@nxp.com
[ Upstream commit 6813cc8cfdaf401476e1a007cec8ae338cefa573 ]
PHY will delay about 11.5ms to generate RXC clock when switching from power down to normal operation. Read/write registers would also cause RXC become unstable and stop for a while during this process. Realtek engineer suggests 15ms or more delay can workaround this issue.
Signed-off-by: Joakim Zhang qiangqing.zhang@nxp.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/phy/realtek.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c index 821e85a97367..7b99a3234c65 100644 --- a/drivers/net/phy/realtek.c +++ b/drivers/net/phy/realtek.c @@ -357,6 +357,19 @@ static int rtl8211f_config_init(struct phy_device *phydev) return 0; }
+static int rtl821x_resume(struct phy_device *phydev) +{ + int ret; + + ret = genphy_resume(phydev); + if (ret < 0) + return ret; + + msleep(20); + + return 0; +} + static int rtl8211e_config_init(struct phy_device *phydev) { int ret = 0, oldpage; @@ -852,7 +865,7 @@ static struct phy_driver realtek_drvs[] = { .config_intr = &rtl8211f_config_intr, .handle_interrupt = rtl8211f_handle_interrupt, .suspend = genphy_suspend, - .resume = genphy_resume, + .resume = rtl821x_resume, .read_page = rtl821x_read_page, .write_page = rtl821x_write_page, }, {
From: Amit Cohen amcohen@nvidia.com
[ Upstream commit e67dfb8d15deb33c425d0b0ee22f2e5eef54c162 ]
Several tests do not set some ports down as part of their cleanup(), resulting in IPv6 link-local addresses and associated routes not being deleted.
These leaks were found using a BPF tool that monitors ASIC resources.
Solve this by setting the ports down at the end of the tests.
Signed-off-by: Amit Cohen amcohen@nvidia.com Reviewed-by: Petr Machata petrm@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/devlink_trap_l3_drops.sh | 3 +++ .../selftests/drivers/net/mlxsw/devlink_trap_l3_exceptions.sh | 3 +++ tools/testing/selftests/drivers/net/mlxsw/qos_dscp_bridge.sh | 2 ++ tools/testing/selftests/net/forwarding/pedit_dsfield.sh | 2 ++ tools/testing/selftests/net/forwarding/pedit_l4port.sh | 2 ++ tools/testing/selftests/net/forwarding/skbedit_priority.sh | 2 ++ 6 files changed, 14 insertions(+)
diff --git a/tools/testing/selftests/drivers/net/mlxsw/devlink_trap_l3_drops.sh b/tools/testing/selftests/drivers/net/mlxsw/devlink_trap_l3_drops.sh index 4029833f7e27..160891dcb4bc 100755 --- a/tools/testing/selftests/drivers/net/mlxsw/devlink_trap_l3_drops.sh +++ b/tools/testing/selftests/drivers/net/mlxsw/devlink_trap_l3_drops.sh @@ -109,6 +109,9 @@ router_destroy() __addr_add_del $rp1 del 192.0.2.2/24 2001:db8:1::2/64
tc qdisc del dev $rp2 clsact + + ip link set dev $rp2 down + ip link set dev $rp1 down }
setup_prepare() diff --git a/tools/testing/selftests/drivers/net/mlxsw/devlink_trap_l3_exceptions.sh b/tools/testing/selftests/drivers/net/mlxsw/devlink_trap_l3_exceptions.sh index 42d44e27802c..190c1b6b5365 100755 --- a/tools/testing/selftests/drivers/net/mlxsw/devlink_trap_l3_exceptions.sh +++ b/tools/testing/selftests/drivers/net/mlxsw/devlink_trap_l3_exceptions.sh @@ -111,6 +111,9 @@ router_destroy() __addr_add_del $rp1 del 192.0.2.2/24 2001:db8:1::2/64
tc qdisc del dev $rp2 clsact + + ip link set dev $rp2 down + ip link set dev $rp1 down }
setup_prepare() diff --git a/tools/testing/selftests/drivers/net/mlxsw/qos_dscp_bridge.sh b/tools/testing/selftests/drivers/net/mlxsw/qos_dscp_bridge.sh index 5cbff8038f84..28a570006d4d 100755 --- a/tools/testing/selftests/drivers/net/mlxsw/qos_dscp_bridge.sh +++ b/tools/testing/selftests/drivers/net/mlxsw/qos_dscp_bridge.sh @@ -93,7 +93,9 @@ switch_destroy() lldptool -T -i $swp1 -V APP -d $(dscp_map 10) >/dev/null lldpad_app_wait_del
+ ip link set dev $swp2 down ip link set dev $swp2 nomaster + ip link set dev $swp1 down ip link set dev $swp1 nomaster ip link del dev br1 } diff --git a/tools/testing/selftests/net/forwarding/pedit_dsfield.sh b/tools/testing/selftests/net/forwarding/pedit_dsfield.sh index 55eeacf59241..64fbd211d907 100755 --- a/tools/testing/selftests/net/forwarding/pedit_dsfield.sh +++ b/tools/testing/selftests/net/forwarding/pedit_dsfield.sh @@ -75,7 +75,9 @@ switch_destroy() tc qdisc del dev $swp2 clsact tc qdisc del dev $swp1 clsact
+ ip link set dev $swp2 down ip link set dev $swp2 nomaster + ip link set dev $swp1 down ip link set dev $swp1 nomaster ip link del dev br1 } diff --git a/tools/testing/selftests/net/forwarding/pedit_l4port.sh b/tools/testing/selftests/net/forwarding/pedit_l4port.sh index 5f20d289ee43..10e594c55117 100755 --- a/tools/testing/selftests/net/forwarding/pedit_l4port.sh +++ b/tools/testing/selftests/net/forwarding/pedit_l4port.sh @@ -71,7 +71,9 @@ switch_destroy() tc qdisc del dev $swp2 clsact tc qdisc del dev $swp1 clsact
+ ip link set dev $swp2 down ip link set dev $swp2 nomaster + ip link set dev $swp1 down ip link set dev $swp1 nomaster ip link del dev br1 } diff --git a/tools/testing/selftests/net/forwarding/skbedit_priority.sh b/tools/testing/selftests/net/forwarding/skbedit_priority.sh index e3bd8a6bb8b4..bde11dc27873 100755 --- a/tools/testing/selftests/net/forwarding/skbedit_priority.sh +++ b/tools/testing/selftests/net/forwarding/skbedit_priority.sh @@ -72,7 +72,9 @@ switch_destroy() tc qdisc del dev $swp2 clsact tc qdisc del dev $swp1 clsact
+ ip link set dev $swp2 down ip link set dev $swp2 nomaster + ip link set dev $swp1 down ip link set dev $swp1 nomaster ip link del dev br1 }
From: Yang Yingliang yangyingliang@huawei.com
[ Upstream commit db8f7be1e1d64fbf113a456ef94534fbf5e9a9af ]
It will cause null-ptr-deref if platform_get_resource() returns NULL, we need check the return value.
Signed-off-by: Yang Yingliang yangyingliang@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/sgi/ioc3-eth.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/drivers/net/ethernet/sgi/ioc3-eth.c b/drivers/net/ethernet/sgi/ioc3-eth.c index 6eef0f45b133..2b29fd4cbdf4 100644 --- a/drivers/net/ethernet/sgi/ioc3-eth.c +++ b/drivers/net/ethernet/sgi/ioc3-eth.c @@ -835,6 +835,10 @@ static int ioc3eth_probe(struct platform_device *pdev) int err;
regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!regs) { + dev_err(&pdev->dev, "Invalid resource\n"); + return -EINVAL; + } /* get mac addr from one wire prom */ if (ioc3eth_get_mac_addr(regs, mac_addr)) return -EPROBE_DEFER; /* not available yet */
From: Nirmoy Das nirmoy.das@amd.com
[ Upstream commit bc05716d4fdd065013633602c5960a2bf1511b9c ]
Fixes handling when page tables are in system memory.
v3: remove struct amdgpu_vm_parser. v2: remove unwanted variable. change amdgpu_amdkfd_validate instead of amdgpu_amdkfd_bo_validate.
Signed-off-by: Nirmoy Das nirmoy.das@amd.com Reviewed-by: Christian König christian.koenig@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 --- .../gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 21 ++++--------------- 1 file changed, 4 insertions(+), 17 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c index 7d4118c8128a..5e69b5b50a19 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c @@ -50,12 +50,6 @@ static struct { spinlock_t mem_limit_lock; } kfd_mem_limit;
-/* Struct used for amdgpu_amdkfd_bo_validate */ -struct amdgpu_vm_parser { - uint32_t domain; - bool wait; -}; - static const char * const domain_bit_to_string[] = { "CPU", "GTT", @@ -346,11 +340,9 @@ static int amdgpu_amdkfd_bo_validate(struct amdgpu_bo *bo, uint32_t domain, return ret; }
-static int amdgpu_amdkfd_validate(void *param, struct amdgpu_bo *bo) +static int amdgpu_amdkfd_validate_vm_bo(void *_unused, struct amdgpu_bo *bo) { - struct amdgpu_vm_parser *p = param; - - return amdgpu_amdkfd_bo_validate(bo, p->domain, p->wait); + return amdgpu_amdkfd_bo_validate(bo, bo->allowed_domains, false); }
/* vm_validate_pt_pd_bos - Validate page table and directory BOs @@ -364,20 +356,15 @@ static int vm_validate_pt_pd_bos(struct amdgpu_vm *vm) { struct amdgpu_bo *pd = vm->root.base.bo; struct amdgpu_device *adev = amdgpu_ttm_adev(pd->tbo.bdev); - struct amdgpu_vm_parser param; int ret;
- param.domain = AMDGPU_GEM_DOMAIN_VRAM; - param.wait = false; - - ret = amdgpu_vm_validate_pt_bos(adev, vm, amdgpu_amdkfd_validate, - ¶m); + ret = amdgpu_vm_validate_pt_bos(adev, vm, amdgpu_amdkfd_validate_vm_bo, NULL); if (ret) { pr_err("failed to validate PT BOs\n"); return ret; }
- ret = amdgpu_amdkfd_validate(¶m, pd); + ret = amdgpu_amdkfd_validate_vm_bo(NULL, pd); if (ret) { pr_err("failed to validate PD\n"); return ret;
From: Yang Yingliang yangyingliang@huawei.com
[ Upstream commit f18c11812c949553d2b2481ecaa274dd51bed1e7 ]
It will cause null-ptr-deref if platform_get_resource() returns NULL, we need check the return value.
Signed-off-by: Yang Yingliang yangyingliang@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/fjes/fjes_main.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c index 466622664424..e449d9466122 100644 --- a/drivers/net/fjes/fjes_main.c +++ b/drivers/net/fjes/fjes_main.c @@ -1262,6 +1262,10 @@ static int fjes_probe(struct platform_device *plat_dev) adapter->interrupt_watch_enable = false;
res = platform_get_resource(plat_dev, IORESOURCE_MEM, 0); + if (!res) { + err = -EINVAL; + goto err_free_control_wq; + } hw->hw_res.start = res->start; hw->hw_res.size = resource_size(res); hw->hw_res.irq = platform_get_irq(plat_dev, 0);
From: Yang Yingliang yangyingliang@huawei.com
[ Upstream commit 8a55a73433e763c8aec4a3e8df5c28c821fc44b9 ]
Use devm_platform_get_and_ioremap_resource() to simplify code and avoid a null-ptr-deref by checking 'res' in it.
Signed-off-by: Yang Yingliang yangyingliang@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/mdio/mdio-mux-bcm-iproc.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/drivers/net/mdio/mdio-mux-bcm-iproc.c b/drivers/net/mdio/mdio-mux-bcm-iproc.c index 03261e6b9ceb..aa29d6bdbdf2 100644 --- a/drivers/net/mdio/mdio-mux-bcm-iproc.c +++ b/drivers/net/mdio/mdio-mux-bcm-iproc.c @@ -187,7 +187,9 @@ static int mdio_mux_iproc_probe(struct platform_device *pdev) return -ENOMEM; md->dev = &pdev->dev;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + md->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); + if (IS_ERR(md->base)) + return PTR_ERR(md->base); if (res->start & 0xfff) { /* For backward compatibility in case the * base address is specified with an offset. @@ -196,9 +198,6 @@ static int mdio_mux_iproc_probe(struct platform_device *pdev) res->start &= ~0xfff; res->end = res->start + MDIO_REG_ADDR_SPACE_SIZE - 1; } - md->base = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(md->base)) - return PTR_ERR(md->base);
md->mii_bus = devm_mdiobus_alloc(&pdev->dev); if (!md->mii_bus) {
From: Minchan Kim minchan@kernel.org
[ Upstream commit 648f2c6100cfa18e7dfe43bc0b9c3b73560d623c ]
In the field, we have seen lots of allocation failure from the call path below.
06-03 13:29:12.999 1010315 31557 31557 W Binder : 31542_2: page allocation failure: order:0, mode:0x800(GFP_NOWAIT), nodemask=(null),cpuset=background,mems_allowed=0 ... ... 06-03 13:29:12.999 1010315 31557 31557 W Call trace: 06-03 13:29:12.999 1010315 31557 31557 W : dump_backtrace.cfi_jt+0x0/0x8 06-03 13:29:12.999 1010315 31557 31557 W : dump_stack+0xc8/0x14c 06-03 13:29:12.999 1010315 31557 31557 W : warn_alloc+0x158/0x1c8 06-03 13:29:12.999 1010315 31557 31557 W : __alloc_pages_slowpath+0x9d8/0xb80 06-03 13:29:12.999 1010315 31557 31557 W : __alloc_pages_nodemask+0x1c4/0x430 06-03 13:29:12.999 1010315 31557 31557 W : allocate_slab+0xb4/0x390 06-03 13:29:12.999 1010315 31557 31557 W : ___slab_alloc+0x12c/0x3a4 06-03 13:29:12.999 1010315 31557 31557 W : kmem_cache_alloc+0x358/0x5e4 06-03 13:29:12.999 1010315 31557 31557 W : avc_alloc_node+0x30/0x184 06-03 13:29:12.999 1010315 31557 31557 W : avc_update_node+0x54/0x4f0 06-03 13:29:12.999 1010315 31557 31557 W : avc_has_extended_perms+0x1a4/0x460 06-03 13:29:12.999 1010315 31557 31557 W : selinux_file_ioctl+0x320/0x3d0 06-03 13:29:12.999 1010315 31557 31557 W : __arm64_sys_ioctl+0xec/0x1fc 06-03 13:29:12.999 1010315 31557 31557 W : el0_svc_common+0xc0/0x24c 06-03 13:29:12.999 1010315 31557 31557 W : el0_svc+0x28/0x88 06-03 13:29:12.999 1010315 31557 31557 W : el0_sync_handler+0x8c/0xf0 06-03 13:29:12.999 1010315 31557 31557 W : el0_sync+0x1a4/0x1c0 .. .. 06-03 13:29:12.999 1010315 31557 31557 W SLUB : Unable to allocate memory on node -1, gfp=0x900(GFP_NOWAIT|__GFP_ZERO) 06-03 13:29:12.999 1010315 31557 31557 W cache : avc_node, object size: 72, buffer size: 80, default order: 0, min order: 0 06-03 13:29:12.999 1010315 31557 31557 W node 0 : slabs: 57, objs: 2907, free: 0 06-03 13:29:12.999 1010161 10686 10686 W SLUB : Unable to allocate memory on node -1, gfp=0x900(GFP_NOWAIT|__GFP_ZERO) 06-03 13:29:12.999 1010161 10686 10686 W cache : avc_node, object size: 72, buffer size: 80, default order: 0, min order: 0 06-03 13:29:12.999 1010161 10686 10686 W node 0 : slabs: 57, objs: 2907, free: 0 06-03 13:29:12.999 1010161 10686 10686 W SLUB : Unable to allocate memory on node -1, gfp=0x900(GFP_NOWAIT|__GFP_ZERO) 06-03 13:29:12.999 1010161 10686 10686 W cache : avc_node, object size: 72, buffer size: 80, default order: 0, min order: 0 06-03 13:29:12.999 1010161 10686 10686 W node 0 : slabs: 57, objs: 2907, free: 0 06-03 13:29:12.999 1010161 10686 10686 W SLUB : Unable to allocate memory on node -1, gfp=0x900(GFP_NOWAIT|__GFP_ZERO) 06-03 13:29:12.999 1010161 10686 10686 W cache : avc_node, object size: 72, buffer size: 80, default order: 0, min order: 0 06-03 13:29:12.999 1010161 10686 10686 W node 0 : slabs: 57, objs: 2907, free: 0 06-03 13:29:13.000 1010161 10686 10686 W SLUB : Unable to allocate memory on node -1, gfp=0x900(GFP_NOWAIT|__GFP_ZERO) 06-03 13:29:13.000 1010161 10686 10686 W cache : avc_node, object size: 72, buffer size: 80, default order: 0, min order: 0 06-03 13:29:13.000 1010161 10686 10686 W node 0 : slabs: 57, objs: 2907, free: 0 06-03 13:29:13.000 1010161 10686 10686 W SLUB : Unable to allocate memory on node -1, gfp=0x900(GFP_NOWAIT|__GFP_ZERO) 06-03 13:29:13.000 1010161 10686 10686 W cache : avc_node, object size: 72, buffer size: 80, default order: 0, min order: 0 06-03 13:29:13.000 1010161 10686 10686 W node 0 : slabs: 57, objs: 2907, free: 0 06-03 13:29:13.000 1010161 10686 10686 W SLUB : Unable to allocate memory on node -1, gfp=0x900(GFP_NOWAIT|__GFP_ZERO) 06-03 13:29:13.000 1010161 10686 10686 W cache : avc_node, object size: 72, buffer size: 80, default order: 0, min order: 0 06-03 13:29:13.000 1010161 10686 10686 W node 0 : slabs: 57, objs: 2907, free: 0 06-03 13:29:13.000 10230 30892 30892 W SLUB : Unable to allocate memory on node -1, gfp=0x900(GFP_NOWAIT|__GFP_ZERO) 06-03 13:29:13.000 10230 30892 30892 W cache : avc_node, object size: 72, buffer size: 80, default order: 0, min order: 0 06-03 13:29:13.000 10230 30892 30892 W node 0 : slabs: 57, objs: 2907, free: 0 06-03 13:29:13.000 10230 30892 30892 W SLUB : Unable to allocate memory on node -1, gfp=0x900(GFP_NOWAIT|__GFP_ZERO) 06-03 13:29:13.000 10230 30892 30892 W cache : avc_node, object size: 72, buffer size: 80, default order: 0, min order: 0
Based on [1], selinux is tolerate for failure of memory allocation. Then, use __GFP_NOWARN together.
[1] 476accbe2f6e ("selinux: use GFP_NOWAIT in the AVC kmem_caches")
Signed-off-by: Minchan Kim minchan@kernel.org [PM: subj fix, line wraps, normalized commit refs] Signed-off-by: Paul Moore paul@paul-moore.com Signed-off-by: Sasha Levin sashal@kernel.org --- security/selinux/avc.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/security/selinux/avc.c b/security/selinux/avc.c index ad451cf9375e..a2dc83228daf 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c @@ -297,26 +297,27 @@ static struct avc_xperms_decision_node struct avc_xperms_decision_node *xpd_node; struct extended_perms_decision *xpd;
- xpd_node = kmem_cache_zalloc(avc_xperms_decision_cachep, GFP_NOWAIT); + xpd_node = kmem_cache_zalloc(avc_xperms_decision_cachep, + GFP_NOWAIT | __GFP_NOWARN); if (!xpd_node) return NULL;
xpd = &xpd_node->xpd; if (which & XPERMS_ALLOWED) { xpd->allowed = kmem_cache_zalloc(avc_xperms_data_cachep, - GFP_NOWAIT); + GFP_NOWAIT | __GFP_NOWARN); if (!xpd->allowed) goto error; } if (which & XPERMS_AUDITALLOW) { xpd->auditallow = kmem_cache_zalloc(avc_xperms_data_cachep, - GFP_NOWAIT); + GFP_NOWAIT | __GFP_NOWARN); if (!xpd->auditallow) goto error; } if (which & XPERMS_DONTAUDIT) { xpd->dontaudit = kmem_cache_zalloc(avc_xperms_data_cachep, - GFP_NOWAIT); + GFP_NOWAIT | __GFP_NOWARN); if (!xpd->dontaudit) goto error; } @@ -344,7 +345,7 @@ static struct avc_xperms_node *avc_xperms_alloc(void) { struct avc_xperms_node *xp_node;
- xp_node = kmem_cache_zalloc(avc_xperms_cachep, GFP_NOWAIT); + xp_node = kmem_cache_zalloc(avc_xperms_cachep, GFP_NOWAIT | __GFP_NOWARN); if (!xp_node) return xp_node; INIT_LIST_HEAD(&xp_node->xpd_head); @@ -500,7 +501,7 @@ static struct avc_node *avc_alloc_node(struct selinux_avc *avc) { struct avc_node *node;
- node = kmem_cache_zalloc(avc_node_cachep, GFP_NOWAIT); + node = kmem_cache_zalloc(avc_node_cachep, GFP_NOWAIT | __GFP_NOWARN); if (!node) goto out;
From: Heiner Kallweit hkallweit1@gmail.com
[ Upstream commit 1ee8856de82faec9bc8bd0f2308a7f27e30ba207 ]
It has been reported that on RTL8106e the link-up interrupt may be significantly delayed if the user enables ASPM L1. Per default ASPM is disabled. The change leaves L1 enabled on the PCIe link (thus still allowing to reach higher package power saving states), but the NIC won't actively trigger it.
Reported-by: Koba Ko koba.ko@canonical.com Tested-by: Koba Ko koba.ko@canonical.com Signed-off-by: Heiner Kallweit hkallweit1@gmail.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/realtek/r8169_main.c | 1 - 1 file changed, 1 deletion(-)
diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c index 2ee72dc431cd..a0d4e052a79e 100644 --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c @@ -3510,7 +3510,6 @@ static void rtl_hw_start_8106(struct rtl8169_private *tp) rtl_eri_write(tp, 0x1b0, ERIAR_MASK_0011, 0x0000);
rtl_pcie_state_l2l3_disable(tp); - rtl_hw_aspm_clkreq_enable(tp, true); }
DECLARE_RTL_COND(rtl_mac_ocp_e00e_cond)
From: Mark Yacoub markyacoub@chromium.org
[ Upstream commit 03fc4cf45d30533d54f0f4ebc02aacfa12f52ce2 ]
For each CRTC state, check the size of Gamma and Degamma LUTs so unexpected and larger sizes wouldn't slip through.
TEST: IGT:kms_color::pipe-invalid-gamma-lut-sizes
v2: fix assignments in if clauses, Mark's email.
Reviewed-by: Harry Wentland harry.wentland@amd.com Signed-off-by: Mark Yacoub markyacoub@chromium.org Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Sasha Levin sashal@kernel.org --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 4 ++ .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 1 + .../amd/display/amdgpu_dm/amdgpu_dm_color.c | 41 ++++++++++++++++--- 3 files changed, 40 insertions(+), 6 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 58577f7a57c1..35def321bae4 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -10040,6 +10040,10 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, dm_old_crtc_state->dsc_force_changed == false) continue;
+ ret = amdgpu_dm_verify_lut_sizes(new_crtc_state); + if (ret) + goto fail; + if (!new_crtc_state->enable) continue;
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h index b2f2ccfc20bb..c8e5bbbb8bce 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -591,6 +591,7 @@ void amdgpu_dm_trigger_timing_sync(struct drm_device *dev); #define MAX_COLOR_LEGACY_LUT_ENTRIES 256
void amdgpu_dm_init_color_mod(void); +int amdgpu_dm_verify_lut_sizes(const struct drm_crtc_state *crtc_state); int amdgpu_dm_update_crtc_color_mgmt(struct dm_crtc_state *crtc); int amdgpu_dm_update_plane_color_mgmt(struct dm_crtc_state *crtc, struct dc_plane_state *dc_plane_state); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c index 157fe4efbb59..a022e5bb30a5 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c @@ -284,6 +284,37 @@ static int __set_input_tf(struct dc_transfer_func *func, return res ? 0 : -ENOMEM; }
+/** + * Verifies that the Degamma and Gamma LUTs attached to the |crtc_state| are of + * the expected size. + * Returns 0 on success. + */ +int amdgpu_dm_verify_lut_sizes(const struct drm_crtc_state *crtc_state) +{ + const struct drm_color_lut *lut = NULL; + uint32_t size = 0; + + lut = __extract_blob_lut(crtc_state->degamma_lut, &size); + if (lut && size != MAX_COLOR_LUT_ENTRIES) { + DRM_DEBUG_DRIVER( + "Invalid Degamma LUT size. Should be %u but got %u.\n", + MAX_COLOR_LUT_ENTRIES, size); + return -EINVAL; + } + + lut = __extract_blob_lut(crtc_state->gamma_lut, &size); + if (lut && size != MAX_COLOR_LUT_ENTRIES && + size != MAX_COLOR_LEGACY_LUT_ENTRIES) { + DRM_DEBUG_DRIVER( + "Invalid Gamma LUT size. Should be %u (or %u for legacy) but got %u.\n", + MAX_COLOR_LUT_ENTRIES, MAX_COLOR_LEGACY_LUT_ENTRIES, + size); + return -EINVAL; + } + + return 0; +} + /** * amdgpu_dm_update_crtc_color_mgmt: Maps DRM color management to DC stream. * @crtc: amdgpu_dm crtc state @@ -317,14 +348,12 @@ int amdgpu_dm_update_crtc_color_mgmt(struct dm_crtc_state *crtc) bool is_legacy; int r;
- degamma_lut = __extract_blob_lut(crtc->base.degamma_lut, °amma_size); - if (degamma_lut && degamma_size != MAX_COLOR_LUT_ENTRIES) - return -EINVAL; + r = amdgpu_dm_verify_lut_sizes(&crtc->base); + if (r) + return r;
+ degamma_lut = __extract_blob_lut(crtc->base.degamma_lut, °amma_size); regamma_lut = __extract_blob_lut(crtc->base.gamma_lut, ®amma_size); - if (regamma_lut && regamma_size != MAX_COLOR_LUT_ENTRIES && - regamma_size != MAX_COLOR_LEGACY_LUT_ENTRIES) - return -EINVAL;
has_degamma = degamma_lut && !__is_lut_linear(degamma_lut, degamma_size);
From: Lijun Pan lijunp213@gmail.com
[ Upstream commit 73214a690c50a134bd364e1a4430e0e7ac81a8d8 ]
Fix the following kernel build warnings: drivers/net/ethernet/ibm/ibmvnic.c:1516: warning: Function parameter or member 'skb' not described in 'build_hdr_descs_arr' drivers/net/ethernet/ibm/ibmvnic.c:1516: warning: Function parameter or member 'indir_arr' not described in 'build_hdr_descs_arr' drivers/net/ethernet/ibm/ibmvnic.c:1516: warning: Excess function parameter 'txbuff' description in 'build_hdr_descs_arr'
Signed-off-by: Lijun Pan lijunp213@gmail.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/ibm/ibmvnic.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c index 5788bb956d73..a764a5e615fa 100644 --- a/drivers/net/ethernet/ibm/ibmvnic.c +++ b/drivers/net/ethernet/ibm/ibmvnic.c @@ -1502,7 +1502,8 @@ static int create_hdr_descs(u8 hdr_field, u8 *hdr_data, int len, int *hdr_len,
/** * build_hdr_descs_arr - build a header descriptor array - * @txbuff: tx buffer + * @skb: tx socket buffer + * @indir_arr: indirect array * @num_entries: number of descriptors to be sent * @hdr_field: bit field determining which headers will be sent *
From: Steffen Klassert steffen.klassert@secunet.com
[ Upstream commit 6fd06963fa74197103cdbb4b494763127b3f2f34 ]
When memory allocation for XFRMA_ENCAP or XFRMA_COADDR fails, the error will not be reported because the -ENOMEM assignment to the err variable is overwritten before. Fix this by moving these two in front of the function so that memory allocation failures will be reported.
Reported-by: Tobias Brunner tobias@strongswan.org Signed-off-by: Steffen Klassert steffen.klassert@secunet.com Signed-off-by: Sasha Levin sashal@kernel.org --- net/xfrm/xfrm_user.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-)
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index f0aecee4d539..b47d613409b7 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -580,6 +580,20 @@ static struct xfrm_state *xfrm_state_construct(struct net *net,
copy_from_user_state(x, p);
+ if (attrs[XFRMA_ENCAP]) { + x->encap = kmemdup(nla_data(attrs[XFRMA_ENCAP]), + sizeof(*x->encap), GFP_KERNEL); + if (x->encap == NULL) + goto error; + } + + if (attrs[XFRMA_COADDR]) { + x->coaddr = kmemdup(nla_data(attrs[XFRMA_COADDR]), + sizeof(*x->coaddr), GFP_KERNEL); + if (x->coaddr == NULL) + goto error; + } + if (attrs[XFRMA_SA_EXTRA_FLAGS]) x->props.extra_flags = nla_get_u32(attrs[XFRMA_SA_EXTRA_FLAGS]);
@@ -600,23 +614,9 @@ static struct xfrm_state *xfrm_state_construct(struct net *net, attrs[XFRMA_ALG_COMP]))) goto error;
- if (attrs[XFRMA_ENCAP]) { - x->encap = kmemdup(nla_data(attrs[XFRMA_ENCAP]), - sizeof(*x->encap), GFP_KERNEL); - if (x->encap == NULL) - goto error; - } - if (attrs[XFRMA_TFCPAD]) x->tfcpad = nla_get_u32(attrs[XFRMA_TFCPAD]);
- if (attrs[XFRMA_COADDR]) { - x->coaddr = kmemdup(nla_data(attrs[XFRMA_COADDR]), - sizeof(*x->coaddr), GFP_KERNEL); - if (x->coaddr == NULL) - goto error; - } - xfrm_mark_get(attrs, &x->mark);
xfrm_smark_init(attrs, &x->props.smark);
From: Mikulas Patocka mpatocka@redhat.com
[ Upstream commit 991bd8d7bc78966b4dc427b53a144f276bffcd52 ]
Some architectures have pages larger than 4k and committing a full page causes needless overhead.
Fix this by writing a single block when committing the superblock.
Signed-off-by: Mikulas Patocka mpatocka@redhat.com Signed-off-by: Mike Snitzer snitzer@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/md/dm-writecache.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/drivers/md/dm-writecache.c b/drivers/md/dm-writecache.c index a44007297e63..0e3a6c4bd5e3 100644 --- a/drivers/md/dm-writecache.c +++ b/drivers/md/dm-writecache.c @@ -532,11 +532,7 @@ static void ssd_commit_superblock(struct dm_writecache *wc)
region.bdev = wc->ssd_dev->bdev; region.sector = 0; - region.count = PAGE_SIZE >> SECTOR_SHIFT; - - if (unlikely(region.sector + region.count > wc->metadata_sectors)) - region.count = wc->metadata_sectors - region.sector; - + region.count = wc->block_size >> SECTOR_SHIFT; region.sector += wc->start_sector;
req.bi_op = REQ_OP_WRITE;
From: Tony Lindgren tony@atomide.com
[ Upstream commit 11ef6bc846dcdce838f0b00c5f6a562c57e5d43b ]
At least on wl12xx, reading the MAC after boot can fail with a warning at drivers/net/wireless/ti/wlcore/sdio.c:78 wl12xx_sdio_raw_read. The failed call comes from wl12xx_get_mac() that wlcore_nvs_cb() calls after request_firmware_work_func().
After the error, no wireless interface is created. Reloading the wl12xx module makes the interface work.
Turns out the wlan controller can be in a low-power ELP state after the boot from the bootloader or kexec, and needs to be woken up first.
Let's wake the hardware and add a sleep after that similar to wl12xx_pre_boot() is already doing.
Note that a similar issue could exist for wl18xx, but I have not seen it so far. And a search for wl18xx_get_mac and wl12xx_sdio_raw_read did not produce similar errors.
Cc: Carl Philipp Klemm philipp@uvos.xyz Signed-off-by: Tony Lindgren tony@atomide.com Signed-off-by: Kalle Valo kvalo@codeaurora.org Link: https://lore.kernel.org/r/20210603062814.19464-1-tony@atomide.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/wireless/ti/wl12xx/main.c | 7 +++++++ 1 file changed, 7 insertions(+)
diff --git a/drivers/net/wireless/ti/wl12xx/main.c b/drivers/net/wireless/ti/wl12xx/main.c index 9d7dbfe7fe0c..c6da0cfb4afb 100644 --- a/drivers/net/wireless/ti/wl12xx/main.c +++ b/drivers/net/wireless/ti/wl12xx/main.c @@ -1503,6 +1503,13 @@ static int wl12xx_get_fuse_mac(struct wl1271 *wl) u32 mac1, mac2; int ret;
+ /* Device may be in ELP from the bootloader or kexec */ + ret = wlcore_write32(wl, WL12XX_WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL); + if (ret < 0) + goto out; + + usleep_range(500000, 700000); + ret = wlcore_set_partition(wl, &wl->ptable[PART_DRPW]); if (ret < 0) goto out;
From: Vladimir Oltean vladimir.oltean@nxp.com
[ Upstream commit 0b5f0f29b118910c89fe249cdfbc11b400a86a18 ]
The SJA1110 switch integrates TJA1103 PHYs, but in SJA1110 switch rev B silicon, there is a bug in that the registers for selecting the 100base-T1 autoneg master/slave roles are not writable.
To enable write access to the master/slave registers, these additional PHY writes are necessary during initialization.
The issue has been corrected in later SJA1110 silicon versions and is not present in the standalone PHY variants, but applying the workaround unconditionally in the driver should not do any harm.
Suggested-by: Radu Pirea (NXP OSS) radu-nicolae.pirea@oss.nxp.com Signed-off-by: Vladimir Oltean vladimir.oltean@nxp.com Reviewed-by: Russell King (Oracle) rmk+kernel@armlinux.org.uk Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/phy/nxp-c45-tja11xx.c | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/drivers/net/phy/nxp-c45-tja11xx.c b/drivers/net/phy/nxp-c45-tja11xx.c index 26b9c0d7cb9d..b7ce0e737333 100644 --- a/drivers/net/phy/nxp-c45-tja11xx.c +++ b/drivers/net/phy/nxp-c45-tja11xx.c @@ -546,6 +546,12 @@ static int nxp_c45_config_init(struct phy_device *phydev) return ret; }
+ /* Bug workaround for SJA1110 rev B: enable write access + * to MDIO_MMD_PMAPMD + */ + phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x01F8, 1); + phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x01F9, 2); + phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_PHY_CONFIG, PHY_CONFIG_AUTO);
From: Lee Gibson leegib@gmail.com
[ Upstream commit d10a87a3535cce2b890897914f5d0d83df669c63 ]
Function wl1251_cmd_scan calls memcpy without checking the length. Harden by checking the length is within the maximum allowed size.
Signed-off-by: Lee Gibson leegib@gmail.com Signed-off-by: Kalle Valo kvalo@codeaurora.org Link: https://lore.kernel.org/r/20210428115508.25624-1-leegib@gmail.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/wireless/ti/wl1251/cmd.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/ti/wl1251/cmd.c b/drivers/net/wireless/ti/wl1251/cmd.c index 498c8db2eb48..d7a869106782 100644 --- a/drivers/net/wireless/ti/wl1251/cmd.c +++ b/drivers/net/wireless/ti/wl1251/cmd.c @@ -454,9 +454,12 @@ int wl1251_cmd_scan(struct wl1251 *wl, u8 *ssid, size_t ssid_len, cmd->channels[i].channel = channels[i]->hw_value; }
- cmd->params.ssid_len = ssid_len; - if (ssid) - memcpy(cmd->params.ssid, ssid, ssid_len); + if (ssid) { + int len = clamp_val(ssid_len, 0, IEEE80211_MAX_SSID_LEN); + + cmd->params.ssid_len = len; + memcpy(cmd->params.ssid, ssid, len); + }
ret = wl1251_cmd_send(wl, CMD_SCAN, cmd, sizeof(*cmd)); if (ret < 0) {
From: Zou Wei zou_wei@huawei.com
[ Upstream commit dd778f89225cd258e8f0fed2b7256124982c8bb5 ]
This patch adds missing MODULE_DEVICE_TABLE definition which generates correct modalias for automatic loading of this driver when it is built as an external module.
Reported-by: Hulk Robot hulkci@huawei.com Signed-off-by: Zou Wei zou_wei@huawei.com Signed-off-by: Kalle Valo kvalo@codeaurora.org Link: https://lore.kernel.org/r/1620788714-14300-1-git-send-email-zou_wei@huawei.c... Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/wireless/st/cw1200/cw1200_sdio.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/net/wireless/st/cw1200/cw1200_sdio.c b/drivers/net/wireless/st/cw1200/cw1200_sdio.c index b65ec14136c7..4c30b5772ce0 100644 --- a/drivers/net/wireless/st/cw1200/cw1200_sdio.c +++ b/drivers/net/wireless/st/cw1200/cw1200_sdio.c @@ -53,6 +53,7 @@ static const struct sdio_device_id cw1200_sdio_ids[] = { { SDIO_DEVICE(SDIO_VENDOR_ID_STE, SDIO_DEVICE_ID_STE_CW1200) }, { /* end: all zeroes */ }, }; +MODULE_DEVICE_TABLE(sdio, cw1200_sdio_ids);
/* hwbus_ops implemetation */
From: Jonathan Kim jonathan.kim@amd.com
[ Upstream commit 63f6e01237257e7226efc5087f3f0b525d320f54 ]
get_wave_state acquires the mmap_lock on copy_to_user but so do mmu_notifiers. mmu_notifiers allows dqm locking so do get_wave_state outside the dqm_lock to prevent circular locking.
v2: squash in unused variable removal.
Signed-off-by: Jonathan Kim jonathan.kim@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 --- .../drm/amd/amdkfd/kfd_device_queue_manager.c | 28 +++++++++---------- 1 file changed, 13 insertions(+), 15 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 d3eaa1549bd7..ccc9d108caff 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c @@ -1674,29 +1674,27 @@ static int get_wave_state(struct device_queue_manager *dqm, u32 *save_area_used_size) { struct mqd_manager *mqd_mgr; - int r;
dqm_lock(dqm);
- if (q->properties.type != KFD_QUEUE_TYPE_COMPUTE || - q->properties.is_active || !q->device->cwsr_enabled) { - r = -EINVAL; - goto dqm_unlock; - } - mqd_mgr = dqm->mqd_mgrs[KFD_MQD_TYPE_CP];
- if (!mqd_mgr->get_wave_state) { - r = -EINVAL; - goto dqm_unlock; + if (q->properties.type != KFD_QUEUE_TYPE_COMPUTE || + q->properties.is_active || !q->device->cwsr_enabled || + !mqd_mgr->get_wave_state) { + dqm_unlock(dqm); + return -EINVAL; }
- r = mqd_mgr->get_wave_state(mqd_mgr, q->mqd, ctl_stack, - ctl_stack_used_size, save_area_used_size); - -dqm_unlock: dqm_unlock(dqm); - return r; + + /* + * get_wave_state is outside the dqm lock to prevent circular locking + * and the queue should be protected against destruction by the process + * lock. + */ + return mqd_mgr->get_wave_state(mqd_mgr, q->mqd, ctl_stack, + ctl_stack_used_size, save_area_used_size); }
static int process_termination_cpsch(struct device_queue_manager *dqm,
From: Wesley Chalmers Wesley.Chalmers@amd.com
[ Upstream commit 78ebca321999699f30ea19029726d1a3908b395f ]
[WHY] When changing the DISPCLK_WDIVIDER value from 126 to 127, the change in clock rate is too great for the FIFOs to handle. This can cause visible corruption during clock change.
HW has handed down this register sequence to fix the issue.
[HOW] The sequence, from HW: a. 127 -> 126 Read DIG_FIFO_CAL_AVERAGE_LEVEL FIFO level N = DIG_FIFO_CAL_AVERAGE_LEVEL / 4 Set DCCG_FIFO_ERRDET_OVR_EN = 1 Write 1 to OTGx_DROP_PIXEL for (N-4) times Set DCCG_FIFO_ERRDET_OVR_EN = 0 Write DENTIST_DISPCLK_RDIVIDER = 126
Because of frequency stepping, sequence a can be executed to change the divider from 127 to any other divider value.
b. 126 -> 127 Read DIG_FIFO_CAL_AVERAGE_LEVEL FIFO level N = DIG_FIFO_CAL_AVERAGE_LEVEL / 4 Set DCCG_FIFO_ERRDET_OVR_EN = 1 Write 1 to OTGx_ADD_PIXEL for (12-N) times Set DCCG_FIFO_ERRDET_OVR_EN = 0 Write DENTIST_DISPCLK_RDIVIDER = 127
Because of frequency stepping, divider must first be set from any other divider value to 126 before executing sequence b.
Signed-off-by: Wesley Chalmers Wesley.Chalmers@amd.com Reviewed-by: Dmytro Laktyushkin Dmytro.Laktyushkin@amd.com Acked-by: Anson Jacob Anson.Jacob@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/dc/clk_mgr/dcn20/dcn20_clk_mgr.c | 68 ++++++++++++++++++- .../display/dc/clk_mgr/dcn20/dcn20_clk_mgr.h | 3 +- .../display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c | 4 +- 3 files changed, 69 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c index 372d53b5a34d..3d335b4e9891 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c @@ -123,7 +123,7 @@ void dcn20_update_clocks_update_dpp_dto(struct clk_mgr_internal *clk_mgr, } }
-void dcn20_update_clocks_update_dentist(struct clk_mgr_internal *clk_mgr) +void dcn20_update_clocks_update_dentist(struct clk_mgr_internal *clk_mgr, struct dc_state *context) { int dpp_divider = DENTIST_DIVIDER_RANGE_SCALE_FACTOR * clk_mgr->base.dentist_vco_freq_khz / clk_mgr->base.clks.dppclk_khz; @@ -132,6 +132,68 @@ void dcn20_update_clocks_update_dentist(struct clk_mgr_internal *clk_mgr)
uint32_t dppclk_wdivider = dentist_get_did_from_divider(dpp_divider); uint32_t dispclk_wdivider = dentist_get_did_from_divider(disp_divider); + uint32_t current_dispclk_wdivider; + uint32_t i; + + REG_GET(DENTIST_DISPCLK_CNTL, + DENTIST_DISPCLK_WDIVIDER, ¤t_dispclk_wdivider); + + /* When changing divider to or from 127, some extra programming is required to prevent corruption */ + if (current_dispclk_wdivider == 127 && dispclk_wdivider != 127) { + for (i = 0; i < clk_mgr->base.ctx->dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; + uint32_t fifo_level; + struct dccg *dccg = clk_mgr->base.ctx->dc->res_pool->dccg; + struct stream_encoder *stream_enc = pipe_ctx->stream_res.stream_enc; + int32_t N; + int32_t j; + + if (!pipe_ctx->stream) + continue; + /* Virtual encoders don't have this function */ + if (!stream_enc->funcs->get_fifo_cal_average_level) + continue; + fifo_level = stream_enc->funcs->get_fifo_cal_average_level( + stream_enc); + N = fifo_level / 4; + dccg->funcs->set_fifo_errdet_ovr_en( + dccg, + true); + for (j = 0; j < N - 4; j++) + dccg->funcs->otg_drop_pixel( + dccg, + pipe_ctx->stream_res.tg->inst); + dccg->funcs->set_fifo_errdet_ovr_en( + dccg, + false); + } + } else if (dispclk_wdivider == 127 && current_dispclk_wdivider != 127) { + REG_UPDATE(DENTIST_DISPCLK_CNTL, + DENTIST_DISPCLK_WDIVIDER, 126); + REG_WAIT(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_CHG_DONE, 1, 50, 100); + for (i = 0; i < clk_mgr->base.ctx->dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; + struct dccg *dccg = clk_mgr->base.ctx->dc->res_pool->dccg; + struct stream_encoder *stream_enc = pipe_ctx->stream_res.stream_enc; + uint32_t fifo_level; + int32_t N; + int32_t j; + + if (!pipe_ctx->stream) + continue; + /* Virtual encoders don't have this function */ + if (!stream_enc->funcs->get_fifo_cal_average_level) + continue; + fifo_level = stream_enc->funcs->get_fifo_cal_average_level( + stream_enc); + N = fifo_level / 4; + dccg->funcs->set_fifo_errdet_ovr_en(dccg, true); + for (j = 0; j < 12 - N; j++) + dccg->funcs->otg_add_pixel(dccg, + pipe_ctx->stream_res.tg->inst); + dccg->funcs->set_fifo_errdet_ovr_en(dccg, false); + } + }
REG_UPDATE(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_WDIVIDER, dispclk_wdivider); @@ -251,11 +313,11 @@ void dcn2_update_clocks(struct clk_mgr *clk_mgr_base, if (dpp_clock_lowered) { // if clock is being lowered, increase DTO before lowering refclk dcn20_update_clocks_update_dpp_dto(clk_mgr, context, safe_to_lower); - dcn20_update_clocks_update_dentist(clk_mgr); + dcn20_update_clocks_update_dentist(clk_mgr, context); } else { // if clock is being raised, increase refclk before lowering DTO if (update_dppclk || update_dispclk) - dcn20_update_clocks_update_dentist(clk_mgr); + dcn20_update_clocks_update_dentist(clk_mgr, context); // always update dtos unless clock is lowered and not safe to lower dcn20_update_clocks_update_dpp_dto(clk_mgr, context, safe_to_lower); } diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.h b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.h index 0b9c045b0c8e..d254d0b6fba1 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.h +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.h @@ -50,7 +50,8 @@ void dcn2_get_clock(struct clk_mgr *clk_mgr, enum dc_clock_type clock_type, struct dc_clock_config *clock_cfg);
-void dcn20_update_clocks_update_dentist(struct clk_mgr_internal *clk_mgr); +void dcn20_update_clocks_update_dentist(struct clk_mgr_internal *clk_mgr, + struct dc_state *context);
void dcn2_read_clocks_from_hw_dentist(struct clk_mgr *clk_mgr_base);
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c index 652fa89fae5f..513676a6f52b 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c @@ -334,11 +334,11 @@ static void dcn3_update_clocks(struct clk_mgr *clk_mgr_base, if (dpp_clock_lowered) { /* if clock is being lowered, increase DTO before lowering refclk */ dcn20_update_clocks_update_dpp_dto(clk_mgr, context, safe_to_lower); - dcn20_update_clocks_update_dentist(clk_mgr); + dcn20_update_clocks_update_dentist(clk_mgr, context); } else { /* if clock is being raised, increase refclk before lowering DTO */ if (update_dppclk || update_dispclk) - dcn20_update_clocks_update_dentist(clk_mgr); + dcn20_update_clocks_update_dentist(clk_mgr, context); /* There is a check inside dcn20_update_clocks_update_dpp_dto which ensures * that we do not lower dto when it is not safe to lower. We do not need to * compare the current and new dppclk before calling this function.*/
From: Yifan Zhang yifan1.zhang@amd.com
[ Upstream commit 631003101c516ea29a74aee59666708857b9a805 ]
If GC has entered CGPG, ringing doorbell > first page doesn't wakeup GC. Enlarge CP_MEC_DOORBELL_RANGE_UPPER to workaround this issue.
Signed-off-by: Yifan Zhang yifan1.zhang@amd.com Reviewed-by: Felix Kuehling Felix.Kuehling@amd.com Reviewed-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c index 516467e962b7..c09225d065c2 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c @@ -3673,8 +3673,12 @@ static int gfx_v9_0_kiq_init_register(struct amdgpu_ring *ring) if (ring->use_doorbell) { WREG32_SOC15(GC, 0, mmCP_MEC_DOORBELL_RANGE_LOWER, (adev->doorbell_index.kiq * 2) << 2); + /* If GC has entered CGPG, ringing doorbell > first page doesn't + * wakeup GC. Enlarge CP_MEC_DOORBELL_RANGE_UPPER to workaround + * this issue. + */ WREG32_SOC15(GC, 0, mmCP_MEC_DOORBELL_RANGE_UPPER, - (adev->doorbell_index.userqueue_end * 2) << 2); + (adev->doorbell.size - 4)); }
WREG32_SOC15_RLC(GC, 0, mmCP_HQD_PQ_DOORBELL_CONTROL,
On Tue, Jul 6, 2021 at 7:16 AM Sasha Levin sashal@kernel.org wrote:
From: Yifan Zhang yifan1.zhang@amd.com
[ Upstream commit 631003101c516ea29a74aee59666708857b9a805 ]
If GC has entered CGPG, ringing doorbell > first page doesn't wakeup GC. Enlarge CP_MEC_DOORBELL_RANGE_UPPER to workaround this issue.
Signed-off-by: Yifan Zhang yifan1.zhang@amd.com Reviewed-by: Felix Kuehling Felix.Kuehling@amd.com Reviewed-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Sasha Levin sashal@kernel.org
This should be dropped. It was already reverted.
Alex
drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c index 516467e962b7..c09225d065c2 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c @@ -3673,8 +3673,12 @@ static int gfx_v9_0_kiq_init_register(struct amdgpu_ring *ring) if (ring->use_doorbell) { WREG32_SOC15(GC, 0, mmCP_MEC_DOORBELL_RANGE_LOWER, (adev->doorbell_index.kiq * 2) << 2);
/* If GC has entered CGPG, ringing doorbell > first page doesn't
* wakeup GC. Enlarge CP_MEC_DOORBELL_RANGE_UPPER to workaround
* this issue.
*/ WREG32_SOC15(GC, 0, mmCP_MEC_DOORBELL_RANGE_UPPER,
(adev->doorbell_index.userqueue_end * 2) << 2);
(adev->doorbell.size - 4)); } WREG32_SOC15_RLC(GC, 0, mmCP_HQD_PQ_DOORBELL_CONTROL,
-- 2.30.2
amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
Am 2021-07-06 um 5:44 p.m. schrieb Alex Deucher:
On Tue, Jul 6, 2021 at 7:16 AM Sasha Levin sashal@kernel.org wrote:
From: Yifan Zhang yifan1.zhang@amd.com
[ Upstream commit 631003101c516ea29a74aee59666708857b9a805 ]
If GC has entered CGPG, ringing doorbell > first page doesn't wakeup GC. Enlarge CP_MEC_DOORBELL_RANGE_UPPER to workaround this issue.
Signed-off-by: Yifan Zhang yifan1.zhang@amd.com Reviewed-by: Felix Kuehling Felix.Kuehling@amd.com Reviewed-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Sasha Levin sashal@kernel.org
This should be dropped. It was already reverted.
Patch 146 of this series is the corresponding revert.
Regards, Felix
Alex
drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c index 516467e962b7..c09225d065c2 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c @@ -3673,8 +3673,12 @@ static int gfx_v9_0_kiq_init_register(struct amdgpu_ring *ring) if (ring->use_doorbell) { WREG32_SOC15(GC, 0, mmCP_MEC_DOORBELL_RANGE_LOWER, (adev->doorbell_index.kiq * 2) << 2);
/* If GC has entered CGPG, ringing doorbell > first page doesn't
* wakeup GC. Enlarge CP_MEC_DOORBELL_RANGE_UPPER to workaround
* this issue.
*/ WREG32_SOC15(GC, 0, mmCP_MEC_DOORBELL_RANGE_UPPER,
(adev->doorbell_index.userqueue_end * 2) << 2);
(adev->doorbell.size - 4)); } WREG32_SOC15_RLC(GC, 0, mmCP_HQD_PQ_DOORBELL_CONTROL,
-- 2.30.2
amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
On Tue, Jul 06, 2021 at 07:09:37PM -0400, Felix Kuehling wrote:
Am 2021-07-06 um 5:44 p.m. schrieb Alex Deucher:
On Tue, Jul 6, 2021 at 7:16 AM Sasha Levin sashal@kernel.org wrote:
From: Yifan Zhang yifan1.zhang@amd.com
[ Upstream commit 631003101c516ea29a74aee59666708857b9a805 ]
If GC has entered CGPG, ringing doorbell > first page doesn't wakeup GC. Enlarge CP_MEC_DOORBELL_RANGE_UPPER to workaround this issue.
Signed-off-by: Yifan Zhang yifan1.zhang@amd.com Reviewed-by: Felix Kuehling Felix.Kuehling@amd.com Reviewed-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Sasha Levin sashal@kernel.org
This should be dropped. It was already reverted.
Patch 146 of this series is the corresponding revert.
I'll drop both, thanks!
From: Amber Lin Amber.Lin@amd.com
[ Upstream commit a7b2451d31cfa2e8aeccf3b35612ce33f02371fc ]
Calling free_mqd inside of destroy_queue_nocpsch_locked can cause a circular lock. destroy_queue_nocpsch_locked is called under a DQM lock, which is taken in MMU notifiers, potentially in FS reclaim context. Taking another lock, which is BO reservation lock from free_mqd, while causing an FS reclaim inside the DQM lock creates a problematic circular lock dependency. Therefore move free_mqd out of destroy_queue_nocpsch_locked and call it after unlocking DQM.
Signed-off-by: Amber Lin Amber.Lin@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 --- .../drm/amd/amdkfd/kfd_device_queue_manager.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 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 ccc9d108caff..e9b3e2e32bf8 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c @@ -486,9 +486,6 @@ static int destroy_queue_nocpsch_locked(struct device_queue_manager *dqm, if (retval == -ETIME) qpd->reset_wavefronts = true;
- - mqd_mgr->free_mqd(mqd_mgr, q->mqd, q->mqd_mem_obj); - list_del(&q->list); if (list_empty(&qpd->queues_list)) { if (qpd->reset_wavefronts) { @@ -523,6 +520,8 @@ static int destroy_queue_nocpsch(struct device_queue_manager *dqm, int retval; uint64_t sdma_val = 0; struct kfd_process_device *pdd = qpd_to_pdd(qpd); + struct mqd_manager *mqd_mgr = + dqm->mqd_mgrs[get_mqd_type_from_queue_type(q->properties.type)];
/* Get the SDMA queue stats */ if ((q->properties.type == KFD_QUEUE_TYPE_SDMA) || @@ -540,6 +539,8 @@ static int destroy_queue_nocpsch(struct device_queue_manager *dqm, pdd->sdma_past_activity_counter += sdma_val; dqm_unlock(dqm);
+ mqd_mgr->free_mqd(mqd_mgr, q->mqd, q->mqd_mem_obj); + return retval; }
@@ -1629,7 +1630,7 @@ static bool set_cache_memory_policy(struct device_queue_manager *dqm, static int process_termination_nocpsch(struct device_queue_manager *dqm, struct qcm_process_device *qpd) { - struct queue *q, *next; + struct queue *q; struct device_process_node *cur, *next_dpn; int retval = 0; bool found = false; @@ -1637,12 +1638,19 @@ static int process_termination_nocpsch(struct device_queue_manager *dqm, dqm_lock(dqm);
/* Clear all user mode queues */ - list_for_each_entry_safe(q, next, &qpd->queues_list, list) { + while (!list_empty(&qpd->queues_list)) { + struct mqd_manager *mqd_mgr; int ret;
+ q = list_first_entry(&qpd->queues_list, struct queue, list); + mqd_mgr = dqm->mqd_mgrs[get_mqd_type_from_queue_type( + q->properties.type)]; ret = destroy_queue_nocpsch_locked(dqm, qpd, q); if (ret) retval = ret; + dqm_unlock(dqm); + mqd_mgr->free_mqd(mqd_mgr, q->mqd, q->mqd_mem_obj); + dqm_lock(dqm); }
/* Unregister process */
From: George McCollister george.mccollister@gmail.com
[ Upstream commit c2ae34a7deaff463ecafb7db627b77faaca8e159 ]
Don't check the sequence number when deciding when to update time_in in the node table if tag removal is offloaded since the sequence number is part of the tag. This fixes a problem where the times in the node table wouldn't update when 0 appeared to be before or equal to seq_out when tag removal was offloaded.
Signed-off-by: George McCollister george.mccollister@gmail.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- net/hsr/hsr_framereg.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/net/hsr/hsr_framereg.c b/net/hsr/hsr_framereg.c index bb1351c38397..e31949479305 100644 --- a/net/hsr/hsr_framereg.c +++ b/net/hsr/hsr_framereg.c @@ -397,7 +397,8 @@ void hsr_register_frame_in(struct hsr_node *node, struct hsr_port *port, * ensures entries of restarted nodes gets pruned so that they can * re-register and resume communications. */ - if (seq_nr_before(sequence_nr, node->seq_out[port->type])) + if (!(port->dev->features & NETIF_F_HW_HSR_TAG_RM) && + seq_nr_before(sequence_nr, node->seq_out[port->type])) return;
node->time_in[port->type] = jiffies;
From: Jason Gunthorpe jgg@nvidia.com
[ Upstream commit 4a7aaf88c89f12f8048137e274ce0d40fe1056b2 ]
qib should not be creating a mess of kobjects to attach to the port kobject - this is all attributes. The proper API is to create an attribute_group list and create it against the port's kobject.
Link: https://lore.kernel.org/r/911e0031e1ed495b0006e8a6efec7b67a702cd5e.162342713... Tested-by: Mike Marciniszyn mike.marciniszyn@cornelisnetworks.com Signed-off-by: Leon Romanovsky leonro@nvidia.com Signed-off-by: Jason Gunthorpe jgg@nvidia.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/infiniband/hw/qib/qib.h | 4 - drivers/infiniband/hw/qib/qib_sysfs.c | 606 +++++++++++--------------- 2 files changed, 254 insertions(+), 356 deletions(-)
diff --git a/drivers/infiniband/hw/qib/qib.h b/drivers/infiniband/hw/qib/qib.h index 88497739029e..b8a2deb5b4d2 100644 --- a/drivers/infiniband/hw/qib/qib.h +++ b/drivers/infiniband/hw/qib/qib.h @@ -521,10 +521,6 @@ struct qib_pportdata {
struct qib_devdata *dd; struct qib_chippport_specific *cpspec; /* chip-specific per-port */ - struct kobject pport_kobj; - struct kobject pport_cc_kobj; - struct kobject sl2vl_kobj; - struct kobject diagc_kobj;
/* GUID for this interface, in network order */ __be64 guid; diff --git a/drivers/infiniband/hw/qib/qib_sysfs.c b/drivers/infiniband/hw/qib/qib_sysfs.c index 5e9e66f27064..a1e22c498712 100644 --- a/drivers/infiniband/hw/qib/qib_sysfs.c +++ b/drivers/infiniband/hw/qib/qib_sysfs.c @@ -32,25 +32,38 @@ * SOFTWARE. */ #include <linux/ctype.h> +#include <rdma/ib_sysfs.h>
#include "qib.h" #include "qib_mad.h"
-/* start of per-port functions */ +static struct qib_pportdata *qib_get_pportdata_kobj(struct kobject *kobj) +{ + u32 port_num; + struct ib_device *ibdev = ib_port_sysfs_get_ibdev_kobj(kobj, &port_num); + struct qib_devdata *dd = dd_from_ibdev(ibdev); + + return &dd->pport[port_num - 1]; +} + /* * Get/Set heartbeat enable. OR of 1=enabled, 2=auto */ -static ssize_t show_hrtbt_enb(struct qib_pportdata *ppd, char *buf) +static ssize_t hrtbt_enable_show(struct ib_device *ibdev, u32 port_num, + struct ib_port_attribute *attr, char *buf) { - struct qib_devdata *dd = ppd->dd; + struct qib_devdata *dd = dd_from_ibdev(ibdev); + struct qib_pportdata *ppd = &dd->pport[port_num - 1];
return sysfs_emit(buf, "%d\n", dd->f_get_ib_cfg(ppd, QIB_IB_CFG_HRTBT)); }
-static ssize_t store_hrtbt_enb(struct qib_pportdata *ppd, const char *buf, - size_t count) +static ssize_t hrtbt_enable_store(struct ib_device *ibdev, u32 port_num, + struct ib_port_attribute *attr, + const char *buf, size_t count) { - struct qib_devdata *dd = ppd->dd; + struct qib_devdata *dd = dd_from_ibdev(ibdev); + struct qib_pportdata *ppd = &dd->pport[port_num - 1]; int ret; u16 val;
@@ -70,11 +83,14 @@ static ssize_t store_hrtbt_enb(struct qib_pportdata *ppd, const char *buf, ret = dd->f_set_ib_cfg(ppd, QIB_IB_CFG_HRTBT, val); return ret < 0 ? ret : count; } +static IB_PORT_ATTR_RW(hrtbt_enable);
-static ssize_t store_loopback(struct qib_pportdata *ppd, const char *buf, +static ssize_t loopback_store(struct ib_device *ibdev, u32 port_num, + struct ib_port_attribute *attr, const char *buf, size_t count) { - struct qib_devdata *dd = ppd->dd; + struct qib_devdata *dd = dd_from_ibdev(ibdev); + struct qib_pportdata *ppd = &dd->pport[port_num - 1]; int ret = count, r;
r = dd->f_set_ib_loopback(ppd, buf); @@ -83,11 +99,14 @@ static ssize_t store_loopback(struct qib_pportdata *ppd, const char *buf,
return ret; } +static IB_PORT_ATTR_WO(loopback);
-static ssize_t store_led_override(struct qib_pportdata *ppd, const char *buf, - size_t count) +static ssize_t led_override_store(struct ib_device *ibdev, u32 port_num, + struct ib_port_attribute *attr, + const char *buf, size_t count) { - struct qib_devdata *dd = ppd->dd; + struct qib_devdata *dd = dd_from_ibdev(ibdev); + struct qib_pportdata *ppd = &dd->pport[port_num - 1]; int ret; u16 val;
@@ -100,14 +119,20 @@ static ssize_t store_led_override(struct qib_pportdata *ppd, const char *buf, qib_set_led_override(ppd, val); return count; } +static IB_PORT_ATTR_WO(led_override);
-static ssize_t show_status(struct qib_pportdata *ppd, char *buf) +static ssize_t status_show(struct ib_device *ibdev, u32 port_num, + struct ib_port_attribute *attr, char *buf) { + struct qib_devdata *dd = dd_from_ibdev(ibdev); + struct qib_pportdata *ppd = &dd->pport[port_num - 1]; + if (!ppd->statusp) return -EINVAL;
return sysfs_emit(buf, "0x%llx\n", (unsigned long long)*(ppd->statusp)); } +static IB_PORT_ATTR_RO(status);
/* * For userland compatibility, these offsets must remain fixed. @@ -127,8 +152,11 @@ static const char * const qib_status_str[] = { NULL, };
-static ssize_t show_status_str(struct qib_pportdata *ppd, char *buf) +static ssize_t status_str_show(struct ib_device *ibdev, u32 port_num, + struct ib_port_attribute *attr, char *buf) { + struct qib_devdata *dd = dd_from_ibdev(ibdev); + struct qib_pportdata *ppd = &dd->pport[port_num - 1]; int i, any; u64 s; ssize_t ret; @@ -160,38 +188,22 @@ static ssize_t show_status_str(struct qib_pportdata *ppd, char *buf) bail: return ret; } +static IB_PORT_ATTR_RO(status_str);
/* end of per-port functions */
-/* - * Start of per-port file structures and support code - * Because we are fitting into other infrastructure, we have to supply the - * full set of kobject/sysfs_ops structures and routines. - */ -#define QIB_PORT_ATTR(name, mode, show, store) \ - static struct qib_port_attr qib_port_attr_##name = \ - __ATTR(name, mode, show, store) - -struct qib_port_attr { - struct attribute attr; - ssize_t (*show)(struct qib_pportdata *, char *); - ssize_t (*store)(struct qib_pportdata *, const char *, size_t); +static struct attribute *port_linkcontrol_attributes[] = { + &ib_port_attr_loopback.attr, + &ib_port_attr_led_override.attr, + &ib_port_attr_hrtbt_enable.attr, + &ib_port_attr_status.attr, + &ib_port_attr_status_str.attr, + NULL };
-QIB_PORT_ATTR(loopback, S_IWUSR, NULL, store_loopback); -QIB_PORT_ATTR(led_override, S_IWUSR, NULL, store_led_override); -QIB_PORT_ATTR(hrtbt_enable, S_IWUSR | S_IRUGO, show_hrtbt_enb, - store_hrtbt_enb); -QIB_PORT_ATTR(status, S_IRUGO, show_status, NULL); -QIB_PORT_ATTR(status_str, S_IRUGO, show_status_str, NULL); - -static struct attribute *port_default_attributes[] = { - &qib_port_attr_loopback.attr, - &qib_port_attr_led_override.attr, - &qib_port_attr_hrtbt_enable.attr, - &qib_port_attr_status.attr, - &qib_port_attr_status_str.attr, - NULL +static const struct attribute_group port_linkcontrol_group = { + .name = "linkcontrol", + .attrs = port_linkcontrol_attributes, };
/* @@ -201,13 +213,12 @@ static struct attribute *port_default_attributes[] = { /* * Congestion control table size followed by table entries */ -static ssize_t read_cc_table_bin(struct file *filp, struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buf, loff_t pos, size_t count) +static ssize_t cc_table_bin_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, char *buf, + loff_t pos, size_t count) { + struct qib_pportdata *ppd = qib_get_pportdata_kobj(kobj); int ret; - struct qib_pportdata *ppd = - container_of(kobj, struct qib_pportdata, pport_cc_kobj);
if (!qib_cc_table_size || !ppd->ccti_entries_shadow) return -EINVAL; @@ -230,34 +241,19 @@ static ssize_t read_cc_table_bin(struct file *filp, struct kobject *kobj,
return count; } - -static void qib_port_release(struct kobject *kobj) -{ - /* nothing to do since memory is freed by qib_free_devdata() */ -} - -static struct kobj_type qib_port_cc_ktype = { - .release = qib_port_release, -}; - -static const struct bin_attribute cc_table_bin_attr = { - .attr = {.name = "cc_table_bin", .mode = 0444}, - .read = read_cc_table_bin, - .size = PAGE_SIZE, -}; +static BIN_ATTR_RO(cc_table_bin, PAGE_SIZE);
/* * Congestion settings: port control, control map and an array of 16 * entries for the congestion entries - increase, timer, event log * trigger threshold and the minimum injection rate delay. */ -static ssize_t read_cc_setting_bin(struct file *filp, struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buf, loff_t pos, size_t count) +static ssize_t cc_setting_bin_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, char *buf, + loff_t pos, size_t count) { + struct qib_pportdata *ppd = qib_get_pportdata_kobj(kobj); int ret; - struct qib_pportdata *ppd = - container_of(kobj, struct qib_pportdata, pport_cc_kobj);
if (!qib_cc_table_size || !ppd->congestion_entries_shadow) return -EINVAL; @@ -278,67 +274,54 @@ static ssize_t read_cc_setting_bin(struct file *filp, struct kobject *kobj,
return count; } +static BIN_ATTR_RO(cc_setting_bin, PAGE_SIZE);
-static const struct bin_attribute cc_setting_bin_attr = { - .attr = {.name = "cc_settings_bin", .mode = 0444}, - .read = read_cc_setting_bin, - .size = PAGE_SIZE, +static struct bin_attribute *port_ccmgta_attributes[] = { + &bin_attr_cc_setting_bin, + &bin_attr_cc_table_bin, + NULL, };
- -static ssize_t qib_portattr_show(struct kobject *kobj, - struct attribute *attr, char *buf) -{ - struct qib_port_attr *pattr = - container_of(attr, struct qib_port_attr, attr); - struct qib_pportdata *ppd = - container_of(kobj, struct qib_pportdata, pport_kobj); - - if (!pattr->show) - return -EIO; - - return pattr->show(ppd, buf); -} - -static ssize_t qib_portattr_store(struct kobject *kobj, - struct attribute *attr, const char *buf, size_t len) +static umode_t qib_ccmgta_is_bin_visible(struct kobject *kobj, + struct bin_attribute *attr, int n) { - struct qib_port_attr *pattr = - container_of(attr, struct qib_port_attr, attr); - struct qib_pportdata *ppd = - container_of(kobj, struct qib_pportdata, pport_kobj); + struct qib_pportdata *ppd = qib_get_pportdata_kobj(kobj);
- if (!pattr->store) - return -EIO; - - return pattr->store(ppd, buf, len); + if (!qib_cc_table_size || !ppd->congestion_entries_shadow) + return 0; + return attr->attr.mode; }
- -static const struct sysfs_ops qib_port_ops = { - .show = qib_portattr_show, - .store = qib_portattr_store, -}; - -static struct kobj_type qib_port_ktype = { - .release = qib_port_release, - .sysfs_ops = &qib_port_ops, - .default_attrs = port_default_attributes +static const struct attribute_group port_ccmgta_attribute_group = { + .name = "CCMgtA", + .is_bin_visible = qib_ccmgta_is_bin_visible, + .bin_attrs = port_ccmgta_attributes, };
/* Start sl2vl */
-#define QIB_SL2VL_ATTR(N) \ - static struct qib_sl2vl_attr qib_sl2vl_attr_##N = { \ - .attr = { .name = __stringify(N), .mode = 0444 }, \ - .sl = N \ - } - struct qib_sl2vl_attr { - struct attribute attr; + struct ib_port_attribute attr; int sl; };
+static ssize_t sl2vl_attr_show(struct ib_device *ibdev, u32 port_num, + struct ib_port_attribute *attr, char *buf) +{ + struct qib_sl2vl_attr *sattr = + container_of(attr, struct qib_sl2vl_attr, attr); + struct qib_devdata *dd = dd_from_ibdev(ibdev); + struct qib_ibport *qibp = &dd->pport[port_num - 1].ibport_data; + + return sysfs_emit(buf, "%u\n", qibp->sl_to_vl[sattr->sl]); +} + +#define QIB_SL2VL_ATTR(N) \ + static struct qib_sl2vl_attr qib_sl2vl_attr_##N = { \ + .attr = __ATTR(N, 0444, sl2vl_attr_show, NULL), \ + .sl = N, \ + } + QIB_SL2VL_ATTR(0); QIB_SL2VL_ATTR(1); QIB_SL2VL_ATTR(2); @@ -356,72 +339,74 @@ QIB_SL2VL_ATTR(13); QIB_SL2VL_ATTR(14); QIB_SL2VL_ATTR(15);
-static struct attribute *sl2vl_default_attributes[] = { - &qib_sl2vl_attr_0.attr, - &qib_sl2vl_attr_1.attr, - &qib_sl2vl_attr_2.attr, - &qib_sl2vl_attr_3.attr, - &qib_sl2vl_attr_4.attr, - &qib_sl2vl_attr_5.attr, - &qib_sl2vl_attr_6.attr, - &qib_sl2vl_attr_7.attr, - &qib_sl2vl_attr_8.attr, - &qib_sl2vl_attr_9.attr, - &qib_sl2vl_attr_10.attr, - &qib_sl2vl_attr_11.attr, - &qib_sl2vl_attr_12.attr, - &qib_sl2vl_attr_13.attr, - &qib_sl2vl_attr_14.attr, - &qib_sl2vl_attr_15.attr, +static struct attribute *port_sl2vl_attributes[] = { + &qib_sl2vl_attr_0.attr.attr, + &qib_sl2vl_attr_1.attr.attr, + &qib_sl2vl_attr_2.attr.attr, + &qib_sl2vl_attr_3.attr.attr, + &qib_sl2vl_attr_4.attr.attr, + &qib_sl2vl_attr_5.attr.attr, + &qib_sl2vl_attr_6.attr.attr, + &qib_sl2vl_attr_7.attr.attr, + &qib_sl2vl_attr_8.attr.attr, + &qib_sl2vl_attr_9.attr.attr, + &qib_sl2vl_attr_10.attr.attr, + &qib_sl2vl_attr_11.attr.attr, + &qib_sl2vl_attr_12.attr.attr, + &qib_sl2vl_attr_13.attr.attr, + &qib_sl2vl_attr_14.attr.attr, + &qib_sl2vl_attr_15.attr.attr, NULL };
-static ssize_t sl2vl_attr_show(struct kobject *kobj, struct attribute *attr, - char *buf) -{ - struct qib_sl2vl_attr *sattr = - container_of(attr, struct qib_sl2vl_attr, attr); - struct qib_pportdata *ppd = - container_of(kobj, struct qib_pportdata, sl2vl_kobj); - struct qib_ibport *qibp = &ppd->ibport_data; - - return sysfs_emit(buf, "%u\n", qibp->sl_to_vl[sattr->sl]); -} - -static const struct sysfs_ops qib_sl2vl_ops = { - .show = sl2vl_attr_show, -}; - -static struct kobj_type qib_sl2vl_ktype = { - .release = qib_port_release, - .sysfs_ops = &qib_sl2vl_ops, - .default_attrs = sl2vl_default_attributes +static const struct attribute_group port_sl2vl_group = { + .name = "sl2vl", + .attrs = port_sl2vl_attributes, };
/* End sl2vl */
/* Start diag_counters */
-#define QIB_DIAGC_ATTR(N) \ - static struct qib_diagc_attr qib_diagc_attr_##N = { \ - .attr = { .name = __stringify(N), .mode = 0664 }, \ - .counter = offsetof(struct qib_ibport, rvp.n_##N) \ - } - -#define QIB_DIAGC_ATTR_PER_CPU(N) \ - static struct qib_diagc_attr qib_diagc_attr_##N = { \ - .attr = { .name = __stringify(N), .mode = 0664 }, \ - .counter = offsetof(struct qib_ibport, rvp.z_##N) \ - } - struct qib_diagc_attr { - struct attribute attr; + struct ib_port_attribute attr; size_t counter; };
-QIB_DIAGC_ATTR_PER_CPU(rc_acks); -QIB_DIAGC_ATTR_PER_CPU(rc_qacks); -QIB_DIAGC_ATTR_PER_CPU(rc_delayed_comp); +static ssize_t diagc_attr_show(struct ib_device *ibdev, u32 port_num, + struct ib_port_attribute *attr, char *buf) +{ + struct qib_diagc_attr *dattr = + container_of(attr, struct qib_diagc_attr, attr); + struct qib_devdata *dd = dd_from_ibdev(ibdev); + struct qib_ibport *qibp = &dd->pport[port_num - 1].ibport_data; + + return sysfs_emit(buf, "%llu\n", *((u64 *)qibp + dattr->counter)); +} + +static ssize_t diagc_attr_store(struct ib_device *ibdev, u32 port_num, + struct ib_port_attribute *attr, const char *buf, + size_t count) +{ + struct qib_diagc_attr *dattr = + container_of(attr, struct qib_diagc_attr, attr); + struct qib_devdata *dd = dd_from_ibdev(ibdev); + struct qib_ibport *qibp = &dd->pport[port_num - 1].ibport_data; + u64 val; + int ret; + + ret = kstrtou64(buf, 0, &val); + if (ret) + return ret; + *((u64 *)qibp + dattr->counter) = val; + return count; +} + +#define QIB_DIAGC_ATTR(N) \ + static struct qib_diagc_attr qib_diagc_attr_##N = { \ + .attr = __ATTR(N, 0664, diagc_attr_show, diagc_attr_store), \ + .counter = &((struct qib_ibport *)0)->rvp.n_##N - (u64 *)0, \ + }
QIB_DIAGC_ATTR(rc_resends); QIB_DIAGC_ATTR(seq_naks); @@ -437,26 +422,6 @@ QIB_DIAGC_ATTR(rc_dupreq); QIB_DIAGC_ATTR(rc_seqnak); QIB_DIAGC_ATTR(rc_crwaits);
-static struct attribute *diagc_default_attributes[] = { - &qib_diagc_attr_rc_resends.attr, - &qib_diagc_attr_rc_acks.attr, - &qib_diagc_attr_rc_qacks.attr, - &qib_diagc_attr_rc_delayed_comp.attr, - &qib_diagc_attr_seq_naks.attr, - &qib_diagc_attr_rdma_seq.attr, - &qib_diagc_attr_rnr_naks.attr, - &qib_diagc_attr_other_naks.attr, - &qib_diagc_attr_rc_timeouts.attr, - &qib_diagc_attr_loop_pkts.attr, - &qib_diagc_attr_pkt_drops.attr, - &qib_diagc_attr_dmawait.attr, - &qib_diagc_attr_unaligned.attr, - &qib_diagc_attr_rc_dupreq.attr, - &qib_diagc_attr_rc_seqnak.attr, - &qib_diagc_attr_rc_crwaits.attr, - NULL -}; - static u64 get_all_cpu_total(u64 __percpu *cntr) { int cpu; @@ -467,86 +432,127 @@ static u64 get_all_cpu_total(u64 __percpu *cntr) return counter; }
-#define def_write_per_cpu(cntr) \ -static void write_per_cpu_##cntr(struct qib_pportdata *ppd, u32 data) \ -{ \ - struct qib_devdata *dd = ppd->dd; \ - struct qib_ibport *qibp = &ppd->ibport_data; \ - /* A write can only zero the counter */ \ - if (data == 0) \ - qibp->rvp.z_##cntr = get_all_cpu_total(qibp->rvp.cntr); \ - else \ - qib_dev_err(dd, "Per CPU cntrs can only be zeroed"); \ +static ssize_t qib_store_per_cpu(struct qib_devdata *dd, const char *buf, + size_t count, u64 *zero, u64 cur) +{ + u32 val; + int ret; + + ret = kstrtou32(buf, 0, &val); + if (ret) + return ret; + if (val != 0) { + qib_dev_err(dd, "Per CPU cntrs can only be zeroed"); + return count; + } + *zero = cur; + return count; }
-def_write_per_cpu(rc_acks) -def_write_per_cpu(rc_qacks) -def_write_per_cpu(rc_delayed_comp) +static ssize_t rc_acks_show(struct ib_device *ibdev, u32 port_num, + struct ib_port_attribute *attr, char *buf) +{ + struct qib_devdata *dd = dd_from_ibdev(ibdev); + struct qib_ibport *qibp = &dd->pport[port_num - 1].ibport_data;
-#define READ_PER_CPU_CNTR(cntr) (get_all_cpu_total(qibp->rvp.cntr) - \ - qibp->rvp.z_##cntr) + return sysfs_emit(buf, "%llu\n", + get_all_cpu_total(qibp->rvp.rc_acks) - + qibp->rvp.z_rc_acks); +}
-static ssize_t diagc_attr_show(struct kobject *kobj, struct attribute *attr, - char *buf) +static ssize_t rc_acks_store(struct ib_device *ibdev, u32 port_num, + struct ib_port_attribute *attr, const char *buf, + size_t count) { - struct qib_diagc_attr *dattr = - container_of(attr, struct qib_diagc_attr, attr); - struct qib_pportdata *ppd = - container_of(kobj, struct qib_pportdata, diagc_kobj); - struct qib_ibport *qibp = &ppd->ibport_data; - u64 val; + struct qib_devdata *dd = dd_from_ibdev(ibdev); + struct qib_ibport *qibp = &dd->pport[port_num - 1].ibport_data;
- if (!strncmp(dattr->attr.name, "rc_acks", 7)) - val = READ_PER_CPU_CNTR(rc_acks); - else if (!strncmp(dattr->attr.name, "rc_qacks", 8)) - val = READ_PER_CPU_CNTR(rc_qacks); - else if (!strncmp(dattr->attr.name, "rc_delayed_comp", 15)) - val = READ_PER_CPU_CNTR(rc_delayed_comp); - else - val = *(u32 *)((char *)qibp + dattr->counter); + return qib_store_per_cpu(dd, buf, count, &qibp->rvp.z_rc_acks, + get_all_cpu_total(qibp->rvp.rc_acks)); +} +static IB_PORT_ATTR_RW(rc_acks); + +static ssize_t rc_qacks_show(struct ib_device *ibdev, u32 port_num, + struct ib_port_attribute *attr, char *buf) +{ + struct qib_devdata *dd = dd_from_ibdev(ibdev); + struct qib_ibport *qibp = &dd->pport[port_num - 1].ibport_data;
- return sysfs_emit(buf, "%llu\n", val); + return sysfs_emit(buf, "%llu\n", + get_all_cpu_total(qibp->rvp.rc_qacks) - + qibp->rvp.z_rc_qacks); }
-static ssize_t diagc_attr_store(struct kobject *kobj, struct attribute *attr, - const char *buf, size_t size) +static ssize_t rc_qacks_store(struct ib_device *ibdev, u32 port_num, + struct ib_port_attribute *attr, const char *buf, + size_t count) { - struct qib_diagc_attr *dattr = - container_of(attr, struct qib_diagc_attr, attr); - struct qib_pportdata *ppd = - container_of(kobj, struct qib_pportdata, diagc_kobj); - struct qib_ibport *qibp = &ppd->ibport_data; - u32 val; - int ret; + struct qib_devdata *dd = dd_from_ibdev(ibdev); + struct qib_ibport *qibp = &dd->pport[port_num - 1].ibport_data;
- ret = kstrtou32(buf, 0, &val); - if (ret) - return ret; + return qib_store_per_cpu(dd, buf, count, &qibp->rvp.z_rc_qacks, + get_all_cpu_total(qibp->rvp.rc_qacks)); +} +static IB_PORT_ATTR_RW(rc_qacks);
- if (!strncmp(dattr->attr.name, "rc_acks", 7)) - write_per_cpu_rc_acks(ppd, val); - else if (!strncmp(dattr->attr.name, "rc_qacks", 8)) - write_per_cpu_rc_qacks(ppd, val); - else if (!strncmp(dattr->attr.name, "rc_delayed_comp", 15)) - write_per_cpu_rc_delayed_comp(ppd, val); - else - *(u32 *)((char *)qibp + dattr->counter) = val; - return size; +static ssize_t rc_delayed_comp_show(struct ib_device *ibdev, u32 port_num, + struct ib_port_attribute *attr, char *buf) +{ + struct qib_devdata *dd = dd_from_ibdev(ibdev); + struct qib_ibport *qibp = &dd->pport[port_num - 1].ibport_data; + + return sysfs_emit(buf, "%llu\n", + get_all_cpu_total(qibp->rvp.rc_delayed_comp) - + qibp->rvp.z_rc_delayed_comp); }
-static const struct sysfs_ops qib_diagc_ops = { - .show = diagc_attr_show, - .store = diagc_attr_store, +static ssize_t rc_delayed_comp_store(struct ib_device *ibdev, u32 port_num, + struct ib_port_attribute *attr, + const char *buf, size_t count) +{ + struct qib_devdata *dd = dd_from_ibdev(ibdev); + struct qib_ibport *qibp = &dd->pport[port_num - 1].ibport_data; + + return qib_store_per_cpu(dd, buf, count, &qibp->rvp.z_rc_delayed_comp, + get_all_cpu_total(qibp->rvp.rc_delayed_comp)); +} +static IB_PORT_ATTR_RW(rc_delayed_comp); + +static struct attribute *port_diagc_attributes[] = { + &qib_diagc_attr_rc_resends.attr.attr, + &qib_diagc_attr_seq_naks.attr.attr, + &qib_diagc_attr_rdma_seq.attr.attr, + &qib_diagc_attr_rnr_naks.attr.attr, + &qib_diagc_attr_other_naks.attr.attr, + &qib_diagc_attr_rc_timeouts.attr.attr, + &qib_diagc_attr_loop_pkts.attr.attr, + &qib_diagc_attr_pkt_drops.attr.attr, + &qib_diagc_attr_dmawait.attr.attr, + &qib_diagc_attr_unaligned.attr.attr, + &qib_diagc_attr_rc_dupreq.attr.attr, + &qib_diagc_attr_rc_seqnak.attr.attr, + &qib_diagc_attr_rc_crwaits.attr.attr, + &ib_port_attr_rc_acks.attr, + &ib_port_attr_rc_qacks.attr, + &ib_port_attr_rc_delayed_comp.attr, + NULL };
-static struct kobj_type qib_diagc_ktype = { - .release = qib_port_release, - .sysfs_ops = &qib_diagc_ops, - .default_attrs = diagc_default_attributes +static const struct attribute_group port_diagc_group = { + .name = "linkcontrol", + .attrs = port_diagc_attributes, };
/* End diag_counters */
+static const struct attribute_group *qib_port_groups[] = { + &port_linkcontrol_group, + &port_ccmgta_attribute_group, + &port_sl2vl_group, + &port_diagc_group, + NULL, +}; + /* end of per-port file structures and support code */
/* @@ -731,99 +737,7 @@ const struct attribute_group qib_attr_group = { int qib_create_port_files(struct ib_device *ibdev, u32 port_num, struct kobject *kobj) { - struct qib_pportdata *ppd; - struct qib_devdata *dd = dd_from_ibdev(ibdev); - int ret; - - if (!port_num || port_num > dd->num_pports) { - qib_dev_err(dd, - "Skipping infiniband class with invalid port %u\n", - port_num); - ret = -ENODEV; - goto bail; - } - ppd = &dd->pport[port_num - 1]; - - ret = kobject_init_and_add(&ppd->pport_kobj, &qib_port_ktype, kobj, - "linkcontrol"); - if (ret) { - qib_dev_err(dd, - "Skipping linkcontrol sysfs info, (err %d) port %u\n", - ret, port_num); - goto bail_link; - } - kobject_uevent(&ppd->pport_kobj, KOBJ_ADD); - - ret = kobject_init_and_add(&ppd->sl2vl_kobj, &qib_sl2vl_ktype, kobj, - "sl2vl"); - if (ret) { - qib_dev_err(dd, - "Skipping sl2vl sysfs info, (err %d) port %u\n", - ret, port_num); - goto bail_sl; - } - kobject_uevent(&ppd->sl2vl_kobj, KOBJ_ADD); - - ret = kobject_init_and_add(&ppd->diagc_kobj, &qib_diagc_ktype, kobj, - "diag_counters"); - if (ret) { - qib_dev_err(dd, - "Skipping diag_counters sysfs info, (err %d) port %u\n", - ret, port_num); - goto bail_diagc; - } - kobject_uevent(&ppd->diagc_kobj, KOBJ_ADD); - - if (!qib_cc_table_size || !ppd->congestion_entries_shadow) - return 0; - - ret = kobject_init_and_add(&ppd->pport_cc_kobj, &qib_port_cc_ktype, - kobj, "CCMgtA"); - if (ret) { - qib_dev_err(dd, - "Skipping Congestion Control sysfs info, (err %d) port %u\n", - ret, port_num); - goto bail_cc; - } - - kobject_uevent(&ppd->pport_cc_kobj, KOBJ_ADD); - - ret = sysfs_create_bin_file(&ppd->pport_cc_kobj, - &cc_setting_bin_attr); - if (ret) { - qib_dev_err(dd, - "Skipping Congestion Control setting sysfs info, (err %d) port %u\n", - ret, port_num); - goto bail_cc; - } - - ret = sysfs_create_bin_file(&ppd->pport_cc_kobj, - &cc_table_bin_attr); - if (ret) { - qib_dev_err(dd, - "Skipping Congestion Control table sysfs info, (err %d) port %u\n", - ret, port_num); - goto bail_cc_entry_bin; - } - - qib_devinfo(dd->pcidev, - "IB%u: Congestion Control Agent enabled for port %d\n", - dd->unit, port_num); - - return 0; - -bail_cc_entry_bin: - sysfs_remove_bin_file(&ppd->pport_cc_kobj, &cc_setting_bin_attr); -bail_cc: - kobject_put(&ppd->pport_cc_kobj); -bail_diagc: - kobject_put(&ppd->diagc_kobj); -bail_sl: - kobject_put(&ppd->sl2vl_kobj); -bail_link: - kobject_put(&ppd->pport_kobj); -bail: - return ret; + return ib_port_sysfs_create_groups(ibdev, port_num, qib_port_groups); }
/* @@ -831,21 +745,9 @@ int qib_create_port_files(struct ib_device *ibdev, u32 port_num, */ void qib_verbs_unregister_sysfs(struct qib_devdata *dd) { - struct qib_pportdata *ppd; int i;
- for (i = 0; i < dd->num_pports; i++) { - ppd = &dd->pport[i]; - if (qib_cc_table_size && - ppd->congestion_entries_shadow) { - sysfs_remove_bin_file(&ppd->pport_cc_kobj, - &cc_setting_bin_attr); - sysfs_remove_bin_file(&ppd->pport_cc_kobj, - &cc_table_bin_attr); - kobject_put(&ppd->pport_cc_kobj); - } - kobject_put(&ppd->diagc_kobj); - kobject_put(&ppd->sl2vl_kobj); - kobject_put(&ppd->pport_kobj); - } + for (i = 0; i < dd->num_pports; i++) + ib_port_sysfs_remove_groups(&dd->verbs_dev.rdi.ibdev, i, + qib_port_groups); }
From: Jason Gunthorpe jgg@nvidia.com
[ Upstream commit 8f1708f19f919135a5d7eddcdccc15b7fd7d524d ]
hfi1 should not be creating a mess of kobjects to attach to the port kobject - this is all attributes. The proper API is to create an attribute_group list and create it against the port's kobject.
Link: https://lore.kernel.org/r/cbe0ccb6175dd22274359b6ad803a37435a70e91.162342713... Tested-by: Mike Marciniszyn mike.marciniszyn@cornelisnetworks.com Signed-off-by: Leon Romanovsky leonro@nvidia.com Signed-off-by: Jason Gunthorpe jgg@nvidia.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/infiniband/hw/hfi1/hfi.h | 4 - drivers/infiniband/hw/hfi1/sysfs.c | 530 +++++++++++------------------ 2 files changed, 194 insertions(+), 340 deletions(-)
diff --git a/drivers/infiniband/hw/hfi1/hfi.h b/drivers/infiniband/hw/hfi1/hfi.h index 867ae0b1aa95..87e101fb1f65 100644 --- a/drivers/infiniband/hw/hfi1/hfi.h +++ b/drivers/infiniband/hw/hfi1/hfi.h @@ -772,10 +772,6 @@ struct hfi1_pportdata { struct hfi1_ibport ibport_data;
struct hfi1_devdata *dd; - struct kobject pport_cc_kobj; - struct kobject sc2vl_kobj; - struct kobject sl2sc_kobj; - struct kobject vl2mtu_kobj;
/* PHY support */ struct qsfp_data qsfp_info; diff --git a/drivers/infiniband/hw/hfi1/sysfs.c b/drivers/infiniband/hw/hfi1/sysfs.c index eaf441ece25e..98bb0b3aac09 100644 --- a/drivers/infiniband/hw/hfi1/sysfs.c +++ b/drivers/infiniband/hw/hfi1/sysfs.c @@ -45,11 +45,21 @@ * */ #include <linux/ctype.h> +#include <rdma/ib_sysfs.h>
#include "hfi.h" #include "mad.h" #include "trace.h"
+static struct hfi1_pportdata *hfi1_get_pportdata_kobj(struct kobject *kobj) +{ + u32 port_num; + struct ib_device *ibdev = ib_port_sysfs_get_ibdev_kobj(kobj, &port_num); + struct hfi1_devdata *dd = dd_from_ibdev(ibdev); + + return &dd->pport[port_num - 1]; +} + /* * Start of per-port congestion control structures and support code */ @@ -57,13 +67,12 @@ /* * Congestion control table size followed by table entries */ -static ssize_t read_cc_table_bin(struct file *filp, struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buf, loff_t pos, size_t count) +static ssize_t cc_table_bin_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, char *buf, + loff_t pos, size_t count) { int ret; - struct hfi1_pportdata *ppd = - container_of(kobj, struct hfi1_pportdata, pport_cc_kobj); + struct hfi1_pportdata *ppd = hfi1_get_pportdata_kobj(kobj); struct cc_state *cc_state;
ret = ppd->total_cct_entry * sizeof(struct ib_cc_table_entry_shadow) @@ -89,30 +98,19 @@ static ssize_t read_cc_table_bin(struct file *filp, struct kobject *kobj,
return count; } - -static void port_release(struct kobject *kobj) -{ - /* nothing to do since memory is freed by hfi1_free_devdata() */ -} - -static const struct bin_attribute cc_table_bin_attr = { - .attr = {.name = "cc_table_bin", .mode = 0444}, - .read = read_cc_table_bin, - .size = PAGE_SIZE, -}; +static BIN_ATTR_RO(cc_table_bin, PAGE_SIZE);
/* * Congestion settings: port control, control map and an array of 16 * entries for the congestion entries - increase, timer, event log * trigger threshold and the minimum injection rate delay. */ -static ssize_t read_cc_setting_bin(struct file *filp, struct kobject *kobj, +static ssize_t cc_setting_bin_read(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t pos, size_t count) { + struct hfi1_pportdata *ppd = hfi1_get_pportdata_kobj(kobj); int ret; - struct hfi1_pportdata *ppd = - container_of(kobj, struct hfi1_pportdata, pport_cc_kobj); struct cc_state *cc_state;
ret = sizeof(struct opa_congestion_setting_attr_shadow); @@ -136,27 +134,30 @@ static ssize_t read_cc_setting_bin(struct file *filp, struct kobject *kobj,
return count; } +static BIN_ATTR_RO(cc_setting_bin, PAGE_SIZE);
-static const struct bin_attribute cc_setting_bin_attr = { - .attr = {.name = "cc_settings_bin", .mode = 0444}, - .read = read_cc_setting_bin, - .size = PAGE_SIZE, -}; - -struct hfi1_port_attr { - struct attribute attr; - ssize_t (*show)(struct hfi1_pportdata *, char *); - ssize_t (*store)(struct hfi1_pportdata *, const char *, size_t); +static struct bin_attribute *port_cc_bin_attributes[] = { + &bin_attr_cc_setting_bin, + &bin_attr_cc_table_bin, + NULL };
-static ssize_t cc_prescan_show(struct hfi1_pportdata *ppd, char *buf) +static ssize_t cc_prescan_show(struct ib_device *ibdev, u32 port_num, + struct ib_port_attribute *attr, char *buf) { + struct hfi1_devdata *dd = dd_from_ibdev(ibdev); + struct hfi1_pportdata *ppd = &dd->pport[port_num - 1]; + return sysfs_emit(buf, "%s\n", ppd->cc_prescan ? "on" : "off"); }
-static ssize_t cc_prescan_store(struct hfi1_pportdata *ppd, const char *buf, +static ssize_t cc_prescan_store(struct ib_device *ibdev, u32 port_num, + struct ib_port_attribute *attr, const char *buf, size_t count) { + struct hfi1_devdata *dd = dd_from_ibdev(ibdev); + struct hfi1_pportdata *ppd = &dd->pport[port_num - 1]; + if (!memcmp(buf, "on", 2)) ppd->cc_prescan = true; else if (!memcmp(buf, "off", 3)) @@ -164,60 +165,41 @@ static ssize_t cc_prescan_store(struct hfi1_pportdata *ppd, const char *buf,
return count; } +static IB_PORT_ATTR_ADMIN_RW(cc_prescan);
-static struct hfi1_port_attr cc_prescan_attr = - __ATTR(cc_prescan, 0600, cc_prescan_show, cc_prescan_store); - -static ssize_t cc_attr_show(struct kobject *kobj, struct attribute *attr, - char *buf) -{ - struct hfi1_port_attr *port_attr = - container_of(attr, struct hfi1_port_attr, attr); - struct hfi1_pportdata *ppd = - container_of(kobj, struct hfi1_pportdata, pport_cc_kobj); - - return port_attr->show(ppd, buf); -} - -static ssize_t cc_attr_store(struct kobject *kobj, struct attribute *attr, - const char *buf, size_t count) -{ - struct hfi1_port_attr *port_attr = - container_of(attr, struct hfi1_port_attr, attr); - struct hfi1_pportdata *ppd = - container_of(kobj, struct hfi1_pportdata, pport_cc_kobj); - - return port_attr->store(ppd, buf, count); -} - -static const struct sysfs_ops port_cc_sysfs_ops = { - .show = cc_attr_show, - .store = cc_attr_store -}; - -static struct attribute *port_cc_default_attributes[] = { - &cc_prescan_attr.attr, +static struct attribute *port_cc_attributes[] = { + &ib_port_attr_cc_prescan.attr, NULL };
-static struct kobj_type port_cc_ktype = { - .release = port_release, - .sysfs_ops = &port_cc_sysfs_ops, - .default_attrs = port_cc_default_attributes +static const struct attribute_group port_cc_group = { + .name = "CCMgtA", + .attrs = port_cc_attributes, + .bin_attrs = port_cc_bin_attributes, };
/* Start sc2vl */ -#define HFI1_SC2VL_ATTR(N) \ - static struct hfi1_sc2vl_attr hfi1_sc2vl_attr_##N = { \ - .attr = { .name = __stringify(N), .mode = 0444 }, \ - .sc = N \ - } - struct hfi1_sc2vl_attr { - struct attribute attr; + struct ib_port_attribute attr; int sc; };
+static ssize_t sc2vl_attr_show(struct ib_device *ibdev, u32 port_num, + struct ib_port_attribute *attr, char *buf) +{ + struct hfi1_sc2vl_attr *sattr = + container_of(attr, struct hfi1_sc2vl_attr, attr); + struct hfi1_devdata *dd = dd_from_ibdev(ibdev); + + return sysfs_emit(buf, "%u\n", *((u8 *)dd->sc2vl + sattr->sc)); +} + +#define HFI1_SC2VL_ATTR(N) \ + static struct hfi1_sc2vl_attr hfi1_sc2vl_attr_##N = { \ + .attr = __ATTR(N, 0444, sc2vl_attr_show, NULL), \ + .sc = N, \ + } + HFI1_SC2VL_ATTR(0); HFI1_SC2VL_ATTR(1); HFI1_SC2VL_ATTR(2); @@ -251,78 +233,70 @@ HFI1_SC2VL_ATTR(29); HFI1_SC2VL_ATTR(30); HFI1_SC2VL_ATTR(31);
-static struct attribute *sc2vl_default_attributes[] = { - &hfi1_sc2vl_attr_0.attr, - &hfi1_sc2vl_attr_1.attr, - &hfi1_sc2vl_attr_2.attr, - &hfi1_sc2vl_attr_3.attr, - &hfi1_sc2vl_attr_4.attr, - &hfi1_sc2vl_attr_5.attr, - &hfi1_sc2vl_attr_6.attr, - &hfi1_sc2vl_attr_7.attr, - &hfi1_sc2vl_attr_8.attr, - &hfi1_sc2vl_attr_9.attr, - &hfi1_sc2vl_attr_10.attr, - &hfi1_sc2vl_attr_11.attr, - &hfi1_sc2vl_attr_12.attr, - &hfi1_sc2vl_attr_13.attr, - &hfi1_sc2vl_attr_14.attr, - &hfi1_sc2vl_attr_15.attr, - &hfi1_sc2vl_attr_16.attr, - &hfi1_sc2vl_attr_17.attr, - &hfi1_sc2vl_attr_18.attr, - &hfi1_sc2vl_attr_19.attr, - &hfi1_sc2vl_attr_20.attr, - &hfi1_sc2vl_attr_21.attr, - &hfi1_sc2vl_attr_22.attr, - &hfi1_sc2vl_attr_23.attr, - &hfi1_sc2vl_attr_24.attr, - &hfi1_sc2vl_attr_25.attr, - &hfi1_sc2vl_attr_26.attr, - &hfi1_sc2vl_attr_27.attr, - &hfi1_sc2vl_attr_28.attr, - &hfi1_sc2vl_attr_29.attr, - &hfi1_sc2vl_attr_30.attr, - &hfi1_sc2vl_attr_31.attr, +static struct attribute *port_sc2vl_attributes[] = { + &hfi1_sc2vl_attr_0.attr.attr, + &hfi1_sc2vl_attr_1.attr.attr, + &hfi1_sc2vl_attr_2.attr.attr, + &hfi1_sc2vl_attr_3.attr.attr, + &hfi1_sc2vl_attr_4.attr.attr, + &hfi1_sc2vl_attr_5.attr.attr, + &hfi1_sc2vl_attr_6.attr.attr, + &hfi1_sc2vl_attr_7.attr.attr, + &hfi1_sc2vl_attr_8.attr.attr, + &hfi1_sc2vl_attr_9.attr.attr, + &hfi1_sc2vl_attr_10.attr.attr, + &hfi1_sc2vl_attr_11.attr.attr, + &hfi1_sc2vl_attr_12.attr.attr, + &hfi1_sc2vl_attr_13.attr.attr, + &hfi1_sc2vl_attr_14.attr.attr, + &hfi1_sc2vl_attr_15.attr.attr, + &hfi1_sc2vl_attr_16.attr.attr, + &hfi1_sc2vl_attr_17.attr.attr, + &hfi1_sc2vl_attr_18.attr.attr, + &hfi1_sc2vl_attr_19.attr.attr, + &hfi1_sc2vl_attr_20.attr.attr, + &hfi1_sc2vl_attr_21.attr.attr, + &hfi1_sc2vl_attr_22.attr.attr, + &hfi1_sc2vl_attr_23.attr.attr, + &hfi1_sc2vl_attr_24.attr.attr, + &hfi1_sc2vl_attr_25.attr.attr, + &hfi1_sc2vl_attr_26.attr.attr, + &hfi1_sc2vl_attr_27.attr.attr, + &hfi1_sc2vl_attr_28.attr.attr, + &hfi1_sc2vl_attr_29.attr.attr, + &hfi1_sc2vl_attr_30.attr.attr, + &hfi1_sc2vl_attr_31.attr.attr, NULL };
-static ssize_t sc2vl_attr_show(struct kobject *kobj, struct attribute *attr, - char *buf) -{ - struct hfi1_sc2vl_attr *sattr = - container_of(attr, struct hfi1_sc2vl_attr, attr); - struct hfi1_pportdata *ppd = - container_of(kobj, struct hfi1_pportdata, sc2vl_kobj); - struct hfi1_devdata *dd = ppd->dd; - - return sysfs_emit(buf, "%u\n", *((u8 *)dd->sc2vl + sattr->sc)); -} - -static const struct sysfs_ops hfi1_sc2vl_ops = { - .show = sc2vl_attr_show, +static const struct attribute_group port_sc2vl_group = { + .name = "sc2vl", + .attrs = port_sc2vl_attributes, }; - -static struct kobj_type hfi1_sc2vl_ktype = { - .release = port_release, - .sysfs_ops = &hfi1_sc2vl_ops, - .default_attrs = sc2vl_default_attributes -}; - /* End sc2vl */
/* Start sl2sc */ -#define HFI1_SL2SC_ATTR(N) \ - static struct hfi1_sl2sc_attr hfi1_sl2sc_attr_##N = { \ - .attr = { .name = __stringify(N), .mode = 0444 }, \ - .sl = N \ - } - struct hfi1_sl2sc_attr { - struct attribute attr; + struct ib_port_attribute attr; int sl; };
+static ssize_t sl2sc_attr_show(struct ib_device *ibdev, u32 port_num, + struct ib_port_attribute *attr, char *buf) +{ + struct hfi1_sl2sc_attr *sattr = + container_of(attr, struct hfi1_sl2sc_attr, attr); + struct hfi1_devdata *dd = dd_from_ibdev(ibdev); + struct hfi1_ibport *ibp = &dd->pport[port_num - 1].ibport_data; + + return sysfs_emit(buf, "%u\n", ibp->sl_to_sc[sattr->sl]); +} + +#define HFI1_SL2SC_ATTR(N) \ + static struct hfi1_sl2sc_attr hfi1_sl2sc_attr_##N = { \ + .attr = __ATTR(N, 0444, sl2sc_attr_show, NULL), .sl = N \ + } + HFI1_SL2SC_ATTR(0); HFI1_SL2SC_ATTR(1); HFI1_SL2SC_ATTR(2); @@ -356,79 +330,72 @@ HFI1_SL2SC_ATTR(29); HFI1_SL2SC_ATTR(30); HFI1_SL2SC_ATTR(31);
-static struct attribute *sl2sc_default_attributes[] = { - &hfi1_sl2sc_attr_0.attr, - &hfi1_sl2sc_attr_1.attr, - &hfi1_sl2sc_attr_2.attr, - &hfi1_sl2sc_attr_3.attr, - &hfi1_sl2sc_attr_4.attr, - &hfi1_sl2sc_attr_5.attr, - &hfi1_sl2sc_attr_6.attr, - &hfi1_sl2sc_attr_7.attr, - &hfi1_sl2sc_attr_8.attr, - &hfi1_sl2sc_attr_9.attr, - &hfi1_sl2sc_attr_10.attr, - &hfi1_sl2sc_attr_11.attr, - &hfi1_sl2sc_attr_12.attr, - &hfi1_sl2sc_attr_13.attr, - &hfi1_sl2sc_attr_14.attr, - &hfi1_sl2sc_attr_15.attr, - &hfi1_sl2sc_attr_16.attr, - &hfi1_sl2sc_attr_17.attr, - &hfi1_sl2sc_attr_18.attr, - &hfi1_sl2sc_attr_19.attr, - &hfi1_sl2sc_attr_20.attr, - &hfi1_sl2sc_attr_21.attr, - &hfi1_sl2sc_attr_22.attr, - &hfi1_sl2sc_attr_23.attr, - &hfi1_sl2sc_attr_24.attr, - &hfi1_sl2sc_attr_25.attr, - &hfi1_sl2sc_attr_26.attr, - &hfi1_sl2sc_attr_27.attr, - &hfi1_sl2sc_attr_28.attr, - &hfi1_sl2sc_attr_29.attr, - &hfi1_sl2sc_attr_30.attr, - &hfi1_sl2sc_attr_31.attr, +static struct attribute *port_sl2sc_attributes[] = { + &hfi1_sl2sc_attr_0.attr.attr, + &hfi1_sl2sc_attr_1.attr.attr, + &hfi1_sl2sc_attr_2.attr.attr, + &hfi1_sl2sc_attr_3.attr.attr, + &hfi1_sl2sc_attr_4.attr.attr, + &hfi1_sl2sc_attr_5.attr.attr, + &hfi1_sl2sc_attr_6.attr.attr, + &hfi1_sl2sc_attr_7.attr.attr, + &hfi1_sl2sc_attr_8.attr.attr, + &hfi1_sl2sc_attr_9.attr.attr, + &hfi1_sl2sc_attr_10.attr.attr, + &hfi1_sl2sc_attr_11.attr.attr, + &hfi1_sl2sc_attr_12.attr.attr, + &hfi1_sl2sc_attr_13.attr.attr, + &hfi1_sl2sc_attr_14.attr.attr, + &hfi1_sl2sc_attr_15.attr.attr, + &hfi1_sl2sc_attr_16.attr.attr, + &hfi1_sl2sc_attr_17.attr.attr, + &hfi1_sl2sc_attr_18.attr.attr, + &hfi1_sl2sc_attr_19.attr.attr, + &hfi1_sl2sc_attr_20.attr.attr, + &hfi1_sl2sc_attr_21.attr.attr, + &hfi1_sl2sc_attr_22.attr.attr, + &hfi1_sl2sc_attr_23.attr.attr, + &hfi1_sl2sc_attr_24.attr.attr, + &hfi1_sl2sc_attr_25.attr.attr, + &hfi1_sl2sc_attr_26.attr.attr, + &hfi1_sl2sc_attr_27.attr.attr, + &hfi1_sl2sc_attr_28.attr.attr, + &hfi1_sl2sc_attr_29.attr.attr, + &hfi1_sl2sc_attr_30.attr.attr, + &hfi1_sl2sc_attr_31.attr.attr, NULL };
-static ssize_t sl2sc_attr_show(struct kobject *kobj, struct attribute *attr, - char *buf) -{ - struct hfi1_sl2sc_attr *sattr = - container_of(attr, struct hfi1_sl2sc_attr, attr); - struct hfi1_pportdata *ppd = - container_of(kobj, struct hfi1_pportdata, sl2sc_kobj); - struct hfi1_ibport *ibp = &ppd->ibport_data; - - return sysfs_emit(buf, "%u\n", ibp->sl_to_sc[sattr->sl]); -} - -static const struct sysfs_ops hfi1_sl2sc_ops = { - .show = sl2sc_attr_show, -}; - -static struct kobj_type hfi1_sl2sc_ktype = { - .release = port_release, - .sysfs_ops = &hfi1_sl2sc_ops, - .default_attrs = sl2sc_default_attributes +static const struct attribute_group port_sl2sc_group = { + .name = "sl2sc", + .attrs = port_sl2sc_attributes, };
/* End sl2sc */
/* Start vl2mtu */
-#define HFI1_VL2MTU_ATTR(N) \ - static struct hfi1_vl2mtu_attr hfi1_vl2mtu_attr_##N = { \ - .attr = { .name = __stringify(N), .mode = 0444 }, \ - .vl = N \ - } - struct hfi1_vl2mtu_attr { - struct attribute attr; + struct ib_port_attribute attr; int vl; };
+static ssize_t vl2mtu_attr_show(struct ib_device *ibdev, u32 port_num, + struct ib_port_attribute *attr, char *buf) +{ + struct hfi1_vl2mtu_attr *vlattr = + container_of(attr, struct hfi1_vl2mtu_attr, attr); + struct hfi1_devdata *dd = dd_from_ibdev(ibdev); + + return sysfs_emit(buf, "%u\n", dd->vld[vlattr->vl].mtu); +} + +#define HFI1_VL2MTU_ATTR(N) \ + static struct hfi1_vl2mtu_attr hfi1_vl2mtu_attr_##N = { \ + .attr = __ATTR(N, 0444, vl2mtu_attr_show, NULL), \ + .vl = N, \ + } + HFI1_VL2MTU_ATTR(0); HFI1_VL2MTU_ATTR(1); HFI1_VL2MTU_ATTR(2); @@ -446,46 +413,29 @@ HFI1_VL2MTU_ATTR(13); HFI1_VL2MTU_ATTR(14); HFI1_VL2MTU_ATTR(15);
-static struct attribute *vl2mtu_default_attributes[] = { - &hfi1_vl2mtu_attr_0.attr, - &hfi1_vl2mtu_attr_1.attr, - &hfi1_vl2mtu_attr_2.attr, - &hfi1_vl2mtu_attr_3.attr, - &hfi1_vl2mtu_attr_4.attr, - &hfi1_vl2mtu_attr_5.attr, - &hfi1_vl2mtu_attr_6.attr, - &hfi1_vl2mtu_attr_7.attr, - &hfi1_vl2mtu_attr_8.attr, - &hfi1_vl2mtu_attr_9.attr, - &hfi1_vl2mtu_attr_10.attr, - &hfi1_vl2mtu_attr_11.attr, - &hfi1_vl2mtu_attr_12.attr, - &hfi1_vl2mtu_attr_13.attr, - &hfi1_vl2mtu_attr_14.attr, - &hfi1_vl2mtu_attr_15.attr, +static struct attribute *port_vl2mtu_attributes[] = { + &hfi1_vl2mtu_attr_0.attr.attr, + &hfi1_vl2mtu_attr_1.attr.attr, + &hfi1_vl2mtu_attr_2.attr.attr, + &hfi1_vl2mtu_attr_3.attr.attr, + &hfi1_vl2mtu_attr_4.attr.attr, + &hfi1_vl2mtu_attr_5.attr.attr, + &hfi1_vl2mtu_attr_6.attr.attr, + &hfi1_vl2mtu_attr_7.attr.attr, + &hfi1_vl2mtu_attr_8.attr.attr, + &hfi1_vl2mtu_attr_9.attr.attr, + &hfi1_vl2mtu_attr_10.attr.attr, + &hfi1_vl2mtu_attr_11.attr.attr, + &hfi1_vl2mtu_attr_12.attr.attr, + &hfi1_vl2mtu_attr_13.attr.attr, + &hfi1_vl2mtu_attr_14.attr.attr, + &hfi1_vl2mtu_attr_15.attr.attr, NULL };
-static ssize_t vl2mtu_attr_show(struct kobject *kobj, struct attribute *attr, - char *buf) -{ - struct hfi1_vl2mtu_attr *vlattr = - container_of(attr, struct hfi1_vl2mtu_attr, attr); - struct hfi1_pportdata *ppd = - container_of(kobj, struct hfi1_pportdata, vl2mtu_kobj); - struct hfi1_devdata *dd = ppd->dd; - - return sysfs_emit(buf, "%u\n", dd->vld[vlattr->vl].mtu); -} - -static const struct sysfs_ops hfi1_vl2mtu_ops = { - .show = vl2mtu_attr_show, -}; - -static struct kobj_type hfi1_vl2mtu_ktype = { - .release = port_release, - .sysfs_ops = &hfi1_vl2mtu_ops, - .default_attrs = vl2mtu_default_attributes +static const struct attribute_group port_vl2mtu_group = { + .name = "vl2mtu", + .attrs = port_vl2mtu_attributes, };
/* end of per-port file structures and support code */ @@ -649,100 +599,18 @@ const struct attribute_group ib_hfi1_attr_group = { .attrs = hfi1_attributes, };
+static const struct attribute_group *hfi1_port_groups[] = { + &port_cc_group, + &port_sc2vl_group, + &port_sl2sc_group, + &port_vl2mtu_group, + NULL, +}; + int hfi1_create_port_files(struct ib_device *ibdev, u32 port_num, struct kobject *kobj) { - struct hfi1_pportdata *ppd; - struct hfi1_devdata *dd = dd_from_ibdev(ibdev); - int ret; - - if (!port_num || port_num > dd->num_pports) { - dd_dev_err(dd, - "Skipping infiniband class with invalid port %u\n", - port_num); - return -ENODEV; - } - ppd = &dd->pport[port_num - 1]; - - ret = kobject_init_and_add(&ppd->sc2vl_kobj, &hfi1_sc2vl_ktype, kobj, - "sc2vl"); - if (ret) { - dd_dev_err(dd, - "Skipping sc2vl sysfs info, (err %d) port %u\n", - ret, port_num); - /* - * Based on the documentation for kobject_init_and_add(), the - * caller should call kobject_put even if this call fails. - */ - goto bail_sc2vl; - } - kobject_uevent(&ppd->sc2vl_kobj, KOBJ_ADD); - - ret = kobject_init_and_add(&ppd->sl2sc_kobj, &hfi1_sl2sc_ktype, kobj, - "sl2sc"); - if (ret) { - dd_dev_err(dd, - "Skipping sl2sc sysfs info, (err %d) port %u\n", - ret, port_num); - goto bail_sl2sc; - } - kobject_uevent(&ppd->sl2sc_kobj, KOBJ_ADD); - - ret = kobject_init_and_add(&ppd->vl2mtu_kobj, &hfi1_vl2mtu_ktype, kobj, - "vl2mtu"); - if (ret) { - dd_dev_err(dd, - "Skipping vl2mtu sysfs info, (err %d) port %u\n", - ret, port_num); - goto bail_vl2mtu; - } - kobject_uevent(&ppd->vl2mtu_kobj, KOBJ_ADD); - - ret = kobject_init_and_add(&ppd->pport_cc_kobj, &port_cc_ktype, - kobj, "CCMgtA"); - if (ret) { - dd_dev_err(dd, - "Skipping Congestion Control sysfs info, (err %d) port %u\n", - ret, port_num); - goto bail_cc; - } - - kobject_uevent(&ppd->pport_cc_kobj, KOBJ_ADD); - - ret = sysfs_create_bin_file(&ppd->pport_cc_kobj, &cc_setting_bin_attr); - if (ret) { - dd_dev_err(dd, - "Skipping Congestion Control setting sysfs info, (err %d) port %u\n", - ret, port_num); - goto bail_cc; - } - - ret = sysfs_create_bin_file(&ppd->pport_cc_kobj, &cc_table_bin_attr); - if (ret) { - dd_dev_err(dd, - "Skipping Congestion Control table sysfs info, (err %d) port %u\n", - ret, port_num); - goto bail_cc_entry_bin; - } - - dd_dev_info(dd, - "Congestion Control Agent enabled for port %d\n", - port_num); - - return 0; - -bail_cc_entry_bin: - sysfs_remove_bin_file(&ppd->pport_cc_kobj, - &cc_setting_bin_attr); -bail_cc: - kobject_put(&ppd->pport_cc_kobj); -bail_vl2mtu: - kobject_put(&ppd->vl2mtu_kobj); -bail_sl2sc: - kobject_put(&ppd->sl2sc_kobj); -bail_sc2vl: - kobject_put(&ppd->sc2vl_kobj); - return ret; + return ib_port_sysfs_create_groups(ibdev, port_num, hfi1_port_groups); }
struct sde_attribute { @@ -868,23 +736,13 @@ int hfi1_verbs_register_sysfs(struct hfi1_devdata *dd) */ void hfi1_verbs_unregister_sysfs(struct hfi1_devdata *dd) { - struct hfi1_pportdata *ppd; int i;
/* Unwind operations in hfi1_verbs_register_sysfs() */ for (i = 0; i < dd->num_sdma; i++) kobject_put(&dd->per_sdma[i].kobj);
- for (i = 0; i < dd->num_pports; i++) { - ppd = &dd->pport[i]; - - sysfs_remove_bin_file(&ppd->pport_cc_kobj, - &cc_setting_bin_attr); - sysfs_remove_bin_file(&ppd->pport_cc_kobj, - &cc_table_bin_attr); - kobject_put(&ppd->pport_cc_kobj); - kobject_put(&ppd->vl2mtu_kobj); - kobject_put(&ppd->sl2sc_kobj); - kobject_put(&ppd->sc2vl_kobj); - } + for (i = 0; i < dd->num_pports; i++) + ib_port_sysfs_remove_groups(&dd->verbs_dev.rdi.ibdev, i + 1, + hfi1_port_groups); }
From: Daniel Borkmann daniel@iogearbox.net
[ Upstream commit 28131e9d933339a92f78e7ab6429f4aaaa07061c ]
syzbot reported a shift-out-of-bounds that KUBSAN observed in the interpreter:
[...] UBSAN: shift-out-of-bounds in kernel/bpf/core.c:1420:2 shift exponent 255 is too large for 64-bit type 'long long unsigned int' CPU: 1 PID: 11097 Comm: syz-executor.4 Not tainted 5.12.0-rc2-syzkaller #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 Call Trace: __dump_stack lib/dump_stack.c:79 [inline] dump_stack+0x141/0x1d7 lib/dump_stack.c:120 ubsan_epilogue+0xb/0x5a lib/ubsan.c:148 __ubsan_handle_shift_out_of_bounds.cold+0xb1/0x181 lib/ubsan.c:327 ___bpf_prog_run.cold+0x19/0x56c kernel/bpf/core.c:1420 __bpf_prog_run32+0x8f/0xd0 kernel/bpf/core.c:1735 bpf_dispatcher_nop_func include/linux/bpf.h:644 [inline] bpf_prog_run_pin_on_cpu include/linux/filter.h:624 [inline] bpf_prog_run_clear_cb include/linux/filter.h:755 [inline] run_filter+0x1a1/0x470 net/packet/af_packet.c:2031 packet_rcv+0x313/0x13e0 net/packet/af_packet.c:2104 dev_queue_xmit_nit+0x7c2/0xa90 net/core/dev.c:2387 xmit_one net/core/dev.c:3588 [inline] dev_hard_start_xmit+0xad/0x920 net/core/dev.c:3609 __dev_queue_xmit+0x2121/0x2e00 net/core/dev.c:4182 __bpf_tx_skb net/core/filter.c:2116 [inline] __bpf_redirect_no_mac net/core/filter.c:2141 [inline] __bpf_redirect+0x548/0xc80 net/core/filter.c:2164 ____bpf_clone_redirect net/core/filter.c:2448 [inline] bpf_clone_redirect+0x2ae/0x420 net/core/filter.c:2420 ___bpf_prog_run+0x34e1/0x77d0 kernel/bpf/core.c:1523 __bpf_prog_run512+0x99/0xe0 kernel/bpf/core.c:1737 bpf_dispatcher_nop_func include/linux/bpf.h:644 [inline] bpf_test_run+0x3ed/0xc50 net/bpf/test_run.c:50 bpf_prog_test_run_skb+0xabc/0x1c50 net/bpf/test_run.c:582 bpf_prog_test_run kernel/bpf/syscall.c:3127 [inline] __do_sys_bpf+0x1ea9/0x4f00 kernel/bpf/syscall.c:4406 do_syscall_64+0x2d/0x70 arch/x86/entry/common.c:46 entry_SYSCALL_64_after_hwframe+0x44/0xae [...]
Generally speaking, KUBSAN reports from the kernel should be fixed. However, in case of BPF, this particular report caused concerns since the large shift is not wrong from BPF point of view, just undefined. In the verifier, K-based shifts that are >= {64,32} (depending on the bitwidth of the instruction) are already rejected. The register-based cases were not given their content might not be known at verification time. Ideas such as verifier instruction rewrite with an additional AND instruction for the source register were brought up, but regularly rejected due to the additional runtime overhead they incur.
As Edward Cree rightly put it:
Shifts by more than insn bitness are legal in the BPF ISA; they are implementation-defined behaviour [of the underlying architecture], rather than UB, and have been made legal for performance reasons. Each of the JIT backends compiles the BPF shift operations to machine instructions which produce implementation-defined results in such a case; the resulting contents of the register may be arbitrary but program behaviour as a whole remains defined.
Guard checks in the fast path (i.e. affecting JITted code) will thus not be accepted.
The case of division by zero is not truly analogous here, as division instructions on many of the JIT-targeted architectures will raise a machine exception / fault on division by zero, whereas (to the best of my knowledge) none will do so on an out-of-bounds shift.
Given the KUBSAN report only affects the BPF interpreter, but not JITs, one solution is to add the ANDs with 63 or 31 into ___bpf_prog_run(). That would make the shifts defined, and thus shuts up KUBSAN, and the compiler would optimize out the AND on any CPU that interprets the shift amounts modulo the width anyway (e.g., confirmed from disassembly that on x86-64 and arm64 the generated interpreter code is the same before and after this fix).
The BPF interpreter is slow path, and most likely compiled out anyway as distros select BPF_JIT_ALWAYS_ON to avoid speculative execution of BPF instructions by the interpreter. Given the main argument was to avoid sacrificing performance, the fact that the AND is optimized away from compiler for mainstream archs helps as well as a solution moving forward. Also add a comment on LSH/RSH/ARSH translation for JIT authors to provide guidance when they see the ___bpf_prog_run() interpreter code and use it as a model for a new JIT backend.
Reported-by: syzbot+bed360704c521841c85d@syzkaller.appspotmail.com Reported-by: Kurt Manucredo fuzzybritches0@gmail.com Signed-off-by: Eric Biggers ebiggers@kernel.org Co-developed-by: Eric Biggers ebiggers@kernel.org Signed-off-by: Daniel Borkmann daniel@iogearbox.net Acked-by: Alexei Starovoitov ast@kernel.org Acked-by: Andrii Nakryiko andrii@kernel.org Tested-by: syzbot+bed360704c521841c85d@syzkaller.appspotmail.com Cc: Edward Cree ecree.xilinx@gmail.com Link: https://lore.kernel.org/bpf/0000000000008f912605bd30d5d7@google.com Link: https://lore.kernel.org/bpf/bac16d8d-c174-bdc4-91bd-bfa62b410190@gmail.com Signed-off-by: Sasha Levin sashal@kernel.org --- kernel/bpf/core.c | 61 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 43 insertions(+), 18 deletions(-)
diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c index 5e31ee9f7512..034ad93a1ad7 100644 --- a/kernel/bpf/core.c +++ b/kernel/bpf/core.c @@ -1392,29 +1392,54 @@ static u64 ___bpf_prog_run(u64 *regs, const struct bpf_insn *insn) select_insn: goto *jumptable[insn->code];
- /* ALU */ -#define ALU(OPCODE, OP) \ - ALU64_##OPCODE##_X: \ - DST = DST OP SRC; \ - CONT; \ - ALU_##OPCODE##_X: \ - DST = (u32) DST OP (u32) SRC; \ - CONT; \ - ALU64_##OPCODE##_K: \ - DST = DST OP IMM; \ - CONT; \ - ALU_##OPCODE##_K: \ - DST = (u32) DST OP (u32) IMM; \ + /* Explicitly mask the register-based shift amounts with 63 or 31 + * to avoid undefined behavior. Normally this won't affect the + * generated code, for example, in case of native 64 bit archs such + * as x86-64 or arm64, the compiler is optimizing the AND away for + * the interpreter. In case of JITs, each of the JIT backends compiles + * the BPF shift operations to machine instructions which produce + * implementation-defined results in such a case; the resulting + * contents of the register may be arbitrary, but program behaviour + * as a whole remains defined. In other words, in case of JIT backends, + * the AND must /not/ be added to the emitted LSH/RSH/ARSH translation. + */ + /* ALU (shifts) */ +#define SHT(OPCODE, OP) \ + ALU64_##OPCODE##_X: \ + DST = DST OP (SRC & 63); \ + CONT; \ + ALU_##OPCODE##_X: \ + DST = (u32) DST OP ((u32) SRC & 31); \ + CONT; \ + ALU64_##OPCODE##_K: \ + DST = DST OP IMM; \ + CONT; \ + ALU_##OPCODE##_K: \ + DST = (u32) DST OP (u32) IMM; \ + CONT; + /* ALU (rest) */ +#define ALU(OPCODE, OP) \ + ALU64_##OPCODE##_X: \ + DST = DST OP SRC; \ + CONT; \ + ALU_##OPCODE##_X: \ + DST = (u32) DST OP (u32) SRC; \ + CONT; \ + ALU64_##OPCODE##_K: \ + DST = DST OP IMM; \ + CONT; \ + ALU_##OPCODE##_K: \ + DST = (u32) DST OP (u32) IMM; \ CONT; - ALU(ADD, +) ALU(SUB, -) ALU(AND, &) ALU(OR, |) - ALU(LSH, <<) - ALU(RSH, >>) ALU(XOR, ^) ALU(MUL, *) + SHT(LSH, <<) + SHT(RSH, >>) +#undef SHT #undef ALU ALU_NEG: DST = (u32) -DST; @@ -1439,13 +1464,13 @@ static u64 ___bpf_prog_run(u64 *regs, const struct bpf_insn *insn) insn++; CONT; ALU_ARSH_X: - DST = (u64) (u32) (((s32) DST) >> SRC); + DST = (u64) (u32) (((s32) DST) >> (SRC & 31)); CONT; ALU_ARSH_K: DST = (u64) (u32) (((s32) DST) >> IMM); CONT; ALU64_ARSH_X: - (*(s64 *) &DST) >>= SRC; + (*(s64 *) &DST) >>= (SRC & 63); CONT; ALU64_ARSH_K: (*(s64 *) &DST) >>= IMM;
From: Pavel Skripkin paskripkin@gmail.com
[ Upstream commit 618f003199c6188e01472b03cdbba227f1dc5f24 ]
static int kthread(void *_create) will return -ENOMEM or -EINTR in case of internal failure or kthread_stop() call happens before threadfn call.
To prevent fancy error checking and make code more straightforward we moved all cleanup code out of kmmpd threadfn.
Also, dropped struct mmpd_data at all. Now struct super_block is a threadfn data and struct buffer_head embedded into struct ext4_sb_info.
Reported-by: syzbot+d9e482e303930fa4f6ff@syzkaller.appspotmail.com Signed-off-by: Pavel Skripkin paskripkin@gmail.com Link: https://lore.kernel.org/r/20210430185046.15742-1-paskripkin@gmail.com Signed-off-by: Theodore Ts'o tytso@mit.edu Signed-off-by: Sasha Levin sashal@kernel.org --- fs/ext4/ext4.h | 4 ++++ fs/ext4/mmp.c | 28 +++++++++++++--------------- fs/ext4/super.c | 10 ++++------ 3 files changed, 21 insertions(+), 21 deletions(-)
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 37002663d521..a179c0bbc12e 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -1488,6 +1488,7 @@ struct ext4_sb_info { struct kobject s_kobj; struct completion s_kobj_unregister; struct super_block *s_sb; + struct buffer_head *s_mmp_bh;
/* Journaling */ struct journal_s *s_journal; @@ -3720,6 +3721,9 @@ extern struct ext4_io_end_vec *ext4_last_io_end_vec(ext4_io_end_t *io_end); /* mmp.c */ extern int ext4_multi_mount_protect(struct super_block *, ext4_fsblk_t);
+/* mmp.c */ +extern void ext4_stop_mmpd(struct ext4_sb_info *sbi); + /* verity.c */ extern const struct fsverity_operations ext4_verityops;
diff --git a/fs/ext4/mmp.c b/fs/ext4/mmp.c index 68fbeedd627b..6cb598b549ca 100644 --- a/fs/ext4/mmp.c +++ b/fs/ext4/mmp.c @@ -127,9 +127,9 @@ void __dump_mmp_msg(struct super_block *sb, struct mmp_struct *mmp, */ static int kmmpd(void *data) { - struct super_block *sb = ((struct mmpd_data *) data)->sb; - struct buffer_head *bh = ((struct mmpd_data *) data)->bh; + struct super_block *sb = (struct super_block *) data; struct ext4_super_block *es = EXT4_SB(sb)->s_es; + struct buffer_head *bh = EXT4_SB(sb)->s_mmp_bh; struct mmp_struct *mmp; ext4_fsblk_t mmp_block; u32 seq = 0; @@ -245,12 +245,18 @@ static int kmmpd(void *data) retval = write_mmp_block(sb, bh);
exit_thread: - EXT4_SB(sb)->s_mmp_tsk = NULL; - kfree(data); - brelse(bh); return retval; }
+void ext4_stop_mmpd(struct ext4_sb_info *sbi) +{ + if (sbi->s_mmp_tsk) { + kthread_stop(sbi->s_mmp_tsk); + brelse(sbi->s_mmp_bh); + sbi->s_mmp_tsk = NULL; + } +} + /* * Get a random new sequence number but make sure it is not greater than * EXT4_MMP_SEQ_MAX. @@ -275,7 +281,6 @@ int ext4_multi_mount_protect(struct super_block *sb, struct ext4_super_block *es = EXT4_SB(sb)->s_es; struct buffer_head *bh = NULL; struct mmp_struct *mmp = NULL; - struct mmpd_data *mmpd_data; u32 seq; unsigned int mmp_check_interval = le16_to_cpu(es->s_mmp_update_interval); unsigned int wait_time = 0; @@ -364,24 +369,17 @@ int ext4_multi_mount_protect(struct super_block *sb, goto failed; }
- mmpd_data = kmalloc(sizeof(*mmpd_data), GFP_KERNEL); - if (!mmpd_data) { - ext4_warning(sb, "not enough memory for mmpd_data"); - goto failed; - } - mmpd_data->sb = sb; - mmpd_data->bh = bh; + EXT4_SB(sb)->s_mmp_bh = bh;
/* * Start a kernel thread to update the MMP block periodically. */ - EXT4_SB(sb)->s_mmp_tsk = kthread_run(kmmpd, mmpd_data, "kmmpd-%.*s", + EXT4_SB(sb)->s_mmp_tsk = kthread_run(kmmpd, sb, "kmmpd-%.*s", (int)sizeof(mmp->mmp_bdevname), bdevname(bh->b_bdev, mmp->mmp_bdevname)); if (IS_ERR(EXT4_SB(sb)->s_mmp_tsk)) { EXT4_SB(sb)->s_mmp_tsk = NULL; - kfree(mmpd_data); ext4_warning(sb, "Unable to create kmmpd thread for %s.", sb->s_id); goto failed; diff --git a/fs/ext4/super.c b/fs/ext4/super.c index d29f6aa7d96e..b6fe1a027c78 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -1245,8 +1245,8 @@ static void ext4_put_super(struct super_block *sb) ext4_xattr_destroy_cache(sbi->s_ea_block_cache); sbi->s_ea_block_cache = NULL;
- if (sbi->s_mmp_tsk) - kthread_stop(sbi->s_mmp_tsk); + ext4_stop_mmpd(sbi); + brelse(sbi->s_sbh); sb->s_fs_info = NULL; /* @@ -5186,8 +5186,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) failed_mount3: flush_work(&sbi->s_error_work); del_timer_sync(&sbi->s_err_report); - if (sbi->s_mmp_tsk) - kthread_stop(sbi->s_mmp_tsk); + ext4_stop_mmpd(sbi); failed_mount2: rcu_read_lock(); group_desc = rcu_dereference(sbi->s_group_desc); @@ -5989,8 +5988,7 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data) */ ext4_mark_recovery_complete(sb, es); } - if (sbi->s_mmp_tsk) - kthread_stop(sbi->s_mmp_tsk); + ext4_stop_mmpd(sbi); } else { /* Make sure we can mount this feature set readwrite */ if (ext4_has_feature_readonly(sb) ||
From: Jacob Keller jacob.e.keller@intel.com
[ Upstream commit 638a0c8c8861cb8a3b54203e632ea5dcc23d8ca5 ]
The entry for PTYPE 90 indicates that the payload is layer 3. This does not match the specification in the datasheet which indicates the packet is a MAC, IPv6, UDP packet, with a payload in layer 4.
Fix the lookup table to match the data sheet.
Signed-off-by: Jacob Keller jacob.e.keller@intel.com Tested-by: Tony Brelinski tonyx.brelinski@intel.com Signed-off-by: Tony Nguyen anthony.l.nguyen@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h b/drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h index 21329ed3087e..fc3b56c13786 100644 --- a/drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h +++ b/drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h @@ -744,7 +744,7 @@ static const struct ice_rx_ptype_decoded ice_ptype_lkup[] = { /* Non Tunneled IPv6 */ ICE_PTT(88, IP, IPV6, FRG, NONE, NONE, NOF, NONE, PAY3), ICE_PTT(89, IP, IPV6, NOF, NONE, NONE, NOF, NONE, PAY3), - ICE_PTT(90, IP, IPV6, NOF, NONE, NONE, NOF, UDP, PAY3), + ICE_PTT(90, IP, IPV6, NOF, NONE, NONE, NOF, UDP, PAY4), ICE_PTT_UNUSED_ENTRY(91), ICE_PTT(92, IP, IPV6, NOF, NONE, NONE, NOF, TCP, PAY4), ICE_PTT(93, IP, IPV6, NOF, NONE, NONE, NOF, SCTP, PAY4),
From: Jacob Keller jacob.e.keller@intel.com
[ Upstream commit 0c526d440f76676733cb470b454db9d5507a3a50 ]
The entry for PTYPE 2 in the ice_ptype_lkup table incorrectly states that this is an L2 packet with no payload. According to the datasheet, this PTYPE is actually unused and reserved.
Fix the lookup entry to indicate this is an unused entry that is reserved.
Signed-off-by: Jacob Keller jacob.e.keller@intel.com Tested-by: Tony Brelinski tonyx.brelinski@intel.com Signed-off-by: Tony Nguyen anthony.l.nguyen@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h b/drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h index fc3b56c13786..4238ab0433ee 100644 --- a/drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h +++ b/drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h @@ -630,7 +630,7 @@ static const struct ice_rx_ptype_decoded ice_ptype_lkup[] = { /* L2 Packet types */ ICE_PTT_UNUSED_ENTRY(0), ICE_PTT(1, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY2), - ICE_PTT(2, L2, NONE, NOF, NONE, NONE, NOF, NONE, NONE), + ICE_PTT_UNUSED_ENTRY(2), ICE_PTT_UNUSED_ENTRY(3), ICE_PTT_UNUSED_ENTRY(4), ICE_PTT_UNUSED_ENTRY(5),
From: Felix Fietkau nbd@nbd.name
[ Upstream commit ec8f1a90d006f7cedcf86ef19fd034a406a213d6 ]
Rely on the txs fixed-rate bit instead of info->control.rates
Signed-off-by: Felix Fietkau nbd@nbd.name Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/wireless/mediatek/mt76/mt7615/mac.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c index e2dcfee6be81..7bdf3378a4d1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c @@ -1235,22 +1235,20 @@ static bool mt7615_fill_txs(struct mt7615_dev *dev, struct mt7615_sta *sta, int first_idx = 0, last_idx; int i, idx, count; bool fixed_rate, ack_timeout; - bool probe, ampdu, cck = false; + bool ampdu, cck = false; bool rs_idx; u32 rate_set_tsf; u32 final_rate, final_rate_flags, final_nss, txs;
- fixed_rate = info->status.rates[0].count; - probe = !!(info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE); - txs = le32_to_cpu(txs_data[1]); - ampdu = !fixed_rate && (txs & MT_TXS1_AMPDU); + ampdu = txs & MT_TXS1_AMPDU;
txs = le32_to_cpu(txs_data[3]); count = FIELD_GET(MT_TXS3_TX_COUNT, txs); last_idx = FIELD_GET(MT_TXS3_LAST_TX_RATE, txs);
txs = le32_to_cpu(txs_data[0]); + fixed_rate = txs & MT_TXS0_FIXED_RATE; final_rate = FIELD_GET(MT_TXS0_TX_RATE, txs); ack_timeout = txs & MT_TXS0_ACK_TIMEOUT;
@@ -1272,7 +1270,7 @@ static bool mt7615_fill_txs(struct mt7615_dev *dev, struct mt7615_sta *sta,
first_idx = max_t(int, 0, last_idx - (count - 1) / MT7615_RATE_RETRY);
- if (fixed_rate && !probe) { + if (fixed_rate) { info->status.rates[0].count = count; i = 0; goto out;
From: Felix Fietkau nbd@nbd.name
[ Upstream commit 94e4f5794627a80ce036c35b32a9900daeb31be3 ]
Fixes AQL issues on full queues, especially with 802.3 encap offload
Signed-off-by: Felix Fietkau nbd@nbd.name Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/wireless/mediatek/mt76/dma.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c index 72b1cc0ecfda..e5c324dd24f9 100644 --- a/drivers/net/wireless/mediatek/mt76/dma.c +++ b/drivers/net/wireless/mediatek/mt76/dma.c @@ -349,6 +349,9 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q, struct sk_buff *skb, struct mt76_wcid *wcid, struct ieee80211_sta *sta) { + struct ieee80211_tx_status status = { + .sta = sta, + }; struct mt76_tx_info tx_info = { .skb = skb, }; @@ -360,11 +363,9 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q, u8 *txwi;
t = mt76_get_txwi(dev); - if (!t) { - hw = mt76_tx_status_get_hw(dev, skb); - ieee80211_free_txskb(hw, skb); - return -ENOMEM; - } + if (!t) + goto free_skb; + txwi = mt76_get_txwi_ptr(dev, t);
skb->prev = skb->next = NULL; @@ -427,8 +428,13 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q, } #endif
- dev_kfree_skb(tx_info.skb); mt76_put_txwi(dev, t); + +free_skb: + status.skb = tx_info.skb; + hw = mt76_tx_status_get_hw(dev, tx_info.skb); + ieee80211_tx_status_ext(hw, &status); + return ret; }
From: Jian Shen shenjian15@huawei.com
[ Upstream commit 2d8ea148e553e1dd4e80a87741abdfb229e2b323 ]
Th_strings arrays netdev_features_strings, tunable_strings, and phy_tunable_strings has been moved to file net/ethtool/common.c. So fixes the comment.
Signed-off-by: Jian Shen shenjian15@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- include/linux/netdev_features.h | 2 +- include/uapi/linux/ethtool.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/include/linux/netdev_features.h b/include/linux/netdev_features.h index 3de38d6a0aea..2c6b9e416225 100644 --- a/include/linux/netdev_features.h +++ b/include/linux/netdev_features.h @@ -93,7 +93,7 @@ enum {
/* * Add your fresh new feature above and remember to update - * netdev_features_strings[] in net/core/ethtool.c and maybe + * netdev_features_strings[] in net/ethtool/common.c and maybe * some feature mask #defines below. Please also describe it * in Documentation/networking/netdev-features.rst. */ diff --git a/include/uapi/linux/ethtool.h b/include/uapi/linux/ethtool.h index cfef6b08169a..67aa7134b301 100644 --- a/include/uapi/linux/ethtool.h +++ b/include/uapi/linux/ethtool.h @@ -233,7 +233,7 @@ enum tunable_id { ETHTOOL_PFC_PREVENTION_TOUT, /* timeout in msecs */ /* * Add your fresh new tunable attribute above and remember to update - * tunable_strings[] in net/core/ethtool.c + * tunable_strings[] in net/ethtool/common.c */ __ETHTOOL_TUNABLE_COUNT, }; @@ -297,7 +297,7 @@ enum phy_tunable_id { ETHTOOL_PHY_EDPD, /* * Add your fresh new phy tunable attribute above and remember to update - * phy_tunable_strings[] in net/core/ethtool.c + * phy_tunable_strings[] in net/ethtool/common.c */ __ETHTOOL_PHY_TUNABLE_COUNT, };
From: Yang Yingliang yangyingliang@huawei.com
[ Upstream commit b244163f2c45c12053cb0291c955f892e79ed8a9 ]
This node pointer is returned by of_parse_phandle() with refcount incremented in this function. of_node_put() on it before exiting this function.
Reported-by: Hulk Robot hulkci@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com Acked-by: Alex Elder elder@linaro.org Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ipa/ipa_main.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/net/ipa/ipa_main.c b/drivers/net/ipa/ipa_main.c index 9915603ed10b..c4ad5f20496e 100644 --- a/drivers/net/ipa/ipa_main.c +++ b/drivers/net/ipa/ipa_main.c @@ -529,6 +529,7 @@ static int ipa_firmware_load(struct device *dev) }
ret = of_address_to_resource(node, 0, &res); + of_node_put(node); if (ret) { dev_err(dev, "error %d getting "memory-region" resource\n", ret);
From: Yang Yingliang yangyingliang@huawei.com
[ Upstream commit 55d96f72e8ddc0a294e0b9c94016edbb699537e1 ]
When nla_put_u32() fails, 'ret' could be 0, it should return error code in tcf_del_walker().
Reported-by: Hulk Robot hulkci@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- net/sched/act_api.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/net/sched/act_api.c b/net/sched/act_api.c index f6d5755d669e..d17a66aab8ee 100644 --- a/net/sched/act_api.c +++ b/net/sched/act_api.c @@ -381,7 +381,8 @@ static int tcf_del_walker(struct tcf_idrinfo *idrinfo, struct sk_buff *skb, } mutex_unlock(&idrinfo->lock);
- if (nla_put_u32(skb, TCA_FCNT, n_i)) + ret = nla_put_u32(skb, TCA_FCNT, n_i); + if (ret) goto nla_put_failure; nla_nest_end(skb, nest);
From: Pavel Begunkov asml.silence@gmail.com
[ Upstream commit e6ab8991c5d0b0deae0961dc22c0edd1dee328f5 ]
WARNING: CPU: 1 PID: 11749 at fs/io-wq.c:244 io_wqe_wake_worker fs/io-wq.c:244 [inline] WARNING: CPU: 1 PID: 11749 at fs/io-wq.c:244 io_wqe_enqueue+0x7f6/0x910 fs/io-wq.c:751
A WARN_ON_ONCE() in io_wqe_wake_worker() can be triggered by a valid userspace setup. Replace it with pr_warn.
Reported-by: syzbot+ea2f1484cffe5109dc10@syzkaller.appspotmail.com Signed-off-by: Pavel Begunkov asml.silence@gmail.com Link: https://lore.kernel.org/r/f7ede342c3342c4c26668f5168e2993e38bbd99c.162394969... Signed-off-by: Jens Axboe axboe@kernel.dk Signed-off-by: Sasha Levin sashal@kernel.org --- fs/io-wq.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/fs/io-wq.c b/fs/io-wq.c index b3e8624a37d0..60f58efdb5f4 100644 --- a/fs/io-wq.c +++ b/fs/io-wq.c @@ -241,7 +241,8 @@ static void io_wqe_wake_worker(struct io_wqe *wqe, struct io_wqe_acct *acct) * Most likely an attempt to queue unbounded work on an io_wq that * wasn't setup with any unbounded workers. */ - WARN_ON_ONCE(!acct->max_workers); + if (unlikely(!acct->max_workers)) + pr_warn_once("io-wq is not configured for unbound workers");
rcu_read_lock(); ret = io_wqe_activate_free_worker(wqe); @@ -906,6 +907,8 @@ struct io_wq *io_wq_create(unsigned bounded, struct io_wq_data *data)
if (WARN_ON_ONCE(!data->free_work || !data->do_work)) return ERR_PTR(-EINVAL); + if (WARN_ON_ONCE(!bounded)) + return ERR_PTR(-EINVAL);
wq = kzalloc(sizeof(*wq), GFP_KERNEL); if (!wq)
From: "Stanley.Yang" Stanley.Yang@amd.com
[ Upstream commit 6ec598cc9dfbf40433e94a2ed1a622e3ef80268b ]
Signed-off-by: Stanley.Yang Stanley.Yang@amd.com Reviewed-by: Hawking Zhang Hawking.Zhang@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_umc.h | 5 +++++ drivers/gpu/drm/amd/amdgpu/umc_v8_7.c | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h index bbcccf53080d..e5a75fb788dd 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h @@ -21,6 +21,11 @@ #ifndef __AMDGPU_UMC_H__ #define __AMDGPU_UMC_H__
+/* + * (addr / 256) * 4096, the higher 26 bits in ErrorAddr + * is the index of 4KB block + */ +#define ADDR_OF_4KB_BLOCK(addr) (((addr) & ~0xffULL) << 4) /* * (addr / 256) * 8192, the higher 26 bits in ErrorAddr * is the index of 8KB block diff --git a/drivers/gpu/drm/amd/amdgpu/umc_v8_7.c b/drivers/gpu/drm/amd/amdgpu/umc_v8_7.c index 89d20adfa001..af59a35788e3 100644 --- a/drivers/gpu/drm/amd/amdgpu/umc_v8_7.c +++ b/drivers/gpu/drm/amd/amdgpu/umc_v8_7.c @@ -234,7 +234,7 @@ static void umc_v8_7_query_error_address(struct amdgpu_device *adev, err_addr &= ~((0x1ULL << lsb) - 1);
/* translate umc channel address to soc pa, 3 parts are included */ - retired_page = ADDR_OF_8KB_BLOCK(err_addr) | + retired_page = ADDR_OF_4KB_BLOCK(err_addr) | ADDR_OF_256B_BLOCK(channel_index) | OFFSET_IN_256B_BLOCK(err_addr);
From: xinhui pan xinhui.pan@amd.com
[ Upstream commit 56f221b6389e7ab99c30bbf01c71998ae92fc584 ]
To avoid any list corruption.
Signed-off-by: xinhui pan xinhui.pan@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 --- .../drm/amd/amdkfd/kfd_device_queue_manager.c | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 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 e9b3e2e32bf8..f0bad74af230 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c @@ -1709,7 +1709,7 @@ static int process_termination_cpsch(struct device_queue_manager *dqm, struct qcm_process_device *qpd) { int retval; - struct queue *q, *next; + struct queue *q; struct kernel_queue *kq, *kq_next; struct mqd_manager *mqd_mgr; struct device_process_node *cur, *next_dpn; @@ -1766,24 +1766,26 @@ static int process_termination_cpsch(struct device_queue_manager *dqm, qpd->reset_wavefronts = false; }
- dqm_unlock(dqm); - - /* Outside the DQM lock because under the DQM lock we can't do - * reclaim or take other locks that others hold while reclaiming. - */ - if (found) - kfd_dec_compute_active(dqm->dev); - /* Lastly, free mqd resources. * Do free_mqd() after dqm_unlock to avoid circular locking. */ - list_for_each_entry_safe(q, next, &qpd->queues_list, list) { + while (!list_empty(&qpd->queues_list)) { + q = list_first_entry(&qpd->queues_list, struct queue, list); mqd_mgr = dqm->mqd_mgrs[get_mqd_type_from_queue_type( q->properties.type)]; list_del(&q->list); qpd->queue_count--; + dqm_unlock(dqm); mqd_mgr->free_mqd(mqd_mgr, q->mqd, q->mqd_mem_obj); + dqm_lock(dqm); } + dqm_unlock(dqm); + + /* Outside the DQM lock because under the DQM lock we can't do + * reclaim or take other locks that others hold while reclaiming. + */ + if (found) + kfd_dec_compute_active(dqm->dev);
return retval; }
From: Evelyn Tsai evelyn.tsai@mediatek.com
[ Upstream commit 64cf5ad3c2fa841e4b416343a7ea69c63d60fa4e ]
Correct the bitfield which indicates TSSI on/off for MT7915D NIC.
Signed-off-by: Evelyn Tsai evelyn.tsai@mediatek.com Signed-off-by: Shayne Chen shayne.chen@mediatek.com Signed-off-by: Felix Fietkau nbd@nbd.name Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/wireless/mediatek/mt76/mt7915/eeprom.h | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.h b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.h index 033fb592bdf0..7896e983209a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.h @@ -99,12 +99,15 @@ static inline bool mt7915_tssi_enabled(struct mt7915_dev *dev, enum nl80211_band band) { u8 *eep = dev->mt76.eeprom.data; + u8 val = eep[MT_EE_WIFI_CONF + 7];
- /* TODO: DBDC */ - if (band == NL80211_BAND_5GHZ) - return eep[MT_EE_WIFI_CONF + 7] & MT_EE_WIFI_CONF7_TSSI0_5G; + if (band == NL80211_BAND_2GHZ) + return val & MT_EE_WIFI_CONF7_TSSI0_2G; + + if (dev->dbdc_support) + return val & MT_EE_WIFI_CONF7_TSSI1_5G; else - return eep[MT_EE_WIFI_CONF + 7] & MT_EE_WIFI_CONF7_TSSI0_2G; + return val & MT_EE_WIFI_CONF7_TSSI0_5G; }
extern const u8 mt7915_sku_group_len[MAX_SKU_RATE_GROUP_NUM];
From: Sean Wang sean.wang@mediatek.com
[ Upstream commit 7bf0a71e839822bb6ba04a6e163ad334314e2659 ]
To fix possibly the race to access register between the WiFi reset and the other context that is caused by explicitly cancelling ps_work and wake_work to break PM_STATE consistency.
Deep sleep would cause the hardware into the inactive state, so we forcely put device drv_own state before we start to reset.
The patch also ignore the reset request when the procedure is in progress to avoid the consecutive WiFi resets.
localhost ~ # [ 2932.073966] SError Interrupt on CPU7, code 0xbe000011 [ 2932.073967] CPU: 7 PID: 8761 Comm: kworker/u16:2 Not tainted 5.4.112 #30 [ 2932.073968] Hardware name: MediaTek Asurada rev1 board (DT) [ 2932.073968] Workqueue: phy0 ieee80211_reconfig_filter [mac80211] [ 2932.073969] pstate: 80400089 (Nzcv daIf +PAN -UAO) [ 2932.073969] pc : el1_irq+0x78/0x180 [ 2932.073970] lr : mt76_mmio_rmw+0x30/0x5c [mt76] [ 2932.073970] sp : ffffffc01142bad0 [ 2932.073970] x29: ffffffc01142bc00 x28: ffffff8f96fb1e00 [ 2932.073971] x27: ffffffd2cdc12138 x26: ffffffd2cdaeb018 [ 2932.073972] x25: 0000000000000000 x24: ffffff8fa8e14c08 [ 2932.073973] x23: 0000000080c00009 x22: ffffffd2a5603918 [ 2932.073974] x21: ffffffc01142bc10 x20: 0000007fffffffff [ 2932.073975] x19: 0000000000000000 x18: 0000000000000400 [ 2932.073975] x17: 0000000000000400 x16: ffffffd2cd2b87dc [ 2932.073976] x15: 0000000000000000 x14: 0000000000000000 [ 2932.073977] x13: 0000000000000001 x12: 0000000000000001 [ 2932.073978] x11: 0000000000000001 x10: 000000000010e000 [ 2932.073978] x9 : 0000000000000000 x8 : ffffffc013921404 [ 2932.073979] x7 : 000000b2b5593519 x6 : 0000000000300000 [ 2932.073980] x5 : 0000000000000000 x4 : ffffffc01142bbc8 [ 2932.073980] x3 : 00000000000001f0 x2 : 0000000000000000 [ 2932.073981] x1 : 0000000000021404 x0 : ffffff8fa8e12300 [ 2932.073982] Kernel panic - not syncing: Asynchronous SError Interrupt [ 2932.073983] CPU: 7 PID: 8761 Comm: kworker/u16:2 Not tainted 5.4.112 #30 [ 2932.073983] Hardware name: MediaTek Asurada rev1 board (DT) [ 2932.073984] Workqueue: phy0 ieee80211_reconfig_filter [mac80211] [ 2932.073984] Call trace: [ 2932.073985] dump_backtrace+0x0/0x14c [ 2932.073985] show_stack+0x20/0x2c [ 2932.073985] dump_stack+0xa0/0xf8 [ 2932.073986] panic+0x154/0x360 [ 2932.073986] test_taint+0x0/0x44 [ 2932.073986] arm64_serror_panic+0x78/0x84 [ 2932.073987] do_serror+0x0/0x118 [ 2932.073987] do_serror+0xa4/0x118 [ 2932.073987] el1_error+0x84/0xf8 [ 2932.073988] el1_irq+0x78/0x180 [ 2932.073988] mt76_mmio_rr+0x30/0xf0 [mt76] [ 2932.073988] mt76_mmio_rmw+0x30/0x5c [mt76] [ 2932.073989] mt7921_rmw+0x4c/0x5c [mt7921e] [ 2932.073989] mt7921_configure_filter+0x138/0x160 [mt7921e] [ 2932.073990] ieee80211_configure_filter+0x2f0/0x3e0 [mac80211] [ 2932.073990] ieee80211_reconfig_filter+0x1c/0x28 [mac80211] [ 2932.073990] process_one_work+0x208/0x3c8 [ 2932.073991] worker_thread+0x23c/0x3e8 [ 2932.073991] kthread+0x140/0x17c [ 2932.073992] ret_from_fork+0x10/0x18 [ 2932.074071] SMP: stopping secondary CPUs [ 2932.074071] Kernel Offset: 0x12bc800000 from 0xffffffc010000000 [ 2932.074072] PHYS_OFFSET: 0xfffffff180000000 [ 2932.074072] CPU features: 0x080026,2a80aa18 [ 2932.074072] Memory Limit: none
Co-developed-by: Lorenzo Bianconi lorenzo@kernel.org Signed-off-by: Lorenzo Bianconi lorenzo@kernel.org Signed-off-by: Sean Wang sean.wang@mediatek.com Signed-off-by: Felix Fietkau nbd@nbd.name Signed-off-by: Sasha Levin sashal@kernel.org --- .../net/wireless/mediatek/mt76/mt7921/mac.c | 21 +++++++++-------- .../net/wireless/mediatek/mt76/mt7921/mcu.c | 23 ++++++++++++++----- .../wireless/mediatek/mt76/mt7921/mt7921.h | 1 + 3 files changed, 30 insertions(+), 15 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c index decf2d5f0ce3..66a12eba32b6 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c @@ -1241,9 +1241,10 @@ mt7921_mac_reset(struct mt7921_dev *dev) mt76_worker_enable(&dev->mt76.tx_worker);
clear_bit(MT76_MCU_RESET, &dev->mphy.state); - clear_bit(MT76_STATE_PM, &dev->mphy.state);
- mt76_wr(dev, MT_WFDMA0_HOST_INT_ENA, 0); + mt76_wr(dev, MT_WFDMA0_HOST_INT_ENA, + MT_INT_RX_DONE_ALL | MT_INT_TX_DONE_ALL | + MT_INT_MCU_CMD); mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff);
err = mt7921_run_firmware(dev); @@ -1261,22 +1262,23 @@ mt7921_mac_reset(struct mt7921_dev *dev) /* system error recovery */ void mt7921_mac_reset_work(struct work_struct *work) { - struct ieee80211_hw *hw; - struct mt7921_dev *dev; + struct mt7921_dev *dev = container_of(work, struct mt7921_dev, + reset_work); + struct ieee80211_hw *hw = mt76_hw(dev); + struct mt76_connac_pm *pm = &dev->pm; int i;
- dev = container_of(work, struct mt7921_dev, reset_work); - hw = mt76_hw(dev); - dev_err(dev->mt76.dev, "chip reset\n"); ieee80211_stop_queues(hw);
cancel_delayed_work_sync(&dev->mphy.mac_work); - cancel_delayed_work_sync(&dev->pm.ps_work); - cancel_work_sync(&dev->pm.wake_work); + cancel_delayed_work_sync(&pm->ps_work); + cancel_work_sync(&pm->wake_work);
mutex_lock(&dev->mt76.mutex); for (i = 0; i < 10; i++) { + __mt7921_mcu_drv_pmctrl(dev); + if (!mt7921_mac_reset(dev)) break; } @@ -1297,6 +1299,7 @@ void mt7921_mac_reset_work(struct work_struct *work) ieee80211_iterate_active_interfaces(hw, IEEE80211_IFACE_ITER_RESUME_ALL, mt7921_vif_connect_iter, NULL); + mt76_connac_power_save_sched(&dev->mt76.phy, pm); }
void mt7921_reset(struct mt76_dev *mdev) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c index 67dc4b4cc094..ef3e454862ad 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c @@ -1288,17 +1288,12 @@ int mt7921_mcu_sta_add(struct mt7921_dev *dev, struct ieee80211_sta *sta, return mt76_connac_mcu_add_sta_cmd(&dev->mphy, &info); }
-int mt7921_mcu_drv_pmctrl(struct mt7921_dev *dev) +int __mt7921_mcu_drv_pmctrl(struct mt7921_dev *dev) { struct mt76_phy *mphy = &dev->mt76.phy; struct mt76_connac_pm *pm = &dev->pm; int i, err = 0;
- mutex_lock(&pm->mutex); - - if (!test_bit(MT76_STATE_PM, &mphy->state)) - goto out; - for (i = 0; i < MT7921_DRV_OWN_RETRY_COUNT; i++) { mt76_wr(dev, MT_CONN_ON_LPCTL, PCIE_LPCR_HOST_CLR_OWN); if (mt76_poll_msec(dev, MT_CONN_ON_LPCTL, @@ -1318,6 +1313,22 @@ int mt7921_mcu_drv_pmctrl(struct mt7921_dev *dev) pm->stats.last_wake_event = jiffies; pm->stats.doze_time += pm->stats.last_wake_event - pm->stats.last_doze_event; +out: + return err; +} + +int mt7921_mcu_drv_pmctrl(struct mt7921_dev *dev) +{ + struct mt76_phy *mphy = &dev->mt76.phy; + struct mt76_connac_pm *pm = &dev->pm; + int err = 0; + + mutex_lock(&pm->mutex); + + if (!test_bit(MT76_STATE_PM, &mphy->state)) + goto out; + + err = __mt7921_mcu_drv_pmctrl(dev); out: mutex_unlock(&pm->mutex);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h index 59862ea4951c..03bcb210c357 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h @@ -368,6 +368,7 @@ int mt7921_mcu_uni_bss_bcnft(struct mt7921_dev *dev, struct ieee80211_vif *vif, bool enable); int mt7921_mcu_set_bss_pm(struct mt7921_dev *dev, struct ieee80211_vif *vif, bool enable); +int __mt7921_mcu_drv_pmctrl(struct mt7921_dev *dev); int mt7921_mcu_drv_pmctrl(struct mt7921_dev *dev); int mt7921_mcu_fw_pmctrl(struct mt7921_dev *dev); void mt7921_pm_wake_work(struct work_struct *work);
From: Lorenzo Bianconi lorenzo@kernel.org
[ Upstream commit 01f7da40917923bf9d8fd8d5c9a6ed646004e47c ]
This patch fixes a mcu hang during device probe on Marvell ESPRESSObin after a hot reboot.
Signed-off-by: Lorenzo Bianconi lorenzo@kernel.org Signed-off-by: Felix Fietkau nbd@nbd.name Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/wireless/mediatek/mt76/mt7921/dma.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/dma.c b/drivers/net/wireless/mediatek/mt76/mt7921/dma.c index 71e664ee7652..a70f0bd875f8 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/dma.c @@ -402,6 +402,10 @@ int mt7921_dma_init(struct mt7921_dev *dev) if (ret) return ret;
+ ret = mt7921_wfsys_reset(dev); + if (ret) + return ret; + /* init tx queue */ ret = mt7921_init_tx_queues(&dev->phy, MT7921_TXQ_BAND0, MT7921_TX_RING_SIZE);
From: Lorenzo Bianconi lorenzo@kernel.org
[ Upstream commit a60951d4faa0ef2e475797dd217c2eaee32ed1c2 ]
Enable wep key hw offloading for sta mode. This patch fixes WoW support for wep connections.
Tested-by: Deren.Wu deren.wu@mediatek.com Signed-off-by: Lorenzo Bianconi lorenzo@kernel.org Signed-off-by: Felix Fietkau nbd@nbd.name Signed-off-by: Sasha Levin sashal@kernel.org --- .../net/wireless/mediatek/mt76/mt7921/main.c | 22 ++++++++++++++----- .../wireless/mediatek/mt76/mt7921/mt7921.h | 2 ++ 2 files changed, 19 insertions(+), 5 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c index 97a0ef331ac3..032122317855 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c @@ -429,6 +429,10 @@ static int mt7921_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIE; wcid_keyidx = &wcid->hw_key_idx2; break; + case WLAN_CIPHER_SUITE_WEP40: + case WLAN_CIPHER_SUITE_WEP104: + if (!mvif->wep_sta) + return -EOPNOTSUPP; case WLAN_CIPHER_SUITE_TKIP: case WLAN_CIPHER_SUITE_CCMP: case WLAN_CIPHER_SUITE_CCMP_256: @@ -436,8 +440,6 @@ static int mt7921_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, case WLAN_CIPHER_SUITE_GCMP_256: case WLAN_CIPHER_SUITE_SMS4: break; - case WLAN_CIPHER_SUITE_WEP40: - case WLAN_CIPHER_SUITE_WEP104: default: return -EOPNOTSUPP; } @@ -455,6 +457,12 @@ static int mt7921_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, cmd == SET_KEY ? key : NULL);
err = mt7921_mcu_add_key(dev, vif, msta, key, cmd); + if (err) + goto out; + + if (key->cipher == WLAN_CIPHER_SUITE_WEP104 || + key->cipher == WLAN_CIPHER_SUITE_WEP40) + err = mt7921_mcu_add_key(dev, vif, mvif->wep_sta, key, cmd); out: mt7921_mutex_release(dev);
@@ -661,9 +669,12 @@ int mt7921_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, if (ret) return ret;
- if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) - mt76_connac_mcu_uni_add_bss(&dev->mphy, vif, &mvif->sta.wcid, - true); + if (vif->type == NL80211_IFTYPE_STATION) { + mvif->wep_sta = msta; + if (!sta->tdls) + mt76_connac_mcu_uni_add_bss(&dev->mphy, vif, + &mvif->sta.wcid, true); + }
mt7921_mac_wtbl_update(dev, idx, MT_WTBL_UPDATE_ADM_COUNT_CLEAR); @@ -693,6 +704,7 @@ void mt7921_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, if (vif->type == NL80211_IFTYPE_STATION) { struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
+ mvif->wep_sta = NULL; ewma_rssi_init(&mvif->rssi); if (!sta->tdls) mt76_connac_mcu_uni_add_bss(&dev->mphy, vif, diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h index 03bcb210c357..434601388a6c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h @@ -100,6 +100,8 @@ struct mt7921_vif { struct mt76_vif mt76; /* must be first */
struct mt7921_sta sta; + struct mt7921_sta *wep_sta; + struct mt7921_phy *phy;
struct ewma_rssi rssi;
From: Lorenzo Bianconi lorenzo@kernel.org
[ Upstream commit 82453b1cbf9ef166364c12b5464251f16bac5f51 ]
Fix UC entry is being overwritten by BC entry
Tested-by: Deren Wu deren.wu@mediatek.com Co-developed-by: Deren Wu deren.wu@mediatek.com Signed-off-by: Deren Wu deren.wu@mediatek.com Signed-off-by: Lorenzo Bianconi lorenzo@kernel.org Signed-off-by: Felix Fietkau nbd@nbd.name Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/wireless/mediatek/mt76/mt7615/mcu.c | 8 +++++--- drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c | 10 ++++++---- drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h | 1 + drivers/net/wireless/mediatek/mt76/mt7921/mcu.c | 1 + 4 files changed, 13 insertions(+), 7 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index aa42af9ebfd6..de7126d45aa6 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -1120,12 +1120,14 @@ mt7615_mcu_sta_rx_ba(struct mt7615_dev *dev,
static int __mt7615_mcu_add_sta(struct mt76_phy *phy, struct ieee80211_vif *vif, - struct ieee80211_sta *sta, bool enable, int cmd) + struct ieee80211_sta *sta, bool enable, int cmd, + bool offload_fw) { struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; struct mt76_sta_cmd_info info = { .sta = sta, .vif = vif, + .offload_fw = offload_fw, .enable = enable, .cmd = cmd, }; @@ -1139,7 +1141,7 @@ mt7615_mcu_add_sta(struct mt7615_phy *phy, struct ieee80211_vif *vif, struct ieee80211_sta *sta, bool enable) { return __mt7615_mcu_add_sta(phy->mt76, vif, sta, enable, - MCU_EXT_CMD_STA_REC_UPDATE); + MCU_EXT_CMD_STA_REC_UPDATE, false); }
static const struct mt7615_mcu_ops sta_update_ops = { @@ -1280,7 +1282,7 @@ mt7615_mcu_uni_add_sta(struct mt7615_phy *phy, struct ieee80211_vif *vif, struct ieee80211_sta *sta, bool enable) { return __mt7615_mcu_add_sta(phy->mt76, vif, sta, enable, - MCU_UNI_CMD_STA_REC_UPDATE); + MCU_UNI_CMD_STA_REC_UPDATE, true); }
static int diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c index 619561606f96..f975f6d98a98 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c @@ -841,10 +841,12 @@ int mt76_connac_mcu_add_sta_cmd(struct mt76_phy *phy, if (IS_ERR(skb)) return PTR_ERR(skb);
- mt76_connac_mcu_sta_basic_tlv(skb, info->vif, info->sta, info->enable); - if (info->enable && info->sta) - mt76_connac_mcu_sta_tlv(phy, skb, info->sta, info->vif, - info->rcpi); + if (info->sta || !info->offload_fw) + mt76_connac_mcu_sta_basic_tlv(skb, info->vif, info->sta, + info->enable); + if (info->sta && info->enable) + mt76_connac_mcu_sta_tlv(phy, skb, info->sta, + info->vif, info->rcpi);
sta_wtbl = mt76_connac_mcu_add_tlv(skb, STA_REC_WTBL, sizeof(struct tlv)); diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h index a1096861d04a..61bed6e89427 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h @@ -891,6 +891,7 @@ struct mt76_sta_cmd_info {
struct ieee80211_vif *vif;
+ bool offload_fw; bool enable; int cmd; u8 rcpi; diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c index ef3e454862ad..23b337b43874 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c @@ -1278,6 +1278,7 @@ int mt7921_mcu_sta_add(struct mt7921_dev *dev, struct ieee80211_sta *sta, .vif = vif, .enable = enable, .cmd = MCU_UNI_CMD_STA_REC_UPDATE, + .offload_fw = true, .rcpi = to_rcpi(rssi), }; struct mt7921_sta *msta;
From: Sean Wang sean.wang@mediatek.com
[ Upstream commit abded041a07467c2f3dfe10afd9ea10572c63cc9 ]
Maximum interval (in seconds) for schedule scan plan supported by the offload firmware can be U16_MAX.
Signed-off-by: Sean Wang sean.wang@mediatek.com Signed-off-by: Felix Fietkau nbd@nbd.name Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/wireless/mediatek/mt76/mt7615/init.c | 2 +- drivers/net/wireless/mediatek/mt76/mt76_connac.h | 3 ++- drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h | 2 +- drivers/net/wireless/mediatek/mt76/mt7921/init.c | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/init.c b/drivers/net/wireless/mediatek/mt76/mt7615/init.c index d20f05a7717d..0d01fd3c77b5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/init.c @@ -362,7 +362,7 @@ mt7615_init_wiphy(struct ieee80211_hw *hw) wiphy->reg_notifier = mt7615_regd_notifier;
wiphy->max_sched_scan_plan_interval = - MT76_CONNAC_MAX_SCHED_SCAN_INTERVAL; + MT76_CONNAC_MAX_TIME_SCHED_SCAN_INTERVAL; wiphy->max_sched_scan_ie_len = IEEE80211_MAX_DATA_LEN; wiphy->max_scan_ie_len = MT76_CONNAC_SCAN_IE_LEN; wiphy->max_sched_scan_ssids = MT76_CONNAC_MAX_SCHED_SCAN_SSID; diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac.h b/drivers/net/wireless/mediatek/mt76/mt76_connac.h index 6c889b90fd12..5b50d29c1cb6 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac.h +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac.h @@ -7,7 +7,8 @@ #include "mt76.h"
#define MT76_CONNAC_SCAN_IE_LEN 600 -#define MT76_CONNAC_MAX_SCHED_SCAN_INTERVAL 10 +#define MT76_CONNAC_MAX_NUM_SCHED_SCAN_INTERVAL 10 +#define MT76_CONNAC_MAX_TIME_SCHED_SCAN_INTERVAL U16_MAX #define MT76_CONNAC_MAX_SCHED_SCAN_SSID 10 #define MT76_CONNAC_MAX_SCAN_MATCH 16
diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h index 61bed6e89427..6093f39ea1dc 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h @@ -762,7 +762,7 @@ struct mt76_connac_sched_scan_req { u8 intervals_num; u8 scan_func; /* MT7663: BIT(0) eable random mac address */ struct mt76_connac_mcu_scan_channel channels[64]; - __le16 intervals[MT76_CONNAC_MAX_SCHED_SCAN_INTERVAL]; + __le16 intervals[MT76_CONNAC_MAX_NUM_SCHED_SCAN_INTERVAL]; union { struct { u8 random_mac[ETH_ALEN]; diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/init.c b/drivers/net/wireless/mediatek/mt76/mt7921/init.c index 1763ea0614ce..bd002b4247c7 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/init.c @@ -92,7 +92,7 @@ mt7921_init_wiphy(struct ieee80211_hw *hw) wiphy->max_scan_ie_len = MT76_CONNAC_SCAN_IE_LEN; wiphy->max_scan_ssids = 4; wiphy->max_sched_scan_plan_interval = - MT76_CONNAC_MAX_SCHED_SCAN_INTERVAL; + MT76_CONNAC_MAX_TIME_SCHED_SCAN_INTERVAL; wiphy->max_sched_scan_ie_len = IEEE80211_MAX_DATA_LEN; wiphy->max_sched_scan_ssids = MT76_CONNAC_MAX_SCHED_SCAN_SSID; wiphy->max_match_sets = MT76_CONNAC_MAX_SCAN_MATCH;
From: Ryder Lee ryder.lee@mediatek.com
[ Upstream commit 2707ff4dd7b1479dbd44ebb3c74788084cc95245 ]
The value of station mode is always 0.
Fixed: 00b2e16e0063 ("mt76: mt7915: add TxBF capabilities") Signed-off-by: Ryder Lee ryder.lee@mediatek.com Signed-off-by: Felix Fietkau nbd@nbd.name Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/wireless/mediatek/mt76/mt7915/init.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/init.c b/drivers/net/wireless/mediatek/mt76/mt7915/init.c index 822f3aa6bb8b..feb2aa57ef22 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c @@ -480,6 +480,9 @@ mt7915_set_stream_he_txbf_caps(struct ieee80211_sta_he_cap *he_cap, if (nss < 2) return;
+ /* the maximum cap is 4 x 3, (Nr, Nc) = (3, 2) */ + elem->phy_cap_info[7] |= min_t(int, nss - 1, 2) << 3; + if (vif != NL80211_IFTYPE_AP) return;
@@ -493,9 +496,6 @@ mt7915_set_stream_he_txbf_caps(struct ieee80211_sta_he_cap *he_cap, c = IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMING_FB | IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMING_PARTIAL_BW_FB; elem->phy_cap_info[6] |= c; - - /* the maximum cap is 4 x 3, (Nr, Nc) = (3, 2) */ - elem->phy_cap_info[7] |= min_t(int, nss - 1, 2) << 3; }
static void
From: Ryder Lee ryder.lee@mediatek.com
[ Upstream commit c368362c36d3d4cedbc9a1c9caa95960912cc429 ]
The iv from RXD is only for TKIP_RSC/CCMP_PN/GCMP_PN, and it needs a check for CCMP header insertion. Move mt76_cipher_type to mt76.h to reduce duplicated code.
Signed-off-by: Xing Song xing.song@mediatek.com Signed-off-by: Ryder Lee ryder.lee@mediatek.com Signed-off-by: Felix Fietkau nbd@nbd.name Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/wireless/mediatek/mt76/mt76.h | 16 +++++ .../net/wireless/mediatek/mt76/mt7603/mac.c | 33 +++++++--- .../net/wireless/mediatek/mt76/mt7603/regs.h | 12 ---- .../net/wireless/mediatek/mt76/mt7615/mac.c | 64 +++++++++++++++---- .../net/wireless/mediatek/mt76/mt7615/mac.h | 42 ------------ .../net/wireless/mediatek/mt76/mt76x02_mac.c | 28 ++++---- .../net/wireless/mediatek/mt76/mt76x02_regs.h | 18 +++--- .../net/wireless/mediatek/mt76/mt7915/mac.c | 29 ++++++--- .../net/wireless/mediatek/mt76/mt7915/mcu.c | 30 ++++----- .../net/wireless/mediatek/mt76/mt7915/mcu.h | 23 ++++--- .../net/wireless/mediatek/mt76/mt7921/mac.c | 29 ++++++--- .../net/wireless/mediatek/mt76/mt7921/mcu.c | 30 ++++----- .../net/wireless/mediatek/mt76/mt7921/mcu.h | 23 ++++--- 13 files changed, 208 insertions(+), 169 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 36ede65919f8..0c23edbfbdbb 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -87,6 +87,22 @@ enum mt76_rxq_id { __MT_RXQ_MAX };
+enum mt76_cipher_type { + MT_CIPHER_NONE, + MT_CIPHER_WEP40, + MT_CIPHER_TKIP, + MT_CIPHER_TKIP_NO_MIC, + MT_CIPHER_AES_CCMP, + MT_CIPHER_WEP104, + MT_CIPHER_BIP_CMAC_128, + MT_CIPHER_WEP128, + MT_CIPHER_WAPI, + MT_CIPHER_CCMP_CCX, + MT_CIPHER_CCMP_256, + MT_CIPHER_GCMP, + MT_CIPHER_GCMP_256, +}; + struct mt76_queue_buf { dma_addr_t addr; u16 len; diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c index fbceb07c5f37..3aa7483e929f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c @@ -550,14 +550,27 @@ mt7603_mac_fill_rx(struct mt7603_dev *dev, struct sk_buff *skb) u8 *data = (u8 *)rxd;
if (status->flag & RX_FLAG_DECRYPTED) { - status->iv[0] = data[5]; - status->iv[1] = data[4]; - status->iv[2] = data[3]; - status->iv[3] = data[2]; - status->iv[4] = data[1]; - status->iv[5] = data[0]; - - insert_ccmp_hdr = FIELD_GET(MT_RXD2_NORMAL_FRAG, rxd2); + switch (FIELD_GET(MT_RXD2_NORMAL_SEC_MODE, rxd2)) { + case MT_CIPHER_AES_CCMP: + case MT_CIPHER_CCMP_CCX: + case MT_CIPHER_CCMP_256: + insert_ccmp_hdr = + FIELD_GET(MT_RXD2_NORMAL_FRAG, rxd2); + fallthrough; + case MT_CIPHER_TKIP: + case MT_CIPHER_TKIP_NO_MIC: + case MT_CIPHER_GCMP: + case MT_CIPHER_GCMP_256: + status->iv[0] = data[5]; + status->iv[1] = data[4]; + status->iv[2] = data[3]; + status->iv[3] = data[2]; + status->iv[4] = data[1]; + status->iv[5] = data[0]; + break; + default: + break; + } }
rxd += 4; @@ -831,7 +844,7 @@ void mt7603_wtbl_set_rates(struct mt7603_dev *dev, struct mt7603_sta *sta, sta->wcid.tx_info |= MT_WCID_TX_INFO_SET; }
-static enum mt7603_cipher_type +static enum mt76_cipher_type mt7603_mac_get_key_info(struct ieee80211_key_conf *key, u8 *key_data) { memset(key_data, 0, 32); @@ -863,7 +876,7 @@ mt7603_mac_get_key_info(struct ieee80211_key_conf *key, u8 *key_data) int mt7603_wtbl_set_key(struct mt7603_dev *dev, int wcid, struct ieee80211_key_conf *key) { - enum mt7603_cipher_type cipher; + enum mt76_cipher_type cipher; u32 addr = mt7603_wtbl3_addr(wcid); u8 key_data[32]; int key_len = sizeof(key_data); diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/regs.h b/drivers/net/wireless/mediatek/mt76/mt7603/regs.h index 6741e6907194..3b901090b29c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7603/regs.h @@ -765,16 +765,4 @@ enum { #define MT_WTBL1_OR (MT_WTBL1_BASE + 0x2300) #define MT_WTBL1_OR_PSM_WRITE BIT(31)
-enum mt7603_cipher_type { - MT_CIPHER_NONE, - MT_CIPHER_WEP40, - MT_CIPHER_TKIP, - MT_CIPHER_TKIP_NO_MIC, - MT_CIPHER_AES_CCMP, - MT_CIPHER_WEP104, - MT_CIPHER_BIP_CMAC_128, - MT_CIPHER_WEP128, - MT_CIPHER_WAPI, -}; - #endif diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c index 7bdf3378a4d1..4873154d082e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c @@ -57,6 +57,33 @@ static const struct mt7615_dfs_radar_spec jp_radar_specs = { }, };
+static enum mt76_cipher_type +mt7615_mac_get_cipher(int cipher) +{ + switch (cipher) { + case WLAN_CIPHER_SUITE_WEP40: + return MT_CIPHER_WEP40; + case WLAN_CIPHER_SUITE_WEP104: + return MT_CIPHER_WEP104; + case WLAN_CIPHER_SUITE_TKIP: + return MT_CIPHER_TKIP; + case WLAN_CIPHER_SUITE_AES_CMAC: + return MT_CIPHER_BIP_CMAC_128; + case WLAN_CIPHER_SUITE_CCMP: + return MT_CIPHER_AES_CCMP; + case WLAN_CIPHER_SUITE_CCMP_256: + return MT_CIPHER_CCMP_256; + case WLAN_CIPHER_SUITE_GCMP: + return MT_CIPHER_GCMP; + case WLAN_CIPHER_SUITE_GCMP_256: + return MT_CIPHER_GCMP_256; + case WLAN_CIPHER_SUITE_SMS4: + return MT_CIPHER_WAPI; + default: + return MT_CIPHER_NONE; + } +} + static struct mt76_wcid *mt7615_rx_get_wcid(struct mt7615_dev *dev, u8 idx, bool unicast) { @@ -313,14 +340,27 @@ static int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb) u8 *data = (u8 *)rxd;
if (status->flag & RX_FLAG_DECRYPTED) { - status->iv[0] = data[5]; - status->iv[1] = data[4]; - status->iv[2] = data[3]; - status->iv[3] = data[2]; - status->iv[4] = data[1]; - status->iv[5] = data[0]; - - insert_ccmp_hdr = FIELD_GET(MT_RXD2_NORMAL_FRAG, rxd2); + switch (FIELD_GET(MT_RXD2_NORMAL_SEC_MODE, rxd2)) { + case MT_CIPHER_AES_CCMP: + case MT_CIPHER_CCMP_CCX: + case MT_CIPHER_CCMP_256: + insert_ccmp_hdr = + FIELD_GET(MT_RXD2_NORMAL_FRAG, rxd2); + fallthrough; + case MT_CIPHER_TKIP: + case MT_CIPHER_TKIP_NO_MIC: + case MT_CIPHER_GCMP: + case MT_CIPHER_GCMP_256: + status->iv[0] = data[5]; + status->iv[1] = data[4]; + status->iv[2] = data[3]; + status->iv[3] = data[2]; + status->iv[4] = data[1]; + status->iv[5] = data[0]; + break; + default: + break; + } } rxd += 4; if ((u8 *)rxd - skb->data >= skb->len) @@ -1078,7 +1118,7 @@ EXPORT_SYMBOL_GPL(mt7615_mac_set_rates); static int mt7615_mac_wtbl_update_key(struct mt7615_dev *dev, struct mt76_wcid *wcid, struct ieee80211_key_conf *key, - enum mt7615_cipher_type cipher, u16 cipher_mask, + enum mt76_cipher_type cipher, u16 cipher_mask, enum set_key_cmd cmd) { u32 addr = mt7615_mac_wtbl_addr(dev, wcid->idx) + 30 * 4; @@ -1118,7 +1158,7 @@ mt7615_mac_wtbl_update_key(struct mt7615_dev *dev, struct mt76_wcid *wcid,
static int mt7615_mac_wtbl_update_pk(struct mt7615_dev *dev, struct mt76_wcid *wcid, - enum mt7615_cipher_type cipher, u16 cipher_mask, + enum mt76_cipher_type cipher, u16 cipher_mask, int keyidx, enum set_key_cmd cmd) { u32 addr = mt7615_mac_wtbl_addr(dev, wcid->idx), w0, w1; @@ -1157,7 +1197,7 @@ mt7615_mac_wtbl_update_pk(struct mt7615_dev *dev, struct mt76_wcid *wcid,
static void mt7615_mac_wtbl_update_cipher(struct mt7615_dev *dev, struct mt76_wcid *wcid, - enum mt7615_cipher_type cipher, u16 cipher_mask, + enum mt76_cipher_type cipher, u16 cipher_mask, enum set_key_cmd cmd) { u32 addr = mt7615_mac_wtbl_addr(dev, wcid->idx); @@ -1183,7 +1223,7 @@ int __mt7615_mac_wtbl_set_key(struct mt7615_dev *dev, struct ieee80211_key_conf *key, enum set_key_cmd cmd) { - enum mt7615_cipher_type cipher; + enum mt76_cipher_type cipher; u16 cipher_mask = wcid->cipher; int err;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.h b/drivers/net/wireless/mediatek/mt76/mt7615/mac.h index 6bf9da040196..46f283eb8d0f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.h @@ -383,48 +383,6 @@ struct mt7615_dfs_radar_spec { struct mt7615_dfs_pattern radar_pattern[16]; };
-enum mt7615_cipher_type { - MT_CIPHER_NONE, - MT_CIPHER_WEP40, - MT_CIPHER_TKIP, - MT_CIPHER_TKIP_NO_MIC, - MT_CIPHER_AES_CCMP, - MT_CIPHER_WEP104, - MT_CIPHER_BIP_CMAC_128, - MT_CIPHER_WEP128, - MT_CIPHER_WAPI, - MT_CIPHER_CCMP_256 = 10, - MT_CIPHER_GCMP, - MT_CIPHER_GCMP_256, -}; - -static inline enum mt7615_cipher_type -mt7615_mac_get_cipher(int cipher) -{ - switch (cipher) { - case WLAN_CIPHER_SUITE_WEP40: - return MT_CIPHER_WEP40; - case WLAN_CIPHER_SUITE_WEP104: - return MT_CIPHER_WEP104; - case WLAN_CIPHER_SUITE_TKIP: - return MT_CIPHER_TKIP; - case WLAN_CIPHER_SUITE_AES_CMAC: - return MT_CIPHER_BIP_CMAC_128; - case WLAN_CIPHER_SUITE_CCMP: - return MT_CIPHER_AES_CCMP; - case WLAN_CIPHER_SUITE_CCMP_256: - return MT_CIPHER_CCMP_256; - case WLAN_CIPHER_SUITE_GCMP: - return MT_CIPHER_GCMP; - case WLAN_CIPHER_SUITE_GCMP_256: - return MT_CIPHER_GCMP_256; - case WLAN_CIPHER_SUITE_SMS4: - return MT_CIPHER_WAPI; - default: - return MT_CIPHER_NONE; - } -} - static inline struct mt7615_txp_common * mt7615_txwi_to_txp(struct mt76_dev *dev, struct mt76_txwi_cache *t) { diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c index 0da37867cb64..10d66775c391 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c @@ -34,24 +34,24 @@ mt76x02_mac_get_key_info(struct ieee80211_key_conf *key, u8 *key_data) { memset(key_data, 0, 32); if (!key) - return MT_CIPHER_NONE; + return MT76X02_CIPHER_NONE;
if (key->keylen > 32) - return MT_CIPHER_NONE; + return MT76X02_CIPHER_NONE;
memcpy(key_data, key->key, key->keylen);
switch (key->cipher) { case WLAN_CIPHER_SUITE_WEP40: - return MT_CIPHER_WEP40; + return MT76X02_CIPHER_WEP40; case WLAN_CIPHER_SUITE_WEP104: - return MT_CIPHER_WEP104; + return MT76X02_CIPHER_WEP104; case WLAN_CIPHER_SUITE_TKIP: - return MT_CIPHER_TKIP; + return MT76X02_CIPHER_TKIP; case WLAN_CIPHER_SUITE_CCMP: - return MT_CIPHER_AES_CCMP; + return MT76X02_CIPHER_AES_CCMP; default: - return MT_CIPHER_NONE; + return MT76X02_CIPHER_NONE; } }
@@ -63,7 +63,7 @@ int mt76x02_mac_shared_key_setup(struct mt76x02_dev *dev, u8 vif_idx, u32 val;
cipher = mt76x02_mac_get_key_info(key, key_data); - if (cipher == MT_CIPHER_NONE && key) + if (cipher == MT76X02_CIPHER_NONE && key) return -EOPNOTSUPP;
val = mt76_rr(dev, MT_SKEY_MODE(vif_idx)); @@ -91,10 +91,10 @@ void mt76x02_mac_wcid_sync_pn(struct mt76x02_dev *dev, u8 idx, eiv = mt76_rr(dev, MT_WCID_IV(idx) + 4);
pn = (u64)eiv << 16; - if (cipher == MT_CIPHER_TKIP) { + if (cipher == MT76X02_CIPHER_TKIP) { pn |= (iv >> 16) & 0xff; pn |= (iv & 0xff) << 8; - } else if (cipher >= MT_CIPHER_AES_CCMP) { + } else if (cipher >= MT76X02_CIPHER_AES_CCMP) { pn |= iv & 0xffff; } else { return; @@ -112,7 +112,7 @@ int mt76x02_mac_wcid_set_key(struct mt76x02_dev *dev, u8 idx, u64 pn;
cipher = mt76x02_mac_get_key_info(key, key_data); - if (cipher == MT_CIPHER_NONE && key) + if (cipher == MT76X02_CIPHER_NONE && key) return -EOPNOTSUPP;
mt76_wr_copy(dev, MT_WCID_KEY(idx), key_data, sizeof(key_data)); @@ -126,16 +126,16 @@ int mt76x02_mac_wcid_set_key(struct mt76x02_dev *dev, u8 idx, pn = atomic64_read(&key->tx_pn);
iv_data[3] = key->keyidx << 6; - if (cipher >= MT_CIPHER_TKIP) { + if (cipher >= MT76X02_CIPHER_TKIP) { iv_data[3] |= 0x20; put_unaligned_le32(pn >> 16, &iv_data[4]); }
- if (cipher == MT_CIPHER_TKIP) { + if (cipher == MT76X02_CIPHER_TKIP) { iv_data[0] = (pn >> 8) & 0xff; iv_data[1] = (iv_data[0] | 0x20) & 0x7f; iv_data[2] = pn & 0xff; - } else if (cipher >= MT_CIPHER_AES_CCMP) { + } else if (cipher >= MT76X02_CIPHER_AES_CCMP) { put_unaligned_le16((pn & 0xffff), &iv_data[0]); } } diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_regs.h b/drivers/net/wireless/mediatek/mt76/mt76x02_regs.h index 3e722276b5c2..fa7872ac22bf 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_regs.h @@ -692,15 +692,15 @@ struct mt76_wcid_key { } __packed __aligned(4);
enum mt76x02_cipher_type { - MT_CIPHER_NONE, - MT_CIPHER_WEP40, - MT_CIPHER_WEP104, - MT_CIPHER_TKIP, - MT_CIPHER_AES_CCMP, - MT_CIPHER_CKIP40, - MT_CIPHER_CKIP104, - MT_CIPHER_CKIP128, - MT_CIPHER_WAPI, + MT76X02_CIPHER_NONE, + MT76X02_CIPHER_WEP40, + MT76X02_CIPHER_WEP104, + MT76X02_CIPHER_TKIP, + MT76X02_CIPHER_AES_CCMP, + MT76X02_CIPHER_CKIP40, + MT76X02_CIPHER_CKIP104, + MT76X02_CIPHER_CKIP128, + MT76X02_CIPHER_WAPI, };
#endif diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c index 7a9759fb79d8..f4544c46c173 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c @@ -412,14 +412,27 @@ int mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb) u8 *data = (u8 *)rxd;
if (status->flag & RX_FLAG_DECRYPTED) { - status->iv[0] = data[5]; - status->iv[1] = data[4]; - status->iv[2] = data[3]; - status->iv[3] = data[2]; - status->iv[4] = data[1]; - status->iv[5] = data[0]; - - insert_ccmp_hdr = FIELD_GET(MT_RXD2_NORMAL_FRAG, rxd2); + switch (FIELD_GET(MT_RXD1_NORMAL_SEC_MODE, rxd1)) { + case MT_CIPHER_AES_CCMP: + case MT_CIPHER_CCMP_CCX: + case MT_CIPHER_CCMP_256: + insert_ccmp_hdr = + FIELD_GET(MT_RXD2_NORMAL_FRAG, rxd2); + fallthrough; + case MT_CIPHER_TKIP: + case MT_CIPHER_TKIP_NO_MIC: + case MT_CIPHER_GCMP: + case MT_CIPHER_GCMP_256: + status->iv[0] = data[5]; + status->iv[1] = data[4]; + status->iv[2] = data[3]; + status->iv[3] = data[2]; + status->iv[4] = data[1]; + status->iv[5] = data[0]; + break; + default: + break; + } } rxd += 4; if ((u8 *)rxd - skb->data >= skb->len) diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c index b3f14ff67c5a..5e74717c3d49 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c @@ -88,28 +88,28 @@ struct mt7915_fw_region { #define HE_PHY(p, c) u8_get_bits(c, IEEE80211_HE_PHY_##p) #define HE_MAC(m, c) u8_get_bits(c, IEEE80211_HE_MAC_##m)
-static enum mt7915_cipher_type +static enum mcu_cipher_type mt7915_mcu_get_cipher(int cipher) { switch (cipher) { case WLAN_CIPHER_SUITE_WEP40: - return MT_CIPHER_WEP40; + return MCU_CIPHER_WEP40; case WLAN_CIPHER_SUITE_WEP104: - return MT_CIPHER_WEP104; + return MCU_CIPHER_WEP104; case WLAN_CIPHER_SUITE_TKIP: - return MT_CIPHER_TKIP; + return MCU_CIPHER_TKIP; case WLAN_CIPHER_SUITE_AES_CMAC: - return MT_CIPHER_BIP_CMAC_128; + return MCU_CIPHER_BIP_CMAC_128; case WLAN_CIPHER_SUITE_CCMP: - return MT_CIPHER_AES_CCMP; + return MCU_CIPHER_AES_CCMP; case WLAN_CIPHER_SUITE_CCMP_256: - return MT_CIPHER_CCMP_256; + return MCU_CIPHER_CCMP_256; case WLAN_CIPHER_SUITE_GCMP: - return MT_CIPHER_GCMP; + return MCU_CIPHER_GCMP; case WLAN_CIPHER_SUITE_GCMP_256: - return MT_CIPHER_GCMP_256; + return MCU_CIPHER_GCMP_256; case WLAN_CIPHER_SUITE_SMS4: - return MT_CIPHER_WAPI; + return MCU_CIPHER_WAPI; default: return MT_CIPHER_NONE; } @@ -1072,14 +1072,14 @@ mt7915_mcu_sta_key_tlv(struct mt7915_sta *msta, struct sk_buff *skb, sec_key = &sec->key[0]; sec_key->cipher_len = sizeof(*sec_key);
- if (cipher == MT_CIPHER_BIP_CMAC_128) { - sec_key->cipher_id = MT_CIPHER_AES_CCMP; + if (cipher == MCU_CIPHER_BIP_CMAC_128) { + sec_key->cipher_id = MCU_CIPHER_AES_CCMP; sec_key->key_id = bip->keyidx; sec_key->key_len = 16; memcpy(sec_key->key, bip->key, 16);
sec_key = &sec->key[1]; - sec_key->cipher_id = MT_CIPHER_BIP_CMAC_128; + sec_key->cipher_id = MCU_CIPHER_BIP_CMAC_128; sec_key->cipher_len = sizeof(*sec_key); sec_key->key_len = 16; memcpy(sec_key->key, key->key, 16); @@ -1091,14 +1091,14 @@ mt7915_mcu_sta_key_tlv(struct mt7915_sta *msta, struct sk_buff *skb, sec_key->key_len = key->keylen; memcpy(sec_key->key, key->key, key->keylen);
- if (cipher == MT_CIPHER_TKIP) { + if (cipher == MCU_CIPHER_TKIP) { /* Rx/Tx MIC keys are swapped */ memcpy(sec_key->key + 16, key->key + 24, 8); memcpy(sec_key->key + 24, key->key + 16, 8); }
/* store key_conf for BIP batch update */ - if (cipher == MT_CIPHER_AES_CCMP) { + if (cipher == MCU_CIPHER_AES_CCMP) { memcpy(bip->key, key->key, key->keylen); bip->keyidx = key->keyidx; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h index 42582a66e42d..517621044d9e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h @@ -1034,18 +1034,17 @@ enum { STA_REC_MAX_NUM };
-enum mt7915_cipher_type { - MT_CIPHER_NONE, - MT_CIPHER_WEP40, - MT_CIPHER_WEP104, - MT_CIPHER_WEP128, - MT_CIPHER_TKIP, - MT_CIPHER_AES_CCMP, - MT_CIPHER_CCMP_256, - MT_CIPHER_GCMP, - MT_CIPHER_GCMP_256, - MT_CIPHER_WAPI, - MT_CIPHER_BIP_CMAC_128, +enum mcu_cipher_type { + MCU_CIPHER_WEP40 = 1, + MCU_CIPHER_WEP104, + MCU_CIPHER_WEP128, + MCU_CIPHER_TKIP, + MCU_CIPHER_AES_CCMP, + MCU_CIPHER_CCMP_256, + MCU_CIPHER_GCMP, + MCU_CIPHER_GCMP_256, + MCU_CIPHER_WAPI, + MCU_CIPHER_BIP_CMAC_128, };
enum { diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c index 66a12eba32b6..08fd141d14fc 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c @@ -386,14 +386,27 @@ int mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb) u8 *data = (u8 *)rxd;
if (status->flag & RX_FLAG_DECRYPTED) { - status->iv[0] = data[5]; - status->iv[1] = data[4]; - status->iv[2] = data[3]; - status->iv[3] = data[2]; - status->iv[4] = data[1]; - status->iv[5] = data[0]; - - insert_ccmp_hdr = FIELD_GET(MT_RXD2_NORMAL_FRAG, rxd2); + switch (FIELD_GET(MT_RXD1_NORMAL_SEC_MODE, rxd1)) { + case MT_CIPHER_AES_CCMP: + case MT_CIPHER_CCMP_CCX: + case MT_CIPHER_CCMP_256: + insert_ccmp_hdr = + FIELD_GET(MT_RXD2_NORMAL_FRAG, rxd2); + fallthrough; + case MT_CIPHER_TKIP: + case MT_CIPHER_TKIP_NO_MIC: + case MT_CIPHER_GCMP: + case MT_CIPHER_GCMP_256: + status->iv[0] = data[5]; + status->iv[1] = data[4]; + status->iv[2] = data[3]; + status->iv[3] = data[2]; + status->iv[4] = data[1]; + status->iv[5] = data[0]; + break; + default: + break; + } } rxd += 4; if ((u8 *)rxd - skb->data >= skb->len) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c index 23b337b43874..01f44170a517 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c @@ -88,28 +88,28 @@ struct mt7921_fw_region { #define to_wcid_lo(id) FIELD_GET(GENMASK(7, 0), (u16)id) #define to_wcid_hi(id) FIELD_GET(GENMASK(9, 8), (u16)id)
-static enum mt7921_cipher_type +static enum mcu_cipher_type mt7921_mcu_get_cipher(int cipher) { switch (cipher) { case WLAN_CIPHER_SUITE_WEP40: - return MT_CIPHER_WEP40; + return MCU_CIPHER_WEP40; case WLAN_CIPHER_SUITE_WEP104: - return MT_CIPHER_WEP104; + return MCU_CIPHER_WEP104; case WLAN_CIPHER_SUITE_TKIP: - return MT_CIPHER_TKIP; + return MCU_CIPHER_TKIP; case WLAN_CIPHER_SUITE_AES_CMAC: - return MT_CIPHER_BIP_CMAC_128; + return MCU_CIPHER_BIP_CMAC_128; case WLAN_CIPHER_SUITE_CCMP: - return MT_CIPHER_AES_CCMP; + return MCU_CIPHER_AES_CCMP; case WLAN_CIPHER_SUITE_CCMP_256: - return MT_CIPHER_CCMP_256; + return MCU_CIPHER_CCMP_256; case WLAN_CIPHER_SUITE_GCMP: - return MT_CIPHER_GCMP; + return MCU_CIPHER_GCMP; case WLAN_CIPHER_SUITE_GCMP_256: - return MT_CIPHER_GCMP_256; + return MCU_CIPHER_GCMP_256; case WLAN_CIPHER_SUITE_SMS4: - return MT_CIPHER_WAPI; + return MCU_CIPHER_WAPI; default: return MT_CIPHER_NONE; } @@ -604,14 +604,14 @@ mt7921_mcu_sta_key_tlv(struct mt7921_sta *msta, struct sk_buff *skb, sec_key = &sec->key[0]; sec_key->cipher_len = sizeof(*sec_key);
- if (cipher == MT_CIPHER_BIP_CMAC_128) { - sec_key->cipher_id = MT_CIPHER_AES_CCMP; + if (cipher == MCU_CIPHER_BIP_CMAC_128) { + sec_key->cipher_id = MCU_CIPHER_AES_CCMP; sec_key->key_id = bip->keyidx; sec_key->key_len = 16; memcpy(sec_key->key, bip->key, 16);
sec_key = &sec->key[1]; - sec_key->cipher_id = MT_CIPHER_BIP_CMAC_128; + sec_key->cipher_id = MCU_CIPHER_BIP_CMAC_128; sec_key->cipher_len = sizeof(*sec_key); sec_key->key_len = 16; memcpy(sec_key->key, key->key, 16); @@ -623,14 +623,14 @@ mt7921_mcu_sta_key_tlv(struct mt7921_sta *msta, struct sk_buff *skb, sec_key->key_len = key->keylen; memcpy(sec_key->key, key->key, key->keylen);
- if (cipher == MT_CIPHER_TKIP) { + if (cipher == MCU_CIPHER_TKIP) { /* Rx/Tx MIC keys are swapped */ memcpy(sec_key->key + 16, key->key + 24, 8); memcpy(sec_key->key + 24, key->key + 16, 8); }
/* store key_conf for BIP batch update */ - if (cipher == MT_CIPHER_AES_CCMP) { + if (cipher == MCU_CIPHER_AES_CCMP) { memcpy(bip->key, key->key, key->keylen); bip->keyidx = key->keyidx; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.h index 49823d0a3d0a..07abe86f07a9 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.h @@ -197,18 +197,17 @@ struct sta_rec_sec { struct sec_key key[2]; } __packed;
-enum mt7921_cipher_type { - MT_CIPHER_NONE, - MT_CIPHER_WEP40, - MT_CIPHER_WEP104, - MT_CIPHER_WEP128, - MT_CIPHER_TKIP, - MT_CIPHER_AES_CCMP, - MT_CIPHER_CCMP_256, - MT_CIPHER_GCMP, - MT_CIPHER_GCMP_256, - MT_CIPHER_WAPI, - MT_CIPHER_BIP_CMAC_128, +enum mcu_cipher_type { + MCU_CIPHER_WEP40 = 1, + MCU_CIPHER_WEP104, + MCU_CIPHER_WEP128, + MCU_CIPHER_TKIP, + MCU_CIPHER_AES_CCMP, + MCU_CIPHER_CCMP_256, + MCU_CIPHER_GCMP, + MCU_CIPHER_GCMP_256, + MCU_CIPHER_WAPI, + MCU_CIPHER_BIP_CMAC_128, };
enum {
From: Pascal Terjan pterjan@google.com
[ Upstream commit c240b044edefa3c3af4014a4030e017dd95b59a1 ]
Based on 2001:3319 and 2357:0109 which I used to test the fix and 0bda:818b and 2357:0108 for which I found efuse dumps online.
== 2357:0109 == === Before === Vendor: Realtek Product: \x03802.11n NI Serial: === After === Vendor: Realtek Product: 802.11n NIC Serial not available.
== 2001:3319 == === Before === Vendor: Realtek Product: Wireless N Serial: no USB Adap === After === Vendor: Realtek Product: Wireless N Nano USB Adapter Serial not available.
Signed-off-by: Pascal Terjan pterjan@google.com Signed-off-by: Kalle Valo kvalo@codeaurora.org Link: https://lore.kernel.org/r/20210424172959.1559890-1-pterjan@google.com Signed-off-by: Sasha Levin sashal@kernel.org --- .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.h | 11 +--- .../realtek/rtl8xxxu/rtl8xxxu_8192e.c | 59 +++++++++++++++++-- 2 files changed, 56 insertions(+), 14 deletions(-)
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h index d1a566cc0c9e..01735776345a 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h @@ -853,15 +853,10 @@ struct rtl8192eu_efuse { u8 usb_optional_function; u8 res9[2]; u8 mac_addr[ETH_ALEN]; /* 0xd7 */ - u8 res10[2]; - u8 vendor_name[7]; - u8 res11[2]; - u8 device_name[0x0b]; /* 0xe8 */ - u8 res12[2]; - u8 serial[0x0b]; /* 0xf5 */ - u8 res13[0x30]; + u8 device_info[80]; + u8 res11[3]; u8 unknown[0x0d]; /* 0x130 */ - u8 res14[0xc3]; + u8 res12[0xc3]; };
struct rtl8xxxu_reg8val { diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c index cfe2dfdae928..b06508d0cdf8 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c @@ -554,9 +554,43 @@ rtl8192e_set_tx_power(struct rtl8xxxu_priv *priv, int channel, bool ht40) } }
+static void rtl8192eu_log_next_device_info(struct rtl8xxxu_priv *priv, + char *record_name, + char *device_info, + unsigned int *record_offset) +{ + char *record = device_info + *record_offset; + + /* A record is [ total length | 0x03 | value ] */ + unsigned char l = record[0]; + + /* + * The whole device info section seems to be 80 characters, make sure + * we don't read further. + */ + if (*record_offset + l > 80) { + dev_warn(&priv->udev->dev, + "invalid record length %d while parsing "%s" at offset %u.\n", + l, record_name, *record_offset); + return; + } + + if (l >= 2) { + char value[80]; + + memcpy(value, &record[2], l - 2); + value[l - 2] = '\0'; + dev_info(&priv->udev->dev, "%s: %s\n", record_name, value); + *record_offset = *record_offset + l; + } else { + dev_info(&priv->udev->dev, "%s not available.\n", record_name); + } +} + static int rtl8192eu_parse_efuse(struct rtl8xxxu_priv *priv) { struct rtl8192eu_efuse *efuse = &priv->efuse_wifi.efuse8192eu; + unsigned int record_offset; int i;
if (efuse->rtl_id != cpu_to_le16(0x8129)) @@ -604,12 +638,25 @@ static int rtl8192eu_parse_efuse(struct rtl8xxxu_priv *priv) priv->has_xtalk = 1; priv->xtalk = priv->efuse_wifi.efuse8192eu.xtal_k & 0x3f;
- dev_info(&priv->udev->dev, "Vendor: %.7s\n", efuse->vendor_name); - dev_info(&priv->udev->dev, "Product: %.11s\n", efuse->device_name); - if (memchr_inv(efuse->serial, 0xff, 11)) - dev_info(&priv->udev->dev, "Serial: %.11s\n", efuse->serial); - else - dev_info(&priv->udev->dev, "Serial not available.\n"); + /* + * device_info section seems to be laid out as records + * [ total length | 0x03 | value ] so: + * - vendor length + 2 + * - 0x03 + * - vendor string (not null terminated) + * - product length + 2 + * - 0x03 + * - product string (not null terminated) + * Then there is one or 2 0x00 on all the 4 devices I own or found + * dumped online. + * As previous version of the code handled an optional serial + * string, I now assume there may be a third record if the + * length is not 0. + */ + record_offset = 0; + rtl8192eu_log_next_device_info(priv, "Vendor", efuse->device_info, &record_offset); + rtl8192eu_log_next_device_info(priv, "Product", efuse->device_info, &record_offset); + rtl8192eu_log_next_device_info(priv, "Serial", efuse->device_info, &record_offset);
if (rtl8xxxu_debug & RTL8XXXU_DEBUG_EFUSE) { unsigned char *raw = priv->efuse_wifi.raw;
From: Huang Pei huangpei@loongson.cn
[ Upstream commit ed914d48b6a1040d1039d371b56273d422c0081e ]
This fixes Page Table accounting bug.
MIPS is the ONLY arch just defining __HAVE_ARCH_PMD_ALLOC_ONE alone. Since commit b2b29d6d011944 (mm: account PMD tables like PTE tables), "pmd_free" in asm-generic with PMD table accounting and "pmd_alloc_one" in MIPS without PMD table accounting causes PageTable accounting number negative, which read by global_zone_page_state(), always returns 0.
Signed-off-by: Huang Pei huangpei@loongson.cn Signed-off-by: Thomas Bogendoerfer tsbogend@alpha.franken.de Signed-off-by: Sasha Levin sashal@kernel.org --- arch/mips/include/asm/pgalloc.h | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/arch/mips/include/asm/pgalloc.h b/arch/mips/include/asm/pgalloc.h index 8b18424b3120..d0cf997b4ba8 100644 --- a/arch/mips/include/asm/pgalloc.h +++ b/arch/mips/include/asm/pgalloc.h @@ -59,11 +59,15 @@ do { \
static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address) { - pmd_t *pmd; + pmd_t *pmd = NULL; + struct page *pg;
- pmd = (pmd_t *) __get_free_pages(GFP_KERNEL, PMD_ORDER); - if (pmd) + pg = alloc_pages(GFP_KERNEL | __GFP_ACCOUNT, PMD_ORDER); + if (pg) { + pgtable_pmd_page_ctor(pg); + pmd = (pmd_t *)page_address(pg); pmd_init((unsigned long)pmd, (unsigned long)invalid_pte_table); + } return pmd; }
From: Weihang Li liweihang@huawei.com
[ Upstream commit fe331da0f210c60342b042a03fe53f1b564b412b ]
GCC may reports an running time assert error when a value calculated from ib_mtu_enum_to_int() is using as 'val' in FIELD_PREDP:
include/linux/compiler_types.h:328:38: error: call to '__compiletime_assert_1524' declared with attribute error: FIELD_PREP: value too large for the field
So a check is added about whether integer mtu from ib_mtu_enum_to_int() is negative to avoid this warning.
Link: https://lore.kernel.org/r/1624262443-24528-3-git-send-email-liweihang@huawei... Reported-by: kernel test robot lkp@intel.com Signed-off-by: Weihang Li liweihang@huawei.com Signed-off-by: Jason Gunthorpe jgg@nvidia.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/infiniband/hw/hns/hns_roce_hw_v2.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-)
diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c index 7652dafe32ec..bedb0d1caeee 100644 --- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c @@ -4485,12 +4485,13 @@ static int modify_qp_init_to_rtr(struct ib_qp *ibqp, struct ib_device *ibdev = &hr_dev->ib_dev; dma_addr_t trrl_ba; dma_addr_t irrl_ba; - enum ib_mtu mtu; + enum ib_mtu ib_mtu; u8 lp_pktn_ini; u64 *mtts; u8 *dmac; u8 *smac; u32 port; + int mtu; int ret;
ret = config_qp_rq_buf(hr_dev, hr_qp, context, qpc_mask); @@ -4574,19 +4575,23 @@ static int modify_qp_init_to_rtr(struct ib_qp *ibqp, roce_set_field(qpc_mask->byte_52_udpspn_dmac, V2_QPC_BYTE_52_DMAC_M, V2_QPC_BYTE_52_DMAC_S, 0);
- mtu = get_mtu(ibqp, attr); - hr_qp->path_mtu = mtu; + ib_mtu = get_mtu(ibqp, attr); + hr_qp->path_mtu = ib_mtu; + + mtu = ib_mtu_enum_to_int(ib_mtu); + if (WARN_ON(mtu < 0)) + return -EINVAL;
if (attr_mask & IB_QP_PATH_MTU) { roce_set_field(context->byte_24_mtu_tc, V2_QPC_BYTE_24_MTU_M, - V2_QPC_BYTE_24_MTU_S, mtu); + V2_QPC_BYTE_24_MTU_S, ib_mtu); roce_set_field(qpc_mask->byte_24_mtu_tc, V2_QPC_BYTE_24_MTU_M, V2_QPC_BYTE_24_MTU_S, 0); }
#define MAX_LP_MSG_LEN 65536 /* MTU * (2 ^ LP_PKTN_INI) shouldn't be bigger than 64KB */ - lp_pktn_ini = ilog2(MAX_LP_MSG_LEN / ib_mtu_enum_to_int(mtu)); + lp_pktn_ini = ilog2(MAX_LP_MSG_LEN / mtu);
roce_set_field(context->byte_56_dqpn_err, V2_QPC_BYTE_56_LP_PKTN_INI_M, V2_QPC_BYTE_56_LP_PKTN_INI_S, lp_pktn_ini);
From: Joakim Zhang qiangqing.zhang@nxp.com
[ Upstream commit 471ff4455d61c9929ae912328859921708e1eafc ]
Frieder Schrempf reported a TX throuthput issue [1], it happens quite often that the measured bandwidth in TX direction drops from its expected/nominal value to something like ~50% (for 100M) or ~67% (for 1G) connections.
[1] https://lore.kernel.org/linux-arm-kernel/421cc86c-b66f-b372-32f7-21e59f9a98b...
The issue becomes clear after digging into it, Net core would select queues when transmitting packets. Since FEC have not impletemented ndo_select_queue callback yet, so it will call netdev_pick_tx to select queues randomly.
For i.MX6SX ENET IP with AVB support, driver default enables this feature. According to the setting of QOS/RCMRn/DMAnCFG registers, AVB configured to Credit-based scheme, 50% bandwidth of each queue 1&2.
With below tests let me think more: 1) With FEC_QUIRK_HAS_AVB quirk, can reproduce TX bandwidth fluctuations issue. 2) Without FEC_QUIRK_HAS_AVB quirk, can't reproduce TX bandwidth fluctuations issue.
The related difference with or w/o FEC_QUIRK_HAS_AVB quirk is that, whether we program FTYPE field of TxBD or not. As I describe above, AVB feature is enabled by default. With FEC_QUIRK_HAS_AVB quirk, frames in queue 0 marked as non-AVB, and frames in queue 1&2 marked as AVB Class A&B. It's unreasonable if frames in queue 1&2 are not required to be time-sensitive. So when Net core select tx queues ramdomly, Credit-based scheme would work and lead to TX bandwidth fluctuated. On the other hand, w/o FEC_QUIRK_HAS_AVB quirk, frames in queue 1&2 are all marked as non-AVB, so Credit-based scheme would not work.
Till now, how can we fix this TX throughput issue? Yes, please remove FEC_QUIRK_HAS_AVB quirk if you suffer it from time-nonsensitive networking. However, this quirk is used to indicate i.MX6SX, other setting depends on it. So this patch adds a new quirk FEC_QUIRK_HAS_MULTI_QUEUES to represent i.MX6SX, it is safe for us remove FEC_QUIRK_HAS_AVB quirk now.
FEC_QUIRK_HAS_AVB quirk is set by default in the driver, and users may not know much about driver details, they would waste effort to find the root cause, that is not we want. The following patch is a implementation to fix it and users don't need to modify the driver.
Tested-by: Frieder Schrempf frieder.schrempf@kontron.de Reported-by: Frieder Schrempf frieder.schrempf@kontron.de Signed-off-by: Joakim Zhang qiangqing.zhang@nxp.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/freescale/fec.h | 5 +++++ drivers/net/ethernet/freescale/fec_main.c | 11 ++++++----- 2 files changed, 11 insertions(+), 5 deletions(-)
diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h index 0602d5d5d2ee..2e002e4b4b4a 100644 --- a/drivers/net/ethernet/freescale/fec.h +++ b/drivers/net/ethernet/freescale/fec.h @@ -467,6 +467,11 @@ struct bufdesc_ex { */ #define FEC_QUIRK_NO_HARD_RESET (1 << 18)
+/* i.MX6SX ENET IP supports multiple queues (3 queues), use this quirk to + * represents this ENET IP. + */ +#define FEC_QUIRK_HAS_MULTI_QUEUES (1 << 19) + struct bufdesc_prop { int qid; /* Address of Rx and Tx buffers */ diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index ad82cffc6f3f..98cd38379275 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -122,7 +122,7 @@ static const struct fec_devinfo fec_imx6x_info = { FEC_QUIRK_HAS_VLAN | FEC_QUIRK_HAS_AVB | FEC_QUIRK_ERR007885 | FEC_QUIRK_BUG_CAPTURE | FEC_QUIRK_HAS_RACC | FEC_QUIRK_HAS_COALESCE | - FEC_QUIRK_CLEAR_SETUP_MII, + FEC_QUIRK_CLEAR_SETUP_MII | FEC_QUIRK_HAS_MULTI_QUEUES, };
static const struct fec_devinfo fec_imx6ul_info = { @@ -421,6 +421,7 @@ fec_enet_txq_submit_frag_skb(struct fec_enet_priv_tx_q *txq, estatus |= FEC_TX_BD_FTYPE(txq->bd.qid); if (skb->ip_summed == CHECKSUM_PARTIAL) estatus |= BD_ENET_TX_PINS | BD_ENET_TX_IINS; + ebdp->cbd_bdu = 0; ebdp->cbd_esc = cpu_to_fec32(estatus); } @@ -954,7 +955,7 @@ fec_restart(struct net_device *ndev) * For i.MX6SX SOC, enet use AXI bus, we use disable MAC * instead of reset MAC itself. */ - if (fep->quirks & FEC_QUIRK_HAS_AVB || + if (fep->quirks & FEC_QUIRK_HAS_MULTI_QUEUES || ((fep->quirks & FEC_QUIRK_NO_HARD_RESET) && fep->link)) { writel(0, fep->hwp + FEC_ECNTRL); } else { @@ -1165,7 +1166,7 @@ fec_stop(struct net_device *ndev) * instead of reset MAC itself. */ if (!(fep->wol_flag & FEC_WOL_FLAG_SLEEP_ON)) { - if (fep->quirks & FEC_QUIRK_HAS_AVB) { + if (fep->quirks & FEC_QUIRK_HAS_MULTI_QUEUES) { writel(0, fep->hwp + FEC_ECNTRL); } else { writel(1, fep->hwp + FEC_ECNTRL); @@ -2570,7 +2571,7 @@ static void fec_enet_itr_coal_set(struct net_device *ndev)
writel(tx_itr, fep->hwp + FEC_TXIC0); writel(rx_itr, fep->hwp + FEC_RXIC0); - if (fep->quirks & FEC_QUIRK_HAS_AVB) { + if (fep->quirks & FEC_QUIRK_HAS_MULTI_QUEUES) { writel(tx_itr, fep->hwp + FEC_TXIC1); writel(rx_itr, fep->hwp + FEC_RXIC1); writel(tx_itr, fep->hwp + FEC_TXIC2); @@ -3371,7 +3372,7 @@ static int fec_enet_init(struct net_device *ndev) fep->csum_flags |= FLAG_RX_CSUM_ENABLED; }
- if (fep->quirks & FEC_QUIRK_HAS_AVB) { + if (fep->quirks & FEC_QUIRK_HAS_MULTI_QUEUES) { fep->tx_align = 0; fep->rx_align = 0x3f; }
From: Fugang Duan fugang.duan@nxp.com
[ Upstream commit 52c4a1a85f4b346c39c896c0168f4a843b3385ff ]
As we know that AVB is enabled by default, and the ENET IP design is queue 0 for best effort, queue 1&2 for AVB Class A&B. Bandwidth of each queue 1&2 set in driver is 50%, TX bandwidth fluctuated when selecting tx queues randomly with FEC_QUIRK_HAS_AVB quirk available.
This patch adds ndo_select_queue callback to select queues for transmitting to fix this issue. It will always return queue 0 if this is not a vlan packet, and return queue 1 or 2 based on priority of vlan packet.
You may complain that in fact we only use single queue for trasmitting if we are not targeted to VLAN. Yes, but seems we have no choice, since AVB is enabled when the driver probed, we can't switch this feature dynamicly. After compare multiple queues to single queue, TX throughput almost no improvement.
One way we can implemet is to configure the driver to multiple queues with Round-robin scheme by default. Then add ndo_setup_tc callback to enable/disable AVB feature for users. Unfortunately, ENET AVB IP seems not follow the standard 802.1Qav spec. We only can program DMAnCFG[IDLE_SLOPE] field to calculate bandwidth fraction. And idle slope is restricted to certain valus (a total of 19). It's far away from CBS QDisc implemented in Linux TC framework. If you strongly suggest to do this, I think we only can support limited numbers of bandwidth and reject others, but it's really urgly and wried.
With this patch, VLAN tagged packets route to queue 0/1/2 based on vlan priority; VLAN untagged packets route to queue 0.
Tested-by: Frieder Schrempf frieder.schrempf@kontron.de Reported-by: Frieder Schrempf frieder.schrempf@kontron.de Signed-off-by: Fugang Duan fugang.duan@nxp.com Signed-off-by: Joakim Zhang qiangqing.zhang@nxp.com Reported-by: kernel test robot lkp@intel.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/freescale/fec_main.c | 32 +++++++++++++++++++++++ 1 file changed, 32 insertions(+)
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index 98cd38379275..8aea707a65a7 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -76,6 +76,8 @@ static void fec_enet_itr_coal_init(struct net_device *ndev);
#define DRIVER_NAME "fec"
+static const u16 fec_enet_vlan_pri_to_queue[8] = {0, 0, 1, 1, 1, 2, 2, 2}; + /* Pause frame feild and FIFO threshold */ #define FEC_ENET_FCE (1 << 5) #define FEC_ENET_RSEM_V 0x84 @@ -3240,10 +3242,40 @@ static int fec_set_features(struct net_device *netdev, return 0; }
+static u16 fec_enet_get_raw_vlan_tci(struct sk_buff *skb) +{ + struct vlan_ethhdr *vhdr; + unsigned short vlan_TCI = 0; + + if (skb->protocol == htons(ETH_P_ALL)) { + vhdr = (struct vlan_ethhdr *)(skb->data); + vlan_TCI = ntohs(vhdr->h_vlan_TCI); + } + + return vlan_TCI; +} + +static u16 fec_enet_select_queue(struct net_device *ndev, struct sk_buff *skb, + struct net_device *sb_dev) +{ + struct fec_enet_private *fep = netdev_priv(ndev); + u16 vlan_tag; + + if (!(fep->quirks & FEC_QUIRK_HAS_AVB)) + return netdev_pick_tx(ndev, skb, NULL); + + vlan_tag = fec_enet_get_raw_vlan_tci(skb); + if (!vlan_tag) + return vlan_tag; + + return fec_enet_vlan_pri_to_queue[vlan_tag >> 13]; +} + static const struct net_device_ops fec_netdev_ops = { .ndo_open = fec_enet_open, .ndo_stop = fec_enet_close, .ndo_start_xmit = fec_enet_start_xmit, + .ndo_select_queue = fec_enet_select_queue, .ndo_set_rx_mode = set_multicast_list, .ndo_validate_addr = eth_validate_addr, .ndo_tx_timeout = fec_timeout,
From: Zheyu Ma zheyuma97@gmail.com
[ Upstream commit 6a1e5a4af17e440dd82a58a2c5f40ff17a82b722 ]
When 'nicstar_init_one' fails, 'ns_init_card_error' will be executed for error handling, but the correct memory free function should be used, otherwise it will cause an error. Since 'card->rsq.org' and 'card->tsq.org' are allocated using 'dma_alloc_coherent' function, they should be freed using 'dma_free_coherent'.
Fix this by using 'dma_free_coherent' instead of 'kfree'
This log reveals it:
[ 3.440294] kernel BUG at mm/slub.c:4206! [ 3.441059] invalid opcode: 0000 [#1] PREEMPT SMP PTI [ 3.441430] CPU: 2 PID: 1 Comm: swapper/0 Not tainted 5.12.4-g70e7f0549188-dirty #141 [ 3.441986] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.12.0-59-gc9ba5276e321-prebuilt.qemu.org 04/01/2014 [ 3.442780] RIP: 0010:kfree+0x26a/0x300 [ 3.443065] Code: e8 3a c3 b9 ff e9 d6 fd ff ff 49 8b 45 00 31 db a9 00 00 01 00 75 4d 49 8b 45 00 a9 00 00 01 00 75 0a 49 8b 45 08 a8 01 75 02 <0f> 0b 89 d9 b8 00 10 00 00 be 06 00 00 00 48 d3 e0 f7 d8 48 63 d0 [ 3.443396] RSP: 0000:ffffc90000017b70 EFLAGS: 00010246 [ 3.443396] RAX: dead000000000100 RBX: 0000000000000000 RCX: 0000000000000000 [ 3.443396] RDX: 0000000000000000 RSI: ffffffff85d3df94 RDI: ffffffff85df38e6 [ 3.443396] RBP: ffffc90000017b90 R08: 0000000000000001 R09: 0000000000000001 [ 3.443396] R10: 0000000000000000 R11: 0000000000000001 R12: ffff888107dc0000 [ 3.443396] R13: ffffea00001f0100 R14: ffff888101a8bf00 R15: ffff888107dc0160 [ 3.443396] FS: 0000000000000000(0000) GS:ffff88817bc80000(0000) knlGS:0000000000000000 [ 3.443396] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 3.443396] CR2: 0000000000000000 CR3: 000000000642e000 CR4: 00000000000006e0 [ 3.443396] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 3.443396] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 [ 3.443396] Call Trace: [ 3.443396] ns_init_card_error+0x12c/0x220 [ 3.443396] nicstar_init_one+0x10d2/0x1130 [ 3.443396] local_pci_probe+0x4a/0xb0 [ 3.443396] pci_device_probe+0x126/0x1d0 [ 3.443396] ? pci_device_remove+0x100/0x100 [ 3.443396] really_probe+0x27e/0x650 [ 3.443396] driver_probe_device+0x84/0x1d0 [ 3.443396] ? mutex_lock_nested+0x16/0x20 [ 3.443396] device_driver_attach+0x63/0x70 [ 3.443396] __driver_attach+0x117/0x1a0 [ 3.443396] ? device_driver_attach+0x70/0x70 [ 3.443396] bus_for_each_dev+0xb6/0x110 [ 3.443396] ? rdinit_setup+0x40/0x40 [ 3.443396] driver_attach+0x22/0x30 [ 3.443396] bus_add_driver+0x1e6/0x2a0 [ 3.443396] driver_register+0xa4/0x180 [ 3.443396] __pci_register_driver+0x77/0x80 [ 3.443396] ? uPD98402_module_init+0xd/0xd [ 3.443396] nicstar_init+0x1f/0x75 [ 3.443396] do_one_initcall+0x7a/0x3d0 [ 3.443396] ? rdinit_setup+0x40/0x40 [ 3.443396] ? rcu_read_lock_sched_held+0x4a/0x70 [ 3.443396] kernel_init_freeable+0x2a7/0x2f9 [ 3.443396] ? rest_init+0x2c0/0x2c0 [ 3.443396] kernel_init+0x13/0x180 [ 3.443396] ? rest_init+0x2c0/0x2c0 [ 3.443396] ? rest_init+0x2c0/0x2c0 [ 3.443396] ret_from_fork+0x1f/0x30 [ 3.443396] Modules linked in: [ 3.443396] Dumping ftrace buffer: [ 3.443396] (ftrace buffer empty) [ 3.458593] ---[ end trace 3c6f8f0d8ef59bcd ]--- [ 3.458922] RIP: 0010:kfree+0x26a/0x300 [ 3.459198] Code: e8 3a c3 b9 ff e9 d6 fd ff ff 49 8b 45 00 31 db a9 00 00 01 00 75 4d 49 8b 45 00 a9 00 00 01 00 75 0a 49 8b 45 08 a8 01 75 02 <0f> 0b 89 d9 b8 00 10 00 00 be 06 00 00 00 48 d3 e0 f7 d8 48 63 d0 [ 3.460499] RSP: 0000:ffffc90000017b70 EFLAGS: 00010246 [ 3.460870] RAX: dead000000000100 RBX: 0000000000000000 RCX: 0000000000000000 [ 3.461371] RDX: 0000000000000000 RSI: ffffffff85d3df94 RDI: ffffffff85df38e6 [ 3.461873] RBP: ffffc90000017b90 R08: 0000000000000001 R09: 0000000000000001 [ 3.462372] R10: 0000000000000000 R11: 0000000000000001 R12: ffff888107dc0000 [ 3.462871] R13: ffffea00001f0100 R14: ffff888101a8bf00 R15: ffff888107dc0160 [ 3.463368] FS: 0000000000000000(0000) GS:ffff88817bc80000(0000) knlGS:0000000000000000 [ 3.463949] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 3.464356] CR2: 0000000000000000 CR3: 000000000642e000 CR4: 00000000000006e0 [ 3.464856] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 3.465356] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 [ 3.465860] Kernel panic - not syncing: Fatal exception [ 3.466370] Dumping ftrace buffer: [ 3.466616] (ftrace buffer empty) [ 3.466871] Kernel Offset: disabled [ 3.467122] Rebooting in 1 seconds..
Signed-off-by: Zheyu Ma zheyuma97@gmail.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/atm/nicstar.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/atm/nicstar.c b/drivers/atm/nicstar.c index b015c3e14336..3a38720acd0e 100644 --- a/drivers/atm/nicstar.c +++ b/drivers/atm/nicstar.c @@ -839,10 +839,12 @@ static void ns_init_card_error(ns_dev *card, int error) dev_kfree_skb_any(hb); } if (error >= 12) { - kfree(card->rsq.org); + dma_free_coherent(&card->pcidev->dev, NS_RSQSIZE + NS_RSQ_ALIGNMENT, + card->rsq.org, card->rsq.dma); } if (error >= 11) { - kfree(card->tsq.org); + dma_free_coherent(&card->pcidev->dev, NS_TSQSIZE + NS_TSQ_ALIGNMENT, + card->tsq.org, card->tsq.dma); } if (error >= 10) { free_irq(card->pcidev->irq, card);
From: Zheyu Ma zheyuma97@gmail.com
[ Upstream commit 70b639dc41ad499384e41e106fce72e36805c9f2 ]
Because the error handling is sequential, the application of resources should be carried out in the order of error handling, so the operation of registering the interrupt handler should be put in front, so as not to free the unregistered interrupt handler during error handling.
This log reveals it:
[ 3.438724] Trying to free already-free IRQ 23 [ 3.439060] WARNING: CPU: 5 PID: 1 at kernel/irq/manage.c:1825 free_irq+0xfb/0x480 [ 3.440039] Modules linked in: [ 3.440257] CPU: 5 PID: 1 Comm: swapper/0 Not tainted 5.12.4-g70e7f0549188-dirty #142 [ 3.440793] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.12.0-59-gc9ba5276e321-prebuilt.qemu.org 04/01/2014 [ 3.441561] RIP: 0010:free_irq+0xfb/0x480 [ 3.441845] Code: 6e 08 74 6f 4d 89 f4 e8 c3 78 09 00 4d 8b 74 24 18 4d 85 f6 75 e3 e8 b4 78 09 00 8b 75 c8 48 c7 c7 a0 ac d5 85 e8 95 d7 f5 ff <0f> 0b 48 8b 75 c0 4c 89 ff e8 87 c5 90 03 48 8b 43 40 4c 8b a0 80 [ 3.443121] RSP: 0000:ffffc90000017b50 EFLAGS: 00010086 [ 3.443483] RAX: 0000000000000000 RBX: ffff888107c6f000 RCX: 0000000000000000 [ 3.443972] RDX: 0000000000000000 RSI: ffffffff8123f301 RDI: 00000000ffffffff [ 3.444462] RBP: ffffc90000017b90 R08: 0000000000000001 R09: 0000000000000003 [ 3.444950] R10: 0000000000000000 R11: 0000000000000001 R12: 0000000000000000 [ 3.444994] R13: ffff888107dc0000 R14: ffff888104f6bf00 R15: ffff888107c6f0a8 [ 3.444994] FS: 0000000000000000(0000) GS:ffff88817bd40000(0000) knlGS:0000000000000000 [ 3.444994] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 3.444994] CR2: 0000000000000000 CR3: 000000000642e000 CR4: 00000000000006e0 [ 3.444994] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 3.444994] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 [ 3.444994] Call Trace: [ 3.444994] ns_init_card_error+0x18e/0x250 [ 3.444994] nicstar_init_one+0x10d2/0x1130 [ 3.444994] local_pci_probe+0x4a/0xb0 [ 3.444994] pci_device_probe+0x126/0x1d0 [ 3.444994] ? pci_device_remove+0x100/0x100 [ 3.444994] really_probe+0x27e/0x650 [ 3.444994] driver_probe_device+0x84/0x1d0 [ 3.444994] ? mutex_lock_nested+0x16/0x20 [ 3.444994] device_driver_attach+0x63/0x70 [ 3.444994] __driver_attach+0x117/0x1a0 [ 3.444994] ? device_driver_attach+0x70/0x70 [ 3.444994] bus_for_each_dev+0xb6/0x110 [ 3.444994] ? rdinit_setup+0x40/0x40 [ 3.444994] driver_attach+0x22/0x30 [ 3.444994] bus_add_driver+0x1e6/0x2a0 [ 3.444994] driver_register+0xa4/0x180 [ 3.444994] __pci_register_driver+0x77/0x80 [ 3.444994] ? uPD98402_module_init+0xd/0xd [ 3.444994] nicstar_init+0x1f/0x75 [ 3.444994] do_one_initcall+0x7a/0x3d0 [ 3.444994] ? rdinit_setup+0x40/0x40 [ 3.444994] ? rcu_read_lock_sched_held+0x4a/0x70 [ 3.444994] kernel_init_freeable+0x2a7/0x2f9 [ 3.444994] ? rest_init+0x2c0/0x2c0 [ 3.444994] kernel_init+0x13/0x180 [ 3.444994] ? rest_init+0x2c0/0x2c0 [ 3.444994] ? rest_init+0x2c0/0x2c0 [ 3.444994] ret_from_fork+0x1f/0x30 [ 3.444994] Kernel panic - not syncing: panic_on_warn set ... [ 3.444994] CPU: 5 PID: 1 Comm: swapper/0 Not tainted 5.12.4-g70e7f0549188-dirty #142 [ 3.444994] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.12.0-59-gc9ba5276e321-prebuilt.qemu.org 04/01/2014 [ 3.444994] Call Trace: [ 3.444994] dump_stack+0xba/0xf5 [ 3.444994] ? free_irq+0xfb/0x480 [ 3.444994] panic+0x155/0x3ed [ 3.444994] ? __warn+0xed/0x150 [ 3.444994] ? free_irq+0xfb/0x480 [ 3.444994] __warn+0x103/0x150 [ 3.444994] ? free_irq+0xfb/0x480 [ 3.444994] report_bug+0x119/0x1c0 [ 3.444994] handle_bug+0x3b/0x80 [ 3.444994] exc_invalid_op+0x18/0x70 [ 3.444994] asm_exc_invalid_op+0x12/0x20 [ 3.444994] RIP: 0010:free_irq+0xfb/0x480 [ 3.444994] Code: 6e 08 74 6f 4d 89 f4 e8 c3 78 09 00 4d 8b 74 24 18 4d 85 f6 75 e3 e8 b4 78 09 00 8b 75 c8 48 c7 c7 a0 ac d5 85 e8 95 d7 f5 ff <0f> 0b 48 8b 75 c0 4c 89 ff e8 87 c5 90 03 48 8b 43 40 4c 8b a0 80 [ 3.444994] RSP: 0000:ffffc90000017b50 EFLAGS: 00010086 [ 3.444994] RAX: 0000000000000000 RBX: ffff888107c6f000 RCX: 0000000000000000 [ 3.444994] RDX: 0000000000000000 RSI: ffffffff8123f301 RDI: 00000000ffffffff [ 3.444994] RBP: ffffc90000017b90 R08: 0000000000000001 R09: 0000000000000003 [ 3.444994] R10: 0000000000000000 R11: 0000000000000001 R12: 0000000000000000 [ 3.444994] R13: ffff888107dc0000 R14: ffff888104f6bf00 R15: ffff888107c6f0a8 [ 3.444994] ? vprintk_func+0x71/0x110 [ 3.444994] ns_init_card_error+0x18e/0x250 [ 3.444994] nicstar_init_one+0x10d2/0x1130 [ 3.444994] local_pci_probe+0x4a/0xb0 [ 3.444994] pci_device_probe+0x126/0x1d0 [ 3.444994] ? pci_device_remove+0x100/0x100 [ 3.444994] really_probe+0x27e/0x650 [ 3.444994] driver_probe_device+0x84/0x1d0 [ 3.444994] ? mutex_lock_nested+0x16/0x20 [ 3.444994] device_driver_attach+0x63/0x70 [ 3.444994] __driver_attach+0x117/0x1a0 [ 3.444994] ? device_driver_attach+0x70/0x70 [ 3.444994] bus_for_each_dev+0xb6/0x110 [ 3.444994] ? rdinit_setup+0x40/0x40 [ 3.444994] driver_attach+0x22/0x30 [ 3.444994] bus_add_driver+0x1e6/0x2a0 [ 3.444994] driver_register+0xa4/0x180 [ 3.444994] __pci_register_driver+0x77/0x80 [ 3.444994] ? uPD98402_module_init+0xd/0xd [ 3.444994] nicstar_init+0x1f/0x75 [ 3.444994] do_one_initcall+0x7a/0x3d0 [ 3.444994] ? rdinit_setup+0x40/0x40 [ 3.444994] ? rcu_read_lock_sched_held+0x4a/0x70 [ 3.444994] kernel_init_freeable+0x2a7/0x2f9 [ 3.444994] ? rest_init+0x2c0/0x2c0 [ 3.444994] kernel_init+0x13/0x180 [ 3.444994] ? rest_init+0x2c0/0x2c0 [ 3.444994] ? rest_init+0x2c0/0x2c0 [ 3.444994] ret_from_fork+0x1f/0x30 [ 3.444994] Dumping ftrace buffer: [ 3.444994] (ftrace buffer empty) [ 3.444994] Kernel Offset: disabled [ 3.444994] Rebooting in 1 seconds..
Signed-off-by: Zheyu Ma zheyuma97@gmail.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/atm/nicstar.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/drivers/atm/nicstar.c b/drivers/atm/nicstar.c index 3a38720acd0e..bc5a6ab6fa4b 100644 --- a/drivers/atm/nicstar.c +++ b/drivers/atm/nicstar.c @@ -527,6 +527,15 @@ static int ns_init_card(int i, struct pci_dev *pcidev) /* Set the VPI/VCI MSb mask to zero so we can receive OAM cells */ writel(0x00000000, card->membase + VPM);
+ card->intcnt = 0; + if (request_irq + (pcidev->irq, &ns_irq_handler, IRQF_SHARED, "nicstar", card) != 0) { + pr_err("nicstar%d: can't allocate IRQ %d.\n", i, pcidev->irq); + error = 9; + ns_init_card_error(card, error); + return error; + } + /* Initialize TSQ */ card->tsq.org = dma_alloc_coherent(&card->pcidev->dev, NS_TSQSIZE + NS_TSQ_ALIGNMENT, @@ -753,15 +762,6 @@ static int ns_init_card(int i, struct pci_dev *pcidev)
card->efbie = 1;
- card->intcnt = 0; - if (request_irq - (pcidev->irq, &ns_irq_handler, IRQF_SHARED, "nicstar", card) != 0) { - printk("nicstar%d: can't allocate IRQ %d.\n", i, pcidev->irq); - error = 9; - ns_init_card_error(card, error); - return error; - } - /* Register device */ card->atmdev = atm_dev_register("nicstar", &card->pcidev->dev, &atm_ops, -1, NULL);
From: "Longpeng(Mike)" longpeng2@huawei.com
[ Upstream commit c7ff9cff70601ea19245d997bb977344663434c7 ]
The client's sk_state will be set to TCP_ESTABLISHED if the server replay the client's connect request.
However, if the client has pending signal, its sk_state will be set to TCP_CLOSE without notify the server, so the server will hold the corrupt connection.
client server
1. sk_state=TCP_SYN_SENT | 2. call ->connect() | 3. wait reply | | 4. sk_state=TCP_ESTABLISHED | 5. insert to connected list | 6. reply to the client 7. sk_state=TCP_ESTABLISHED | 8. insert to connected list | 9. *signal pending* <--------------------- the user kill client 10. sk_state=TCP_CLOSE | client is exiting... | 11. call ->release() | virtio_transport_close if (!(sk->sk_state == TCP_ESTABLISHED || sk->sk_state == TCP_CLOSING)) return true; *return at here, the server cannot notice the connection is corrupt*
So the client should notify the peer in this case.
Cc: David S. Miller davem@davemloft.net Cc: Jakub Kicinski kuba@kernel.org Cc: Jorgen Hansen jhansen@vmware.com Cc: Norbert Slusarek nslusarek@gmx.net Cc: Andra Paraschiv andraprs@amazon.com Cc: Colin Ian King colin.king@canonical.com Cc: David Brazdil dbrazdil@google.com Cc: Alexander Popov alex.popov@linux.com Suggested-by: Stefano Garzarella sgarzare@redhat.com Link: https://lkml.org/lkml/2021/5/17/418 Signed-off-by: lixianming lixianming5@huawei.com Signed-off-by: Longpeng(Mike) longpeng2@huawei.com Reviewed-by: Stefano Garzarella sgarzare@redhat.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- net/vmw_vsock/af_vsock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c index 92a72f0e0d94..ae11311807fd 100644 --- a/net/vmw_vsock/af_vsock.c +++ b/net/vmw_vsock/af_vsock.c @@ -1369,7 +1369,7 @@ static int vsock_stream_connect(struct socket *sock, struct sockaddr *addr,
if (signal_pending(current)) { err = sock_intr_errno(timeout); - sk->sk_state = TCP_CLOSE; + sk->sk_state = sk->sk_state == TCP_ESTABLISHED ? TCP_CLOSING : TCP_CLOSE; sock->state = SS_UNCONNECTED; vsock_transport_cancel_pkt(vsk); goto out_wait;
From: Yifan Zhang yifan1.zhang@amd.com
[ Upstream commit 962f2f1ae273399e357a3192d5413ca57f9b4885 ]
This reverts commit 631003101c516ea29a74aee59666708857b9a805.
Reason for revert: side effect of enlarging CP_MEC_DOORBELL_RANGE may cause some APUs fail to enter gfxoff in certain user cases.
Signed-off-by: Yifan Zhang yifan1.zhang@amd.com Acked-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c index c09225d065c2..516467e962b7 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c @@ -3673,12 +3673,8 @@ static int gfx_v9_0_kiq_init_register(struct amdgpu_ring *ring) if (ring->use_doorbell) { WREG32_SOC15(GC, 0, mmCP_MEC_DOORBELL_RANGE_LOWER, (adev->doorbell_index.kiq * 2) << 2); - /* If GC has entered CGPG, ringing doorbell > first page doesn't - * wakeup GC. Enlarge CP_MEC_DOORBELL_RANGE_UPPER to workaround - * this issue. - */ WREG32_SOC15(GC, 0, mmCP_MEC_DOORBELL_RANGE_UPPER, - (adev->doorbell.size - 4)); + (adev->doorbell_index.userqueue_end * 2) << 2); }
WREG32_SOC15_RLC(GC, 0, mmCP_HQD_PQ_DOORBELL_CONTROL,
From: Logush Oliver ollogush@amd.com
[ Upstream commit eeb90e26ed05dd44553d557057bf35f08f853af8 ]
[why] Updating the file to fix the missing line
Signed-off-by: Logush Oliver ollogush@amd.com Reviewed-by: Charlene Liu Charlene.Liu@amd.com Acked-by: Bindu Ramamurthy bindu.r@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/bios/bios_parser2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c index d79f4fe06c47..4812a72f8aad 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c @@ -2131,7 +2131,7 @@ static enum bp_result get_integrated_info_v2_1( info_v2_1->edp1_info.edp_pwr_down_bloff_to_vary_bloff; info->edp1_info.edp_panel_bpc = info_v2_1->edp1_info.edp_panel_bpc; - info->edp1_info.edp_bootup_bl_level = + info->edp1_info.edp_bootup_bl_level = info_v2_1->edp1_info.edp_bootup_bl_level;
info->edp2_info.edp_backlight_pwm_hz = le16_to_cpu(info_v2_1->edp2_info.edp_backlight_pwm_hz);
From: Xiao Yang yangx.jy@fujitsu.com
[ Upstream commit 20ec0a6d6016aa28b9b3299be18baef1a0f91cd2 ]
rxe_mr_init_user() always returns the fixed -EINVAL when ib_umem_get() fails so it's hard for user to know which actual error happens in ib_umem_get(). For example, ib_umem_get() will return -EOPNOTSUPP when trying to pin pages on a DAX file.
Return actual error as mlx4/mlx5 does.
Link: https://lore.kernel.org/r/20210621071456.4259-1-ice_yangxiao@163.com Signed-off-by: Xiao Yang yangx.jy@fujitsu.com Signed-off-by: Jason Gunthorpe jgg@nvidia.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/infiniband/sw/rxe/rxe_mr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/infiniband/sw/rxe/rxe_mr.c b/drivers/infiniband/sw/rxe/rxe_mr.c index 9f63947bab12..fe2b7d223183 100644 --- a/drivers/infiniband/sw/rxe/rxe_mr.c +++ b/drivers/infiniband/sw/rxe/rxe_mr.c @@ -135,7 +135,7 @@ int rxe_mr_init_user(struct rxe_pd *pd, u64 start, u64 length, u64 iova, if (IS_ERR(umem)) { pr_warn("err %d from rxe_umem_get\n", (int)PTR_ERR(umem)); - err = -EINVAL; + err = PTR_ERR(umem); goto err1; }
From: Johannes Berg johannes.berg@intel.com
[ Upstream commit 8835a64f74c46baebfc946cd5a2c861b866ebcee ]
When we have a P2P Device active, we attempt to only change the PHY context it uses when we get a new remain-on-channel, if the P2P Device is the only user of the PHY context.
This is fine if we're switching within a band, but if we're switching bands then the switch implies a removal and re-add of the PHY context, which isn't permitted by the firmware while it's bound to an interface.
Fix the code to skip the unbind/release/... cycle only if the band doesn't change (or we have old devices that can switch the band on the fly as well.)
Signed-off-by: Johannes Berg johannes.berg@intel.com Signed-off-by: Luca Coelho luciano.coelho@intel.com Link: https://lore.kernel.org/r/iwlwifi.20210612142637.e9ac313f70f3.I713b9d109957d... Signed-off-by: Luca Coelho luciano.coelho@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- .../net/wireless/intel/iwlwifi/mvm/mac80211.c | 24 ++++++++++++++----- 1 file changed, 18 insertions(+), 6 deletions(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index 607d5d564928..141d9fc299b0 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -3800,6 +3800,7 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw, struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); struct cfg80211_chan_def chandef; struct iwl_mvm_phy_ctxt *phy_ctxt; + bool band_change_removal; int ret, i;
IWL_DEBUG_MAC80211(mvm, "enter (%d, %d, %d)\n", channel->hw_value, @@ -3880,19 +3881,30 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw, cfg80211_chandef_create(&chandef, channel, NL80211_CHAN_NO_HT);
/* - * Change the PHY context configuration as it is currently referenced - * only by the P2P Device MAC + * Check if the remain-on-channel is on a different band and that + * requires context removal, see iwl_mvm_phy_ctxt_changed(). If + * so, we'll need to release and then re-configure here, since we + * must not remove a PHY context that's part of a binding. */ - if (mvmvif->phy_ctxt->ref == 1) { + band_change_removal = + fw_has_capa(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_CAPA_BINDING_CDB_SUPPORT) && + mvmvif->phy_ctxt->channel->band != chandef.chan->band; + + if (mvmvif->phy_ctxt->ref == 1 && !band_change_removal) { + /* + * Change the PHY context configuration as it is currently + * referenced only by the P2P Device MAC (and we can modify it) + */ ret = iwl_mvm_phy_ctxt_changed(mvm, mvmvif->phy_ctxt, &chandef, 1, 1); if (ret) goto out_unlock; } else { /* - * The PHY context is shared with other MACs. Need to remove the - * P2P Device from the binding, allocate an new PHY context and - * create a new binding + * The PHY context is shared with other MACs (or we're trying to + * switch bands), so remove the P2P Device from the binding, + * allocate an new PHY context and create a new binding. */ phy_ctxt = iwl_mvm_get_free_phy_ctxt(mvm); if (!phy_ctxt) {
From: Johannes Berg johannes.berg@intel.com
[ Upstream commit a171399fd687a7d2fa56a10c9a2d7084a647677d ]
SMPS requests may differ per interfaces due to e.g. Bluetooth only interfering on 2.4 GHz, so if that's the case we should, in the case of multiple PHY contexts, still allow RX diversity on PHY context that have no interfaces with SMPS requests.
Fix the code to pass through the PHY context in question and skip interfaces with non-matching PHY context while iterating.
Signed-off-by: Johannes Berg johannes.berg@intel.com Signed-off-by: Luca Coelho luciano.coelho@intel.com Link: https://lore.kernel.org/r/iwlwifi.20210617100544.123c6b05809d.I992e3d1c6a298... Signed-off-by: Luca Coelho luciano.coelho@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 3 +- .../net/wireless/intel/iwlwifi/mvm/phy-ctxt.c | 15 ++++++---- .../net/wireless/intel/iwlwifi/mvm/utils.c | 28 ++++++++++++++----- 3 files changed, 32 insertions(+), 14 deletions(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index 4d9d4d6892fc..02cf52133857 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -1827,7 +1827,8 @@ int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm, void iwl_mvm_update_smps(struct iwl_mvm *mvm, struct ieee80211_vif *vif, enum iwl_mvm_smps_type_request req_type, enum ieee80211_smps_mode smps_request); -bool iwl_mvm_rx_diversity_allowed(struct iwl_mvm *mvm); +bool iwl_mvm_rx_diversity_allowed(struct iwl_mvm *mvm, + struct iwl_mvm_phy_ctxt *ctxt);
/* Low latency */ int iwl_mvm_update_low_latency(struct iwl_mvm *mvm, struct ieee80211_vif *vif, diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c index 0fd51f6aa206..4ed2338027d1 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2012-2014, 2018-2020 Intel Corporation + * Copyright (C) 2012-2014, 2018-2021 Intel Corporation * Copyright (C) 2013-2014 Intel Mobile Communications GmbH * Copyright (C) 2017 Intel Deutschland GmbH */ @@ -76,6 +76,7 @@ static void iwl_mvm_phy_ctxt_cmd_hdr(struct iwl_mvm_phy_ctxt *ctxt, }
static void iwl_mvm_phy_ctxt_set_rxchain(struct iwl_mvm *mvm, + struct iwl_mvm_phy_ctxt *ctxt, __le32 *rxchain_info, u8 chains_static, u8 chains_dynamic) @@ -93,7 +94,7 @@ static void iwl_mvm_phy_ctxt_set_rxchain(struct iwl_mvm *mvm, * between the two antennas is sufficiently different to impact * performance. */ - if (active_cnt == 1 && iwl_mvm_rx_diversity_allowed(mvm)) { + if (active_cnt == 1 && iwl_mvm_rx_diversity_allowed(mvm, ctxt)) { idle_cnt = 2; active_cnt = 2; } @@ -113,6 +114,7 @@ static void iwl_mvm_phy_ctxt_set_rxchain(struct iwl_mvm *mvm, * Add the phy configuration to the PHY context command */ static void iwl_mvm_phy_ctxt_cmd_data_v1(struct iwl_mvm *mvm, + struct iwl_mvm_phy_ctxt *ctxt, struct iwl_phy_context_cmd_v1 *cmd, struct cfg80211_chan_def *chandef, u8 chains_static, u8 chains_dynamic) @@ -123,7 +125,7 @@ static void iwl_mvm_phy_ctxt_cmd_data_v1(struct iwl_mvm *mvm, /* Set the channel info data */ iwl_mvm_set_chan_info_chandef(mvm, &cmd->ci, chandef);
- iwl_mvm_phy_ctxt_set_rxchain(mvm, &tail->rxchain_info, + iwl_mvm_phy_ctxt_set_rxchain(mvm, ctxt, &tail->rxchain_info, chains_static, chains_dynamic);
tail->txchain_info = cpu_to_le32(iwl_mvm_get_valid_tx_ant(mvm)); @@ -133,6 +135,7 @@ static void iwl_mvm_phy_ctxt_cmd_data_v1(struct iwl_mvm *mvm, * Add the phy configuration to the PHY context command */ static void iwl_mvm_phy_ctxt_cmd_data(struct iwl_mvm *mvm, + struct iwl_mvm_phy_ctxt *ctxt, struct iwl_phy_context_cmd *cmd, struct cfg80211_chan_def *chandef, u8 chains_static, u8 chains_dynamic) @@ -143,7 +146,7 @@ static void iwl_mvm_phy_ctxt_cmd_data(struct iwl_mvm *mvm, /* Set the channel info data */ iwl_mvm_set_chan_info_chandef(mvm, &cmd->ci, chandef);
- iwl_mvm_phy_ctxt_set_rxchain(mvm, &cmd->rxchain_info, + iwl_mvm_phy_ctxt_set_rxchain(mvm, ctxt, &cmd->rxchain_info, chains_static, chains_dynamic); }
@@ -170,7 +173,7 @@ static int iwl_mvm_phy_ctxt_apply(struct iwl_mvm *mvm, iwl_mvm_phy_ctxt_cmd_hdr(ctxt, &cmd, action);
/* Set the command data */ - iwl_mvm_phy_ctxt_cmd_data(mvm, &cmd, chandef, + iwl_mvm_phy_ctxt_cmd_data(mvm, ctxt, &cmd, chandef, chains_static, chains_dynamic);
@@ -186,7 +189,7 @@ static int iwl_mvm_phy_ctxt_apply(struct iwl_mvm *mvm, action);
/* Set the command data */ - iwl_mvm_phy_ctxt_cmd_data_v1(mvm, &cmd, chandef, + iwl_mvm_phy_ctxt_cmd_data_v1(mvm, ctxt, &cmd, chandef, chains_static, chains_dynamic); ret = iwl_mvm_send_cmd_pdu(mvm, PHY_CONTEXT_CMD, diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c index c566be99a4c7..a89eb7c40ee7 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c @@ -683,23 +683,37 @@ void iwl_mvm_accu_radio_stats(struct iwl_mvm *mvm) mvm->accu_radio_stats.on_time_scan += mvm->radio_stats.on_time_scan; }
+struct iwl_mvm_diversity_iter_data { + struct iwl_mvm_phy_ctxt *ctxt; + bool result; +}; + static void iwl_mvm_diversity_iter(void *_data, u8 *mac, struct ieee80211_vif *vif) { struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); - bool *result = _data; + struct iwl_mvm_diversity_iter_data *data = _data; int i;
+ if (mvmvif->phy_ctxt != data->ctxt) + return; + for (i = 0; i < NUM_IWL_MVM_SMPS_REQ; i++) { if (mvmvif->smps_requests[i] == IEEE80211_SMPS_STATIC || - mvmvif->smps_requests[i] == IEEE80211_SMPS_DYNAMIC) - *result = false; + mvmvif->smps_requests[i] == IEEE80211_SMPS_DYNAMIC) { + data->result = false; + break; + } } }
-bool iwl_mvm_rx_diversity_allowed(struct iwl_mvm *mvm) +bool iwl_mvm_rx_diversity_allowed(struct iwl_mvm *mvm, + struct iwl_mvm_phy_ctxt *ctxt) { - bool result = true; + struct iwl_mvm_diversity_iter_data data = { + .ctxt = ctxt, + .result = true, + };
lockdep_assert_held(&mvm->mutex);
@@ -711,9 +725,9 @@ bool iwl_mvm_rx_diversity_allowed(struct iwl_mvm *mvm)
ieee80211_iterate_active_interfaces_atomic( mvm->hw, IEEE80211_IFACE_ITER_NORMAL, - iwl_mvm_diversity_iter, &result); + iwl_mvm_diversity_iter, &data);
- return result; + return data.result; }
void iwl_mvm_send_low_latency_cmd(struct iwl_mvm *mvm,
From: Shaul Triebitz shaul.triebitz@intel.com
[ Upstream commit 976ac0af7ba2c5424bc305b926c0807d96fdcc83 ]
When the session protection ends and the Driver is not associated or a beacon was not heard, the Driver prints "No beacons heard...". That's confusing for the case where not associated. Change the print when not associated to "Not associated...".
Signed-off-by: Shaul Triebitz shaul.triebitz@intel.com Signed-off-by: Luca Coelho luciano.coelho@intel.com Link: https://lore.kernel.org/r/iwlwifi.20210617100544.41a5a5a894fa.I9eabb76e7a3a7... Signed-off-by: Luca Coelho luciano.coelho@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/wireless/intel/iwlwifi/mvm/time-event.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c index 83342a6a6d5b..f19081a6f046 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c @@ -310,6 +310,8 @@ static void iwl_mvm_te_handle_notif(struct iwl_mvm *mvm, * and know the dtim period. */ iwl_mvm_te_check_disconnect(mvm, te_data->vif, + !te_data->vif->bss_conf.assoc ? + "Not associated and the time event is over already..." : "No beacon heard and the time event is over already..."); break; default: @@ -808,6 +810,8 @@ void iwl_mvm_rx_session_protect_notif(struct iwl_mvm *mvm, * and know the dtim period. */ iwl_mvm_te_check_disconnect(mvm, vif, + !vif->bss_conf.assoc ? + "Not associated and the session protection is over already..." : "No beacon heard and the session protection is over already..."); spin_lock_bh(&mvm->time_event_lock); iwl_mvm_te_clear_data(mvm, te_data);
From: Emmanuel Grumbach emmanuel.grumbach@intel.com
[ Upstream commit d65ab7c0e0b92056754185d3f6925d7318730e94 ]
It's been a while that the firmware uses LONG_GROUP by default and not LEGACY_GROUP. Until now the firmware wrongly advertise the WOWLAN_GET_STATUS command's version with LEGACY_GROUP, but it is now being fixed. In order to support both firmwares, first try to get the version number of the command with the LONG_GROUP and if the firmware didn't advertise the command version with LONG_GROUP, try to get the command version with LEGACY_GROUP.
Signed-off-by: Emmanuel Grumbach emmanuel.grumbach@intel.com Signed-off-by: Luca Coelho luciano.coelho@intel.com Link: https://lore.kernel.org/r/iwlwifi.20210618105614.cd6f4e421430.Iec07c746c8e65... Signed-off-by: Luca Coelho luciano.coelho@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/wireless/intel/iwlwifi/mvm/d3.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c index 2e28cf299ef4..9c16303e58a9 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c @@ -1608,8 +1608,11 @@ struct iwl_wowlan_status *iwl_mvm_send_wowlan_get_status(struct iwl_mvm *mvm) len = iwl_rx_packet_payload_len(cmd.resp_pkt);
/* default to 7 (when we have IWL_UCODE_TLV_API_WOWLAN_KEY_MATERIAL) */ - notif_ver = iwl_fw_lookup_notif_ver(mvm->fw, LEGACY_GROUP, - WOWLAN_GET_STATUSES, 7); + notif_ver = iwl_fw_lookup_notif_ver(mvm->fw, LONG_GROUP, + WOWLAN_GET_STATUSES, 0); + if (!notif_ver) + notif_ver = iwl_fw_lookup_notif_ver(mvm->fw, LEGACY_GROUP, + WOWLAN_GET_STATUSES, 7);
if (!fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_WOWLAN_KEY_MATERIAL)) {
On Tue, 2021-07-06 at 07:13 -0400, Sasha Levin wrote:
From: Emmanuel Grumbach emmanuel.grumbach@intel.com
[ Upstream commit d65ab7c0e0b92056754185d3f6925d7318730e94 ]
It's been a while that the firmware uses LONG_GROUP by default and not LEGACY_GROUP. Until now the firmware wrongly advertise the WOWLAN_GET_STATUS command's version with LEGACY_GROUP, but it is now being fixed.
"Being fixed" here is the key - this will affect only firmware versions that the older drivers in stable won't load. No need to backport this.
johannes
On Tue, Jul 06, 2021 at 04:09:10PM +0200, Johannes Berg wrote:
On Tue, 2021-07-06 at 07:13 -0400, Sasha Levin wrote:
From: Emmanuel Grumbach emmanuel.grumbach@intel.com
[ Upstream commit d65ab7c0e0b92056754185d3f6925d7318730e94 ]
It's been a while that the firmware uses LONG_GROUP by default and not LEGACY_GROUP. Until now the firmware wrongly advertise the WOWLAN_GET_STATUS command's version with LEGACY_GROUP, but it is now being fixed.
"Being fixed" here is the key - this will affect only firmware versions that the older drivers in stable won't load. No need to backport this.
I'll drop it, thanks!
From: Johannes Berg johannes.berg@intel.com
[ Upstream commit 310f60f53a86eba680d9bc20a371e13b06a5f903 ]
In the case of gen3 devices with image loader (IML) support, we were leaking the IML DMA allocation and never freeing it. Fix that.
Signed-off-by: Johannes Berg johannes.berg@intel.com Signed-off-by: Luca Coelho luciano.coelho@intel.com Link: https://lore.kernel.org/r/iwlwifi.20210618105614.07e117dbedb7.I7bb9ebbe06176... Signed-off-by: Luca Coelho luciano.coelho@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- .../wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c | 15 ++++++++++----- .../net/wireless/intel/iwlwifi/pcie/internal.h | 3 +++ 2 files changed, 13 insertions(+), 5 deletions(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c index cecc32e7dbe8..2dbc51daa2f8 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c @@ -79,7 +79,6 @@ int iwl_pcie_ctxt_info_gen3_init(struct iwl_trans *trans, struct iwl_prph_scratch *prph_scratch; struct iwl_prph_scratch_ctrl_cfg *prph_sc_ctrl; struct iwl_prph_info *prph_info; - void *iml_img; u32 control_flags = 0; int ret; int cmdq_size = max_t(u32, IWL_CMD_QUEUE_SIZE, @@ -187,14 +186,15 @@ int iwl_pcie_ctxt_info_gen3_init(struct iwl_trans *trans, trans_pcie->prph_scratch = prph_scratch;
/* Allocate IML */ - iml_img = dma_alloc_coherent(trans->dev, trans->iml_len, - &trans_pcie->iml_dma_addr, GFP_KERNEL); - if (!iml_img) { + trans_pcie->iml = dma_alloc_coherent(trans->dev, trans->iml_len, + &trans_pcie->iml_dma_addr, + GFP_KERNEL); + if (!trans_pcie->iml) { ret = -ENOMEM; goto err_free_ctxt_info; }
- memcpy(iml_img, trans->iml, trans->iml_len); + memcpy(trans_pcie->iml, trans->iml, trans->iml_len);
iwl_enable_fw_load_int_ctx_info(trans);
@@ -243,6 +243,11 @@ void iwl_pcie_ctxt_info_gen3_free(struct iwl_trans *trans) trans_pcie->ctxt_info_dma_addr = 0; trans_pcie->ctxt_info_gen3 = NULL;
+ dma_free_coherent(trans->dev, trans->iml_len, trans_pcie->iml, + trans_pcie->iml_dma_addr); + trans_pcie->iml_dma_addr = 0; + trans_pcie->iml = NULL; + iwl_pcie_ctxt_info_free_fw_img(trans);
dma_free_coherent(trans->dev, sizeof(*trans_pcie->prph_scratch), diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h index 76a512cd2e5c..3f7cfbf707fd 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h @@ -279,6 +279,8 @@ struct cont_rec { * Context information addresses will be taken from here. * This is driver's local copy for keeping track of size and * count for allocating and freeing the memory. + * @iml: image loader image virtual address + * @iml_dma_addr: image loader image DMA address * @trans: pointer to the generic transport area * @scd_base_addr: scheduler sram base address in SRAM * @kw: keep warm address @@ -329,6 +331,7 @@ struct iwl_trans_pcie { }; struct iwl_prph_info *prph_info; struct iwl_prph_scratch *prph_scratch; + void *iml; dma_addr_t ctxt_info_dma_addr; dma_addr_t prph_info_dma_addr; dma_addr_t prph_scratch_dma_addr;
From: Johannes Berg johannes.berg@intel.com
[ Upstream commit 26d18c75a7496c4c52b0b6789e713dc76ebfbc87 ]
After firmware alive, iwl_trans_pcie_gen2_fw_alive() is called to free the context info. However, on gen3 that will then free the context info with the wrong size.
Since we free this allocation later, let it stick around until the device is stopped for now, freeing some of it earlier is a separate change.
Signed-off-by: Johannes Berg johannes.berg@intel.com Signed-off-by: Luca Coelho luciano.coelho@intel.com Link: https://lore.kernel.org/r/iwlwifi.20210618105614.afb63fb8cbc1.If4968db8e09f4... Signed-off-by: Luca Coelho luciano.coelho@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c index 1bcd36e9e008..9ce195d80c51 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c @@ -254,7 +254,8 @@ void iwl_trans_pcie_gen2_fw_alive(struct iwl_trans *trans, u32 scd_addr) /* now that we got alive we can free the fw image & the context info. * paging memory cannot be freed included since FW will still use it */ - iwl_pcie_ctxt_info_free(trans); + if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210) + iwl_pcie_ctxt_info_free(trans);
/* * Re-enable all the interrupts, including the RF-Kill one, now that
From: Po-Hao Huang phhuang@realtek.com
[ Upstream commit 7a1baaaee6c866455c9c77bf9b0405941a3678c7 ]
Update RTL8822C devices' RF tables to v62. This fixes higher than expected spur in 2400 MHz under CCK mask.
Signed-off-by: Po-Hao Huang phhuang@realtek.com Signed-off-by: Ping-Ke Shih pkshih@realtek.com Signed-off-by: Kalle Valo kvalo@codeaurora.org Link: https://lore.kernel.org/r/20210506083643.18317-1-pkshih@realtek.com Signed-off-by: Sasha Levin sashal@kernel.org --- .../wireless/realtek/rtw88/rtw8822c_table.c | 1008 ++++++++--------- 1 file changed, 504 insertions(+), 504 deletions(-)
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c_table.c b/drivers/net/wireless/realtek/rtw88/rtw8822c_table.c index 822f3da91f1b..f9e3d0779c59 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8822c_table.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8822c_table.c @@ -16812,53 +16812,53 @@ static const u32 rtw8822c_rf_a[] = { 0x92000002, 0x00000000, 0x40000000, 0x00000000, 0x03F, 0x00010E46, 0x93000001, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00030246, + 0x03F, 0x0003D646, 0x93000002, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00030246, + 0x03F, 0x0003D646, 0x93000003, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00030246, + 0x03F, 0x0003D646, 0x93000004, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00030246, + 0x03F, 0x0003D646, 0x93000005, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00030246, + 0x03F, 0x0003D646, 0x93000006, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00030246, + 0x03F, 0x0003D646, 0x93000015, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00030246, + 0x03F, 0x0003D646, 0x93000016, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00030246, + 0x03F, 0x0003D646, 0x94000001, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00030246, + 0x03F, 0x0003D646, 0x94000002, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00030246, + 0x03F, 0x0003D646, 0x94000003, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00030246, + 0x03F, 0x0003D646, 0x94000004, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00030246, + 0x03F, 0x0003D646, 0x94000005, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00030246, + 0x03F, 0x0003D646, 0x94000006, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00030246, + 0x03F, 0x0003D646, 0x94000015, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00030246, + 0x03F, 0x0003D646, 0x94000016, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00030246, + 0x03F, 0x0003D646, 0x95000001, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00030246, + 0x03F, 0x0003D646, 0x95000002, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00030246, + 0x03F, 0x0003D646, 0x95000003, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00030246, + 0x03F, 0x0003D646, 0x95000004, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00030246, + 0x03F, 0x0003D646, 0x95000005, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00030246, + 0x03F, 0x0003D646, 0x95000006, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00030246, + 0x03F, 0x0003D646, 0x95000015, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00030246, + 0x03F, 0x0003D646, 0x95000016, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00030246, + 0x03F, 0x0003D646, 0xA0000000, 0x00000000, 0x03F, 0x00002A46, 0xB0000000, 0x00000000, @@ -18762,53 +18762,53 @@ static const u32 rtw8822c_rf_a[] = { 0x92000002, 0x00000000, 0x40000000, 0x00000000, 0x03F, 0x0000EA46, 0x93000001, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x93000002, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x93000003, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x93000004, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x93000005, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x93000006, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x93000015, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x93000016, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x94000001, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x94000002, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x94000003, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x94000004, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x94000005, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x94000006, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x94000015, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x94000016, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x95000001, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x95000002, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x95000003, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x95000004, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x95000005, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x95000006, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x95000015, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x95000016, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0xA0000000, 0x00000000, 0x03F, 0x00002A46, 0xB0000000, 0x00000000, @@ -18957,53 +18957,53 @@ static const u32 rtw8822c_rf_a[] = { 0x92000002, 0x00000000, 0x40000000, 0x00000000, 0x03F, 0x0000EA46, 0x93000001, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x93000002, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x93000003, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x93000004, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x93000005, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x93000006, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x93000015, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x93000016, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x94000001, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x94000002, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x94000003, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x94000004, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x94000005, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x94000006, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x94000015, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x94000016, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x95000001, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x95000002, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x95000003, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x95000004, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x95000005, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x95000006, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x95000015, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x95000016, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0xA0000000, 0x00000000, 0x03F, 0x00002A46, 0xB0000000, 0x00000000, @@ -19152,53 +19152,53 @@ static const u32 rtw8822c_rf_a[] = { 0x92000002, 0x00000000, 0x40000000, 0x00000000, 0x03F, 0x0000EA46, 0x93000001, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x93000002, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x93000003, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x93000004, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x93000005, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x93000006, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x93000015, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x93000016, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x94000001, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x94000002, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x94000003, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x94000004, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x94000005, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x94000006, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x94000015, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x94000016, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x95000001, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x95000002, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x95000003, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x95000004, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x95000005, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x95000006, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x95000015, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x95000016, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0xA0000000, 0x00000000, 0x03F, 0x00002A46, 0xB0000000, 0x00000000, @@ -19347,53 +19347,53 @@ static const u32 rtw8822c_rf_a[] = { 0x92000002, 0x00000000, 0x40000000, 0x00000000, 0x03F, 0x0000EA46, 0x93000001, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x93000002, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x93000003, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x93000004, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x93000005, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x93000006, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x93000015, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x93000016, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x94000001, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x94000002, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x94000003, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x94000004, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x94000005, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x94000006, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x94000015, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x94000016, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x95000001, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x95000002, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x95000003, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x95000004, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x95000005, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x95000006, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x95000015, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0x95000016, 0x00000000, 0x40000000, 0x00000000, - 0x03F, 0x00031E46, + 0x03F, 0x0003D646, 0xA0000000, 0x00000000, 0x03F, 0x00002A46, 0xB0000000, 0x00000000, @@ -19610,21 +19610,21 @@ static const u32 rtw8822c_rf_a[] = { 0x033, 0x00000062, 0x03F, 0x00000908, 0x033, 0x00000063, - 0x03F, 0x00000D09, + 0x03F, 0x000008C8, 0x033, 0x00000064, - 0x03F, 0x00000D49, + 0x03F, 0x000008CB, 0x033, 0x00000065, - 0x03F, 0x00000D8A, + 0x03F, 0x000008CE, 0x033, 0x00000066, - 0x03F, 0x00000DEB, + 0x03F, 0x000008D1, 0x033, 0x00000067, - 0x03F, 0x00000DEE, + 0x03F, 0x000008D4, 0x033, 0x00000068, - 0x03F, 0x00000DF1, + 0x03F, 0x00000DD1, 0x033, 0x00000069, - 0x03F, 0x00000DF4, + 0x03F, 0x00000DD4, 0x033, 0x0000006A, - 0x03F, 0x00000DF7, + 0x03F, 0x00000DD7, 0x93000002, 0x00000000, 0x40000000, 0x00000000, 0x033, 0x00000060, 0x03F, 0x00000467, @@ -19633,21 +19633,21 @@ static const u32 rtw8822c_rf_a[] = { 0x033, 0x00000062, 0x03F, 0x00000908, 0x033, 0x00000063, - 0x03F, 0x00000D09, + 0x03F, 0x000008C8, 0x033, 0x00000064, - 0x03F, 0x00000D49, + 0x03F, 0x000008CB, 0x033, 0x00000065, - 0x03F, 0x00000D8A, + 0x03F, 0x000008CE, 0x033, 0x00000066, - 0x03F, 0x00000DEB, + 0x03F, 0x000008D1, 0x033, 0x00000067, - 0x03F, 0x00000DEE, + 0x03F, 0x000008D4, 0x033, 0x00000068, - 0x03F, 0x00000DF1, + 0x03F, 0x00000DD1, 0x033, 0x00000069, - 0x03F, 0x00000DF4, + 0x03F, 0x00000DD4, 0x033, 0x0000006A, - 0x03F, 0x00000DF7, + 0x03F, 0x00000DD7, 0x93000003, 0x00000000, 0x40000000, 0x00000000, 0x033, 0x00000060, 0x03F, 0x00000467, @@ -19656,21 +19656,21 @@ static const u32 rtw8822c_rf_a[] = { 0x033, 0x00000062, 0x03F, 0x00000908, 0x033, 0x00000063, - 0x03F, 0x00000D09, + 0x03F, 0x000008C8, 0x033, 0x00000064, - 0x03F, 0x00000D49, + 0x03F, 0x000008CB, 0x033, 0x00000065, - 0x03F, 0x00000D8A, + 0x03F, 0x000008CE, 0x033, 0x00000066, - 0x03F, 0x00000DEB, + 0x03F, 0x000008D1, 0x033, 0x00000067, - 0x03F, 0x00000DEE, + 0x03F, 0x000008D4, 0x033, 0x00000068, - 0x03F, 0x00000DF1, + 0x03F, 0x00000DD1, 0x033, 0x00000069, - 0x03F, 0x00000DF4, + 0x03F, 0x00000DD4, 0x033, 0x0000006A, - 0x03F, 0x00000DF7, + 0x03F, 0x00000DD7, 0x93000004, 0x00000000, 0x40000000, 0x00000000, 0x033, 0x00000060, 0x03F, 0x00000467, @@ -19679,21 +19679,21 @@ static const u32 rtw8822c_rf_a[] = { 0x033, 0x00000062, 0x03F, 0x00000908, 0x033, 0x00000063, - 0x03F, 0x00000D09, + 0x03F, 0x000008C8, 0x033, 0x00000064, - 0x03F, 0x00000D49, + 0x03F, 0x000008CB, 0x033, 0x00000065, - 0x03F, 0x00000D8A, + 0x03F, 0x000008CE, 0x033, 0x00000066, - 0x03F, 0x00000DEB, + 0x03F, 0x000008D1, 0x033, 0x00000067, - 0x03F, 0x00000DEE, + 0x03F, 0x000008D4, 0x033, 0x00000068, - 0x03F, 0x00000DF1, + 0x03F, 0x00000DD1, 0x033, 0x00000069, - 0x03F, 0x00000DF4, + 0x03F, 0x00000DD4, 0x033, 0x0000006A, - 0x03F, 0x00000DF7, + 0x03F, 0x00000DD7, 0x93000005, 0x00000000, 0x40000000, 0x00000000, 0x033, 0x00000060, 0x03F, 0x00000467, @@ -19702,21 +19702,21 @@ static const u32 rtw8822c_rf_a[] = { 0x033, 0x00000062, 0x03F, 0x00000908, 0x033, 0x00000063, - 0x03F, 0x00000D09, + 0x03F, 0x000008C8, 0x033, 0x00000064, - 0x03F, 0x00000D49, + 0x03F, 0x000008CB, 0x033, 0x00000065, - 0x03F, 0x00000D8A, + 0x03F, 0x000008CE, 0x033, 0x00000066, - 0x03F, 0x00000DEB, + 0x03F, 0x000008D1, 0x033, 0x00000067, - 0x03F, 0x00000DEE, + 0x03F, 0x000008D4, 0x033, 0x00000068, - 0x03F, 0x00000DF1, + 0x03F, 0x00000DD1, 0x033, 0x00000069, - 0x03F, 0x00000DF4, + 0x03F, 0x00000DD4, 0x033, 0x0000006A, - 0x03F, 0x00000DF7, + 0x03F, 0x00000DD7, 0x93000006, 0x00000000, 0x40000000, 0x00000000, 0x033, 0x00000060, 0x03F, 0x00000467, @@ -19725,21 +19725,21 @@ static const u32 rtw8822c_rf_a[] = { 0x033, 0x00000062, 0x03F, 0x00000908, 0x033, 0x00000063, - 0x03F, 0x00000D09, + 0x03F, 0x000008C8, 0x033, 0x00000064, - 0x03F, 0x00000D49, + 0x03F, 0x000008CB, 0x033, 0x00000065, - 0x03F, 0x00000D8A, + 0x03F, 0x000008CE, 0x033, 0x00000066, - 0x03F, 0x00000DEB, + 0x03F, 0x000008D1, 0x033, 0x00000067, - 0x03F, 0x00000DEE, + 0x03F, 0x000008D4, 0x033, 0x00000068, - 0x03F, 0x00000DF1, + 0x03F, 0x00000DD1, 0x033, 0x00000069, - 0x03F, 0x00000DF4, + 0x03F, 0x00000DD4, 0x033, 0x0000006A, - 0x03F, 0x00000DF7, + 0x03F, 0x00000DD7, 0x93000015, 0x00000000, 0x40000000, 0x00000000, 0x033, 0x00000060, 0x03F, 0x00000467, @@ -19748,21 +19748,21 @@ static const u32 rtw8822c_rf_a[] = { 0x033, 0x00000062, 0x03F, 0x00000908, 0x033, 0x00000063, - 0x03F, 0x00000D09, + 0x03F, 0x000008C8, 0x033, 0x00000064, - 0x03F, 0x00000D49, + 0x03F, 0x000008CB, 0x033, 0x00000065, - 0x03F, 0x00000D8A, + 0x03F, 0x000008CE, 0x033, 0x00000066, - 0x03F, 0x00000DEB, + 0x03F, 0x000008D1, 0x033, 0x00000067, - 0x03F, 0x00000DEE, + 0x03F, 0x000008D4, 0x033, 0x00000068, - 0x03F, 0x00000DF1, + 0x03F, 0x00000DD1, 0x033, 0x00000069, - 0x03F, 0x00000DF4, + 0x03F, 0x00000DD4, 0x033, 0x0000006A, - 0x03F, 0x00000DF7, + 0x03F, 0x00000DD7, 0x93000016, 0x00000000, 0x40000000, 0x00000000, 0x033, 0x00000060, 0x03F, 0x00000467, @@ -19771,21 +19771,21 @@ static const u32 rtw8822c_rf_a[] = { 0x033, 0x00000062, 0x03F, 0x00000908, 0x033, 0x00000063, - 0x03F, 0x00000D09, + 0x03F, 0x000008C8, 0x033, 0x00000064, - 0x03F, 0x00000D49, + 0x03F, 0x000008CB, 0x033, 0x00000065, - 0x03F, 0x00000D8A, + 0x03F, 0x000008CE, 0x033, 0x00000066, - 0x03F, 0x00000DEB, + 0x03F, 0x000008D1, 0x033, 0x00000067, - 0x03F, 0x00000DEE, + 0x03F, 0x000008D4, 0x033, 0x00000068, - 0x03F, 0x00000DF1, + 0x03F, 0x00000DD1, 0x033, 0x00000069, - 0x03F, 0x00000DF4, + 0x03F, 0x00000DD4, 0x033, 0x0000006A, - 0x03F, 0x00000DF7, + 0x03F, 0x00000DD7, 0x94000001, 0x00000000, 0x40000000, 0x00000000, 0x033, 0x00000060, 0x03F, 0x00000467, @@ -19794,21 +19794,21 @@ static const u32 rtw8822c_rf_a[] = { 0x033, 0x00000062, 0x03F, 0x00000908, 0x033, 0x00000063, - 0x03F, 0x00000D09, + 0x03F, 0x000008C8, 0x033, 0x00000064, - 0x03F, 0x00000D49, + 0x03F, 0x000008CB, 0x033, 0x00000065, - 0x03F, 0x00000D8A, + 0x03F, 0x000008CE, 0x033, 0x00000066, - 0x03F, 0x00000DEB, + 0x03F, 0x000008D1, 0x033, 0x00000067, - 0x03F, 0x00000DEE, + 0x03F, 0x000008D4, 0x033, 0x00000068, - 0x03F, 0x00000DF1, + 0x03F, 0x00000DD1, 0x033, 0x00000069, - 0x03F, 0x00000DF4, + 0x03F, 0x00000DD4, 0x033, 0x0000006A, - 0x03F, 0x00000DF7, + 0x03F, 0x00000DD7, 0x94000002, 0x00000000, 0x40000000, 0x00000000, 0x033, 0x00000060, 0x03F, 0x00000467, @@ -19817,21 +19817,21 @@ static const u32 rtw8822c_rf_a[] = { 0x033, 0x00000062, 0x03F, 0x00000908, 0x033, 0x00000063, - 0x03F, 0x00000D09, + 0x03F, 0x000008C8, 0x033, 0x00000064, - 0x03F, 0x00000D49, + 0x03F, 0x000008CB, 0x033, 0x00000065, - 0x03F, 0x00000D8A, + 0x03F, 0x000008CE, 0x033, 0x00000066, - 0x03F, 0x00000DEB, + 0x03F, 0x000008D1, 0x033, 0x00000067, - 0x03F, 0x00000DEE, + 0x03F, 0x000008D4, 0x033, 0x00000068, - 0x03F, 0x00000DF1, + 0x03F, 0x00000DD1, 0x033, 0x00000069, - 0x03F, 0x00000DF4, + 0x03F, 0x00000DD4, 0x033, 0x0000006A, - 0x03F, 0x00000DF7, + 0x03F, 0x00000DD7, 0x94000003, 0x00000000, 0x40000000, 0x00000000, 0x033, 0x00000060, 0x03F, 0x00000467, @@ -19840,21 +19840,21 @@ static const u32 rtw8822c_rf_a[] = { 0x033, 0x00000062, 0x03F, 0x00000908, 0x033, 0x00000063, - 0x03F, 0x00000D09, + 0x03F, 0x000008C8, 0x033, 0x00000064, - 0x03F, 0x00000D49, + 0x03F, 0x000008CB, 0x033, 0x00000065, - 0x03F, 0x00000D8A, + 0x03F, 0x000008CE, 0x033, 0x00000066, - 0x03F, 0x00000DEB, + 0x03F, 0x000008D1, 0x033, 0x00000067, - 0x03F, 0x00000DEE, + 0x03F, 0x000008D4, 0x033, 0x00000068, - 0x03F, 0x00000DF1, + 0x03F, 0x00000DD1, 0x033, 0x00000069, - 0x03F, 0x00000DF4, + 0x03F, 0x00000DD4, 0x033, 0x0000006A, - 0x03F, 0x00000DF7, + 0x03F, 0x00000DD7, 0x94000004, 0x00000000, 0x40000000, 0x00000000, 0x033, 0x00000060, 0x03F, 0x00000467, @@ -19863,21 +19863,21 @@ static const u32 rtw8822c_rf_a[] = { 0x033, 0x00000062, 0x03F, 0x00000908, 0x033, 0x00000063, - 0x03F, 0x00000D09, + 0x03F, 0x000008C8, 0x033, 0x00000064, - 0x03F, 0x00000D49, + 0x03F, 0x000008CB, 0x033, 0x00000065, - 0x03F, 0x00000D8A, + 0x03F, 0x000008CE, 0x033, 0x00000066, - 0x03F, 0x00000DEB, + 0x03F, 0x000008D1, 0x033, 0x00000067, - 0x03F, 0x00000DEE, + 0x03F, 0x000008D4, 0x033, 0x00000068, - 0x03F, 0x00000DF1, + 0x03F, 0x00000DD1, 0x033, 0x00000069, - 0x03F, 0x00000DF4, + 0x03F, 0x00000DD4, 0x033, 0x0000006A, - 0x03F, 0x00000DF7, + 0x03F, 0x00000DD7, 0x94000005, 0x00000000, 0x40000000, 0x00000000, 0x033, 0x00000060, 0x03F, 0x00000467, @@ -19886,21 +19886,21 @@ static const u32 rtw8822c_rf_a[] = { 0x033, 0x00000062, 0x03F, 0x00000908, 0x033, 0x00000063, - 0x03F, 0x00000D09, + 0x03F, 0x000008C8, 0x033, 0x00000064, - 0x03F, 0x00000D49, + 0x03F, 0x000008CB, 0x033, 0x00000065, - 0x03F, 0x00000D8A, + 0x03F, 0x000008CE, 0x033, 0x00000066, - 0x03F, 0x00000DEB, + 0x03F, 0x000008D1, 0x033, 0x00000067, - 0x03F, 0x00000DEE, + 0x03F, 0x000008D4, 0x033, 0x00000068, - 0x03F, 0x00000DF1, + 0x03F, 0x00000DD1, 0x033, 0x00000069, - 0x03F, 0x00000DF4, + 0x03F, 0x00000DD4, 0x033, 0x0000006A, - 0x03F, 0x00000DF7, + 0x03F, 0x00000DD7, 0x94000006, 0x00000000, 0x40000000, 0x00000000, 0x033, 0x00000060, 0x03F, 0x00000467, @@ -19909,21 +19909,21 @@ static const u32 rtw8822c_rf_a[] = { 0x033, 0x00000062, 0x03F, 0x00000908, 0x033, 0x00000063, - 0x03F, 0x00000D09, + 0x03F, 0x000008C8, 0x033, 0x00000064, - 0x03F, 0x00000D49, + 0x03F, 0x000008CB, 0x033, 0x00000065, - 0x03F, 0x00000D8A, + 0x03F, 0x000008CE, 0x033, 0x00000066, - 0x03F, 0x00000DEB, + 0x03F, 0x000008D1, 0x033, 0x00000067, - 0x03F, 0x00000DEE, + 0x03F, 0x000008D4, 0x033, 0x00000068, - 0x03F, 0x00000DF1, + 0x03F, 0x00000DD1, 0x033, 0x00000069, - 0x03F, 0x00000DF4, + 0x03F, 0x00000DD4, 0x033, 0x0000006A, - 0x03F, 0x00000DF7, + 0x03F, 0x00000DD7, 0x94000015, 0x00000000, 0x40000000, 0x00000000, 0x033, 0x00000060, 0x03F, 0x00000467, @@ -19932,21 +19932,21 @@ static const u32 rtw8822c_rf_a[] = { 0x033, 0x00000062, 0x03F, 0x00000908, 0x033, 0x00000063, - 0x03F, 0x00000D09, + 0x03F, 0x000008C8, 0x033, 0x00000064, - 0x03F, 0x00000D49, + 0x03F, 0x000008CB, 0x033, 0x00000065, - 0x03F, 0x00000D8A, + 0x03F, 0x000008CE, 0x033, 0x00000066, - 0x03F, 0x00000DEB, + 0x03F, 0x000008D1, 0x033, 0x00000067, - 0x03F, 0x00000DEE, + 0x03F, 0x000008D4, 0x033, 0x00000068, - 0x03F, 0x00000DF1, + 0x03F, 0x00000DD1, 0x033, 0x00000069, - 0x03F, 0x00000DF4, + 0x03F, 0x00000DD4, 0x033, 0x0000006A, - 0x03F, 0x00000DF7, + 0x03F, 0x00000DD7, 0x94000016, 0x00000000, 0x40000000, 0x00000000, 0x033, 0x00000060, 0x03F, 0x00000467, @@ -19955,21 +19955,21 @@ static const u32 rtw8822c_rf_a[] = { 0x033, 0x00000062, 0x03F, 0x00000908, 0x033, 0x00000063, - 0x03F, 0x00000D09, + 0x03F, 0x000008C8, 0x033, 0x00000064, - 0x03F, 0x00000D49, + 0x03F, 0x000008CB, 0x033, 0x00000065, - 0x03F, 0x00000D8A, + 0x03F, 0x000008CE, 0x033, 0x00000066, - 0x03F, 0x00000DEB, + 0x03F, 0x000008D1, 0x033, 0x00000067, - 0x03F, 0x00000DEE, + 0x03F, 0x000008D4, 0x033, 0x00000068, - 0x03F, 0x00000DF1, + 0x03F, 0x00000DD1, 0x033, 0x00000069, - 0x03F, 0x00000DF4, + 0x03F, 0x00000DD4, 0x033, 0x0000006A, - 0x03F, 0x00000DF7, + 0x03F, 0x00000DD7, 0x95000001, 0x00000000, 0x40000000, 0x00000000, 0x033, 0x00000060, 0x03F, 0x00000467, @@ -19978,21 +19978,21 @@ static const u32 rtw8822c_rf_a[] = { 0x033, 0x00000062, 0x03F, 0x00000908, 0x033, 0x00000063, - 0x03F, 0x00000D09, + 0x03F, 0x000008C8, 0x033, 0x00000064, - 0x03F, 0x00000D49, + 0x03F, 0x000008CB, 0x033, 0x00000065, - 0x03F, 0x00000D8A, + 0x03F, 0x000008CE, 0x033, 0x00000066, - 0x03F, 0x00000DEB, + 0x03F, 0x000008D1, 0x033, 0x00000067, - 0x03F, 0x00000DEE, + 0x03F, 0x000008D4, 0x033, 0x00000068, - 0x03F, 0x00000DF1, + 0x03F, 0x00000DD1, 0x033, 0x00000069, - 0x03F, 0x00000DF4, + 0x03F, 0x00000DD4, 0x033, 0x0000006A, - 0x03F, 0x00000DF7, + 0x03F, 0x00000DD7, 0x95000002, 0x00000000, 0x40000000, 0x00000000, 0x033, 0x00000060, 0x03F, 0x00000467, @@ -20001,21 +20001,21 @@ static const u32 rtw8822c_rf_a[] = { 0x033, 0x00000062, 0x03F, 0x00000908, 0x033, 0x00000063, - 0x03F, 0x00000D09, + 0x03F, 0x000008C8, 0x033, 0x00000064, - 0x03F, 0x00000D49, + 0x03F, 0x000008CB, 0x033, 0x00000065, - 0x03F, 0x00000D8A, + 0x03F, 0x000008CE, 0x033, 0x00000066, - 0x03F, 0x00000DEB, + 0x03F, 0x000008D1, 0x033, 0x00000067, - 0x03F, 0x00000DEE, + 0x03F, 0x000008D4, 0x033, 0x00000068, - 0x03F, 0x00000DF1, + 0x03F, 0x00000DD1, 0x033, 0x00000069, - 0x03F, 0x00000DF4, + 0x03F, 0x00000DD4, 0x033, 0x0000006A, - 0x03F, 0x00000DF7, + 0x03F, 0x00000DD7, 0x95000003, 0x00000000, 0x40000000, 0x00000000, 0x033, 0x00000060, 0x03F, 0x00000467, @@ -20024,21 +20024,21 @@ static const u32 rtw8822c_rf_a[] = { 0x033, 0x00000062, 0x03F, 0x00000908, 0x033, 0x00000063, - 0x03F, 0x00000D09, + 0x03F, 0x000008C8, 0x033, 0x00000064, - 0x03F, 0x00000D49, + 0x03F, 0x000008CB, 0x033, 0x00000065, - 0x03F, 0x00000D8A, + 0x03F, 0x000008CE, 0x033, 0x00000066, - 0x03F, 0x00000DEB, + 0x03F, 0x000008D1, 0x033, 0x00000067, - 0x03F, 0x00000DEE, + 0x03F, 0x000008D4, 0x033, 0x00000068, - 0x03F, 0x00000DF1, + 0x03F, 0x00000DD1, 0x033, 0x00000069, - 0x03F, 0x00000DF4, + 0x03F, 0x00000DD4, 0x033, 0x0000006A, - 0x03F, 0x00000DF7, + 0x03F, 0x00000DD7, 0x95000004, 0x00000000, 0x40000000, 0x00000000, 0x033, 0x00000060, 0x03F, 0x00000467, @@ -20047,21 +20047,21 @@ static const u32 rtw8822c_rf_a[] = { 0x033, 0x00000062, 0x03F, 0x00000908, 0x033, 0x00000063, - 0x03F, 0x00000D09, + 0x03F, 0x000008C8, 0x033, 0x00000064, - 0x03F, 0x00000D49, + 0x03F, 0x000008CB, 0x033, 0x00000065, - 0x03F, 0x00000D8A, + 0x03F, 0x000008CE, 0x033, 0x00000066, - 0x03F, 0x00000DEB, + 0x03F, 0x000008D1, 0x033, 0x00000067, - 0x03F, 0x00000DEE, + 0x03F, 0x000008D4, 0x033, 0x00000068, - 0x03F, 0x00000DF1, + 0x03F, 0x00000DD1, 0x033, 0x00000069, - 0x03F, 0x00000DF4, + 0x03F, 0x00000DD4, 0x033, 0x0000006A, - 0x03F, 0x00000DF7, + 0x03F, 0x00000DD7, 0x95000005, 0x00000000, 0x40000000, 0x00000000, 0x033, 0x00000060, 0x03F, 0x00000467, @@ -20070,21 +20070,21 @@ static const u32 rtw8822c_rf_a[] = { 0x033, 0x00000062, 0x03F, 0x00000908, 0x033, 0x00000063, - 0x03F, 0x00000D09, + 0x03F, 0x000008C8, 0x033, 0x00000064, - 0x03F, 0x00000D49, + 0x03F, 0x000008CB, 0x033, 0x00000065, - 0x03F, 0x00000D8A, + 0x03F, 0x000008CE, 0x033, 0x00000066, - 0x03F, 0x00000DEB, + 0x03F, 0x000008D1, 0x033, 0x00000067, - 0x03F, 0x00000DEE, + 0x03F, 0x000008D4, 0x033, 0x00000068, - 0x03F, 0x00000DF1, + 0x03F, 0x00000DD1, 0x033, 0x00000069, - 0x03F, 0x00000DF4, + 0x03F, 0x00000DD4, 0x033, 0x0000006A, - 0x03F, 0x00000DF7, + 0x03F, 0x00000DD7, 0x95000006, 0x00000000, 0x40000000, 0x00000000, 0x033, 0x00000060, 0x03F, 0x00000467, @@ -20093,21 +20093,21 @@ static const u32 rtw8822c_rf_a[] = { 0x033, 0x00000062, 0x03F, 0x00000908, 0x033, 0x00000063, - 0x03F, 0x00000D09, + 0x03F, 0x000008C8, 0x033, 0x00000064, - 0x03F, 0x00000D49, + 0x03F, 0x000008CB, 0x033, 0x00000065, - 0x03F, 0x00000D8A, + 0x03F, 0x000008CE, 0x033, 0x00000066, - 0x03F, 0x00000DEB, + 0x03F, 0x000008D1, 0x033, 0x00000067, - 0x03F, 0x00000DEE, + 0x03F, 0x000008D4, 0x033, 0x00000068, - 0x03F, 0x00000DF1, + 0x03F, 0x00000DD1, 0x033, 0x00000069, - 0x03F, 0x00000DF4, + 0x03F, 0x00000DD4, 0x033, 0x0000006A, - 0x03F, 0x00000DF7, + 0x03F, 0x00000DD7, 0x95000015, 0x00000000, 0x40000000, 0x00000000, 0x033, 0x00000060, 0x03F, 0x00000467, @@ -20116,21 +20116,21 @@ static const u32 rtw8822c_rf_a[] = { 0x033, 0x00000062, 0x03F, 0x00000908, 0x033, 0x00000063, - 0x03F, 0x00000D09, + 0x03F, 0x000008C8, 0x033, 0x00000064, - 0x03F, 0x00000D49, + 0x03F, 0x000008CB, 0x033, 0x00000065, - 0x03F, 0x00000D8A, + 0x03F, 0x000008CE, 0x033, 0x00000066, - 0x03F, 0x00000DEB, + 0x03F, 0x000008D1, 0x033, 0x00000067, - 0x03F, 0x00000DEE, + 0x03F, 0x000008D4, 0x033, 0x00000068, - 0x03F, 0x00000DF1, + 0x03F, 0x00000DD1, 0x033, 0x00000069, - 0x03F, 0x00000DF4, + 0x03F, 0x00000DD4, 0x033, 0x0000006A, - 0x03F, 0x00000DF7, + 0x03F, 0x00000DD7, 0x95000016, 0x00000000, 0x40000000, 0x00000000, 0x033, 0x00000060, 0x03F, 0x00000467, @@ -20139,21 +20139,21 @@ static const u32 rtw8822c_rf_a[] = { 0x033, 0x00000062, 0x03F, 0x00000908, 0x033, 0x00000063, - 0x03F, 0x00000D09, + 0x03F, 0x000008C8, 0x033, 0x00000064, - 0x03F, 0x00000D49, + 0x03F, 0x000008CB, 0x033, 0x00000065, - 0x03F, 0x00000D8A, + 0x03F, 0x000008CE, 0x033, 0x00000066, - 0x03F, 0x00000DEB, + 0x03F, 0x000008D1, 0x033, 0x00000067, - 0x03F, 0x00000DEE, + 0x03F, 0x000008D4, 0x033, 0x00000068, - 0x03F, 0x00000DF1, + 0x03F, 0x00000DD1, 0x033, 0x00000069, - 0x03F, 0x00000DF4, + 0x03F, 0x00000DD4, 0x033, 0x0000006A, - 0x03F, 0x00000DF7, + 0x03F, 0x00000DD7, 0xA0000000, 0x00000000, 0x033, 0x00000060, 0x03F, 0x00000487, @@ -38484,21 +38484,21 @@ static const u32 rtw8822c_rf_b[] = { 0x033, 0x00000062, 0x03F, 0x00000908, 0x033, 0x00000063, - 0x03F, 0x00000D09, + 0x03F, 0x00000CC6, 0x033, 0x00000064, - 0x03F, 0x00000D49, + 0x03F, 0x00000CC9, 0x033, 0x00000065, - 0x03F, 0x00000D8A, + 0x03F, 0x00000CCC, 0x033, 0x00000066, - 0x03F, 0x00000DEB, + 0x03F, 0x00000CCF, 0x033, 0x00000067, - 0x03F, 0x00000DEE, + 0x03F, 0x00000CD2, 0x033, 0x00000068, - 0x03F, 0x00000DF1, + 0x03F, 0x00000CD5, 0x033, 0x00000069, - 0x03F, 0x00000DF4, + 0x03F, 0x00000DD4, 0x033, 0x0000006A, - 0x03F, 0x00000DF7, + 0x03F, 0x00000DD7, 0x93000002, 0x00000000, 0x40000000, 0x00000000, 0x033, 0x00000060, 0x03F, 0x00000467, @@ -38507,21 +38507,21 @@ static const u32 rtw8822c_rf_b[] = { 0x033, 0x00000062, 0x03F, 0x00000908, 0x033, 0x00000063, - 0x03F, 0x00000D09, + 0x03F, 0x00000CC6, 0x033, 0x00000064, - 0x03F, 0x00000D49, + 0x03F, 0x00000CC9, 0x033, 0x00000065, - 0x03F, 0x00000D8A, + 0x03F, 0x00000CCC, 0x033, 0x00000066, - 0x03F, 0x00000DEB, + 0x03F, 0x00000CCF, 0x033, 0x00000067, - 0x03F, 0x00000DEE, + 0x03F, 0x00000CD2, 0x033, 0x00000068, - 0x03F, 0x00000DF1, + 0x03F, 0x00000CD5, 0x033, 0x00000069, - 0x03F, 0x00000DF4, + 0x03F, 0x00000DD4, 0x033, 0x0000006A, - 0x03F, 0x00000DF7, + 0x03F, 0x00000DD7, 0x93000003, 0x00000000, 0x40000000, 0x00000000, 0x033, 0x00000060, 0x03F, 0x00000467, @@ -38530,21 +38530,21 @@ static const u32 rtw8822c_rf_b[] = { 0x033, 0x00000062, 0x03F, 0x00000908, 0x033, 0x00000063, - 0x03F, 0x00000D09, + 0x03F, 0x00000CC6, 0x033, 0x00000064, - 0x03F, 0x00000D49, + 0x03F, 0x00000CC9, 0x033, 0x00000065, - 0x03F, 0x00000D8A, + 0x03F, 0x00000CCC, 0x033, 0x00000066, - 0x03F, 0x00000DEB, + 0x03F, 0x00000CCF, 0x033, 0x00000067, - 0x03F, 0x00000DEE, + 0x03F, 0x00000CD2, 0x033, 0x00000068, - 0x03F, 0x00000DF1, + 0x03F, 0x00000CD5, 0x033, 0x00000069, - 0x03F, 0x00000DF4, + 0x03F, 0x00000DD4, 0x033, 0x0000006A, - 0x03F, 0x00000DF7, + 0x03F, 0x00000DD7, 0x93000004, 0x00000000, 0x40000000, 0x00000000, 0x033, 0x00000060, 0x03F, 0x00000467, @@ -38553,21 +38553,21 @@ static const u32 rtw8822c_rf_b[] = { 0x033, 0x00000062, 0x03F, 0x00000908, 0x033, 0x00000063, - 0x03F, 0x00000D09, + 0x03F, 0x00000CC6, 0x033, 0x00000064, - 0x03F, 0x00000D49, + 0x03F, 0x00000CC9, 0x033, 0x00000065, - 0x03F, 0x00000D8A, + 0x03F, 0x00000CCC, 0x033, 0x00000066, - 0x03F, 0x00000DEB, + 0x03F, 0x00000CCF, 0x033, 0x00000067, - 0x03F, 0x00000DEE, + 0x03F, 0x00000CD2, 0x033, 0x00000068, - 0x03F, 0x00000DF1, + 0x03F, 0x00000CD5, 0x033, 0x00000069, - 0x03F, 0x00000DF4, + 0x03F, 0x00000DD4, 0x033, 0x0000006A, - 0x03F, 0x00000DF7, + 0x03F, 0x00000DD7, 0x93000005, 0x00000000, 0x40000000, 0x00000000, 0x033, 0x00000060, 0x03F, 0x00000467, @@ -38576,21 +38576,21 @@ static const u32 rtw8822c_rf_b[] = { 0x033, 0x00000062, 0x03F, 0x00000908, 0x033, 0x00000063, - 0x03F, 0x00000D09, + 0x03F, 0x00000CC6, 0x033, 0x00000064, - 0x03F, 0x00000D49, + 0x03F, 0x00000CC9, 0x033, 0x00000065, - 0x03F, 0x00000D8A, + 0x03F, 0x00000CCC, 0x033, 0x00000066, - 0x03F, 0x00000DEB, + 0x03F, 0x00000CCF, 0x033, 0x00000067, - 0x03F, 0x00000DEE, + 0x03F, 0x00000CD2, 0x033, 0x00000068, - 0x03F, 0x00000DF1, + 0x03F, 0x00000CD5, 0x033, 0x00000069, - 0x03F, 0x00000DF4, + 0x03F, 0x00000DD4, 0x033, 0x0000006A, - 0x03F, 0x00000DF7, + 0x03F, 0x00000DD7, 0x93000006, 0x00000000, 0x40000000, 0x00000000, 0x033, 0x00000060, 0x03F, 0x00000467, @@ -38599,21 +38599,21 @@ static const u32 rtw8822c_rf_b[] = { 0x033, 0x00000062, 0x03F, 0x00000908, 0x033, 0x00000063, - 0x03F, 0x00000D09, + 0x03F, 0x00000CC6, 0x033, 0x00000064, - 0x03F, 0x00000D49, + 0x03F, 0x00000CC9, 0x033, 0x00000065, - 0x03F, 0x00000D8A, + 0x03F, 0x00000CCC, 0x033, 0x00000066, - 0x03F, 0x00000DEB, + 0x03F, 0x00000CCF, 0x033, 0x00000067, - 0x03F, 0x00000DEE, + 0x03F, 0x00000CD2, 0x033, 0x00000068, - 0x03F, 0x00000DF1, + 0x03F, 0x00000CD5, 0x033, 0x00000069, - 0x03F, 0x00000DF4, + 0x03F, 0x00000DD4, 0x033, 0x0000006A, - 0x03F, 0x00000DF7, + 0x03F, 0x00000DD7, 0x93000015, 0x00000000, 0x40000000, 0x00000000, 0x033, 0x00000060, 0x03F, 0x00000467, @@ -38622,21 +38622,21 @@ static const u32 rtw8822c_rf_b[] = { 0x033, 0x00000062, 0x03F, 0x00000908, 0x033, 0x00000063, - 0x03F, 0x00000D09, + 0x03F, 0x00000CC6, 0x033, 0x00000064, - 0x03F, 0x00000D49, + 0x03F, 0x00000CC9, 0x033, 0x00000065, - 0x03F, 0x00000D8A, + 0x03F, 0x00000CCC, 0x033, 0x00000066, - 0x03F, 0x00000DEB, + 0x03F, 0x00000CCF, 0x033, 0x00000067, - 0x03F, 0x00000DEE, + 0x03F, 0x00000CD2, 0x033, 0x00000068, - 0x03F, 0x00000DF1, + 0x03F, 0x00000CD5, 0x033, 0x00000069, - 0x03F, 0x00000DF4, + 0x03F, 0x00000DD4, 0x033, 0x0000006A, - 0x03F, 0x00000DF7, + 0x03F, 0x00000DD7, 0x93000016, 0x00000000, 0x40000000, 0x00000000, 0x033, 0x00000060, 0x03F, 0x00000467, @@ -38645,21 +38645,21 @@ static const u32 rtw8822c_rf_b[] = { 0x033, 0x00000062, 0x03F, 0x00000908, 0x033, 0x00000063, - 0x03F, 0x00000D09, + 0x03F, 0x00000CC6, 0x033, 0x00000064, - 0x03F, 0x00000D49, + 0x03F, 0x00000CC9, 0x033, 0x00000065, - 0x03F, 0x00000D8A, + 0x03F, 0x00000CCC, 0x033, 0x00000066, - 0x03F, 0x00000DEB, + 0x03F, 0x00000CCF, 0x033, 0x00000067, - 0x03F, 0x00000DEE, + 0x03F, 0x00000CD2, 0x033, 0x00000068, - 0x03F, 0x00000DF1, + 0x03F, 0x00000CD5, 0x033, 0x00000069, - 0x03F, 0x00000DF4, + 0x03F, 0x00000DD4, 0x033, 0x0000006A, - 0x03F, 0x00000DF7, + 0x03F, 0x00000DD7, 0x94000001, 0x00000000, 0x40000000, 0x00000000, 0x033, 0x00000060, 0x03F, 0x00000467, @@ -38668,21 +38668,21 @@ static const u32 rtw8822c_rf_b[] = { 0x033, 0x00000062, 0x03F, 0x00000908, 0x033, 0x00000063, - 0x03F, 0x00000D09, + 0x03F, 0x00000CC6, 0x033, 0x00000064, - 0x03F, 0x00000D49, + 0x03F, 0x00000CC9, 0x033, 0x00000065, - 0x03F, 0x00000D8A, + 0x03F, 0x00000CCC, 0x033, 0x00000066, - 0x03F, 0x00000DEB, + 0x03F, 0x00000CCF, 0x033, 0x00000067, - 0x03F, 0x00000DEE, + 0x03F, 0x00000CD2, 0x033, 0x00000068, - 0x03F, 0x00000DF1, + 0x03F, 0x00000CD5, 0x033, 0x00000069, - 0x03F, 0x00000DF4, + 0x03F, 0x00000DD4, 0x033, 0x0000006A, - 0x03F, 0x00000DF7, + 0x03F, 0x00000DD7, 0x94000002, 0x00000000, 0x40000000, 0x00000000, 0x033, 0x00000060, 0x03F, 0x00000467, @@ -38691,21 +38691,21 @@ static const u32 rtw8822c_rf_b[] = { 0x033, 0x00000062, 0x03F, 0x00000908, 0x033, 0x00000063, - 0x03F, 0x00000D09, + 0x03F, 0x00000CC6, 0x033, 0x00000064, - 0x03F, 0x00000D49, + 0x03F, 0x00000CC9, 0x033, 0x00000065, - 0x03F, 0x00000D8A, + 0x03F, 0x00000CCC, 0x033, 0x00000066, - 0x03F, 0x00000DEB, + 0x03F, 0x00000CCF, 0x033, 0x00000067, - 0x03F, 0x00000DEE, + 0x03F, 0x00000CD2, 0x033, 0x00000068, - 0x03F, 0x00000DF1, + 0x03F, 0x00000CD5, 0x033, 0x00000069, - 0x03F, 0x00000DF4, + 0x03F, 0x00000DD4, 0x033, 0x0000006A, - 0x03F, 0x00000DF7, + 0x03F, 0x00000DD7, 0x94000003, 0x00000000, 0x40000000, 0x00000000, 0x033, 0x00000060, 0x03F, 0x00000467, @@ -38714,21 +38714,21 @@ static const u32 rtw8822c_rf_b[] = { 0x033, 0x00000062, 0x03F, 0x00000908, 0x033, 0x00000063, - 0x03F, 0x00000D09, + 0x03F, 0x00000CC6, 0x033, 0x00000064, - 0x03F, 0x00000D49, + 0x03F, 0x00000CC9, 0x033, 0x00000065, - 0x03F, 0x00000D8A, + 0x03F, 0x00000CCC, 0x033, 0x00000066, - 0x03F, 0x00000DEB, + 0x03F, 0x00000CCF, 0x033, 0x00000067, - 0x03F, 0x00000DEE, + 0x03F, 0x00000CD2, 0x033, 0x00000068, - 0x03F, 0x00000DF1, + 0x03F, 0x00000CD5, 0x033, 0x00000069, - 0x03F, 0x00000DF4, + 0x03F, 0x00000DD4, 0x033, 0x0000006A, - 0x03F, 0x00000DF7, + 0x03F, 0x00000DD7, 0x94000004, 0x00000000, 0x40000000, 0x00000000, 0x033, 0x00000060, 0x03F, 0x00000467, @@ -38737,21 +38737,21 @@ static const u32 rtw8822c_rf_b[] = { 0x033, 0x00000062, 0x03F, 0x00000908, 0x033, 0x00000063, - 0x03F, 0x00000D09, + 0x03F, 0x00000CC6, 0x033, 0x00000064, - 0x03F, 0x00000D49, + 0x03F, 0x00000CC9, 0x033, 0x00000065, - 0x03F, 0x00000D8A, + 0x03F, 0x00000CCC, 0x033, 0x00000066, - 0x03F, 0x00000DEB, + 0x03F, 0x00000CCF, 0x033, 0x00000067, - 0x03F, 0x00000DEE, + 0x03F, 0x00000CD2, 0x033, 0x00000068, - 0x03F, 0x00000DF1, + 0x03F, 0x00000CD5, 0x033, 0x00000069, - 0x03F, 0x00000DF4, + 0x03F, 0x00000DD4, 0x033, 0x0000006A, - 0x03F, 0x00000DF7, + 0x03F, 0x00000DD7, 0x94000005, 0x00000000, 0x40000000, 0x00000000, 0x033, 0x00000060, 0x03F, 0x00000467, @@ -38760,21 +38760,21 @@ static const u32 rtw8822c_rf_b[] = { 0x033, 0x00000062, 0x03F, 0x00000908, 0x033, 0x00000063, - 0x03F, 0x00000D09, + 0x03F, 0x00000CC6, 0x033, 0x00000064, - 0x03F, 0x00000D49, + 0x03F, 0x00000CC9, 0x033, 0x00000065, - 0x03F, 0x00000D8A, + 0x03F, 0x00000CCC, 0x033, 0x00000066, - 0x03F, 0x00000DEB, + 0x03F, 0x00000CCF, 0x033, 0x00000067, - 0x03F, 0x00000DEE, + 0x03F, 0x00000CD2, 0x033, 0x00000068, - 0x03F, 0x00000DF1, + 0x03F, 0x00000CD5, 0x033, 0x00000069, - 0x03F, 0x00000DF4, + 0x03F, 0x00000DD4, 0x033, 0x0000006A, - 0x03F, 0x00000DF7, + 0x03F, 0x00000DD7, 0x94000006, 0x00000000, 0x40000000, 0x00000000, 0x033, 0x00000060, 0x03F, 0x00000467, @@ -38783,21 +38783,21 @@ static const u32 rtw8822c_rf_b[] = { 0x033, 0x00000062, 0x03F, 0x00000908, 0x033, 0x00000063, - 0x03F, 0x00000D09, + 0x03F, 0x00000CC6, 0x033, 0x00000064, - 0x03F, 0x00000D49, + 0x03F, 0x00000CC9, 0x033, 0x00000065, - 0x03F, 0x00000D8A, + 0x03F, 0x00000CCC, 0x033, 0x00000066, - 0x03F, 0x00000DEB, + 0x03F, 0x00000CCF, 0x033, 0x00000067, - 0x03F, 0x00000DEE, + 0x03F, 0x00000CD2, 0x033, 0x00000068, - 0x03F, 0x00000DF1, + 0x03F, 0x00000CD5, 0x033, 0x00000069, - 0x03F, 0x00000DF4, + 0x03F, 0x00000DD4, 0x033, 0x0000006A, - 0x03F, 0x00000DF7, + 0x03F, 0x00000DD7, 0x94000015, 0x00000000, 0x40000000, 0x00000000, 0x033, 0x00000060, 0x03F, 0x00000467, @@ -38806,21 +38806,21 @@ static const u32 rtw8822c_rf_b[] = { 0x033, 0x00000062, 0x03F, 0x00000908, 0x033, 0x00000063, - 0x03F, 0x00000D09, + 0x03F, 0x00000CC6, 0x033, 0x00000064, - 0x03F, 0x00000D49, + 0x03F, 0x00000CC9, 0x033, 0x00000065, - 0x03F, 0x00000D8A, + 0x03F, 0x00000CCC, 0x033, 0x00000066, - 0x03F, 0x00000DEB, + 0x03F, 0x00000CCF, 0x033, 0x00000067, - 0x03F, 0x00000DEE, + 0x03F, 0x00000CD2, 0x033, 0x00000068, - 0x03F, 0x00000DF1, + 0x03F, 0x00000CD5, 0x033, 0x00000069, - 0x03F, 0x00000DF4, + 0x03F, 0x00000DD4, 0x033, 0x0000006A, - 0x03F, 0x00000DF7, + 0x03F, 0x00000DD7, 0x94000016, 0x00000000, 0x40000000, 0x00000000, 0x033, 0x00000060, 0x03F, 0x00000467, @@ -38829,21 +38829,21 @@ static const u32 rtw8822c_rf_b[] = { 0x033, 0x00000062, 0x03F, 0x00000908, 0x033, 0x00000063, - 0x03F, 0x00000D09, + 0x03F, 0x00000CC6, 0x033, 0x00000064, - 0x03F, 0x00000D49, + 0x03F, 0x00000CC9, 0x033, 0x00000065, - 0x03F, 0x00000D8A, + 0x03F, 0x00000CCC, 0x033, 0x00000066, - 0x03F, 0x00000DEB, + 0x03F, 0x00000CCF, 0x033, 0x00000067, - 0x03F, 0x00000DEE, + 0x03F, 0x00000CD2, 0x033, 0x00000068, - 0x03F, 0x00000DF1, + 0x03F, 0x00000CD5, 0x033, 0x00000069, - 0x03F, 0x00000DF4, + 0x03F, 0x00000DD4, 0x033, 0x0000006A, - 0x03F, 0x00000DF7, + 0x03F, 0x00000DD7, 0x95000001, 0x00000000, 0x40000000, 0x00000000, 0x033, 0x00000060, 0x03F, 0x00000467, @@ -38852,21 +38852,21 @@ static const u32 rtw8822c_rf_b[] = { 0x033, 0x00000062, 0x03F, 0x00000908, 0x033, 0x00000063, - 0x03F, 0x00000D09, + 0x03F, 0x00000CC6, 0x033, 0x00000064, - 0x03F, 0x00000D49, + 0x03F, 0x00000CC9, 0x033, 0x00000065, - 0x03F, 0x00000D8A, + 0x03F, 0x00000CCC, 0x033, 0x00000066, - 0x03F, 0x00000DEB, + 0x03F, 0x00000CCF, 0x033, 0x00000067, - 0x03F, 0x00000DEE, + 0x03F, 0x00000CD2, 0x033, 0x00000068, - 0x03F, 0x00000DF1, + 0x03F, 0x00000CD5, 0x033, 0x00000069, - 0x03F, 0x00000DF4, + 0x03F, 0x00000DD4, 0x033, 0x0000006A, - 0x03F, 0x00000DF7, + 0x03F, 0x00000DD7, 0x95000002, 0x00000000, 0x40000000, 0x00000000, 0x033, 0x00000060, 0x03F, 0x00000467, @@ -38875,21 +38875,21 @@ static const u32 rtw8822c_rf_b[] = { 0x033, 0x00000062, 0x03F, 0x00000908, 0x033, 0x00000063, - 0x03F, 0x00000D09, + 0x03F, 0x00000CC6, 0x033, 0x00000064, - 0x03F, 0x00000D49, + 0x03F, 0x00000CC9, 0x033, 0x00000065, - 0x03F, 0x00000D8A, + 0x03F, 0x00000CCC, 0x033, 0x00000066, - 0x03F, 0x00000DEB, + 0x03F, 0x00000CCF, 0x033, 0x00000067, - 0x03F, 0x00000DEE, + 0x03F, 0x00000CD2, 0x033, 0x00000068, - 0x03F, 0x00000DF1, + 0x03F, 0x00000CD5, 0x033, 0x00000069, - 0x03F, 0x00000DF4, + 0x03F, 0x00000DD4, 0x033, 0x0000006A, - 0x03F, 0x00000DF7, + 0x03F, 0x00000DD7, 0x95000003, 0x00000000, 0x40000000, 0x00000000, 0x033, 0x00000060, 0x03F, 0x00000467, @@ -38898,21 +38898,21 @@ static const u32 rtw8822c_rf_b[] = { 0x033, 0x00000062, 0x03F, 0x00000908, 0x033, 0x00000063, - 0x03F, 0x00000D09, + 0x03F, 0x00000CC6, 0x033, 0x00000064, - 0x03F, 0x00000D49, + 0x03F, 0x00000CC9, 0x033, 0x00000065, - 0x03F, 0x00000D8A, + 0x03F, 0x00000CCC, 0x033, 0x00000066, - 0x03F, 0x00000DEB, + 0x03F, 0x00000CCF, 0x033, 0x00000067, - 0x03F, 0x00000DEE, + 0x03F, 0x00000CD2, 0x033, 0x00000068, - 0x03F, 0x00000DF1, + 0x03F, 0x00000CD5, 0x033, 0x00000069, - 0x03F, 0x00000DF4, + 0x03F, 0x00000DD4, 0x033, 0x0000006A, - 0x03F, 0x00000DF7, + 0x03F, 0x00000DD7, 0x95000004, 0x00000000, 0x40000000, 0x00000000, 0x033, 0x00000060, 0x03F, 0x00000467, @@ -38921,21 +38921,21 @@ static const u32 rtw8822c_rf_b[] = { 0x033, 0x00000062, 0x03F, 0x00000908, 0x033, 0x00000063, - 0x03F, 0x00000D09, + 0x03F, 0x00000CC6, 0x033, 0x00000064, - 0x03F, 0x00000D49, + 0x03F, 0x00000CC9, 0x033, 0x00000065, - 0x03F, 0x00000D8A, + 0x03F, 0x00000CCC, 0x033, 0x00000066, - 0x03F, 0x00000DEB, + 0x03F, 0x00000CCF, 0x033, 0x00000067, - 0x03F, 0x00000DEE, + 0x03F, 0x00000CD2, 0x033, 0x00000068, - 0x03F, 0x00000DF1, + 0x03F, 0x00000CD5, 0x033, 0x00000069, - 0x03F, 0x00000DF4, + 0x03F, 0x00000DD4, 0x033, 0x0000006A, - 0x03F, 0x00000DF7, + 0x03F, 0x00000DD7, 0x95000005, 0x00000000, 0x40000000, 0x00000000, 0x033, 0x00000060, 0x03F, 0x00000467, @@ -38944,21 +38944,21 @@ static const u32 rtw8822c_rf_b[] = { 0x033, 0x00000062, 0x03F, 0x00000908, 0x033, 0x00000063, - 0x03F, 0x00000D09, + 0x03F, 0x00000CC6, 0x033, 0x00000064, - 0x03F, 0x00000D49, + 0x03F, 0x00000CC9, 0x033, 0x00000065, - 0x03F, 0x00000D8A, + 0x03F, 0x00000CCC, 0x033, 0x00000066, - 0x03F, 0x00000DEB, + 0x03F, 0x00000CCF, 0x033, 0x00000067, - 0x03F, 0x00000DEE, + 0x03F, 0x00000CD2, 0x033, 0x00000068, - 0x03F, 0x00000DF1, + 0x03F, 0x00000CD5, 0x033, 0x00000069, - 0x03F, 0x00000DF4, + 0x03F, 0x00000DD4, 0x033, 0x0000006A, - 0x03F, 0x00000DF7, + 0x03F, 0x00000DD7, 0x95000006, 0x00000000, 0x40000000, 0x00000000, 0x033, 0x00000060, 0x03F, 0x00000467, @@ -38967,21 +38967,21 @@ static const u32 rtw8822c_rf_b[] = { 0x033, 0x00000062, 0x03F, 0x00000908, 0x033, 0x00000063, - 0x03F, 0x00000D09, + 0x03F, 0x00000CC6, 0x033, 0x00000064, - 0x03F, 0x00000D49, + 0x03F, 0x00000CC9, 0x033, 0x00000065, - 0x03F, 0x00000D8A, + 0x03F, 0x00000CCC, 0x033, 0x00000066, - 0x03F, 0x00000DEB, + 0x03F, 0x00000CCF, 0x033, 0x00000067, - 0x03F, 0x00000DEE, + 0x03F, 0x00000CD2, 0x033, 0x00000068, - 0x03F, 0x00000DF1, + 0x03F, 0x00000CD5, 0x033, 0x00000069, - 0x03F, 0x00000DF4, + 0x03F, 0x00000DD4, 0x033, 0x0000006A, - 0x03F, 0x00000DF7, + 0x03F, 0x00000DD7, 0x95000015, 0x00000000, 0x40000000, 0x00000000, 0x033, 0x00000060, 0x03F, 0x00000467, @@ -38990,21 +38990,21 @@ static const u32 rtw8822c_rf_b[] = { 0x033, 0x00000062, 0x03F, 0x00000908, 0x033, 0x00000063, - 0x03F, 0x00000D09, + 0x03F, 0x00000CC6, 0x033, 0x00000064, - 0x03F, 0x00000D49, + 0x03F, 0x00000CC9, 0x033, 0x00000065, - 0x03F, 0x00000D8A, + 0x03F, 0x00000CCC, 0x033, 0x00000066, - 0x03F, 0x00000DEB, + 0x03F, 0x00000CCF, 0x033, 0x00000067, - 0x03F, 0x00000DEE, + 0x03F, 0x00000CD2, 0x033, 0x00000068, - 0x03F, 0x00000DF1, + 0x03F, 0x00000CD5, 0x033, 0x00000069, - 0x03F, 0x00000DF4, + 0x03F, 0x00000DD4, 0x033, 0x0000006A, - 0x03F, 0x00000DF7, + 0x03F, 0x00000DD7, 0x95000016, 0x00000000, 0x40000000, 0x00000000, 0x033, 0x00000060, 0x03F, 0x00000467, @@ -39013,21 +39013,21 @@ static const u32 rtw8822c_rf_b[] = { 0x033, 0x00000062, 0x03F, 0x00000908, 0x033, 0x00000063, - 0x03F, 0x00000D09, + 0x03F, 0x00000CC6, 0x033, 0x00000064, - 0x03F, 0x00000D49, + 0x03F, 0x00000CC9, 0x033, 0x00000065, - 0x03F, 0x00000D8A, + 0x03F, 0x00000CCC, 0x033, 0x00000066, - 0x03F, 0x00000DEB, + 0x03F, 0x00000CCF, 0x033, 0x00000067, - 0x03F, 0x00000DEE, + 0x03F, 0x00000CD2, 0x033, 0x00000068, - 0x03F, 0x00000DF1, + 0x03F, 0x00000CD5, 0x033, 0x00000069, - 0x03F, 0x00000DF4, + 0x03F, 0x00000DD4, 0x033, 0x0000006A, - 0x03F, 0x00000DF7, + 0x03F, 0x00000DD7, 0xA0000000, 0x00000000, 0x033, 0x00000060, 0x03F, 0x00000487,
From: Ping-Ke Shih pkshih@realtek.com
[ Upstream commit 956c6d4f20c5446727e0c912dd8f527f2dc7b779 ]
8821CE with ASPM cannot work properly on Protempo Ltd L116HTN6SPW. Add a quirk to disable the cap.
The reporter describes the symptom is that this module (driver) causes frequent freezes, randomly but usually within a few minutes of running (thus very soon after boot): screen display remains frozen, no response to either keyboard or mouse input. All I can do is to hold the power button to power off, then reboot.
Reported-by: Paul Szabo psz2036@gmail.com Signed-off-by: Ping-Ke Shih pkshih@realtek.com Signed-off-by: Kalle Valo kvalo@codeaurora.org Link: https://lore.kernel.org/r/20210607012254.6306-1-pkshih@realtek.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/wireless/realtek/rtw88/pci.c | 32 ++++++++++++++++++++++++ 1 file changed, 32 insertions(+)
diff --git a/drivers/net/wireless/realtek/rtw88/pci.c b/drivers/net/wireless/realtek/rtw88/pci.c index f59a4c462e3b..e7d17ab8f113 100644 --- a/drivers/net/wireless/realtek/rtw88/pci.c +++ b/drivers/net/wireless/realtek/rtw88/pci.c @@ -2,6 +2,7 @@ /* Copyright(c) 2018-2019 Realtek Corporation */
+#include <linux/dmi.h> #include <linux/module.h> #include <linux/pci.h> #include "main.h" @@ -1673,6 +1674,36 @@ static void rtw_pci_napi_deinit(struct rtw_dev *rtwdev) netif_napi_del(&rtwpci->napi); }
+enum rtw88_quirk_dis_pci_caps { + QUIRK_DIS_PCI_CAP_MSI, + QUIRK_DIS_PCI_CAP_ASPM, +}; + +static int disable_pci_caps(const struct dmi_system_id *dmi) +{ + uintptr_t dis_caps = (uintptr_t)dmi->driver_data; + + if (dis_caps & BIT(QUIRK_DIS_PCI_CAP_MSI)) + rtw_disable_msi = true; + if (dis_caps & BIT(QUIRK_DIS_PCI_CAP_ASPM)) + rtw_pci_disable_aspm = true; + + return 1; +} + +static const struct dmi_system_id rtw88_pci_quirks[] = { + { + .callback = disable_pci_caps, + .ident = "Protempo Ltd L116HTN6SPW", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Protempo Ltd"), + DMI_MATCH(DMI_PRODUCT_NAME, "L116HTN6SPW"), + }, + .driver_data = (void *)BIT(QUIRK_DIS_PCI_CAP_ASPM), + }, + {} +}; + int rtw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) { @@ -1723,6 +1754,7 @@ int rtw_pci_probe(struct pci_dev *pdev, goto err_destroy_pci; }
+ dmi_check_system(rtw88_pci_quirks); rtw_pci_phy_cfg(rtwdev);
ret = rtw_register_hw(rtwdev, hw);
From: Íñigo Huguet ihuguet@redhat.com
[ Upstream commit 45423cff1db66cf0993e8a9bd0ac93e740149e49 ]
If pci_remove was called for a PF with VFs, the removal of the VFs was called twice from efx_ef10_sriov_fini: one directly with pci_driver->remove and another implicit by calling pci_disable_sriov, which also perform the VFs remove. This was leading to crashing the kernel on the second attempt.
Given that pci_disable_sriov already calls to pci remove function, get rid of the direct call to pci_driver->remove from the driver.
2 different ways to trigger the bug: - Create one or more VFs, then attach the PF to a virtual machine (at least with qemu/KVM) - Create one or more VFs, then remove the PF with: echo 1 > /sys/bus/pci/devices/PF_PCI_ID/remove
Removing sfc module does not trigger the error, at least for me, because it removes the VF first, and then the PF.
Example of a log with the error: list_del corruption, ffff967fd20a8ad0->next is LIST_POISON1 (dead000000000100) ------------[ cut here ]------------ kernel BUG at lib/list_debug.c:47! [...trimmed...] RIP: 0010:__list_del_entry_valid.cold.1+0x12/0x4c [...trimmed...] Call Trace: efx_dissociate+0x1f/0x140 [sfc] efx_pci_remove+0x27/0x150 [sfc] pci_device_remove+0x3b/0xc0 device_release_driver_internal+0x103/0x1f0 pci_stop_bus_device+0x69/0x90 pci_stop_and_remove_bus_device+0xe/0x20 pci_iov_remove_virtfn+0xba/0x120 sriov_disable+0x2f/0xe0 efx_ef10_pci_sriov_disable+0x52/0x80 [sfc] ? pcie_aer_is_native+0x12/0x40 efx_ef10_sriov_fini+0x72/0x110 [sfc] efx_pci_remove+0x62/0x150 [sfc] pci_device_remove+0x3b/0xc0 device_release_driver_internal+0x103/0x1f0 unbind_store+0xf6/0x130 kernfs_fop_write+0x116/0x190 vfs_write+0xa5/0x1a0 ksys_write+0x4f/0xb0 do_syscall_64+0x5b/0x1a0 entry_SYSCALL_64_after_hwframe+0x65/0xca
Signed-off-by: Íñigo Huguet ihuguet@redhat.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/sfc/ef10_sriov.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-)
diff --git a/drivers/net/ethernet/sfc/ef10_sriov.c b/drivers/net/ethernet/sfc/ef10_sriov.c index 21fa6c0e8873..a5d28b0f75ba 100644 --- a/drivers/net/ethernet/sfc/ef10_sriov.c +++ b/drivers/net/ethernet/sfc/ef10_sriov.c @@ -439,7 +439,6 @@ int efx_ef10_sriov_init(struct efx_nic *efx) void efx_ef10_sriov_fini(struct efx_nic *efx) { struct efx_ef10_nic_data *nic_data = efx->nic_data; - unsigned int i; int rc;
if (!nic_data->vf) { @@ -449,14 +448,7 @@ void efx_ef10_sriov_fini(struct efx_nic *efx) return; }
- /* Remove any VFs in the host */ - for (i = 0; i < efx->vf_count; ++i) { - struct efx_nic *vf_efx = nic_data->vf[i].efx; - - if (vf_efx) - vf_efx->pci_dev->driver->remove(vf_efx->pci_dev); - } - + /* Disable SRIOV and remove any VFs in the host */ rc = efx_ef10_pci_sriov_disable(efx, true); if (rc) netif_dbg(efx, drv, efx->net_dev,
From: Íñigo Huguet ihuguet@redhat.com
[ Upstream commit 1ebe4feb8b442884f5a28d2437040096723dd1ea ]
If SRIOV cannot be disabled during device removal or module unloading, return error code so it can be logged properly in the calling function.
Note that this can only happen if any VF is currently attached to a guest using Xen, but not with vfio/KVM. Despite that in that case the VFs won't work properly with PF removed and/or the module unloaded, I have let it as is because I don't know what side effects may have changing it, and also it seems to be the same that other drivers are doing in this situation.
In the case of being called during SRIOV reconfiguration, the behavior hasn't changed because the function is called with force=false.
Signed-off-by: Íñigo Huguet ihuguet@redhat.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/ethernet/sfc/ef10_sriov.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/sfc/ef10_sriov.c b/drivers/net/ethernet/sfc/ef10_sriov.c index a5d28b0f75ba..84041cd587d7 100644 --- a/drivers/net/ethernet/sfc/ef10_sriov.c +++ b/drivers/net/ethernet/sfc/ef10_sriov.c @@ -402,12 +402,17 @@ static int efx_ef10_pci_sriov_enable(struct efx_nic *efx, int num_vfs) return rc; }
+/* Disable SRIOV and remove VFs + * If some VFs are attached to a guest (using Xen, only) nothing is + * done if force=false, and vports are freed if force=true (for the non + * attachedc ones, only) but SRIOV is not disabled and VFs are not + * removed in either case. + */ static int efx_ef10_pci_sriov_disable(struct efx_nic *efx, bool force) { struct pci_dev *dev = efx->pci_dev; - unsigned int vfs_assigned = 0; - - vfs_assigned = pci_vfs_assigned(dev); + unsigned int vfs_assigned = pci_vfs_assigned(dev); + int rc = 0;
if (vfs_assigned && !force) { netif_info(efx, drv, efx->net_dev, "VFs are assigned to guests; " @@ -417,10 +422,12 @@ static int efx_ef10_pci_sriov_disable(struct efx_nic *efx, bool force)
if (!vfs_assigned) pci_disable_sriov(dev); + else + rc = -EBUSY;
efx_ef10_sriov_free_vf_vswitching(efx); efx->vf_count = 0; - return 0; + return rc; }
int efx_ef10_sriov_configure(struct efx_nic *efx, int num_vfs)
From: Florian Fainelli f.fainelli@gmail.com
[ Upstream commit 64a81b24487f0d2fba0f033029eec2abc7d82cee ]
In case CONFIG_VLAN_8021Q is not set, there will be no call down to the b53 driver to ensure that the default PVID VLAN entry will be configured with the appropriate untagged attribute towards the CPU port. We were implicitly relying on dsa_slave_vlan_rx_add_vid() to do that for us, instead make it explicit.
Reported-by: Vladimir Oltean olteanv@gmail.com Signed-off-by: Florian Fainelli f.fainelli@gmail.com Reviewed-by: Vladimir Oltean olteanv@gmail.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/dsa/b53/b53_common.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-)
diff --git a/drivers/net/dsa/b53/b53_common.c b/drivers/net/dsa/b53/b53_common.c index 3ca6b394dd5f..67a7de87c17a 100644 --- a/drivers/net/dsa/b53/b53_common.c +++ b/drivers/net/dsa/b53/b53_common.c @@ -728,6 +728,13 @@ static u16 b53_default_pvid(struct b53_device *dev) return 0; }
+static bool b53_vlan_port_needs_forced_tagged(struct dsa_switch *ds, int port) +{ + struct b53_device *dev = ds->priv; + + return dev->tag_protocol == DSA_TAG_PROTO_NONE && dsa_is_cpu_port(ds, port); +} + int b53_configure_vlan(struct dsa_switch *ds) { struct b53_device *dev = ds->priv; @@ -748,9 +755,20 @@ int b53_configure_vlan(struct dsa_switch *ds)
b53_enable_vlan(dev, -1, dev->vlan_enabled, ds->vlan_filtering);
- b53_for_each_port(dev, i) + /* Create an untagged VLAN entry for the default PVID in case + * CONFIG_VLAN_8021Q is disabled and there are no calls to + * dsa_slave_vlan_rx_add_vid() to create the default VLAN + * entry. Do this only when the tagging protocol is not + * DSA_TAG_PROTO_NONE + */ + b53_for_each_port(dev, i) { + v = &dev->vlans[def_vid]; + v->members |= BIT(i); + if (!b53_vlan_port_needs_forced_tagged(ds, i)) + v->untag = v->members; b53_write16(dev, B53_VLAN_PAGE, B53_VLAN_PORT_DEF_TAG(i), def_vid); + }
/* Upon initial call we have not set-up any VLANs, but upon * system resume, we need to restore all VLAN entries.
On 7/6/2021 4:13 AM, Sasha Levin wrote:
From: Florian Fainelli f.fainelli@gmail.com
[ Upstream commit 64a81b24487f0d2fba0f033029eec2abc7d82cee ]
In case CONFIG_VLAN_8021Q is not set, there will be no call down to the b53 driver to ensure that the default PVID VLAN entry will be configured with the appropriate untagged attribute towards the CPU port. We were implicitly relying on dsa_slave_vlan_rx_add_vid() to do that for us, instead make it explicit.
Reported-by: Vladimir Oltean olteanv@gmail.com Signed-off-by: Florian Fainelli f.fainelli@gmail.com Reviewed-by: Vladimir Oltean olteanv@gmail.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org
Please discard back porting this patch from 5.13, 5.12 and 5.10 it is part of a larger series and does not fix known uses until 5.14.
On Tue, Jul 06, 2021 at 08:07:34AM -0700, Florian Fainelli wrote:
On 7/6/2021 4:13 AM, Sasha Levin wrote:
From: Florian Fainelli f.fainelli@gmail.com
[ Upstream commit 64a81b24487f0d2fba0f033029eec2abc7d82cee ]
In case CONFIG_VLAN_8021Q is not set, there will be no call down to the b53 driver to ensure that the default PVID VLAN entry will be configured with the appropriate untagged attribute towards the CPU port. We were implicitly relying on dsa_slave_vlan_rx_add_vid() to do that for us, instead make it explicit.
Reported-by: Vladimir Oltean olteanv@gmail.com Signed-off-by: Florian Fainelli f.fainelli@gmail.com Reviewed-by: Vladimir Oltean olteanv@gmail.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org
Please discard back porting this patch from 5.13, 5.12 and 5.10 it is part of a larger series and does not fix known uses until 5.14.
Will do, thanks!
From: "Gustavo A. R. Silva" gustavoars@kernel.org
[ Upstream commit e93bdd78406da9ed01554c51e38b2a02c8ef8025 ]
Fix the following out-of-bounds warning:
net/wireless/wext-spy.c:178:2: warning: 'memcpy' offset [25, 28] from the object at 'threshold' is out of the bounds of referenced subobject 'low' with type 'struct iw_quality' at offset 20 [-Warray-bounds]
The problem is that the original code is trying to copy data into a couple of struct members adjacent to each other in a single call to memcpy(). This causes a legitimate compiler warning because memcpy() overruns the length of &threshold.low and &spydata->spy_thr_low. As these are just a couple of struct members, fix this by using direct assignments, instead of memcpy().
This helps with the ongoing efforts to globally enable -Warray-bounds and get us closer to being able to tighten the FORTIFY_SOURCE routines on memcpy().
Link: https://github.com/KSPP/linux/issues/109 Reported-by: kernel test robot lkp@intel.com Signed-off-by: Gustavo A. R. Silva gustavoars@kernel.org Reviewed-by: Kees Cook keescook@chromium.org Link: https://lore.kernel.org/r/20210422200032.GA168995@embeddedor Signed-off-by: Johannes Berg johannes.berg@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- net/wireless/wext-spy.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/net/wireless/wext-spy.c b/net/wireless/wext-spy.c index 33bef22e44e9..b379a0371653 100644 --- a/net/wireless/wext-spy.c +++ b/net/wireless/wext-spy.c @@ -120,8 +120,8 @@ int iw_handler_set_thrspy(struct net_device * dev, return -EOPNOTSUPP;
/* Just do it */ - memcpy(&(spydata->spy_thr_low), &(threshold->low), - 2 * sizeof(struct iw_quality)); + spydata->spy_thr_low = threshold->low; + spydata->spy_thr_high = threshold->high;
/* Clear flag */ memset(spydata->spy_thr_under, '\0', sizeof(spydata->spy_thr_under)); @@ -147,8 +147,8 @@ int iw_handler_get_thrspy(struct net_device * dev, return -EOPNOTSUPP;
/* Just do it */ - memcpy(&(threshold->low), &(spydata->spy_thr_low), - 2 * sizeof(struct iw_quality)); + threshold->low = spydata->spy_thr_low; + threshold->high = spydata->spy_thr_high;
return 0; } @@ -173,10 +173,10 @@ static void iw_send_thrspy_event(struct net_device * dev, memcpy(threshold.addr.sa_data, address, ETH_ALEN); threshold.addr.sa_family = ARPHRD_ETHER; /* Copy stats */ - memcpy(&(threshold.qual), wstats, sizeof(struct iw_quality)); + threshold.qual = *wstats; /* Copy also thresholds */ - memcpy(&(threshold.low), &(spydata->spy_thr_low), - 2 * sizeof(struct iw_quality)); + threshold.low = spydata->spy_thr_low; + threshold.high = spydata->spy_thr_high;
/* Send event to user space */ wireless_send_event(dev, SIOCGIWTHRSPY, &wrqu, (char *) &threshold);
From: Ping-Ke Shih pkshih@realtek.com
[ Upstream commit 9df66d5b9f45c39b3925d16e8947cc10009b186d ]
In 2G band, a HE sta can only supports HT and HE, but not supports VHT. In this case, default HE tx bitrate mask isn't filled, when we use iw to set bitrates without any parameter.
Signed-off-by: Ping-Ke Shih pkshih@realtek.com Link: https://lore.kernel.org/r/20210609075944.51130-1-pkshih@realtek.com Signed-off-by: Johannes Berg johannes.berg@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- net/wireless/nl80211.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index fc9286afe3c9..912977bf3ec8 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -4781,11 +4781,10 @@ static int nl80211_parse_tx_bitrate_mask(struct genl_info *info, sband->ht_cap.mcs.rx_mask, sizeof(mask->control[i].ht_mcs));
- if (!sband->vht_cap.vht_supported) - continue; - - vht_tx_mcs_map = le16_to_cpu(sband->vht_cap.vht_mcs.tx_mcs_map); - vht_build_mcs_mask(vht_tx_mcs_map, mask->control[i].vht_mcs); + if (sband->vht_cap.vht_supported) { + vht_tx_mcs_map = le16_to_cpu(sband->vht_cap.vht_mcs.tx_mcs_map); + vht_build_mcs_mask(vht_tx_mcs_map, mask->control[i].vht_mcs); + }
he_cap = ieee80211_get_he_iftype_cap(sband, wdev->iftype); if (!he_cap)
From: Johannes Berg johannes.berg@intel.com
[ Upstream commit d656a4c6ead6c3f252b2f2532bc9735598f7e317 ]
If we have been keeping per-CPU statistics, consider them regardless of USES_RSS, because we may not actually fill those, for example in non-fast-RX cases when the connection is not compatible with fast-RX. If we didn't fill them, the additional data will be zero and not affect anything, and if we did fill them then it's more correct to consider them.
This fixes an issue in mesh mode where some statistics are not updated due to USES_RSS being set, but fast-RX isn't used.
Reported-by: Thiraviyam Mariyappan tmariyap@codeaurora.org Link: https://lore.kernel.org/r/20210610220814.13b35f5797c5.I511e9b33c5694e0d6cef4... Signed-off-by: Johannes Berg johannes.berg@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- net/mac80211/sta_info.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-)
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index f2fb69da9b6e..641a6657d0c9 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -2093,10 +2093,9 @@ static struct ieee80211_sta_rx_stats * sta_get_last_rx_stats(struct sta_info *sta) { struct ieee80211_sta_rx_stats *stats = &sta->rx_stats; - struct ieee80211_local *local = sta->local; int cpu;
- if (!ieee80211_hw_check(&local->hw, USES_RSS)) + if (!sta->pcpu_rx_stats) return stats;
for_each_possible_cpu(cpu) { @@ -2196,9 +2195,7 @@ static void sta_set_tidstats(struct sta_info *sta, int cpu;
if (!(tidstats->filled & BIT(NL80211_TID_STATS_RX_MSDU))) { - if (!ieee80211_hw_check(&local->hw, USES_RSS)) - tidstats->rx_msdu += - sta_get_tidstats_msdu(&sta->rx_stats, tid); + tidstats->rx_msdu += sta_get_tidstats_msdu(&sta->rx_stats, tid);
if (sta->pcpu_rx_stats) { for_each_possible_cpu(cpu) { @@ -2277,7 +2274,6 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo, sinfo->rx_beacon = sdata->u.mgd.count_beacon_signal;
drv_sta_statistics(local, sdata, &sta->sta, sinfo); - sinfo->filled |= BIT_ULL(NL80211_STA_INFO_INACTIVE_TIME) | BIT_ULL(NL80211_STA_INFO_STA_FLAGS) | BIT_ULL(NL80211_STA_INFO_BSS_PARAM) | @@ -2312,8 +2308,7 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo,
if (!(sinfo->filled & (BIT_ULL(NL80211_STA_INFO_RX_BYTES64) | BIT_ULL(NL80211_STA_INFO_RX_BYTES)))) { - if (!ieee80211_hw_check(&local->hw, USES_RSS)) - sinfo->rx_bytes += sta_get_stats_bytes(&sta->rx_stats); + sinfo->rx_bytes += sta_get_stats_bytes(&sta->rx_stats);
if (sta->pcpu_rx_stats) { for_each_possible_cpu(cpu) {
From: Weilun Du wdu@google.com
[ Upstream commit 626c30f9e77354301ff9162c3bdddaf92d9b5cf3 ]
This fixed the crash when setting channels to 2 or more when communicating over virtio.
Signed-off-by: Weilun Du wdu@google.com Link: https://lore.kernel.org/r/20210506180530.3418576-1-wdu@google.com Signed-off-by: Johannes Berg johannes.berg@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/wireless/mac80211_hwsim.c | 48 +++++++++++++++++++++------ 1 file changed, 38 insertions(+), 10 deletions(-)
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 7a6fd46d0c6e..ceb089e4a136 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -626,6 +626,7 @@ struct mac80211_hwsim_data { u32 ciphers[ARRAY_SIZE(hwsim_ciphers)];
struct mac_address addresses[2]; + struct ieee80211_chanctx_conf *chanctx; int channels, idx; bool use_chanctx; bool destroy_on_close; @@ -1257,7 +1258,8 @@ static inline u16 trans_tx_rate_flags_ieee2hwsim(struct ieee80211_tx_rate *rate)
static void mac80211_hwsim_tx_frame_nl(struct ieee80211_hw *hw, struct sk_buff *my_skb, - int dst_portid) + int dst_portid, + struct ieee80211_channel *channel) { struct sk_buff *skb; struct mac80211_hwsim_data *data = hw->priv; @@ -1312,7 +1314,7 @@ static void mac80211_hwsim_tx_frame_nl(struct ieee80211_hw *hw, if (nla_put_u32(skb, HWSIM_ATTR_FLAGS, hwsim_flags)) goto nla_put_failure;
- if (nla_put_u32(skb, HWSIM_ATTR_FREQ, data->channel->center_freq)) + if (nla_put_u32(skb, HWSIM_ATTR_FREQ, channel->center_freq)) goto nla_put_failure;
/* We get the tx control (rate and retries) info*/ @@ -1659,7 +1661,7 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw, _portid = READ_ONCE(data->wmediumd);
if (_portid || hwsim_virtio_enabled) - return mac80211_hwsim_tx_frame_nl(hw, skb, _portid); + return mac80211_hwsim_tx_frame_nl(hw, skb, _portid, channel);
/* NO wmediumd detected, perfect medium simulation */ data->tx_pkts++; @@ -1775,7 +1777,7 @@ static void mac80211_hwsim_tx_frame(struct ieee80211_hw *hw, mac80211_hwsim_monitor_rx(hw, skb, chan);
if (_pid || hwsim_virtio_enabled) - return mac80211_hwsim_tx_frame_nl(hw, skb, _pid); + return mac80211_hwsim_tx_frame_nl(hw, skb, _pid, chan);
mac80211_hwsim_tx_frame_no_nl(hw, skb, chan); dev_kfree_skb(skb); @@ -2514,6 +2516,11 @@ static int mac80211_hwsim_croc(struct ieee80211_hw *hw, static int mac80211_hwsim_add_chanctx(struct ieee80211_hw *hw, struct ieee80211_chanctx_conf *ctx) { + struct mac80211_hwsim_data *hwsim = hw->priv; + + mutex_lock(&hwsim->mutex); + hwsim->chanctx = ctx; + mutex_unlock(&hwsim->mutex); hwsim_set_chanctx_magic(ctx); wiphy_dbg(hw->wiphy, "add channel context control: %d MHz/width: %d/cfreqs:%d/%d MHz\n", @@ -2525,6 +2532,11 @@ static int mac80211_hwsim_add_chanctx(struct ieee80211_hw *hw, static void mac80211_hwsim_remove_chanctx(struct ieee80211_hw *hw, struct ieee80211_chanctx_conf *ctx) { + struct mac80211_hwsim_data *hwsim = hw->priv; + + mutex_lock(&hwsim->mutex); + hwsim->chanctx = NULL; + mutex_unlock(&hwsim->mutex); wiphy_dbg(hw->wiphy, "remove channel context control: %d MHz/width: %d/cfreqs:%d/%d MHz\n", ctx->def.chan->center_freq, ctx->def.width, @@ -2537,6 +2549,11 @@ static void mac80211_hwsim_change_chanctx(struct ieee80211_hw *hw, struct ieee80211_chanctx_conf *ctx, u32 changed) { + struct mac80211_hwsim_data *hwsim = hw->priv; + + mutex_lock(&hwsim->mutex); + hwsim->chanctx = ctx; + mutex_unlock(&hwsim->mutex); hwsim_check_chanctx_magic(ctx); wiphy_dbg(hw->wiphy, "change channel context control: %d MHz/width: %d/cfreqs:%d/%d MHz\n", @@ -3129,6 +3146,7 @@ static int mac80211_hwsim_new_radio(struct genl_info *info, hw->wiphy->max_remain_on_channel_duration = 1000; data->if_combination.radar_detect_widths = 0; data->if_combination.num_different_channels = data->channels; + data->chanctx = NULL; } else { data->if_combination.num_different_channels = 1; data->if_combination.radar_detect_widths = @@ -3638,6 +3656,7 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2, int frame_data_len; void *frame_data; struct sk_buff *skb = NULL; + struct ieee80211_channel *channel = NULL;
if (!info->attrs[HWSIM_ATTR_ADDR_RECEIVER] || !info->attrs[HWSIM_ATTR_FRAME] || @@ -3664,6 +3683,17 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2, if (!data2) goto out;
+ if (data2->use_chanctx) { + if (data2->tmp_chan) + channel = data2->tmp_chan; + else if (data2->chanctx) + channel = data2->chanctx->def.chan; + } else { + channel = data2->channel; + } + if (!channel) + goto out; + if (!hwsim_virtio_enabled) { if (hwsim_net_get_netgroup(genl_info_net(info)) != data2->netgroup) @@ -3675,7 +3705,7 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2,
/* check if radio is configured properly */
- if (data2->idle || !data2->started) + if ((data2->idle && !data2->tmp_chan) || !data2->started) goto out;
/* A frame is received from user space */ @@ -3688,18 +3718,16 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2, mutex_lock(&data2->mutex); rx_status.freq = nla_get_u32(info->attrs[HWSIM_ATTR_FREQ]);
- if (rx_status.freq != data2->channel->center_freq && - (!data2->tmp_chan || - rx_status.freq != data2->tmp_chan->center_freq)) { + if (rx_status.freq != channel->center_freq) { mutex_unlock(&data2->mutex); goto out; } mutex_unlock(&data2->mutex); } else { - rx_status.freq = data2->channel->center_freq; + rx_status.freq = channel->center_freq; }
- rx_status.band = data2->channel->band; + rx_status.band = channel->band; rx_status.rate_idx = nla_get_u32(info->attrs[HWSIM_ATTR_RX_RATE]); rx_status.signal = nla_get_u32(info->attrs[HWSIM_ATTR_SIGNAL]);
From: Ilan Peer ilan.peer@intel.com
[ Upstream commit 45daaa1318410794de956fb8e9d06aed2dbb23d0 ]
The following race was possible:
1. The device driver requests HW restart. 2. A scan is requested from user space and is propagated to the driver. During this flow HW_SCANNING flag is set. 3. The thread that handles the HW restart is scheduled, and before starting the actual reconfiguration it checks that HW_SCANNING is not set. The flow does so without acquiring any lock, and thus the WARN fires.
Fix this by checking that HW_SCANNING is on only after RTNL is acquired, i.e., user space scan request handling is no longer in transit.
Signed-off-by: Ilan Peer ilan.peer@intel.com Signed-off-by: Luca Coelho luciano.coelho@intel.com Link: https://lore.kernel.org/r/iwlwifi.20210618133832.8238ab3e19ab.I2693c581c7025... Signed-off-by: Johannes Berg johannes.berg@intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- net/mac80211/main.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index f33a3acd7f96..2481bfdfafd0 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -257,14 +257,13 @@ static void ieee80211_restart_work(struct work_struct *work) /* wait for scan work complete */ flush_workqueue(local->workqueue); flush_work(&local->sched_scan_stopped_work); + flush_work(&local->radar_detected_work); + + rtnl_lock();
WARN(test_bit(SCAN_HW_SCANNING, &local->scanning), "%s called with hardware scan in progress\n", __func__);
- flush_work(&local->radar_detected_work); - /* we might do interface manipulations, so need both */ - rtnl_lock(); - wiphy_lock(local->hw.wiphy); list_for_each_entry(sdata, &local->interfaces, list) { /* * XXX: there may be more work for other vif types and even
From: Max Gurtovoy mgurtovoy@nvidia.com
[ Upstream commit 109d19a5eb3ddbdb87c43bfd4bcf644f4569da64 ]
Since the Linux iser initiator default max I/O size set to 512KB and since there is no handshake procedure for this size in iser protocol, set the default max IO size of the target to 512KB as well.
For changing the default values, there is a module parameter for both drivers.
Link: https://lore.kernel.org/r/20210524085215.29005-1-mgurtovoy@nvidia.com Reviewed-by: Alaa Hleihel alaa@nvidia.com Reviewed-by: Israel Rukshin israelr@nvidia.com Signed-off-by: Max Gurtovoy mgurtovoy@nvidia.com Acked-by: Sagi Grimberg sagi@grimberg.me Signed-off-by: Jason Gunthorpe jgg@nvidia.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/infiniband/ulp/isert/ib_isert.c | 4 ++-- drivers/infiniband/ulp/isert/ib_isert.h | 3 --- 2 files changed, 2 insertions(+), 5 deletions(-)
diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c index 18266f07c58d..de3fc05fd2e8 100644 --- a/drivers/infiniband/ulp/isert/ib_isert.c +++ b/drivers/infiniband/ulp/isert/ib_isert.c @@ -35,10 +35,10 @@ static const struct kernel_param_ops sg_tablesize_ops = { .get = param_get_int, };
-static int isert_sg_tablesize = ISCSI_ISER_DEF_SG_TABLESIZE; +static int isert_sg_tablesize = ISCSI_ISER_MIN_SG_TABLESIZE; module_param_cb(sg_tablesize, &sg_tablesize_ops, &isert_sg_tablesize, 0644); MODULE_PARM_DESC(sg_tablesize, - "Number of gather/scatter entries in a single scsi command, should >= 128 (default: 256, max: 4096)"); + "Number of gather/scatter entries in a single scsi command, should >= 128 (default: 128, max: 4096)");
static DEFINE_MUTEX(device_list_mutex); static LIST_HEAD(device_list); diff --git a/drivers/infiniband/ulp/isert/ib_isert.h b/drivers/infiniband/ulp/isert/ib_isert.h index 6c5af13db4e0..ca8cfebe26ca 100644 --- a/drivers/infiniband/ulp/isert/ib_isert.h +++ b/drivers/infiniband/ulp/isert/ib_isert.h @@ -65,9 +65,6 @@ */ #define ISER_RX_SIZE (ISCSI_DEF_MAX_RECV_SEG_LEN + 1024)
-/* Default I/O size is 1MB */ -#define ISCSI_ISER_DEF_SG_TABLESIZE 256 - /* Minimum I/O size is 512KB */ #define ISCSI_ISER_MIN_SG_TABLESIZE 128
From: Sean Young sean@mess.org
[ Upstream commit 647d446d66e493d23ca1047fa8492b0269674530 ]
The syscall bpf(BPF_PROG_QUERY, &attr) should use the prog_cnt field to see how many entries user space provided and return ENOSPC if there are more programs than that. Before this patch, this is not checked and ENOSPC is never returned.
Note that one lirc device is limited to 64 bpf programs, and user space I'm aware of -- ir-keytable -- always gives enough space for 64 entries already. However, we should not copy program ids than are requested.
Signed-off-by: Sean Young sean@mess.org Signed-off-by: Daniel Borkmann daniel@iogearbox.net Link: https://lore.kernel.org/bpf/20210623213754.632-1-sean@mess.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/media/rc/bpf-lirc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/media/rc/bpf-lirc.c b/drivers/media/rc/bpf-lirc.c index 3fe3edd80876..afae0afe3f81 100644 --- a/drivers/media/rc/bpf-lirc.c +++ b/drivers/media/rc/bpf-lirc.c @@ -326,7 +326,8 @@ int lirc_prog_query(const union bpf_attr *attr, union bpf_attr __user *uattr) }
if (attr->query.prog_cnt != 0 && prog_ids && cnt) - ret = bpf_prog_array_copy_to_user(progs, prog_ids, cnt); + ret = bpf_prog_array_copy_to_user(progs, prog_ids, + attr->query.prog_cnt);
unlock: mutex_unlock(&ir_raw_handler_lock);
From: Martynas Pumputis m@lambda.lt
[ Upstream commit e8b9eab99232c4e62ada9d7976c80fd5e8118289 ]
It's getting more common to run nested container environments for testing cloud software. One of such examples is Kind [1] which runs a Kubernetes cluster in Docker containers on a single host. Each container acts as a Kubernetes node, and thus can run any Pod (aka container) inside the former. This approach simplifies testing a lot, as it eliminates complicated VM setups.
Unfortunately, such a setup breaks some functionality when cgroupv2 BPF programs are used for load-balancing. The load-balancer BPF program needs to detect whether a request originates from the host netns or a container netns in order to allow some access, e.g. to a service via a loopback IP address. Typically, the programs detect this by comparing netns cookies with the one of the init ns via a call to bpf_get_netns_cookie(NULL). However, in nested environments the latter cannot be used given the Kubernetes node's netns is outside the init ns. To fix this, we need to pass the Kubernetes node netns cookie to the program in a different way: by extending getsockopt() with a SO_NETNS_COOKIE option, the orchestrator which runs in the Kubernetes node netns can retrieve the cookie and pass it to the program instead.
Thus, this is following up on Eric's commit 3d368ab87cf6 ("net: initialize net->net_cookie at netns setup") to allow retrieval via SO_NETNS_COOKIE. This is also in line in how we retrieve socket cookie via SO_COOKIE.
Signed-off-by: Lorenz Bauer lmb@cloudflare.com Signed-off-by: Martynas Pumputis m@lambda.lt Cc: Eric Dumazet edumazet@google.com Reviewed-by: Eric Dumazet edumazet@google.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- arch/alpha/include/uapi/asm/socket.h | 2 ++ arch/mips/include/uapi/asm/socket.h | 2 ++ arch/parisc/include/uapi/asm/socket.h | 2 ++ arch/sparc/include/uapi/asm/socket.h | 2 ++ include/uapi/asm-generic/socket.h | 2 ++ net/core/sock.c | 7 +++++++ 6 files changed, 17 insertions(+)
diff --git a/arch/alpha/include/uapi/asm/socket.h b/arch/alpha/include/uapi/asm/socket.h index 57420356ce4c..6b3daba60987 100644 --- a/arch/alpha/include/uapi/asm/socket.h +++ b/arch/alpha/include/uapi/asm/socket.h @@ -127,6 +127,8 @@ #define SO_PREFER_BUSY_POLL 69 #define SO_BUSY_POLL_BUDGET 70
+#define SO_NETNS_COOKIE 71 + #if !defined(__KERNEL__)
#if __BITS_PER_LONG == 64 diff --git a/arch/mips/include/uapi/asm/socket.h b/arch/mips/include/uapi/asm/socket.h index 2d949969313b..cdf404a831b2 100644 --- a/arch/mips/include/uapi/asm/socket.h +++ b/arch/mips/include/uapi/asm/socket.h @@ -138,6 +138,8 @@ #define SO_PREFER_BUSY_POLL 69 #define SO_BUSY_POLL_BUDGET 70
+#define SO_NETNS_COOKIE 71 + #if !defined(__KERNEL__)
#if __BITS_PER_LONG == 64 diff --git a/arch/parisc/include/uapi/asm/socket.h b/arch/parisc/include/uapi/asm/socket.h index f60904329bbc..5b5351cdcb33 100644 --- a/arch/parisc/include/uapi/asm/socket.h +++ b/arch/parisc/include/uapi/asm/socket.h @@ -119,6 +119,8 @@ #define SO_PREFER_BUSY_POLL 0x4043 #define SO_BUSY_POLL_BUDGET 0x4044
+#define SO_NETNS_COOKIE 0x4045 + #if !defined(__KERNEL__)
#if __BITS_PER_LONG == 64 diff --git a/arch/sparc/include/uapi/asm/socket.h b/arch/sparc/include/uapi/asm/socket.h index 848a22fbac20..92675dc380fa 100644 --- a/arch/sparc/include/uapi/asm/socket.h +++ b/arch/sparc/include/uapi/asm/socket.h @@ -120,6 +120,8 @@ #define SO_PREFER_BUSY_POLL 0x0048 #define SO_BUSY_POLL_BUDGET 0x0049
+#define SO_NETNS_COOKIE 0x0050 + #if !defined(__KERNEL__)
diff --git a/include/uapi/asm-generic/socket.h b/include/uapi/asm-generic/socket.h index 4dcd13d097a9..d588c244ec2f 100644 --- a/include/uapi/asm-generic/socket.h +++ b/include/uapi/asm-generic/socket.h @@ -122,6 +122,8 @@ #define SO_PREFER_BUSY_POLL 69 #define SO_BUSY_POLL_BUDGET 70
+#define SO_NETNS_COOKIE 71 + #if !defined(__KERNEL__)
#if __BITS_PER_LONG == 64 || (defined(__x86_64__) && defined(__ILP32__)) diff --git a/net/core/sock.c b/net/core/sock.c index 946888afef88..2003c5ebb4c2 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -1622,6 +1622,13 @@ int sock_getsockopt(struct socket *sock, int level, int optname, v.val = sk->sk_bound_dev_if; break;
+ case SO_NETNS_COOKIE: + lv = sizeof(u64); + if (len != lv) + return -EINVAL; + v.val64 = sock_net(sk)->net_cookie; + break; + default: /* We implement the SO_SNDLOWAT etc to not be settable * (1003.1g 7).
From: Jakub Kicinski kuba@kernel.org
[ Upstream commit 6d123b81ac615072a8525c13c6c41b695270a15d ]
Dave observed number of machines hitting OOM on the UDP send path. The workload seems to be sending large UDP packets over loopback. Since loopback has MTU of 64k kernel will try to allocate an skb with up to 64k of head space. This has a good chance of failing under memory pressure. What's worse if the message length is <32k the allocation may trigger an OOM killer.
This is entirely avoidable, we can use an skb with page frags.
af_unix solves a similar problem by limiting the head length to SKB_MAX_ALLOC. This seems like a good and simple approach. It means that UDP messages > 16kB will now use fragments if underlying device supports SG, if extra allocator pressure causes regressions in real workloads we can switch to trying the large allocation first and falling back.
v4: pre-calculate all the additions to alloclen so we can be sure it won't go over order-2
Reported-by: Dave Jones dsj@fb.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- net/ipv4/ip_output.c | 32 ++++++++++++++++++-------------- net/ipv6/ip6_output.c | 32 +++++++++++++++++--------------- 2 files changed, 35 insertions(+), 29 deletions(-)
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index c3efc7d658f6..8d8a8da3ae7e 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -1054,7 +1054,7 @@ static int __ip_append_data(struct sock *sk, unsigned int datalen; unsigned int fraglen; unsigned int fraggap; - unsigned int alloclen; + unsigned int alloclen, alloc_extra; unsigned int pagedlen; struct sk_buff *skb_prev; alloc_new_skb: @@ -1074,35 +1074,39 @@ static int __ip_append_data(struct sock *sk, fraglen = datalen + fragheaderlen; pagedlen = 0;
+ alloc_extra = hh_len + 15; + alloc_extra += exthdrlen; + + /* The last fragment gets additional space at tail. + * Note, with MSG_MORE we overallocate on fragments, + * because we have no idea what fragment will be + * the last. + */ + if (datalen == length + fraggap) + alloc_extra += rt->dst.trailer_len; + if ((flags & MSG_MORE) && !(rt->dst.dev->features&NETIF_F_SG)) alloclen = mtu; - else if (!paged) + else if (!paged && + (fraglen + alloc_extra < SKB_MAX_ALLOC || + !(rt->dst.dev->features & NETIF_F_SG))) alloclen = fraglen; else { alloclen = min_t(int, fraglen, MAX_HEADER); pagedlen = fraglen - alloclen; }
- alloclen += exthdrlen; - - /* The last fragment gets additional space at tail. - * Note, with MSG_MORE we overallocate on fragments, - * because we have no idea what fragment will be - * the last. - */ - if (datalen == length + fraggap) - alloclen += rt->dst.trailer_len; + alloclen += alloc_extra;
if (transhdrlen) { - skb = sock_alloc_send_skb(sk, - alloclen + hh_len + 15, + skb = sock_alloc_send_skb(sk, alloclen, (flags & MSG_DONTWAIT), &err); } else { skb = NULL; if (refcount_read(&sk->sk_wmem_alloc) + wmem_alloc_delta <= 2 * sk->sk_sndbuf) - skb = alloc_skb(alloclen + hh_len + 15, + skb = alloc_skb(alloclen, sk->sk_allocation); if (unlikely(!skb)) err = -ENOBUFS; diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index ff4f9ebcf7f6..497974b4372a 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -1555,7 +1555,7 @@ static int __ip6_append_data(struct sock *sk, unsigned int datalen; unsigned int fraglen; unsigned int fraggap; - unsigned int alloclen; + unsigned int alloclen, alloc_extra; unsigned int pagedlen; alloc_new_skb: /* There's no room in the current skb */ @@ -1582,17 +1582,28 @@ static int __ip6_append_data(struct sock *sk, fraglen = datalen + fragheaderlen; pagedlen = 0;
+ alloc_extra = hh_len; + alloc_extra += dst_exthdrlen; + alloc_extra += rt->dst.trailer_len; + + /* We just reserve space for fragment header. + * Note: this may be overallocation if the message + * (without MSG_MORE) fits into the MTU. + */ + alloc_extra += sizeof(struct frag_hdr); + if ((flags & MSG_MORE) && !(rt->dst.dev->features&NETIF_F_SG)) alloclen = mtu; - else if (!paged) + else if (!paged && + (fraglen + alloc_extra < SKB_MAX_ALLOC || + !(rt->dst.dev->features & NETIF_F_SG))) alloclen = fraglen; else { alloclen = min_t(int, fraglen, MAX_HEADER); pagedlen = fraglen - alloclen; } - - alloclen += dst_exthdrlen; + alloclen += alloc_extra;
if (datalen != length + fraggap) { /* @@ -1602,30 +1613,21 @@ static int __ip6_append_data(struct sock *sk, datalen += rt->dst.trailer_len; }
- alloclen += rt->dst.trailer_len; fraglen = datalen + fragheaderlen;
- /* - * We just reserve space for fragment header. - * Note: this may be overallocation if the message - * (without MSG_MORE) fits into the MTU. - */ - alloclen += sizeof(struct frag_hdr); - copy = datalen - transhdrlen - fraggap - pagedlen; if (copy < 0) { err = -EINVAL; goto error; } if (transhdrlen) { - skb = sock_alloc_send_skb(sk, - alloclen + hh_len, + skb = sock_alloc_send_skb(sk, alloclen, (flags & MSG_DONTWAIT), &err); } else { skb = NULL; if (refcount_read(&sk->sk_wmem_alloc) + wmem_alloc_delta <= 2 * sk->sk_sndbuf) - skb = alloc_skb(alloclen + hh_len, + skb = alloc_skb(alloclen, sk->sk_allocation); if (unlikely(!skb)) err = -ENOBUFS;
From: Gerd Rausch gerd.rausch@oracle.com
[ Upstream commit 74f160ead74bfe5f2b38afb4fcf86189f9ff40c9 ]
Fix a memory leak when "mda_resolve_route() is called more than once on the same "rdma_cm_id".
This is possible if cma_query_handler() triggers the RDMA_CM_EVENT_ROUTE_ERROR flow which puts the state machine back and allows rdma_resolve_route() to be called again.
Link: https://lore.kernel.org/r/f6662b7b-bdb7-2706-1e12-47c61d3474b6@oracle.com Signed-off-by: Gerd Rausch gerd.rausch@oracle.com Signed-off-by: Jason Gunthorpe jgg@nvidia.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/infiniband/core/cma.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index ab148a696c0c..4a76d5b4163e 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -2819,7 +2819,8 @@ static int cma_resolve_ib_route(struct rdma_id_private *id_priv,
cma_init_resolve_route_work(work, id_priv);
- route->path_rec = kmalloc(sizeof *route->path_rec, GFP_KERNEL); + if (!route->path_rec) + route->path_rec = kmalloc(sizeof *route->path_rec, GFP_KERNEL); if (!route->path_rec) { ret = -ENOMEM; goto err1;
From: "mark-yw.chen" mark-yw.chen@mediatek.com
[ Upstream commit 8454ed9ff9647e31e061fb5eb2e39ce79bc5e960 ]
This patch reduce in-token during download patch procedure. Don't submit urb for polling event before sending hci command.
Signed-off-by: mark-yw.chen mark-yw.chen@mediatek.com Signed-off-by: Marcel Holtmann marcel@holtmann.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/bluetooth/btusb.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 7f6ba2c975ed..99fd88f7653d 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -3312,11 +3312,6 @@ static int btusb_mtk_hci_wmt_sync(struct hci_dev *hdev, struct btmtk_wmt_hdr *hdr; int err;
- /* Submit control IN URB on demand to process the WMT event */ - err = btusb_mtk_submit_wmt_recv_urb(hdev); - if (err < 0) - return err; - /* Send the WMT command and wait until the WMT event returns */ hlen = sizeof(*hdr) + wmt_params->dlen; if (hlen > 255) @@ -3342,6 +3337,11 @@ static int btusb_mtk_hci_wmt_sync(struct hci_dev *hdev, goto err_free_wc; }
+ /* Submit control IN URB on demand to process the WMT event */ + err = btusb_mtk_submit_wmt_recv_urb(hdev); + if (err < 0) + return err; + /* The vendor specific WMT commands are all answered by a vendor * specific event and will have the Command Status or Command * Complete as with usual HCI command flow control.
From: Thadeu Lima de Souza Cascardo cascardo@canonical.com
[ Upstream commit 3cfdf8fcaafa62a4123f92eb0f4a72650da3a479 ]
When cmtp_attach_device fails, cmtp_add_connection returns the error value which leads to the caller to doing fput through sockfd_put. But cmtp_session kthread, which is stopped in this path will also call fput, leading to a potential refcount underflow or a use-after-free.
Add a refcount before we signal the kthread to stop. The kthread will try to grab the cmtp_session_sem mutex before doing the fput, which is held when get_file is called, so there should be no races there.
Reported-by: Ryota Shiga Signed-off-by: Thadeu Lima de Souza Cascardo cascardo@canonical.com Signed-off-by: Marcel Holtmann marcel@holtmann.org Signed-off-by: Sasha Levin sashal@kernel.org --- net/bluetooth/cmtp/core.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/net/bluetooth/cmtp/core.c b/net/bluetooth/cmtp/core.c index 07cfa3249f83..0a2d78e811cf 100644 --- a/net/bluetooth/cmtp/core.c +++ b/net/bluetooth/cmtp/core.c @@ -392,6 +392,11 @@ int cmtp_add_connection(struct cmtp_connadd_req *req, struct socket *sock) if (!(session->flags & BIT(CMTP_LOOPBACK))) { err = cmtp_attach_device(session); if (err < 0) { + /* Caller will call fput in case of failure, and so + * will cmtp_session kthread. + */ + get_file(session->sock->file); + atomic_inc(&session->terminate); wake_up_interruptible(sk_sleep(session->sock->sk)); up_write(&cmtp_session_sem);
From: Yu Liu yudiliu@google.com
[ Upstream commit 4ef36a52b0e47c80bbfd69c0cce61c7ae9f541ed ]
0x2B, 0x31 and 0x33 are reserved for future use but were not present in the HCI to MGMT conversion table, this caused the conversion to be incorrect for the HCI status code greater than 0x2A.
Reviewed-by: Miao-chen Chou mcchou@chromium.org Signed-off-by: Yu Liu yudiliu@google.com Signed-off-by: Marcel Holtmann marcel@holtmann.org Signed-off-by: Sasha Levin sashal@kernel.org --- net/bluetooth/mgmt.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index f9be7f9084d6..425502f1d380 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -252,12 +252,15 @@ static const u8 mgmt_status_table[] = { MGMT_STATUS_TIMEOUT, /* Instant Passed */ MGMT_STATUS_NOT_SUPPORTED, /* Pairing Not Supported */ MGMT_STATUS_FAILED, /* Transaction Collision */ + MGMT_STATUS_FAILED, /* Reserved for future use */ MGMT_STATUS_INVALID_PARAMS, /* Unacceptable Parameter */ MGMT_STATUS_REJECTED, /* QoS Rejected */ MGMT_STATUS_NOT_SUPPORTED, /* Classification Not Supported */ MGMT_STATUS_REJECTED, /* Insufficient Security */ MGMT_STATUS_INVALID_PARAMS, /* Parameter Out Of Range */ + MGMT_STATUS_FAILED, /* Reserved for future use */ MGMT_STATUS_BUSY, /* Role Switch Pending */ + MGMT_STATUS_FAILED, /* Reserved for future use */ MGMT_STATUS_FAILED, /* Slot Violation */ MGMT_STATUS_FAILED, /* Role Switch Failed */ MGMT_STATUS_INVALID_PARAMS, /* EIR Too Large */
From: Kiran K kiran.k@intel.com
[ Upstream commit 06d213d8a89a6f55b708422c3dda2b22add10748 ]
For incoming SCO connection with transparent coding format, alt setting of CVSD is getting applied instead of Transparent.
Before fix: < HCI Command: Accept Synchron.. (0x01|0x0029) plen 21 #2196 [hci0] 321.342548 Address: 1C:CC:D6:E2:EA:80 (Xiaomi Communications Co Ltd) Transmit bandwidth: 8000 Receive bandwidth: 8000 Max latency: 13 Setting: 0x0003 Input Coding: Linear Input Data Format: 1's complement Input Sample Size: 8-bit # of bits padding at MSB: 0 Air Coding Format: Transparent Data Retransmission effort: Optimize for link quality (0x02) Packet type: 0x003f HV1 may be used HV2 may be used HV3 may be used EV3 may be used EV4 may be used EV5 may be used
HCI Event: Command Status (0x0f) plen 4 #2197 [hci0] 321.343585
Accept Synchronous Connection Request (0x01|0x0029) ncmd 1 Status: Success (0x00)
HCI Event: Synchronous Connect Comp.. (0x2c) plen 17 #2198 [hci0] 321.351666
Status: Success (0x00) Handle: 257 Address: 1C:CC:D6:E2:EA:80 (Xiaomi Communications Co Ltd) Link type: eSCO (0x02) Transmission interval: 0x0c Retransmission window: 0x04 RX packet length: 60 TX packet length: 60 Air mode: Transparent (0x03) ........
SCO Data RX: Handle 257 flags 0x00 dlen 48 #2336 [hci0] 321.383655
< SCO Data TX: Handle 257 flags 0x00 dlen 60 #2337 [hci0] 321.389558
SCO Data RX: Handle 257 flags 0x00 dlen 48 #2338 [hci0] 321.393615 SCO Data RX: Handle 257 flags 0x00 dlen 48 #2339 [hci0] 321.393618 SCO Data RX: Handle 257 flags 0x00 dlen 48 #2340 [hci0] 321.393618
< SCO Data TX: Handle 257 flags 0x00 dlen 60 #2341 [hci0] 321.397070
SCO Data RX: Handle 257 flags 0x00 dlen 48 #2342 [hci0] 321.403622 SCO Data RX: Handle 257 flags 0x00 dlen 48 #2343 [hci0] 321.403625 SCO Data RX: Handle 257 flags 0x00 dlen 48 #2344 [hci0] 321.403625 SCO Data RX: Handle 257 flags 0x00 dlen 48 #2345 [hci0] 321.403625
< SCO Data TX: Handle 257 flags 0x00 dlen 60 #2346 [hci0] 321.404569 < SCO Data TX: Handle 257 flags 0x00 dlen 60 #2347 [hci0] 321.412091
SCO Data RX: Handle 257 flags 0x00 dlen 48 #2348 [hci0] 321.413626 SCO Data RX: Handle 257 flags 0x00 dlen 48 #2349 [hci0] 321.413630 SCO Data RX: Handle 257 flags 0x00 dlen 48 #2350 [hci0] 321.413630
< SCO Data TX: Handle 257 flags 0x00 dlen 60 #2351 [hci0] 321.419674
After fix:
< HCI Command: Accept Synchronou.. (0x01|0x0029) plen 21 #309 [hci0] 49.439693 Address: 1C:CC:D6:E2:EA:80 (Xiaomi Communications Co Ltd) Transmit bandwidth: 8000 Receive bandwidth: 8000 Max latency: 13 Setting: 0x0003 Input Coding: Linear Input Data Format: 1's complement Input Sample Size: 8-bit # of bits padding at MSB: 0 Air Coding Format: Transparent Data Retransmission effort: Optimize for link quality (0x02) Packet type: 0x003f HV1 may be used HV2 may be used HV3 may be used EV3 may be used EV4 may be used EV5 may be used
HCI Event: Command Status (0x0f) plen 4 #310 [hci0] 49.440308
Accept Synchronous Connection Request (0x01|0x0029) ncmd 1 Status: Success (0x00)
HCI Event: Synchronous Connect Complete (0x2c) plen 17 #311 [hci0] 49.449308
Status: Success (0x00) Handle: 257 Address: 1C:CC:D6:E2:EA:80 (Xiaomi Communications Co Ltd) Link type: eSCO (0x02) Transmission interval: 0x0c Retransmission window: 0x04 RX packet length: 60 TX packet length: 60 Air mode: Transparent (0x03) < SCO Data TX: Handle 257 flags 0x00 dlen 60 #312 [hci0] 49.450421 < SCO Data TX: Handle 257 flags 0x00 dlen 60 #313 [hci0] 49.457927
HCI Event: Max Slots Change (0x1b) plen 3 #314 [hci0] 49.460345
Handle: 256 Max slots: 5 < SCO Data TX: Handle 257 flags 0x00 dlen 60 #315 [hci0] 49.465453
SCO Data RX: Handle 257 flags 0x00 dlen 60 #316 [hci0] 49.470502 SCO Data RX: Handle 257 flags 0x00 dlen 60 #317 [hci0] 49.470519
< SCO Data TX: Handle 257 flags 0x00 dlen 60 #318 [hci0] 49.472996
SCO Data RX: Handle 257 flags 0x00 dlen 60 #319 [hci0] 49.480412
< SCO Data TX: Handle 257 flags 0x00 dlen 60 #320 [hci0] 49.480492 < SCO Data TX: Handle 257 flags 0x00 dlen 60 #321 [hci0] 49.487989
SCO Data RX: Handle 257 flags 0x00 dlen 60 #322 [hci0] 49.490303
< SCO Data TX: Handle 257 flags 0x00 dlen 60 #323 [hci0] 49.495496
SCO Data RX: Handle 257 flags 0x00 dlen 60 #324 [hci0] 49.500304 SCO Data RX: Handle 257 flags 0x00 dlen 60 #325 [hci0] 49.500311
Signed-off-by: Kiran K kiran.k@intel.com Signed-off-by: Lokendra Singh lokendra.singh@intel.com Signed-off-by: Marcel Holtmann marcel@holtmann.org Signed-off-by: Sasha Levin sashal@kernel.org --- net/bluetooth/hci_event.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 016b2999f219..47166cea68bb 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -4404,12 +4404,12 @@ static void hci_sync_conn_complete_evt(struct hci_dev *hdev,
bt_dev_dbg(hdev, "SCO connected with air mode: %02x", ev->air_mode);
- switch (conn->setting & SCO_AIRMODE_MASK) { - case SCO_AIRMODE_CVSD: + switch (ev->air_mode) { + case 0x02: if (hdev->notify) hdev->notify(hdev, HCI_NOTIFY_ENABLE_SCO_CVSD); break; - case SCO_AIRMODE_TRANSP: + case 0x03: if (hdev->notify) hdev->notify(hdev, HCI_NOTIFY_ENABLE_SCO_TRANSP); break;
From: Kai-Heng Feng kai.heng.feng@canonical.com
[ Upstream commit 0ea9fd001a14ebc294f112b0361a4e601551d508 ]
Rfkill block and unblock Intel USB Bluetooth [8087:0026] may make it stops working: [ 509.691509] Bluetooth: hci0: HCI reset during shutdown failed [ 514.897584] Bluetooth: hci0: MSFT filter_enable is already on [ 530.044751] usb 3-10: reset full-speed USB device number 5 using xhci_hcd [ 545.660350] usb 3-10: device descriptor read/64, error -110 [ 561.283530] usb 3-10: device descriptor read/64, error -110 [ 561.519682] usb 3-10: reset full-speed USB device number 5 using xhci_hcd [ 566.686650] Bluetooth: hci0: unexpected event for opcode 0x0500 [ 568.752452] Bluetooth: hci0: urb 0000000096cd309b failed to resubmit (113) [ 578.797955] Bluetooth: hci0: Failed to read MSFT supported features (-110) [ 586.286565] Bluetooth: hci0: urb 00000000c522f633 failed to resubmit (113) [ 596.215302] Bluetooth: hci0: Failed to read MSFT supported features (-110)
Or kernel panics because other workqueues already freed skb: [ 2048.663763] BUG: kernel NULL pointer dereference, address: 0000000000000000 [ 2048.663775] #PF: supervisor read access in kernel mode [ 2048.663779] #PF: error_code(0x0000) - not-present page [ 2048.663782] PGD 0 P4D 0 [ 2048.663787] Oops: 0000 [#1] SMP NOPTI [ 2048.663793] CPU: 3 PID: 4491 Comm: rfkill Tainted: G W 5.13.0-rc1-next-20210510+ #20 [ 2048.663799] Hardware name: HP HP EliteBook 850 G8 Notebook PC/8846, BIOS T76 Ver. 01.01.04 12/02/2020 [ 2048.663801] RIP: 0010:__skb_ext_put+0x6/0x50 [ 2048.663814] Code: 8b 1b 48 85 db 75 db 5b 41 5c 5d c3 be 01 00 00 00 e8 de 13 c0 ff eb e7 be 02 00 00 00 e8 d2 13 c0 ff eb db 0f 1f 44 00 00 55 <8b> 07 48 89 e5 83 f8 01 74 14 b8 ff ff ff ff f0 0f c1 07 83 f8 01 [ 2048.663819] RSP: 0018:ffffc1d105b6fd80 EFLAGS: 00010286 [ 2048.663824] RAX: 0000000000000000 RBX: ffff9d9ac5649000 RCX: 0000000000000000 [ 2048.663827] RDX: ffffffffc0d1daf6 RSI: 0000000000000206 RDI: 0000000000000000 [ 2048.663830] RBP: ffffc1d105b6fd98 R08: 0000000000000001 R09: ffff9d9ace8ceac0 [ 2048.663834] R10: ffff9d9ace8ceac0 R11: 0000000000000001 R12: ffff9d9ac5649000 [ 2048.663838] R13: 0000000000000000 R14: 00007ffe0354d650 R15: 0000000000000000 [ 2048.663843] FS: 00007fe02ab19740(0000) GS:ffff9d9e5f8c0000(0000) knlGS:0000000000000000 [ 2048.663849] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 2048.663853] CR2: 0000000000000000 CR3: 0000000111a52004 CR4: 0000000000770ee0 [ 2048.663856] PKRU: 55555554 [ 2048.663859] Call Trace: [ 2048.663865] ? skb_release_head_state+0x5e/0x80 [ 2048.663873] kfree_skb+0x2f/0xb0 [ 2048.663881] btusb_shutdown_intel_new+0x36/0x60 [btusb] [ 2048.663905] hci_dev_do_close+0x48c/0x5e0 [bluetooth] [ 2048.663954] ? __cond_resched+0x1a/0x50 [ 2048.663962] hci_rfkill_set_block+0x56/0xa0 [bluetooth] [ 2048.664007] rfkill_set_block+0x98/0x170 [ 2048.664016] rfkill_fop_write+0x136/0x1e0 [ 2048.664022] vfs_write+0xc7/0x260 [ 2048.664030] ksys_write+0xb1/0xe0 [ 2048.664035] ? exit_to_user_mode_prepare+0x37/0x1c0 [ 2048.664042] __x64_sys_write+0x1a/0x20 [ 2048.664048] do_syscall_64+0x40/0xb0 [ 2048.664055] entry_SYSCALL_64_after_hwframe+0x44/0xae [ 2048.664060] RIP: 0033:0x7fe02ac23c27 [ 2048.664066] 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 [ 2048.664070] RSP: 002b:00007ffe0354d638 EFLAGS: 00000246 ORIG_RAX: 0000000000000001 [ 2048.664075] RAX: ffffffffffffffda RBX: 0000000000000001 RCX: 00007fe02ac23c27 [ 2048.664078] RDX: 0000000000000008 RSI: 00007ffe0354d650 RDI: 0000000000000003 [ 2048.664081] RBP: 0000000000000000 R08: 0000559b05998440 R09: 0000559b05998440 [ 2048.664084] R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000003 [ 2048.664086] R13: 0000000000000000 R14: ffffffff00000000 R15: 00000000ffffffff
So move the shutdown callback to a place where workqueues are either flushed or cancelled to resolve the issue.
Signed-off-by: Kai-Heng Feng kai.heng.feng@canonical.com Signed-off-by: Marcel Holtmann marcel@holtmann.org Signed-off-by: Sasha Levin sashal@kernel.org --- net/bluetooth/hci_core.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 7d71d104fdfd..ded55f54d9c8 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -1721,14 +1721,6 @@ int hci_dev_do_close(struct hci_dev *hdev)
BT_DBG("%s %p", hdev->name, hdev);
- if (!hci_dev_test_flag(hdev, HCI_UNREGISTER) && - !hci_dev_test_flag(hdev, HCI_USER_CHANNEL) && - test_bit(HCI_UP, &hdev->flags)) { - /* Execute vendor specific shutdown routine */ - if (hdev->shutdown) - hdev->shutdown(hdev); - } - cancel_delayed_work(&hdev->power_off);
hci_request_cancel_all(hdev); @@ -1805,6 +1797,14 @@ int hci_dev_do_close(struct hci_dev *hdev) clear_bit(HCI_INIT, &hdev->flags); }
+ if (!hci_dev_test_flag(hdev, HCI_UNREGISTER) && + !hci_dev_test_flag(hdev, HCI_USER_CHANNEL) && + test_bit(HCI_UP, &hdev->flags)) { + /* Execute vendor specific shutdown routine */ + if (hdev->shutdown) + hdev->shutdown(hdev); + } + /* flush cmd work */ flush_work(&hdev->cmd_work);
From: Daniel Lenski dlenski@gmail.com
[ Upstream commit 0324d19cb99804d99e42c990b8b1e191575a091b ]
This patch adds the 0cf3:e500 Bluetooth device (from a QCA9377 board) as a QCA_ROME device. It appears to be functionally identical to another device ID, also from a QCA9377 board, which was previously marked as QCA_ROME in 0a03f98b98c201191e3ba15a0e33f46d8660e1fd ("Bluetooth: Add a new 04ca:3015 QCA_ROME device").
Without this patch, the WiFi side of the QCA9377 board is slow or unusable when the Bluetooth side is in use.
See https://askubuntu.com/a/1137852 for another report of QCA_ROME fixing this issue for this device ID.
/sys/kernel/debug/usb/devices:
T: Bus=05 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 2 Spd=12 MxCh= 0 D: Ver= 2.01 Cls=e0(wlcon) Sub=01 Prot=01 MxPS=64 #Cfgs= 1 P: Vendor=0cf3 ProdID=e500 Rev= 0.01 C:* #Ifs= 2 Cfg#= 1 Atr=e0 MxPwr=100mA I:* If#= 0 Alt= 0 #EPs= 3 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=81(I) Atr=03(Int.) MxPS= 16 Ivl=1ms E: Ad=82(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms E: Ad=02(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms I:* If#= 1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=83(I) Atr=01(Isoc) MxPS= 0 Ivl=1ms E: Ad=03(O) Atr=01(Isoc) MxPS= 0 Ivl=1ms I: If#= 1 Alt= 1 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=83(I) Atr=01(Isoc) MxPS= 9 Ivl=1ms E: Ad=03(O) Atr=01(Isoc) MxPS= 9 Ivl=1ms I: If#= 1 Alt= 2 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=83(I) Atr=01(Isoc) MxPS= 17 Ivl=1ms E: Ad=03(O) Atr=01(Isoc) MxPS= 17 Ivl=1ms I: If#= 1 Alt= 3 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=83(I) Atr=01(Isoc) MxPS= 25 Ivl=1ms E: Ad=03(O) Atr=01(Isoc) MxPS= 25 Ivl=1ms I: If#= 1 Alt= 4 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=83(I) Atr=01(Isoc) MxPS= 33 Ivl=1ms E: Ad=03(O) Atr=01(Isoc) MxPS= 33 Ivl=1ms I: If#= 1 Alt= 5 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=83(I) Atr=01(Isoc) MxPS= 49 Ivl=1ms E: Ad=03(O) Atr=01(Isoc) MxPS= 49 Ivl=1ms
Signed-off-by: Daniel Lenski dlenski@gmail.com Signed-off-by: Marcel Holtmann marcel@holtmann.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/bluetooth/btusb.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 99fd88f7653d..90872099d9c3 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -270,6 +270,8 @@ static const struct usb_device_id blacklist_table[] = { BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x0cf3, 0xe360), .driver_info = BTUSB_QCA_ROME | BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x0cf3, 0xe500), .driver_info = BTUSB_QCA_ROME | + BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x0489, 0xe092), .driver_info = BTUSB_QCA_ROME | BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x0489, 0xe09f), .driver_info = BTUSB_QCA_ROME |
From: Luiz Augusto von Dentz luiz.von.dentz@intel.com
[ Upstream commit 1fa20d7d4aad02206e84b74915819fbe9f81dab3 ]
The use of l2cap_chan_del is not safe under a loop using list_for_each_entry.
Reported-by: Dan Carpenter dan.carpenter@oracle.com Signed-off-by: Luiz Augusto von Dentz luiz.von.dentz@intel.com Signed-off-by: Marcel Holtmann marcel@holtmann.org Signed-off-by: Sasha Levin sashal@kernel.org --- net/bluetooth/l2cap_core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index b6a88b8256c7..9b6e57204f51 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -6248,7 +6248,7 @@ static inline int l2cap_ecred_reconf_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data) { - struct l2cap_chan *chan; + struct l2cap_chan *chan, *tmp; struct l2cap_ecred_conn_rsp *rsp = (void *) data; u16 result;
@@ -6262,7 +6262,7 @@ static inline int l2cap_ecred_reconf_rsp(struct l2cap_conn *conn, if (!result) return 0;
- list_for_each_entry(chan, &conn->chan_l, list) { + list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) { if (chan->ident != cmd->ident) continue;
From: Luiz Augusto von Dentz luiz.von.dentz@intel.com
[ Upstream commit de895b43932cb47e69480540be7eca289af24f23 ]
The use of l2cap_chan_del is not safe under a loop using list_for_each_entry.
Signed-off-by: Luiz Augusto von Dentz luiz.von.dentz@intel.com Signed-off-by: Marcel Holtmann marcel@holtmann.org Signed-off-by: Sasha Levin sashal@kernel.org --- net/bluetooth/l2cap_core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 9b6e57204f51..9908aa53a682 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -6066,7 +6066,7 @@ static inline int l2cap_ecred_conn_rsp(struct l2cap_conn *conn, struct l2cap_ecred_conn_rsp *rsp = (void *) data; struct hci_conn *hcon = conn->hcon; u16 mtu, mps, credits, result; - struct l2cap_chan *chan; + struct l2cap_chan *chan, *tmp; int err = 0, sec_level; int i = 0;
@@ -6085,7 +6085,7 @@ static inline int l2cap_ecred_conn_rsp(struct l2cap_conn *conn,
cmd_len -= sizeof(*rsp);
- list_for_each_entry(chan, &conn->chan_l, list) { + list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) { u16 dcid;
if (chan->ident != cmd->ident ||
From: Hilda Wu hildawu@realtek.com
[ Upstream commit e848dbd364aca44c9d23c04bef964fab79e2b34f ]
Because mSBC frames do not need to be aligned to the SCO packet boundary. Using USB ALT 3 let HCI payload >= 60 bytes, let mSBC data satisfy 60 Bytes avoid payload unaligned situation and fixed some headset no voise issue.
USB Alt 3 supported also need HFP support transparent MTU in 72 Bytes.
Signed-off-by: Hilda Wu hildawu@realtek.com Signed-off-by: Marcel Holtmann marcel@holtmann.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/bluetooth/btusb.c | 7 +++++++ 1 file changed, 7 insertions(+)
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 90872099d9c3..4c18a85a1070 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -1751,6 +1751,13 @@ static void btusb_work(struct work_struct *work) * which work with WBS at all. */ new_alts = btusb_find_altsetting(data, 6) ? 6 : 1; + /* Because mSBC frames do not need to be aligned to the + * SCO packet boundary. If support the Alt 3, use the + * Alt 3 for HCI payload >= 60 Bytes let air packet + * data satisfy 60 bytes. + */ + if (new_alts == 1 && btusb_find_altsetting(data, 3)) + new_alts = 3; }
if (btusb_switch_alt_setting(hdev, new_alts) < 0)
From: Tedd Ho-Jeong An tedd.an@intel.com
[ Upstream commit 02ce2c2c24024aade65a8d91d6a596651eaf2d0a ]
When the Get Device Flags command fails, it returns the error status with the parameters filled with the garbage values. Although the parameters are not used, it is better to fill with zero than the random values.
Signed-off-by: Tedd Ho-Jeong An tedd.an@intel.com Signed-off-by: Marcel Holtmann marcel@holtmann.org Signed-off-by: Sasha Levin sashal@kernel.org --- net/bluetooth/mgmt.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 425502f1d380..d0c8b8a41914 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -4061,6 +4061,8 @@ static int get_device_flags(struct sock *sk, struct hci_dev *hdev, void *data,
hci_dev_lock(hdev);
+ memset(&rp, 0, sizeof(rp)); + if (cp->addr.type == BDADDR_BREDR) { br_params = hci_bdaddr_list_lookup_with_flags(&hdev->whitelist, &cp->addr.bdaddr,
From: Tim Jiang tjiang@codeaurora.org
[ Upstream commit ca17a5cccf8b6d35dab4729bea8f4350bc0b4caf ]
if boardID is 0, will use the default nvm file without surfix.
Signed-off-by: Tim Jiang tjiang@codeaurora.org Signed-off-by: Marcel Holtmann marcel@holtmann.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/bluetooth/btusb.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 4c18a85a1070..1cec9b2353c6 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -4163,9 +4163,15 @@ static int btusb_setup_qca_load_nvm(struct hci_dev *hdev, int err;
if (((ver->flag >> 8) & 0xff) == QCA_FLAG_MULTI_NVM) { - snprintf(fwname, sizeof(fwname), "qca/nvm_usb_%08x_%04x.bin", - le32_to_cpu(ver->rom_version), - le16_to_cpu(ver->board_id)); + /* if boardid equal 0, use default nvm without surfix */ + if (le16_to_cpu(ver->board_id) == 0x0) { + snprintf(fwname, sizeof(fwname), "qca/nvm_usb_%08x.bin", + le32_to_cpu(ver->rom_version)); + } else { + snprintf(fwname, sizeof(fwname), "qca/nvm_usb_%08x_%04x.bin", + le32_to_cpu(ver->rom_version), + le16_to_cpu(ver->board_id)); + } } else { snprintf(fwname, sizeof(fwname), "qca/nvm_usb_%08x.bin", le32_to_cpu(ver->rom_version));
From: Tim Jiang tjiang@codeaurora.org
[ Upstream commit 4f00bfb372674d586c4a261bfc595cbce101fbb6 ]
This is btsoc timing issue, after host start to downloading bt firmware, ep2 need time to switch from function acl to function dfu, so host add 20ms delay as workaround.
Signed-off-by: Tim Jiang tjiang@codeaurora.org Signed-off-by: Marcel Holtmann marcel@holtmann.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/bluetooth/btusb.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 1cec9b2353c6..6d23308119d1 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -4071,6 +4071,11 @@ static int btusb_setup_qca_download_fw(struct hci_dev *hdev, sent += size; count -= size;
+ /* ep2 need time to switch from function acl to function dfu, + * so we add 20ms delay here. + */ + msleep(20); + while (count) { size = min_t(size_t, count, QCA_DFU_PACKET_LEN);
From: Odin Ugedal odin@uged.al
[ Upstream commit 1c35b07e6d3986474e5635be566e7bc79d97c64d ]
The _sum and _avg values are in general sync together with the PELT divider. They are however not always completely in perfect sync, resulting in situations where _sum gets to zero while _avg stays positive. Such situations are undesirable.
This comes from the fact that PELT will increase period_contrib, also increasing the PELT divider, without updating _sum and _avg values to stay in perfect sync where (_sum == _avg * divider). However, such PELT change will never lower _sum, making it impossible to end up in a situation where _sum is zero and _avg is not.
Therefore, we need to ensure that when subtracting load outside PELT, that when _sum is zero, _avg is also set to zero. This occurs when (_sum < _avg * divider), and the subtracted (_avg * divider) is bigger or equal to the current _sum, while the subtracted _avg is smaller than the current _avg.
Reported-by: Sachin Sant sachinp@linux.vnet.ibm.com Reported-by: Naresh Kamboju naresh.kamboju@linaro.org Signed-off-by: Odin Ugedal odin@uged.al Signed-off-by: Peter Zijlstra (Intel) peterz@infradead.org Reviewed-by: Vincent Guittot vincent.guittot@linaro.org Tested-by: Sachin Sant sachinp@linux.vnet.ibm.com Link: https://lore.kernel.org/r/20210624111815.57937-1-odin@uged.al Signed-off-by: Sasha Levin sashal@kernel.org --- kernel/sched/fair.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 23663318fb81..1dd1ed98171b 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -3716,15 +3716,15 @@ update_cfs_rq_load_avg(u64 now, struct cfs_rq *cfs_rq)
r = removed_load; sub_positive(&sa->load_avg, r); - sub_positive(&sa->load_sum, r * divider); + sa->load_sum = sa->load_avg * divider;
r = removed_util; sub_positive(&sa->util_avg, r); - sub_positive(&sa->util_sum, r * divider); + sa->util_sum = sa->util_avg * divider;
r = removed_runnable; sub_positive(&sa->runnable_avg, r); - sub_positive(&sa->runnable_sum, r * divider); + sa->runnable_sum = sa->runnable_avg * divider;
/* * removed_runnable is the unweighted version of removed_load so we
From: Rustam Kovhaev rkovhaev@gmail.com
[ Upstream commit ccff81e1d028bbbf8573d3364a87542386c707bf ]
kmemleak scans struct page, but it does not scan the page content. If we allocate some memory with kmalloc(), then allocate page with alloc_page(), and if we put kmalloc pointer somewhere inside that page, kmemleak will report kmalloc pointer as a false positive.
We can instruct kmemleak to scan the memory area by calling kmemleak_alloc() and kmemleak_free(), but part of struct bpf_ringbuf is mmaped to user space, and if struct bpf_ringbuf changes we would have to revisit and review size argument in kmemleak_alloc(), because we do not want kmemleak to scan the user space memory. Let's simplify things and use kmemleak_not_leak() here.
For posterity, also adding additional prior analysis from Andrii:
I think either kmemleak or syzbot are misreporting this. I've added a bunch of printks around all allocations performed by BPF ringbuf. [...] On repro side I get these two warnings:
[vmuser@archvm bpf]$ sudo ./repro BUG: memory leak unreferenced object 0xffff88810d538c00 (size 64): comm "repro", pid 2140, jiffies 4294692933 (age 14.540s) hex dump (first 32 bytes): 00 af 19 04 00 ea ff ff c0 ae 19 04 00 ea ff ff ................ 80 ae 19 04 00 ea ff ff c0 29 2e 04 00 ea ff ff .........)...... backtrace: [<0000000077bfbfbd>] __bpf_map_area_alloc+0x31/0xc0 [<00000000587fa522>] ringbuf_map_alloc.cold.4+0x48/0x218 [<0000000044d49e96>] __do_sys_bpf+0x359/0x1d90 [<00000000f601d565>] do_syscall_64+0x2d/0x40 [<0000000043d3112a>] entry_SYSCALL_64_after_hwframe+0x44/0xae
BUG: memory leak unreferenced object 0xffff88810d538c80 (size 64): comm "repro", pid 2143, jiffies 4294699025 (age 8.448s) hex dump (first 32 bytes): 80 aa 19 04 00 ea ff ff 00 ab 19 04 00 ea ff ff ................ c0 ab 19 04 00 ea ff ff 80 44 28 04 00 ea ff ff .........D(..... backtrace: [<0000000077bfbfbd>] __bpf_map_area_alloc+0x31/0xc0 [<00000000587fa522>] ringbuf_map_alloc.cold.4+0x48/0x218 [<0000000044d49e96>] __do_sys_bpf+0x359/0x1d90 [<00000000f601d565>] do_syscall_64+0x2d/0x40 [<0000000043d3112a>] entry_SYSCALL_64_after_hwframe+0x44/0xae
Note that both reported leaks (ffff88810d538c80 and ffff88810d538c00) correspond to pages array bpf_ringbuf is allocating and tracking properly internally. Note also that syzbot repro doesn't close FD of created BPF ringbufs, and even when ./repro itself exits with error, there are still two forked processes hanging around in my system. So clearly ringbuf maps are alive at that point. So reporting any memory leak looks weird at that point, because that memory is being used by active referenced BPF ringbuf.
It's also a question why repro doesn't clean up its forks. But if I do a `pkill repro`, I do see that all the allocated memory is /properly/ cleaned up [and the] "leaks" are deallocated properly.
BTW, if I add close() right after bpf() syscall in syzbot repro, I see that everything is immediately deallocated, like designed. And no memory leak is reported. So I don't think the problem is anywhere in bpf_ringbuf code, rather in the leak detection and/or repro itself.
Reported-by: syzbot+5d895828587f49e7fe9b@syzkaller.appspotmail.com Signed-off-by: Rustam Kovhaev rkovhaev@gmail.com [ Daniel: also included analysis from Andrii to the commit log ] Signed-off-by: Daniel Borkmann daniel@iogearbox.net Tested-by: syzbot+5d895828587f49e7fe9b@syzkaller.appspotmail.com Cc: Dmitry Vyukov dvyukov@google.com Cc: Andrii Nakryiko andrii@kernel.org Link: https://lore.kernel.org/bpf/CAEf4BzYk+dqs+jwu6VKXP-RttcTEGFe+ySTGWT9CRNkagDi... Link: https://lore.kernel.org/lkml/YNTAqiE7CWJhOK2M@nuc10 Link: https://lore.kernel.org/lkml/20210615101515.GC26027@arm.com Link: https://syzkaller.appspot.com/bug?extid=5d895828587f49e7fe9b Link: https://lore.kernel.org/bpf/20210626181156.1873604-1-rkovhaev@gmail.com Signed-off-by: Sasha Levin sashal@kernel.org --- kernel/bpf/ringbuf.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/kernel/bpf/ringbuf.c b/kernel/bpf/ringbuf.c index 84b3b35fc0d0..9e0c10c6892a 100644 --- a/kernel/bpf/ringbuf.c +++ b/kernel/bpf/ringbuf.c @@ -8,6 +8,7 @@ #include <linux/vmalloc.h> #include <linux/wait.h> #include <linux/poll.h> +#include <linux/kmemleak.h> #include <uapi/linux/btf.h>
#define RINGBUF_CREATE_FLAG_MASK (BPF_F_NUMA_NODE) @@ -105,6 +106,7 @@ static struct bpf_ringbuf *bpf_ringbuf_area_alloc(size_t data_sz, int numa_node) rb = vmap(pages, nr_meta_pages + 2 * nr_data_pages, VM_ALLOC | VM_USERMAP, PAGE_KERNEL); if (rb) { + kmemleak_not_leak(pages); rb->pages = pages; rb->nr_pages = nr_pages; return rb;
From: gushengxian gushengxian@yulong.com
[ Upstream commit 9ea3e52c5bc8bb4a084938dc1e3160643438927a ]
"action" should not be NULL when it is referenced.
Signed-off-by: gushengxian 13145886936@163.com Signed-off-by: gushengxian gushengxian@yulong.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- include/net/flow_offload.h | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/include/net/flow_offload.h b/include/net/flow_offload.h index dc5c1e69cd9f..69c9eabf8325 100644 --- a/include/net/flow_offload.h +++ b/include/net/flow_offload.h @@ -319,12 +319,14 @@ flow_action_mixed_hw_stats_check(const struct flow_action *action, if (flow_offload_has_one_action(action)) return true;
- flow_action_for_each(i, action_entry, action) { - if (i && action_entry->hw_stats != last_hw_stats) { - NL_SET_ERR_MSG_MOD(extack, "Mixing HW stats types for actions is not supported"); - return false; + if (action) { + flow_action_for_each(i, action_entry, action) { + if (i && action_entry->hw_stats != last_hw_stats) { + NL_SET_ERR_MSG_MOD(extack, "Mixing HW stats types for actions is not supported"); + return false; + } + last_hw_stats = action_entry->hw_stats; } - last_hw_stats = action_entry->hw_stats; } return true; }
On 7/6/21 1:14 PM, Sasha Levin wrote:
From: gushengxian gushengxian@yulong.com
[ Upstream commit 9ea3e52c5bc8bb4a084938dc1e3160643438927a ]
"action" should not be NULL when it is referenced.
Signed-off-by: gushengxian 13145886936@163.com Signed-off-by: gushengxian gushengxian@yulong.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org
include/net/flow_offload.h | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/include/net/flow_offload.h b/include/net/flow_offload.h index dc5c1e69cd9f..69c9eabf8325 100644 --- a/include/net/flow_offload.h +++ b/include/net/flow_offload.h @@ -319,12 +319,14 @@ flow_action_mixed_hw_stats_check(const struct flow_action *action, if (flow_offload_has_one_action(action)) return true;
- flow_action_for_each(i, action_entry, action) {
if (i && action_entry->hw_stats != last_hw_stats) {
NL_SET_ERR_MSG_MOD(extack, "Mixing HW stats types for actions is not supported");
return false;
- if (action) {
flow_action_for_each(i, action_entry, action) {
if (i && action_entry->hw_stats != last_hw_stats) {
NL_SET_ERR_MSG_MOD(extack, "Mixing HW stats types for actions is not supported");
return false;
}
}last_hw_stats = action_entry->hw_stats;
} return true;last_hw_stats = action_entry->hw_stats;
}
This patch makes no sense really.
If action is NULL, a crash would happen earlier anyway in
if (flow_offload_has_one_action(action)) return true;
Also, I wonder why it has been backported to stable version, there was no Fixes: tag in the submission.
On Fri, Aug 06, 2021 at 11:30:04AM +0200, Eric Dumazet wrote:
On 7/6/21 1:14 PM, Sasha Levin wrote:
From: gushengxian gushengxian@yulong.com
[ Upstream commit 9ea3e52c5bc8bb4a084938dc1e3160643438927a ]
"action" should not be NULL when it is referenced.
Signed-off-by: gushengxian 13145886936@163.com Signed-off-by: gushengxian gushengxian@yulong.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org
include/net/flow_offload.h | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/include/net/flow_offload.h b/include/net/flow_offload.h index dc5c1e69cd9f..69c9eabf8325 100644 --- a/include/net/flow_offload.h +++ b/include/net/flow_offload.h @@ -319,12 +319,14 @@ flow_action_mixed_hw_stats_check(const struct flow_action *action, if (flow_offload_has_one_action(action)) return true;
- flow_action_for_each(i, action_entry, action) {
if (i && action_entry->hw_stats != last_hw_stats) {
NL_SET_ERR_MSG_MOD(extack, "Mixing HW stats types for actions is not supported");
return false;
- if (action) {
flow_action_for_each(i, action_entry, action) {
if (i && action_entry->hw_stats != last_hw_stats) {
NL_SET_ERR_MSG_MOD(extack, "Mixing HW stats types for actions is not supported");
return false;
}
}last_hw_stats = action_entry->hw_stats;
} return true;last_hw_stats = action_entry->hw_stats;
}
This patch makes no sense really.
If action is NULL, a crash would happen earlier anyway in
if (flow_offload_has_one_action(action)) return true;
Also, I wonder why it has been backported to stable version, there was no Fixes: tag in the submission.
That's the AUTOSEL logic: it will attempt to find fixes in commits that don't have a fixes: tag. Those get longer review times and aren't backported as quickly as commits with a stable tag or a fixes tag.
From: Marcelo Ricardo Leitner marcelo.leitner@gmail.com
[ Upstream commit 0c5dc070ff3d6246d22ddd931f23a6266249e3db ]
Ilja reported that, simply putting it, nothing was validating that from_addr_param functions were operating on initialized memory. That is, the parameter itself was being validated by sctp_walk_params, but it doesn't check for types and their specific sizes and it could be a 0-length one, causing from_addr_param to potentially work over the next parameter or even uninitialized memory.
The fix here is to, in all calls to from_addr_param, check if enough space is there for the wanted IP address type.
Reported-by: Ilja Van Sprundel ivansprundel@ioactive.com Signed-off-by: Marcelo Ricardo Leitner marcelo.leitner@gmail.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- include/net/sctp/structs.h | 2 +- net/sctp/bind_addr.c | 19 +++++++++++-------- net/sctp/input.c | 6 ++++-- net/sctp/ipv6.c | 7 ++++++- net/sctp/protocol.c | 7 ++++++- net/sctp/sm_make_chunk.c | 29 ++++++++++++++++------------- 6 files changed, 44 insertions(+), 26 deletions(-)
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index 1aa585216f34..d49593c72a55 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -461,7 +461,7 @@ struct sctp_af { int saddr); void (*from_sk) (union sctp_addr *, struct sock *sk); - void (*from_addr_param) (union sctp_addr *, + bool (*from_addr_param) (union sctp_addr *, union sctp_addr_param *, __be16 port, int iif); int (*to_addr_param) (const union sctp_addr *, diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c index 53e5ed79f63f..59e653b528b1 100644 --- a/net/sctp/bind_addr.c +++ b/net/sctp/bind_addr.c @@ -270,22 +270,19 @@ int sctp_raw_to_bind_addrs(struct sctp_bind_addr *bp, __u8 *raw_addr_list, rawaddr = (union sctp_addr_param *)raw_addr_list;
af = sctp_get_af_specific(param_type2af(param->type)); - if (unlikely(!af)) { + if (unlikely(!af) || + !af->from_addr_param(&addr, rawaddr, htons(port), 0)) { retval = -EINVAL; - sctp_bind_addr_clean(bp); - break; + goto out_err; }
- af->from_addr_param(&addr, rawaddr, htons(port), 0); if (sctp_bind_addr_state(bp, &addr) != -1) goto next; retval = sctp_add_bind_addr(bp, &addr, sizeof(addr), SCTP_ADDR_SRC, gfp); - if (retval) { + if (retval) /* Can't finish building the list, clean up. */ - sctp_bind_addr_clean(bp); - break; - } + goto out_err;
next: len = ntohs(param->length); @@ -294,6 +291,12 @@ int sctp_raw_to_bind_addrs(struct sctp_bind_addr *bp, __u8 *raw_addr_list, }
return retval; + +out_err: + if (retval) + sctp_bind_addr_clean(bp); + + return retval; }
/******************************************************************** diff --git a/net/sctp/input.c b/net/sctp/input.c index d508f6f3dd08..8924e2e142c8 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c @@ -1131,7 +1131,8 @@ static struct sctp_association *__sctp_rcv_init_lookup(struct net *net, if (!af) continue;
- af->from_addr_param(paddr, params.addr, sh->source, 0); + if (!af->from_addr_param(paddr, params.addr, sh->source, 0)) + continue;
asoc = __sctp_lookup_association(net, laddr, paddr, transportp); if (asoc) @@ -1174,7 +1175,8 @@ static struct sctp_association *__sctp_rcv_asconf_lookup( if (unlikely(!af)) return NULL;
- af->from_addr_param(&paddr, param, peer_port, 0); + if (af->from_addr_param(&paddr, param, peer_port, 0)) + return NULL;
return __sctp_lookup_association(net, laddr, &paddr, transportp); } diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index bd08807c9e44..5c6f5ced9cfa 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c @@ -551,15 +551,20 @@ static void sctp_v6_to_sk_daddr(union sctp_addr *addr, struct sock *sk) }
/* Initialize a sctp_addr from an address parameter. */ -static void sctp_v6_from_addr_param(union sctp_addr *addr, +static bool sctp_v6_from_addr_param(union sctp_addr *addr, union sctp_addr_param *param, __be16 port, int iif) { + if (ntohs(param->v6.param_hdr.length) < sizeof(struct sctp_ipv6addr_param)) + return false; + addr->v6.sin6_family = AF_INET6; addr->v6.sin6_port = port; addr->v6.sin6_flowinfo = 0; /* BUG */ addr->v6.sin6_addr = param->v6.addr; addr->v6.sin6_scope_id = iif; + + return true; }
/* Initialize an address parameter from a sctp_addr and return the length diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 6f2bbfeec3a4..25192b378e2e 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -254,14 +254,19 @@ static void sctp_v4_to_sk_daddr(union sctp_addr *addr, struct sock *sk) }
/* Initialize a sctp_addr from an address parameter. */ -static void sctp_v4_from_addr_param(union sctp_addr *addr, +static bool sctp_v4_from_addr_param(union sctp_addr *addr, union sctp_addr_param *param, __be16 port, int iif) { + if (ntohs(param->v4.param_hdr.length) < sizeof(struct sctp_ipv4addr_param)) + return false; + addr->v4.sin_family = AF_INET; addr->v4.sin_port = port; addr->v4.sin_addr.s_addr = param->v4.addr.s_addr; memset(addr->v4.sin_zero, 0, sizeof(addr->v4.sin_zero)); + + return true; }
/* Initialize an address parameter from a sctp_addr and return the length diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 5b44d228b6ca..f33a870b483d 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -2346,11 +2346,13 @@ int sctp_process_init(struct sctp_association *asoc, struct sctp_chunk *chunk,
/* Process the initialization parameters. */ sctp_walk_params(param, peer_init, init_hdr.params) { - if (!src_match && (param.p->type == SCTP_PARAM_IPV4_ADDRESS || - param.p->type == SCTP_PARAM_IPV6_ADDRESS)) { + if (!src_match && + (param.p->type == SCTP_PARAM_IPV4_ADDRESS || + param.p->type == SCTP_PARAM_IPV6_ADDRESS)) { af = sctp_get_af_specific(param_type2af(param.p->type)); - af->from_addr_param(&addr, param.addr, - chunk->sctp_hdr->source, 0); + if (!af->from_addr_param(&addr, param.addr, + chunk->sctp_hdr->source, 0)) + continue; if (sctp_cmp_addr_exact(sctp_source(chunk), &addr)) src_match = 1; } @@ -2531,7 +2533,8 @@ static int sctp_process_param(struct sctp_association *asoc, break; do_addr_param: af = sctp_get_af_specific(param_type2af(param.p->type)); - af->from_addr_param(&addr, param.addr, htons(asoc->peer.port), 0); + if (!af->from_addr_param(&addr, param.addr, htons(asoc->peer.port), 0)) + break; scope = sctp_scope(peer_addr); if (sctp_in_scope(net, &addr, scope)) if (!sctp_assoc_add_peer(asoc, &addr, gfp, SCTP_UNCONFIRMED)) @@ -2632,15 +2635,13 @@ static int sctp_process_param(struct sctp_association *asoc, addr_param = param.v + sizeof(struct sctp_addip_param);
af = sctp_get_af_specific(param_type2af(addr_param->p.type)); - if (af == NULL) + if (!af) break;
- af->from_addr_param(&addr, addr_param, - htons(asoc->peer.port), 0); + if (!af->from_addr_param(&addr, addr_param, + htons(asoc->peer.port), 0)) + break;
- /* if the address is invalid, we can't process it. - * XXX: see spec for what to do. - */ if (!af->addr_valid(&addr, NULL, NULL)) break;
@@ -3054,7 +3055,8 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc, if (unlikely(!af)) return SCTP_ERROR_DNS_FAILED;
- af->from_addr_param(&addr, addr_param, htons(asoc->peer.port), 0); + if (!af->from_addr_param(&addr, addr_param, htons(asoc->peer.port), 0)) + return SCTP_ERROR_DNS_FAILED;
/* ADDIP 4.2.1 This parameter MUST NOT contain a broadcast * or multicast address. @@ -3331,7 +3333,8 @@ static void sctp_asconf_param_success(struct sctp_association *asoc,
/* We have checked the packet before, so we do not check again. */ af = sctp_get_af_specific(param_type2af(addr_param->p.type)); - af->from_addr_param(&addr, addr_param, htons(bp->port), 0); + if (!af->from_addr_param(&addr, addr_param, htons(bp->port), 0)) + return;
switch (asconf_param->param_hdr.type) { case SCTP_PARAM_ADD_IP:
From: Marcelo Ricardo Leitner marcelo.leitner@gmail.com
[ Upstream commit 50619dbf8db77e98d821d615af4f634d08e22698 ]
The first chunk in a packet is ensured to be present at the beginning of sctp_rcv(), as a packet needs to have at least 1 chunk. But the second one, may not be completely available and ch->length can be over uninitialized memory.
Fix here is by only trying to walk on the next chunk if there is enough to hold at least the header, and then proceed with the ch->length validation that is already there.
Reported-by: Ilja Van Sprundel ivansprundel@ioactive.com Signed-off-by: Marcelo Ricardo Leitner marcelo.leitner@gmail.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org --- net/sctp/input.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/sctp/input.c b/net/sctp/input.c index 8924e2e142c8..f72bff93745c 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c @@ -1247,7 +1247,7 @@ static struct sctp_association *__sctp_rcv_walk_lookup(struct net *net,
ch = (struct sctp_chunkhdr *)ch_end; chunk_num++; - } while (ch_end < skb_tail_pointer(skb)); + } while (ch_end + sizeof(*ch) < skb_tail_pointer(skb));
return asoc; }
From: zhanglianjie zhanglianjie@uniontech.com
[ Upstream commit 6817c944430d00f71ccaa9c99ff5b0096aeb7873 ]
The cause of the problem is as follows: 1. when cat /sys/devices/system/memory/memory0/valid_zones, test_pages_in_a_zone() will be called. 2. test_pages_in_a_zone() finds the zone according to stat_pfn = 0. The smallest pfn of the numa node in the mips architecture is 128, and the page corresponding to the previous 0~127 pfn is not initialized (page->flags is 0xFFFFFFFF) 3. The nid and zonenum obtained using page_zone(pfn_to_page(0)) are out of bounds in the corresponding array, &NODE_DATA(page_to_nid(page))->node_zones[page_zonenum(page)], access to the out-of-bounds zone member variables appear abnormal, resulting in Oops. Therefore, it is necessary to keep the page between 0 and the minimum pfn to prevent Oops from appearing.
Signed-off-by: zhanglianjie zhanglianjie@uniontech.com Signed-off-by: Thomas Bogendoerfer tsbogend@alpha.franken.de Signed-off-by: Sasha Levin sashal@kernel.org --- arch/mips/loongson64/numa.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/arch/mips/loongson64/numa.c b/arch/mips/loongson64/numa.c index fa9b4a487a47..e8e3e48c5333 100644 --- a/arch/mips/loongson64/numa.c +++ b/arch/mips/loongson64/numa.c @@ -129,6 +129,9 @@ static void __init node_mem_init(unsigned int node) if (node_end_pfn(0) >= (0xffffffff >> PAGE_SHIFT)) memblock_reserve((node_addrspace_offset | 0xfe000000), 32 << 20); + + /* Reserve pfn range 0~node[0]->node_start_pfn */ + memblock_reserve(0, PAGE_SIZE * start_pfn); } }
From: Nick Desaulniers ndesaulniers@google.com
[ Upstream commit c994a3ec7ecc8bd2a837b2061e8a76eb8efc082b ]
Clang's integrated assembler only accepts these instructions when the cpu is set to mips32r5. With this change, we can assemble malta_defconfig with Clang via `make LLVM_IAS=1`.
Link: https://github.com/ClangBuiltLinux/linux/issues/763 Reported-by: Dmitry Golovin dima@golovin.in Signed-off-by: Nick Desaulniers ndesaulniers@google.com Signed-off-by: Thomas Bogendoerfer tsbogend@alpha.franken.de Signed-off-by: Sasha Levin sashal@kernel.org --- arch/mips/include/asm/mipsregs.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h index 9c8099a6ffed..acdf8c69220b 100644 --- a/arch/mips/include/asm/mipsregs.h +++ b/arch/mips/include/asm/mipsregs.h @@ -2077,7 +2077,7 @@ _ASM_MACRO_0(tlbginvf, _ASM_INSN_IF_MIPS(0x4200000c) ({ int __res; \ __asm__ __volatile__( \ ".set\tpush\n\t" \ - ".set\tmips32r2\n\t" \ + ".set\tmips32r5\n\t" \ _ASM_SET_VIRT \ "mfgc0\t%0, " #source ", %1\n\t" \ ".set\tpop" \ @@ -2090,7 +2090,7 @@ _ASM_MACRO_0(tlbginvf, _ASM_INSN_IF_MIPS(0x4200000c) ({ unsigned long long __res; \ __asm__ __volatile__( \ ".set\tpush\n\t" \ - ".set\tmips64r2\n\t" \ + ".set\tmips64r5\n\t" \ _ASM_SET_VIRT \ "dmfgc0\t%0, " #source ", %1\n\t" \ ".set\tpop" \ @@ -2103,7 +2103,7 @@ _ASM_MACRO_0(tlbginvf, _ASM_INSN_IF_MIPS(0x4200000c) do { \ __asm__ __volatile__( \ ".set\tpush\n\t" \ - ".set\tmips32r2\n\t" \ + ".set\tmips32r5\n\t" \ _ASM_SET_VIRT \ "mtgc0\t%z0, " #register ", %1\n\t" \ ".set\tpop" \ @@ -2115,7 +2115,7 @@ do { \ do { \ __asm__ __volatile__( \ ".set\tpush\n\t" \ - ".set\tmips64r2\n\t" \ + ".set\tmips64r5\n\t" \ _ASM_SET_VIRT \ "dmtgc0\t%z0, " #register ", %1\n\t" \ ".set\tpop" \
From: 周琰杰 (Zhou Yanjie) zhouyanjie@wanyeetech.com
[ Upstream commit 23c64447b3538a6f34cb38aae3bc19dc1ec53436 ]
The original clock (3 MHz) is too fast for the clocksource, there will be a chance that the system may get stuck.
Reported-by: Nikolaus Schaller hns@goldelico.com Tested-by: Nikolaus Schaller hns@goldelico.com # on CI20 Signed-off-by: 周琰杰 (Zhou Yanjie) zhouyanjie@wanyeetech.com Acked-by: Paul Cercueil paul@crapouillou.net Signed-off-by: Thomas Bogendoerfer tsbogend@alpha.franken.de Signed-off-by: Sasha Levin sashal@kernel.org --- arch/mips/boot/dts/ingenic/ci20.dts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/mips/boot/dts/ingenic/ci20.dts b/arch/mips/boot/dts/ingenic/ci20.dts index 8877c62609de..3a4eaf1f3f48 100644 --- a/arch/mips/boot/dts/ingenic/ci20.dts +++ b/arch/mips/boot/dts/ingenic/ci20.dts @@ -525,10 +525,10 @@ pins_mmc1: mmc1 {
&tcu { /* - * 750 kHz for the system timer and 3 MHz for the clocksource, + * 750 kHz for the system timer and clocksource, * use channel #0 for the system timer, #1 for the clocksource. */ assigned-clocks = <&tcu TCU_CLK_TIMER0>, <&tcu TCU_CLK_TIMER1>, <&tcu TCU_CLK_OST>; - assigned-clock-rates = <750000>, <3000000>, <3000000>; + assigned-clock-rates = <750000>, <750000>, <3000000>; };
Am Dienstag, dem 06.07.2021 um 07:11 -0400 schrieb Sasha Levin:
From: Tian Tao tiantao6@hisilicon.com
[ Upstream commit 7d614ab2f20503ed8766363d41f8607337571adf ]
fixed the below warning: drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c:84:2-8: WARNING: NULL check before some freeing functions is not needed.
While the subject contains "fix" this only removes a duplicated NULL check, so the code is correct before and after this change. Is this really stable material? Doesn't this just add commit noise to the stable kernels?
Regards, Lucas
Signed-off-by: Tian Tao tiantao6@hisilicon.com Acked-by: Christian König christian.koenig@amd.com Signed-off-by: Lucas Stach l.stach@pengutronix.de Signed-off-by: Sasha Levin sashal@kernel.org
drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c b/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c index b390dd4d60b7..d741b1d735f7 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c @@ -80,8 +80,7 @@ static void etnaviv_gem_prime_release(struct etnaviv_gem_object *etnaviv_obj) /* Don't drop the pages for imported dmabuf, as they are not * ours, just free the array we allocated: */
- if (etnaviv_obj->pages)
kvfree(etnaviv_obj->pages);
- kvfree(etnaviv_obj->pages);
drm_prime_gem_destroy(&etnaviv_obj->base, etnaviv_obj->sgt); }
Am 07.07.21 um 12:52 schrieb Lucas Stach:
Am Dienstag, dem 06.07.2021 um 07:11 -0400 schrieb Sasha Levin:
From: Tian Tao tiantao6@hisilicon.com
[ Upstream commit 7d614ab2f20503ed8766363d41f8607337571adf ]
fixed the below warning: drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c:84:2-8: WARNING: NULL check before some freeing functions is not needed.
While the subject contains "fix" this only removes a duplicated NULL check, so the code is correct before and after this change. Is this really stable material? Doesn't this just add commit noise to the stable kernels?
Yeah, agree.
I also had a case where a NULL check was removed in amdgpu and then a bit later back ported to stable.
Maybe just use something like "remove superfluous NULL check".
Regards, Christian.
Regards, Lucas
Signed-off-by: Tian Tao tiantao6@hisilicon.com Acked-by: Christian König christian.koenig@amd.com Signed-off-by: Lucas Stach l.stach@pengutronix.de Signed-off-by: Sasha Levin sashal@kernel.org
drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c b/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c index b390dd4d60b7..d741b1d735f7 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c @@ -80,8 +80,7 @@ static void etnaviv_gem_prime_release(struct etnaviv_gem_object *etnaviv_obj) /* Don't drop the pages for imported dmabuf, as they are not * ours, just free the array we allocated: */
- if (etnaviv_obj->pages)
kvfree(etnaviv_obj->pages);
- kvfree(etnaviv_obj->pages);
drm_prime_gem_destroy(&etnaviv_obj->base, etnaviv_obj->sgt); }
On Wed, Jul 07, 2021 at 01:50:21PM +0200, Christian König wrote:
Am 07.07.21 um 12:52 schrieb Lucas Stach:
Am Dienstag, dem 06.07.2021 um 07:11 -0400 schrieb Sasha Levin:
From: Tian Tao tiantao6@hisilicon.com
[ Upstream commit 7d614ab2f20503ed8766363d41f8607337571adf ]
fixed the below warning: drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c:84:2-8: WARNING: NULL check before some freeing functions is not needed.
While the subject contains "fix" this only removes a duplicated NULL check, so the code is correct before and after this change. Is this really stable material? Doesn't this just add commit noise to the stable kernels?
Yeah, agree.
I also had a case where a NULL check was removed in amdgpu and then a bit later back ported to stable.
Maybe just use something like "remove superfluous NULL check".
Sorry for missing that, I'll drop it. Thanks!
linux-stable-mirror@lists.linaro.org